Randomize player and creep placement

This commit is contained in:
Trevor Slocum 2021-10-06 08:03:13 -07:00
parent 5b1bf05d12
commit e5e8af1e9b
3 changed files with 85 additions and 49 deletions

View File

@ -18,36 +18,59 @@ type gameCreep struct {
level *Level
health int
sync.Mutex
}
func NewCreep(sprite *ebiten.Image, level *Level) *gameCreep {
return &gameCreep{
x: float64(1 + rand.Intn(64)),
y: float64(1 + rand.Intn(64)),
x: float64(1 + rand.Intn(108)),
y: float64(1 + rand.Intn(108)),
sprite: sprite,
level: level,
health: 1,
}
}
func (c *gameCreep) doNextAction() {
c.moveX = (rand.Float64() - 0.5) / 10
c.moveY = (rand.Float64() - 0.5) / 10
c.moveX = (rand.Float64() - 0.5) / 7
c.moveY = (rand.Float64() - 0.5) / 7
c.nextAction = 400 + rand.Intn(1000)
if c.x <= 2 && c.moveX < 0 {
c.moveX *= 1
} else if c.x >= float64(c.level.w-3) && c.moveX > 0 {
c.moveX *= 1
}
if c.y <= 2 && c.moveY > 0 {
c.moveY *= 1
} else if c.y >= float64(c.level.h-3) && c.moveY < 0 {
c.moveY *= 1
}
c.nextAction = 400 + rand.Intn(400)
}
func (c *gameCreep) Update() {
c.Lock()
defer c.Unlock()
if c.health == 0 {
return
}
c.tick++
if c.tick >= c.nextAction {
c.doNextAction()
c.tick = 0
}
c.x, c.y = c.level.Clamp(c.x+c.moveX, c.y+c.moveY)
x, y := c.x+c.moveX, c.y+c.moveY
clampX, clampY := c.level.Clamp(x, y)
c.x, c.y = clampX, clampY
if clampX != x || clampY != y {
c.nextAction = 0
}
}
func (c *gameCreep) Position() (float64, float64) {

83
game.go
View File

@ -9,14 +9,12 @@ import (
"os"
"time"
"github.com/hajimehoshi/ebiten/v2/audio"
"github.com/hajimehoshi/ebiten/v2/audio/mp3"
"golang.org/x/image/colornames"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/audio"
"github.com/hajimehoshi/ebiten/v2/audio/mp3"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"golang.org/x/image/colornames"
)
var spinner = []byte(`-\|/`)
@ -59,6 +57,8 @@ type game struct {
overlayImg *ebiten.Image
op *ebiten.DrawImageOptions
godMode bool
}
const sampleRate = 48000
@ -79,16 +79,16 @@ func NewGame() (*game, error) {
g := &game{
currentLevel: l,
camScale: 4,
camScaleTo: 4,
camScale: 2,
camScaleTo: 2,
mousePanX: math.MinInt32,
mousePanY: math.MinInt32,
player: p,
op: &ebiten.DrawImageOptions{},
}
g.player.x = 7
g.player.y = 7
g.player.x = float64(rand.Intn(108))
g.player.y = float64(rand.Intn(108))
// Load SpriteSheets.
g.ojasSS, err = LoadCharacterSpriteSheet()
@ -137,11 +137,13 @@ func NewGame() (*game, error) {
if err != nil {
return nil, err
}
g.audioPlayerGunshot.SetVolume(0.6)
g.audioPlayerGib, err = loadSound("assets/audio/gib.mp3")
if err != nil {
return nil, err
}
g.audioPlayerGib.SetVolume(1.0)
g.audioPlayerDie, err = loadSound("assets/audio/die.mp3")
if err != nil {
@ -196,12 +198,12 @@ func NewGame() (*game, error) {
// Update reads current user input and updates the game state.
func (g *game) Update() error {
if ebiten.IsWindowBeingClosed() {
if ebiten.IsKeyPressed(ebiten.KeyEscape) || ebiten.IsWindowBeingClosed() {
g.exit()
return nil
}
if g.player.health <= 0 {
if g.player.health <= 0 && !g.godMode {
// Game over.
return nil
}
@ -227,8 +229,8 @@ func (g *game) Update() error {
g.camScaleTo += scrollY * (g.camScaleTo / 7)
// Clamp target zoom level.
if g.camScaleTo < 1 {
g.camScaleTo = 1
if g.camScaleTo < 2 {
g.camScaleTo = 2
} else if g.camScaleTo > 4 {
g.camScaleTo = 4
}
@ -243,6 +245,11 @@ func (g *game) Update() error {
// Pan camera via keyboard.
pan := 0.05
// TODO debug only
if ebiten.IsKeyPressed(ebiten.KeyShift) {
pan *= 5
}
if ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA) {
g.player.x -= pan
}
@ -257,11 +264,7 @@ func (g *game) Update() error {
}
// Clamp camera position.
if g.player.y < 0.6 {
g.player.y = 0.6
} else if g.player.y > float64(g.currentLevel.h)-1.4 {
g.player.y = float64(g.currentLevel.h) - 1.4
}
g.player.x, g.player.y = g.currentLevel.Clamp(g.player.x, g.player.y)
// Update player angle.
cx, cy := ebiten.CursorPosition()
@ -275,24 +278,29 @@ func (g *game) Update() error {
p.y += math.Sin(p.angle) * p.speed
for _, c := range g.creeps {
if c.health == 0 {
continue
}
cx, cy := c.Position()
dx, dy := deltaXY(p.x, p.y, cx, cy)
if dx <= bulletHitThreshold && dy <= bulletHitThreshold {
// Kill gameCreep
g.addBloodSplatter(cx, cy)
c.x = 1000
c.y = 1000
c.health--
// Killed creep.
if c.health == 0 {
g.addBloodSplatter(cx, cy)
// Play gib sound.
g.audioPlayerGib.Pause()
g.audioPlayerGib.Rewind()
g.audioPlayerGib.Play()
}
// 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
}
}
@ -309,18 +317,19 @@ func (g *game) Update() error {
}
g.projectiles = append(g.projectiles, p)
v := 0.75 + (rand.Float64() / 4)
v = 0.6 // TODO
g.player.weapon.lastFire = time.Now()
// Play gunshot sound.
g.audioPlayerGunshot.SetVolume(v)
g.audioPlayerGunshot.Pause()
g.audioPlayerGunshot.Rewind()
g.audioPlayerGunshot.Play()
}
// TODO debug only
if inpututil.IsKeyJustPressed(ebiten.KeyG) {
g.godMode = !g.godMode
}
return nil
}
@ -363,7 +372,7 @@ 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 {
if g.player.health <= 0 && !g.godMode {
screen.Fill(color.RGBA{102, 0, 0, 255})
if time.Since(g.gameOverTime).Milliseconds()%2000 < 1500 {
@ -467,12 +476,16 @@ func (g *game) renderLevel(screen *ebiten.Image) int {
biteThreshold := 0.5
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--
if g.player.health == 0 {
if g.player.health == 0 && !g.godMode {
ebiten.SetCursorShape(ebiten.CursorShapeDefault)
g.gameOverTime = time.Now()

View File

@ -28,15 +28,15 @@ func (l *Level) Size() (width, height int) {
}
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 x < 0.3 {
x = 0.3
} else if x > float64(l.w)-1.3 {
x = float64(l.w) - 1.3
}
if y < 0 {
y = 0
} else if y > float64(l.h)-1 {
y = float64(l.h)
if y < 0.4 {
y = 0.4
} else if y > float64(l.h)-1.8 {
y = float64(l.h) - 1.8
}
return x, y
}