diff --git a/altar.png b/altar.png new file mode 100644 index 0000000..0e5586d Binary files /dev/null and b/altar.png differ diff --git a/game.go b/game.go index 9909ce2..464b811 100644 --- a/game.go +++ b/game.go @@ -25,9 +25,12 @@ const ( var ( tilesetImage *ebiten.Image + altarImage *ebiten.Image //go:embed grasstile.png tileset_img []byte + //go:embed altar.png + altar_img []byte ) type Game struct { @@ -64,6 +67,12 @@ func init() { log.Fatal(err) } tilesetImage = ebiten.NewImageFromImage(img) + + img, _, err = image.Decode(bytes.NewReader(altar_img)) + if err != nil { + log.Fatal(err) + } + altarImage = ebiten.NewImageFromImage(img) } func (g *Game) Initialize() { @@ -87,6 +96,7 @@ func (g *Game) Initialize() { g.score = 0 g.reset = false + //clean up all targets for j := 0; j < len(g.targets); j++ { g.targets[j] = nil } @@ -97,6 +107,10 @@ func (g *Game) Initialize() { g.timer = 0 g.runtime = 0. + g.projectiles = make(map[int]*Projectile) + g.initialized = true + g.reset = false + } func (g *Game) Update() error { @@ -119,10 +133,6 @@ func (g *Game) Update() error { if !g.initialized || g.reset { g.Initialize() - - g.projectiles = make(map[int]*Projectile) - g.initialized = true - g.reset = false } else { g.StepGame() } @@ -221,8 +231,6 @@ func (g *Game) StepGame() { if !g.Paused { - g.UpdateHeroPosition() - g.hero.Update() g.explosion.Update() @@ -230,10 +238,11 @@ func (g *Game) StepGame() { g.UpdateProjectiles() if !g.gameover { + g.UpdateHeroPosition() //append new projectiles g.AppendProjectiles() //add new target with increasing frequency - g.AddNewTargets() + g.SpawnEnemies() //handle pulsewave updates g.HandlePulseWaveUpdate() } @@ -243,11 +252,29 @@ func (g *Game) StepGame() { } } -func (g *Game) AddNewTargets() { +func (g *Game) SpawnEnemies() { f := 40000 / (g.counter + 1) if g.counter%f == 0 { g.targets = append(g.targets, NewMover()) - g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: rand.Float64() * 640, Y: rand.Float64() * 480}) + + x0 := rand.Float64() * 640 + y0 := rand.Float64() * 480 + quadrant := rand.IntN(3) + + switch quadrant { + case 0: + g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: x0, Y: -MOVER_HEIGHT}) + case 1: + g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: x0, Y: screenHeight + MOVER_HEIGHT}) + case 2: + g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: -MOVER_WIDTH, Y: y0}) + case 3: + g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: screenWidth + x0, Y: y0}) + default: + g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: x0, Y: y0}) + fmt.Println("WTF " + string(quadrant)) + } + } } @@ -331,13 +358,14 @@ func (g *Game) UpdateTargets() { dy := g.hero.Pos.Y - target.Pos.Y angle := math.Atan2(dy, dx) - maxspeed := 3. + //maxspeed := (float64(g.counter) + 1.) / 1000. + maxspeed := 2.9 target.Pos.X += maxspeed * math.Cos(angle) target.Pos.Y += maxspeed * math.Sin(angle) } //compute collision with hero - if g.hero.Pos.X >= target.Pos.X-MOVER_WIDTH/2 && g.hero.Pos.X <= target.Pos.X+MOVER_WIDTH/2 && g.hero.Pos.Y >= target.Pos.Y-MOVER_HEIGHT/2 && g.hero.Pos.Y <= target.Pos.Y+MOVER_HEIGHT/2 && target.Action < MoverActionDying { + if g.hero.Pos.X >= target.Pos.X-MOVER_WIDTH/2 && g.hero.Pos.X <= target.Pos.X+MOVER_WIDTH/2 && g.hero.Pos.Y >= target.Pos.Y-MOVER_HEIGHT/2 && g.hero.Pos.Y <= target.Pos.Y+MOVER_HEIGHT/2 && target.Action < MoverActionDying && g.hero.Action < MoverActionDying { g.heroCollisionMask.Clear() g.heroCollisionMask.DrawImage(g.hero.Sprite, nil) @@ -352,8 +380,8 @@ func (g *Game) UpdateTargets() { g.heroCollisionMask.ReadPixels(pixels) for i := 0; i < len(pixels); i = i + 4 { if pixels[i+3] != 0 { - fmt.Println("pixel death") - g.hero.Action = MoverActionDying + //fmt.Println("pixel death") + g.hero.SetHit() g.gameover = true break } @@ -381,7 +409,7 @@ func (g *Game) AppendProjectiles() { func (g *Game) HandleInput() { if len(g.gamepadIDs) > 0 { if ebiten.IsGamepadButtonPressed(0, ebiten.GamepadButton11) { - if !g.explosion.Active { + if !g.explosion.Active && !g.gameover { g.explosion.SetOrigin(g.hero.Pos) g.explosion.Reset() g.explosion.ToggleActivate() @@ -397,18 +425,20 @@ func (g *Game) HandleInput() { } //account for controller sensitivity - xaxis := ebiten.StandardGamepadAxisValue(0, ebiten.StandardGamepadAxisRightStickHorizontal) - yaxis := ebiten.StandardGamepadAxisValue(0, ebiten.StandardGamepadAxisRightStickVertical) + if !g.gameover { + xaxis := ebiten.StandardGamepadAxisValue(0, ebiten.StandardGamepadAxisRightStickHorizontal) + yaxis := ebiten.StandardGamepadAxisValue(0, ebiten.StandardGamepadAxisRightStickVertical) - if yaxis <= 0.09 && yaxis >= -0.09 { - yaxis = 0 - } - if xaxis <= 0.09 && xaxis >= -0.09 { - xaxis = 0 - } + if yaxis <= 0.09 && yaxis >= -0.09 { + yaxis = 0 + } + if xaxis <= 0.09 && xaxis >= -0.09 { + xaxis = 0 + } - inputangle := math.Atan2(yaxis, xaxis) - g.hero.SetAngle(inputangle) + inputangle := math.Atan2(yaxis, xaxis) + g.hero.SetAngle(inputangle) + } } } @@ -427,18 +457,19 @@ func (g *Game) UpdateHeroPosition() { func (g *Game) ConstructBackground() { g.background = ebiten.NewImage(screenWidth, screenHeight) + BLOCK_SIZE := 32 for i := 0; i < 640/16; i++ { for j := 0; j < 480/16; j++ { //select random tile in x and y from tileset - idx_x := rand.IntN(256 / 16) - idx_y := rand.IntN(256 / 16) + idx_y := rand.IntN(256 / BLOCK_SIZE) + idx_x := rand.IntN(256 / BLOCK_SIZE) - x0 := 16 * idx_x - y0 := 16 * idx_y - x1 := x0 + 16 - y1 := y0 + 16 + x0 := BLOCK_SIZE * idx_x + y0 := BLOCK_SIZE * idx_y + x1 := x0 + BLOCK_SIZE + y1 := y0 + BLOCK_SIZE //translate for grid element we're painting op := &ebiten.DrawImageOptions{} @@ -446,4 +477,11 @@ func (g *Game) ConstructBackground() { g.background.DrawImage(tilesetImage.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op) } } + + ax := float64(rand.IntN(640/BLOCK_SIZE) * BLOCK_SIZE) + ay := float64(rand.IntN(480/BLOCK_SIZE) * BLOCK_SIZE) + + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(ax, ay) + g.background.DrawImage(altarImage, op) } diff --git a/grasstile.png b/grasstile.png index 7299ad8..8dc62e0 100644 Binary files a/grasstile.png and b/grasstile.png differ diff --git a/hero.go b/hero.go index ae4f3e0..48c2d51 100644 --- a/hero.go +++ b/hero.go @@ -14,9 +14,13 @@ import ( var ( heroImage *ebiten.Image + heroDeath *ebiten.Image //go:embed hero.png hero_img []byte + + //go:embed herodeath.png + herodeath_img []byte ) const ( @@ -36,6 +40,12 @@ func init() { log.Fatal(err) } heroImage = ebiten.NewImageFromImage(img) + + img, _, err = image.Decode(bytes.NewReader(herodeath_img)) + if err != nil { + log.Fatal(err) + } + heroDeath = ebiten.NewImageFromImage(img) } type Hero struct { @@ -98,6 +108,17 @@ func (m *Hero) Draw() { switch m.Action { case HeroActionDefault: m.Sprite.DrawImage(heroImage.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil) + case HeroActionDying: + m.dyingcount++ + + m.Sprite.DrawImage(heroDeath.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil) + + if m.dyingcount > 60 { + m.cycles = 0 + m.Action++ + } + case HeroActionExploding: + m.Sprite.DrawImage(heroDeath.SubImage(image.Rect(48*3, 0, 48*4, 48)).(*ebiten.Image), nil) default: } } @@ -106,8 +127,11 @@ func (m *Hero) Update() { m.cycles++ } +// one hit death for the hero func (m *Hero) SetHit() { - m.Action++ // = (m.Action + 1) % HeroActionMax + m.Action = MoverActionDying + m.Angle = 0 + m.cycles = 0 } func (m *Hero) ToggleColor() { diff --git a/hero.png b/hero.png index a622d0d..0359058 100644 Binary files a/hero.png and b/hero.png differ diff --git a/herodeath.png b/herodeath.png new file mode 100644 index 0000000..75c2f81 Binary files /dev/null and b/herodeath.png differ diff --git a/main.go b/main.go index 30a9115..b0b54eb 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ const ( ) func main() { - ver := "survive v0.08" + ver := "survive v0.10" fmt.Println(ver) diff --git a/mover.go b/mover.go index 3fd8065..3ab9cc8 100644 --- a/mover.go +++ b/mover.go @@ -16,6 +16,7 @@ var ( flyeyeImage *ebiten.Image flyeyeImage2 *ebiten.Image flyeyeImage3 *ebiten.Image + shadow *ebiten.Image //go:embed fly-eye.png flyeye_img []byte @@ -23,6 +24,8 @@ var ( flyeye_img2 []byte //go:embed fly-eye3.png flyeye_img3 []byte + //go:embed shadow.png + shadow_img []byte ) const ( @@ -54,6 +57,12 @@ func init() { log.Fatal(err) } flyeyeImage3 = ebiten.NewImageFromImage(img) + + img, _, err = image.Decode(bytes.NewReader(shadow_img)) + if err != nil { + log.Fatal(err) + } + shadow = ebiten.NewImageFromImage(img) } type Mover struct { @@ -115,8 +124,14 @@ func (m *Mover) Draw() { switch m.Action { case MoverActionDefault: + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(14, 40) + m.Sprite.DrawImage(shadow, op) m.Sprite.DrawImage(flyeyeImage.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil) case MoverActionDamaged: + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(14, 40) + m.Sprite.DrawImage(shadow, op) m.Sprite.DrawImage(flyeyeImage2.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil) case MoverActionDying: m.dyingcount++ diff --git a/shadow.png b/shadow.png new file mode 100644 index 0000000..3d7fa88 Binary files /dev/null and b/shadow.png differ