Draw hearts to indicate player health

This commit is contained in:
Trevor Slocum 2021-10-07 21:00:33 -07:00
parent ada9ada6f9
commit b812b092e0
4 changed files with 101 additions and 52 deletions

BIN
assets/ui/heart.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

View File

@ -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
View File

@ -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)
}

View File

@ -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)
}