Draw hearts to indicate player health
This commit is contained in:
parent
ada9ada6f9
commit
b812b092e0
4 changed files with 101 additions and 52 deletions
BIN
assets/ui/heart.png
Normal file
BIN
assets/ui/heart.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 960 B |
51
creep.go
51
creep.go
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
|
@ -16,7 +17,8 @@ type gameCreep struct {
|
|||
tick int
|
||||
nextAction int
|
||||
|
||||
level *Level
|
||||
level *Level
|
||||
player *gamePlayer
|
||||
|
||||
health int
|
||||
|
||||
|
@ -25,20 +27,27 @@ type gameCreep struct {
|
|||
sync.Mutex
|
||||
}
|
||||
|
||||
func NewCreep(sprite *ebiten.Image, level *Level) *gameCreep {
|
||||
return &gameCreep{
|
||||
x: float64(1 + rand.Intn(108)),
|
||||
y: float64(1 + rand.Intn(108)),
|
||||
sprite: sprite,
|
||||
level: level,
|
||||
health: 1,
|
||||
killScore: 50,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *gameCreep) doNextAction() {
|
||||
c.moveX = (rand.Float64() - 0.5) / 7
|
||||
c.moveY = (rand.Float64() - 0.5) / 7
|
||||
randMovementA := (rand.Float64() - 0.5) / 7
|
||||
randMovementB := (rand.Float64() - 0.5) / 7
|
||||
if rand.Intn(7) == 0 {
|
||||
// Seek player.
|
||||
c.moveX = c.x - c.player.x
|
||||
if c.moveX < 0 {
|
||||
c.moveX = math.Abs(randMovementA)
|
||||
} else {
|
||||
c.moveX = math.Abs(randMovementA) * -1
|
||||
}
|
||||
c.moveY = c.y - c.player.y
|
||||
if c.moveY < 0 {
|
||||
c.moveY = math.Abs(randMovementB)
|
||||
} else {
|
||||
c.moveY = math.Abs(randMovementB) * -1
|
||||
}
|
||||
} else {
|
||||
c.moveX = randMovementA
|
||||
c.moveY = randMovementB
|
||||
}
|
||||
|
||||
if c.x <= 2 && c.moveX < 0 {
|
||||
c.moveX *= 1
|
||||
|
@ -51,7 +60,19 @@ func (c *gameCreep) doNextAction() {
|
|||
c.moveY *= 1
|
||||
}
|
||||
|
||||
c.nextAction = 400 + rand.Intn(400)
|
||||
c.nextAction = 144 + rand.Intn(720)
|
||||
}
|
||||
|
||||
func NewCreep(sprite *ebiten.Image, level *Level, player *gamePlayer) *gameCreep {
|
||||
return &gameCreep{
|
||||
x: float64(1 + rand.Intn(108)),
|
||||
y: float64(1 + rand.Intn(108)),
|
||||
sprite: sprite,
|
||||
level: level,
|
||||
player: player,
|
||||
health: 1,
|
||||
killScore: 50,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *gameCreep) Update() {
|
||||
|
|
97
game.go
97
game.go
|
@ -57,6 +57,8 @@ type game struct {
|
|||
|
||||
ojasSS *CharacterSpriteSheet
|
||||
|
||||
heartImg *ebiten.Image
|
||||
|
||||
overlayImg *ebiten.Image
|
||||
op *ebiten.DrawImageOptions
|
||||
|
||||
|
@ -172,9 +174,20 @@ func NewGame() (*game, error) {
|
|||
|
||||
vampireImage := ebiten.NewImageFromImage(img)
|
||||
|
||||
f, err = assetsFS.Open("assets/ui/heart.png")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
img, _, err = image.Decode(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
g.heartImg = ebiten.NewImageFromImage(img)
|
||||
|
||||
addedCreeps := make(map[string]bool)
|
||||
for i := 0; i < 1000; i++ {
|
||||
c := NewCreep(vampireImage, g.currentLevel)
|
||||
c := NewCreep(vampireImage, g.currentLevel, g.player)
|
||||
|
||||
safeSpace := 7.0
|
||||
dx, dy := deltaXY(g.player.x, g.player.y, c.x, c.y)
|
||||
|
@ -249,8 +262,46 @@ func (g *game) Update() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
biteThreshold := 0.75
|
||||
for _, c := range g.creeps {
|
||||
if c.health == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
c.Update()
|
||||
|
||||
cx, cy := c.Position()
|
||||
dx, dy := deltaXY(g.player.x, g.player.y, cx, cy)
|
||||
if dx <= biteThreshold && dy <= biteThreshold {
|
||||
g.player.health--
|
||||
|
||||
err := g.hurtCreep(c, -1)
|
||||
if err != nil {
|
||||
// TODO
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if g.player.health == 2 {
|
||||
g.playSound(SoundPlayerHurt, 0.4)
|
||||
} else if g.player.health == 1 {
|
||||
g.playSound(SoundPlayerHurt, 0.8)
|
||||
}
|
||||
|
||||
g.addBloodSplatter(g.player.x, g.player.y)
|
||||
|
||||
if g.player.health == 0 && !g.godMode {
|
||||
ebiten.SetCursorShape(ebiten.CursorShapeDefault)
|
||||
|
||||
g.gameOverTime = time.Now()
|
||||
|
||||
// Play die sound.
|
||||
err := g.playSound(SoundPlayerDie, 1.6)
|
||||
if err != nil {
|
||||
// TODO return err
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update target zoom level.
|
||||
|
@ -309,7 +360,7 @@ func (g *game) Update() error {
|
|||
|
||||
// Update player angle.
|
||||
cx, cy := ebiten.CursorPosition()
|
||||
g.player.angle = math.Atan2(float64(cy-g.h/2), float64(cx-g.w/2))
|
||||
g.player.angle = angle(float64(cx), float64(cy), float64(g.w/2), float64(g.h/2))
|
||||
|
||||
// Update boolets.
|
||||
bulletHitThreshold := 0.5
|
||||
|
@ -463,7 +514,13 @@ func (g *game) Draw(screen *ebiten.Image) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO draw hearts for lives
|
||||
heartSpace := 64
|
||||
heartX := (g.w / 2) - ((heartSpace * g.player.health) / 2) + 16
|
||||
for i := 0; i < g.player.health; i++ {
|
||||
g.op.GeoM.Reset()
|
||||
g.op.GeoM.Translate(float64(heartX+(i*heartSpace)), 32)
|
||||
screen.DrawImage(g.heartImg, g.op)
|
||||
}
|
||||
|
||||
scoreLabel := numberPrinter.Sprintf("%d", g.player.score)
|
||||
|
||||
|
@ -561,45 +618,11 @@ func (g *game) renderLevel(screen *ebiten.Image) int {
|
|||
}
|
||||
}
|
||||
|
||||
biteThreshold := 0.75
|
||||
for _, c := range g.creeps {
|
||||
if c.health == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cx, cy := c.Position()
|
||||
dx, dy := deltaXY(g.player.x, g.player.y, cx, cy)
|
||||
if dx <= biteThreshold && dy <= biteThreshold {
|
||||
g.player.health--
|
||||
|
||||
err := g.hurtCreep(c, -1)
|
||||
if err != nil {
|
||||
// TODO
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if g.player.health == 2 {
|
||||
g.playSound(SoundPlayerHurt, 0.4)
|
||||
} else if g.player.health == 1 {
|
||||
g.playSound(SoundPlayerHurt, 0.8)
|
||||
}
|
||||
|
||||
g.addBloodSplatter(g.player.x, g.player.y)
|
||||
|
||||
if g.player.health == 0 && !g.godMode {
|
||||
ebiten.SetCursorShape(ebiten.CursorShapeDefault)
|
||||
|
||||
g.gameOverTime = time.Now()
|
||||
|
||||
// Play die sound.
|
||||
err := g.playSound(SoundPlayerDie, 1.6)
|
||||
if err != nil {
|
||||
// TODO return err
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drawn += g.renderSprite(c.x, c.y, 0, 0, 0, c.sprite, screen)
|
||||
}
|
||||
|
||||
|
|
5
level.go
5
level.go
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
@ -101,3 +102,7 @@ func NewLevel() (*Level, error) {
|
|||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func angle(x1, y1, x2, y2 float64) float64 {
|
||||
return math.Atan2(y1-y2, x1-x2)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue