Add gib and die sounds
This commit is contained in:
parent
aba5ddbd99
commit
5b1bf05d12
Binary file not shown.
Binary file not shown.
21
creep.go
21
creep.go
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
type creep struct {
|
||||
type gameCreep struct {
|
||||
x, y float64
|
||||
sprite *ebiten.Image
|
||||
|
||||
|
@ -16,17 +16,28 @@ type creep struct {
|
|||
tick int
|
||||
nextAction int
|
||||
|
||||
level *Level
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (c *creep) doNextAction() {
|
||||
func NewCreep(sprite *ebiten.Image, level *Level) *gameCreep {
|
||||
return &gameCreep{
|
||||
x: float64(1 + rand.Intn(64)),
|
||||
y: float64(1 + rand.Intn(64)),
|
||||
sprite: sprite,
|
||||
level: level,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *gameCreep) doNextAction() {
|
||||
c.moveX = (rand.Float64() - 0.5) / 10
|
||||
c.moveY = (rand.Float64() - 0.5) / 10
|
||||
|
||||
c.nextAction = 400 + rand.Intn(1000)
|
||||
}
|
||||
|
||||
func (c *creep) Update() {
|
||||
func (c *gameCreep) Update() {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
|
@ -36,10 +47,10 @@ func (c *creep) Update() {
|
|||
c.tick = 0
|
||||
}
|
||||
|
||||
c.x, c.y = c.x+c.moveX, c.y+c.moveY
|
||||
c.x, c.y = c.level.Clamp(c.x+c.moveX, c.y+c.moveY)
|
||||
}
|
||||
|
||||
func (c *creep) Position() (float64, float64) {
|
||||
func (c *gameCreep) Position() (float64, float64) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
return c.x, c.y
|
||||
|
|
129
game.go
129
game.go
|
@ -36,10 +36,14 @@ type game struct {
|
|||
w, h int
|
||||
currentLevel *Level
|
||||
|
||||
audioPlayer *audio.Player
|
||||
audioPlayerGunshot *audio.Player
|
||||
audioPlayerGib *audio.Player
|
||||
audioPlayerDie *audio.Player
|
||||
|
||||
player *gamePlayer
|
||||
|
||||
gameOverTime time.Time
|
||||
|
||||
camScale float64
|
||||
camScaleTo float64
|
||||
|
||||
|
@ -47,7 +51,7 @@ type game struct {
|
|||
|
||||
spinnerIndex int
|
||||
|
||||
creeps []*creep
|
||||
creeps []*gameCreep
|
||||
|
||||
projectiles []*projectile
|
||||
|
||||
|
@ -114,20 +118,40 @@ func NewGame() (*game, error) {
|
|||
|
||||
flashImage = ebiten.NewImageFromImage(img)
|
||||
|
||||
f, err = assetsFS.Open("assets/audio/gunshot.mp3")
|
||||
loadSound := func(p string) (*audio.Player, error) {
|
||||
f, err := assetsFS.Open(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
gunshotSound, err := mp3.DecodeWithSampleRate(sampleRate, f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return audioContext.NewPlayer(gunshotSound)
|
||||
}
|
||||
|
||||
g.audioPlayerGunshot, err = loadSound("assets/audio/gunshot.mp3")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gunshotSound, err := mp3.DecodeWithSampleRate(sampleRate, f)
|
||||
g.audioPlayerGib, err = loadSound("assets/audio/gib.mp3")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
g.audioPlayer, err = audioContext.NewPlayer(gunshotSound)
|
||||
|
||||
g.audioPlayerDie, err = loadSound("assets/audio/die.mp3")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The death sound will have a delay without this.
|
||||
g.audioPlayerDie.SetVolume(0)
|
||||
g.audioPlayerDie.Play()
|
||||
|
||||
f, err = assetsFS.Open("assets/creeps/vampire.png")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -141,15 +165,18 @@ func NewGame() (*game, error) {
|
|||
|
||||
addedCreeps := make(map[string]bool)
|
||||
for i := 0; i < 1000; i++ {
|
||||
c := &creep{
|
||||
x: float64(1 + rand.Intn(64)),
|
||||
y: float64(1 + rand.Intn(64)),
|
||||
sprite: vampireImage,
|
||||
c := NewCreep(vampireImage, g.currentLevel)
|
||||
|
||||
safeSpace := 7.0
|
||||
dx, dy := deltaXY(g.player.x, g.player.y, c.x, c.y)
|
||||
if dx <= safeSpace || dy <= safeSpace {
|
||||
// Too close to the spawn point.
|
||||
continue
|
||||
}
|
||||
|
||||
addedCreep := fmt.Sprintf("%0.0f-%0.0f", c.x, c.y)
|
||||
if addedCreeps[addedCreep] {
|
||||
// Already added a creep here
|
||||
// Already added a gameCreep here.
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -159,6 +186,11 @@ func NewGame() (*game, error) {
|
|||
|
||||
ebiten.SetCursorShape(ebiten.CursorShapeCrosshair)
|
||||
|
||||
// The death sound will have a delay without this.
|
||||
g.audioPlayerDie.Pause()
|
||||
g.audioPlayerDie.Rewind()
|
||||
g.audioPlayerDie.SetVolume(1.6)
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
|
@ -169,6 +201,11 @@ func (g *game) Update() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if g.player.health <= 0 {
|
||||
// Game over.
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, c := range g.creeps {
|
||||
c.Update()
|
||||
}
|
||||
|
@ -239,21 +276,23 @@ func (g *game) Update() error {
|
|||
|
||||
for _, c := range g.creeps {
|
||||
cx, cy := c.Position()
|
||||
dx, dy := p.x-cx, p.y-cy
|
||||
if dx < 0 {
|
||||
dx *= -1
|
||||
}
|
||||
if dy < 0 {
|
||||
dy *= -1
|
||||
}
|
||||
dx, dy := deltaXY(p.x, p.y, cx, cy)
|
||||
if dx <= bulletHitThreshold && dy <= bulletHitThreshold {
|
||||
// Kill creep
|
||||
// Kill gameCreep
|
||||
g.addBloodSplatter(cx, cy)
|
||||
c.x = 1000
|
||||
c.y = 1000
|
||||
|
||||
// Remove projectile
|
||||
g.projectiles = append(g.projectiles[:i-removed], g.projectiles[i-removed+1:]...)
|
||||
removed++
|
||||
|
||||
// Play gib sound.
|
||||
g.audioPlayerGib.SetVolume(1.0)
|
||||
g.audioPlayerGib.Pause()
|
||||
g.audioPlayerGib.Rewind()
|
||||
g.audioPlayerGib.Play()
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -271,13 +310,15 @@ func (g *game) Update() error {
|
|||
g.projectiles = append(g.projectiles, p)
|
||||
|
||||
v := 0.75 + (rand.Float64() / 4)
|
||||
v = 1.0 // TODO
|
||||
v = 0.6 // TODO
|
||||
|
||||
g.player.weapon.lastFire = time.Now()
|
||||
g.audioPlayer.SetVolume(v)
|
||||
g.audioPlayer.Pause()
|
||||
g.audioPlayer.Rewind()
|
||||
g.audioPlayer.Play()
|
||||
|
||||
// Play gunshot sound.
|
||||
g.audioPlayerGunshot.SetVolume(v)
|
||||
g.audioPlayerGunshot.Pause()
|
||||
g.audioPlayerGunshot.Rewind()
|
||||
g.audioPlayerGunshot.Play()
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -321,8 +362,20 @@ func (g *game) addBloodSplatter(x, y float64) {
|
|||
|
||||
// Draw draws the game on the screen.
|
||||
func (g *game) Draw(screen *ebiten.Image) {
|
||||
// Game over.
|
||||
if g.player.health <= 0 {
|
||||
screen.Fill(colornames.Red)
|
||||
screen.Fill(color.RGBA{102, 0, 0, 255})
|
||||
|
||||
if time.Since(g.gameOverTime).Milliseconds()%2000 < 1500 {
|
||||
g.overlayImg.Clear()
|
||||
ebitenutil.DebugPrint(g.overlayImg, "GAME OVER")
|
||||
g.op.GeoM.Reset()
|
||||
g.op.GeoM.Translate(3, 0)
|
||||
g.op.GeoM.Scale(16, 16)
|
||||
g.op.GeoM.Translate(float64(g.w/2)-485, float64(g.h/2)-200)
|
||||
screen.DrawImage(g.overlayImg, g.op)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -415,15 +468,18 @@ func (g *game) renderLevel(screen *ebiten.Image) int {
|
|||
biteThreshold := 0.5
|
||||
for _, c := range g.creeps {
|
||||
cx, cy := c.Position()
|
||||
dx, dy := g.player.x-cx, g.player.y-cy
|
||||
if dx < 0 {
|
||||
dx *= -1
|
||||
}
|
||||
if dy < 0 {
|
||||
dy *= -1
|
||||
}
|
||||
dx, dy := deltaXY(g.player.x, g.player.y, cx, cy)
|
||||
if dx <= biteThreshold && dy <= biteThreshold {
|
||||
g.player.health--
|
||||
|
||||
if g.player.health == 0 {
|
||||
ebiten.SetCursorShape(ebiten.CursorShapeDefault)
|
||||
|
||||
g.gameOverTime = time.Now()
|
||||
|
||||
// Play die sound.
|
||||
g.audioPlayerDie.Play()
|
||||
}
|
||||
}
|
||||
|
||||
drawn += g.renderSprite(c.x, c.y, 0, 0, 0, c.sprite, screen)
|
||||
|
@ -459,3 +515,14 @@ func (g *game) renderLevel(screen *ebiten.Image) int {
|
|||
func (g *game) exit() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func deltaXY(x1, y1, x2, y2 float64) (dx float64, dy float64) {
|
||||
dx, dy = x1-x2, y1-y2
|
||||
if dx < 0 {
|
||||
dx *= -1
|
||||
}
|
||||
if dy < 0 {
|
||||
dy *= -1
|
||||
}
|
||||
return dx, dy
|
||||
}
|
||||
|
|
14
level.go
14
level.go
|
@ -27,6 +27,20 @@ func (l *Level) Size() (width, height int) {
|
|||
return l.w, l.h
|
||||
}
|
||||
|
||||
func (l *Level) Clamp(x, y float64) (float64, float64) {
|
||||
if x < 0 {
|
||||
x = 0
|
||||
} else if x > float64(l.w)-1 {
|
||||
x = float64(l.w)
|
||||
}
|
||||
if y < 0 {
|
||||
y = 0
|
||||
} else if y > float64(l.h)-1 {
|
||||
y = float64(l.h)
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
|
||||
// NewLevel returns a new randomly generated Level.
|
||||
func NewLevel() (*Level, error) {
|
||||
// Create a 108x108 Level.
|
||||
|
|
Loading…
Reference in New Issue