Added new enemy character. WIP.

This commit is contained in:
2024-11-13 07:44:56 -05:00
parent 8a1194eca3
commit 478ba994d6
6 changed files with 367 additions and 34 deletions

View File

@@ -49,6 +49,7 @@ type Game struct {
counter int
timer int
targets []*elements.Mover
boss *elements.Boss
}
var (
@@ -59,6 +60,7 @@ func NewGame() *Game {
g := &Game{
events: make(map[ScreenManagerEvent]func()),
musicInitialized: false,
boss: elements.NewBoss(),
}
return g
}
@@ -102,6 +104,8 @@ func (g *Game) Initialize() {
g.timer = 0
g.runtime = 0.
g.boss.Reset()
g.projectiles = make(map[int]*elements.Projectile)
g.initialized = true
g.reset = false
@@ -158,7 +162,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
}
*/
//draw shadows
//draw shadows--------------------------------------------------------------
for _, target := range g.targets {
if target.Action < elements.MoverActionExploding {
op := &ebiten.DrawImageOptions{}
@@ -167,6 +171,14 @@ func (g *Game) Draw(screen *ebiten.Image) {
}
}
if g.boss.Spawned && g.boss.Action < elements.MoverActionExploding {
op := &ebiten.DrawImageOptions{}
op.GeoM.Scale(4, 2)
op.GeoM.Translate(g.boss.Pos.X-96/2, g.boss.Pos.Y+96/2-10)
screen.DrawImage(assets.ImageBank[assets.FlyEyeShadow], op)
}
//draw enemies--------------------------------------------------------------
for _, target := range g.targets {
target.Draw()
@@ -177,6 +189,14 @@ func (g *Game) Draw(screen *ebiten.Image) {
screen.DrawImage(target.Sprite, op)
}
if g.boss.Spawned {
g.boss.Draw()
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(-MOVER_WIDTH, -MOVER_HEIGHT)
op.GeoM.Translate(g.boss.Pos.X, g.boss.Pos.Y)
screen.DrawImage(g.boss.Sprite, op)
}
g.projectileMask.Clear()
for _, p := range g.projectiles {
@@ -185,6 +205,12 @@ func (g *Game) Draw(screen *ebiten.Image) {
screen.DrawImage(g.projectileMask, nil)
/*
op.GeoM.Reset()
op.GeoM.Scale(0.25, 0.25)
screen.DrawImage(g.collisionMask, op)
*/
vector.StrokeCircle(screen, float32(g.explosion.Origin.X), float32(g.explosion.Origin.Y), float32(g.explosion.Radius), 3, color.White, true)
s := fmt.Sprintf("%02.3f", g.runtime)
@@ -243,16 +269,27 @@ func (g *Game) StepGame() {
g.explosion.Update()
g.UpdateTargets()
if g.boss.Spawned {
g.UpdateBoss()
}
g.UpdateProjectiles()
if !g.gameover {
g.UpdateHeroPosition()
//append new projectiles
g.AppendProjectiles()
//add new target with increasing frequency
g.SpawnEnemies()
//handle pulsewave updates
g.HandlePulseWaveUpdate()
if !g.boss.Spawned && g.counter > 600 {
g.SpawnBoss()
}
}
g.CleanupTargets()
@@ -342,30 +379,51 @@ func (g *Game) UpdateProjectiles() {
op.GeoM.Translate(target.Pos.X-MOVER_WIDTH/2, target.Pos.Y-MOVER_HEIGHT/2)
g.collisionMask.DrawImage(target.Sprite, op)
//var pixels []byte = make([]byte, MOVER_WIDTH*MOVER_HEIGHT*4)
var pixels []byte = make([]byte, g.dimensions.Width*g.dimensions.Height*4)
g.collisionMask.ReadPixels(pixels)
for i := 0; i < len(pixels); i = i + 4 {
if pixels[i+3] != 0 {
//fmt.Println("pixel collision")
delete(g.projectiles, k)
//target.ToggleColor()
target.SetHit()
//target.SetOrigin(gamedata.Coordinates{X: rand.Float64() * 640, Y: rand.Float64() * 480})
target.Hit = true
if g.HasCollided(g.collisionMask, g.dimensions.Width*g.dimensions.Height*4) {
//fmt.Println("pixel collision")
delete(g.projectiles, k)
//target.ToggleColor()
target.SetHit()
//target.SetOrigin(gamedata.Coordinates{X: rand.Float64() * 640, Y: rand.Float64() * 480})
target.Hit = true
//var err error
//player, err := audioContext.NewPlayer(assets.SoundBank[assets.Explode])
player := audioContext.NewPlayerFromBytes(assets.TargetHit)
player.Play()
break
}
player := audioContext.NewPlayerFromBytes(assets.TargetHit)
player.Play()
}
}
}
//boss check first, boundary check
if p.Pos.X >= g.boss.Pos.X-MOVER_WIDTH && p.Pos.X <= g.boss.Pos.X+MOVER_WIDTH &&
p.Pos.Y >= g.boss.Pos.Y-MOVER_HEIGHT && p.Pos.Y <= g.boss.Pos.Y+MOVER_HEIGHT &&
g.boss.Action < elements.MoverActionDying {
//fmt.Println("potential collision")
//the following computes total collisions in the image using a projectile mask that is a duplicate of what is on screen
//there's definitely room for optimization here
g.collisionMask.Clear()
g.collisionMask.DrawImage(g.projectileMask, nil)
op := &ebiten.DrawImageOptions{}
op.GeoM.Reset()
op.Blend = ebiten.BlendSourceIn
op.GeoM.Translate(g.boss.Pos.X-MOVER_WIDTH/2, g.boss.Pos.Y-MOVER_HEIGHT/2)
g.collisionMask.DrawImage(g.boss.Sprite, op)
if g.HasCollided(g.collisionMask, g.dimensions.Width*g.dimensions.Height*4) {
//fmt.Println("pixel collision")
delete(g.projectiles, k)
//target.ToggleColor()
g.boss.SetHit()
//target.SetOrigin(gamedata.Coordinates{X: rand.Float64() * 640, Y: rand.Float64() * 480})
//g.boss.Hit = true
player := audioContext.NewPlayerFromBytes(assets.TargetHit)
player.Play()
}
}
}
}
func (g *Game) UpdateTargets() {
@@ -401,19 +459,12 @@ func (g *Game) UpdateTargets() {
op.GeoM.Translate((g.hero.Pos.X-target.Pos.X)-MOVER_WIDTH/2, (g.hero.Pos.Y-target.Pos.Y)-MOVER_HEIGHT/2)
g.heroCollisionMask.DrawImage(target.Sprite, op)
//var pixels []byte = make([]byte, MOVER_WIDTH*MOVER_HEIGHT*4)
var pixels []byte = make([]byte, MOVER_HEIGHT*MOVER_HEIGHT*4)
g.heroCollisionMask.ReadPixels(pixels)
for i := 0; i < len(pixels); i = i + 4 {
if pixels[i+3] != 0 {
//fmt.Println("pixel death")
g.hero.SetHit()
g.gameover = true
if g.HasCollided(g.heroCollisionMask, MOVER_HEIGHT*MOVER_HEIGHT*4) {
g.hero.SetHit()
g.gameover = true
player := audioContext.NewPlayerFromBytes(assets.HeroDeath)
player.Play()
break
}
player := audioContext.NewPlayerFromBytes(assets.HeroDeath)
player.Play()
}
}
@@ -494,6 +545,21 @@ func (g *Game) UpdateHeroPosition() {
//handle gamepad input
inpx := ebiten.GamepadAxisValue(0, 0)
inpy := ebiten.GamepadAxisValue(0, 1)
//handle wasd input
if ebiten.IsKeyPressed(ebiten.KeyD) {
inpx = 1
}
if ebiten.IsKeyPressed(ebiten.KeyA) {
inpx = -1
}
if ebiten.IsKeyPressed(ebiten.KeyS) {
inpy = 1
}
if ebiten.IsKeyPressed(ebiten.KeyW) {
inpy = -1
}
if inpx >= 0.15 || inpx <= -0.15 {
g.hero.Left = inpx < 0
g.hero.Pos.X += inpx * 5
@@ -502,6 +568,7 @@ func (g *Game) UpdateHeroPosition() {
if inpy >= 0.15 || inpy <= -0.15 {
g.hero.Pos.Y += inpy * 5
}
}
func (g *Game) ConstructBackground() {
@@ -542,3 +609,91 @@ func (g *Game) SetDimensions(a gamedata.Area) {
func (g *Game) SetEventHandler(e ScreenManagerEvent, f func()) {
g.events[e] = f
}
func (g *Game) SpawnBoss() {
x0 := rand.Float64() * 640
y0 := rand.Float64() * 480
quadrant := rand.IntN(3)
switch quadrant {
case 0:
g.boss.Pos = gamedata.Coordinates{X: x0, Y: -(MOVER_HEIGHT * 2)}
case 1:
g.boss.Pos = gamedata.Coordinates{X: x0, Y: float64(g.dimensions.Height) + (MOVER_HEIGHT * 2)}
case 2:
g.boss.Pos = gamedata.Coordinates{X: -(MOVER_HEIGHT * 2), Y: y0}
case 3:
g.boss.Pos = gamedata.Coordinates{X: float64(g.dimensions.Width) + x0, Y: y0}
default:
g.boss.Pos = gamedata.Coordinates{X: x0, Y: y0}
fmt.Println("WTF " + string(quadrant))
}
//g.boss.Pos = gamedata.Coordinates{X: 640 / 2, Y: 480 / 2}
g.boss.Spawned = true
}
func (g *Game) UpdateBoss() {
g.boss.Update()
if g.boss.Action == elements.MoverActionExploding && !g.boss.SplodeInitiated {
player := audioContext.NewPlayerFromBytes(assets.Splode)
player.Play()
g.boss.SplodeInitiated = true
}
/*
if g.boss.Action >= elements.MoverActionDying {
g.boss.Spawned = false
}*/
if g.boss.Action >= elements.MoverActionDead {
g.boss.Pos = gamedata.Coordinates{X: -96, Y: -96}
}
if g.boss.Action < elements.MoverActionDying {
dx := g.hero.Pos.X - g.boss.Pos.X
dy := g.hero.Pos.Y - g.boss.Pos.Y
g.boss.Right = dx/48 > 0
g.boss.Pos = gamedata.Coordinates{
X: g.boss.Pos.X + dx/48,
Y: g.boss.Pos.Y + dy/48,
}
}
//compute collision with hero
if g.hero.Pos.X >= g.boss.Pos.X-MOVER_WIDTH && g.hero.Pos.X <= g.boss.Pos.X+MOVER_WIDTH &&
g.hero.Pos.Y >= g.boss.Pos.Y-MOVER_HEIGHT && g.hero.Pos.Y <= g.boss.Pos.Y+MOVER_HEIGHT &&
g.boss.Action < elements.MoverActionDying && g.hero.Action < elements.HeroActionDying {
g.heroCollisionMask.Clear()
g.heroCollisionMask.DrawImage(g.hero.Sprite, nil)
op := &ebiten.DrawImageOptions{}
op.GeoM.Reset()
op.Blend = ebiten.BlendSourceIn
op.GeoM.Translate((g.hero.Pos.X-g.boss.Pos.X)-MOVER_WIDTH, (g.hero.Pos.Y-g.boss.Pos.Y)-MOVER_HEIGHT)
g.heroCollisionMask.DrawImage(g.boss.Sprite, op)
if g.HasCollided(g.heroCollisionMask, MOVER_HEIGHT*MOVER_HEIGHT*4) {
g.hero.SetHit()
g.gameover = true
player := audioContext.NewPlayerFromBytes(assets.HeroDeath)
player.Play()
}
}
}
func (g *Game) HasCollided(mask *ebiten.Image, size int) bool {
var result bool = false
var pixels []byte = make([]byte, size)
mask.ReadPixels(pixels)
for i := 0; i < len(pixels); i = i + 4 {
if pixels[i+3] != 0 {
result = true
break
}
}
return result
}