Added new enemy character. WIP.
This commit is contained in:
219
screens/game.go
219
screens/game.go
@@ -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
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"mover/assets"
|
||||
"mover/fonts"
|
||||
"mover/gamedata"
|
||||
"mover/touch"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/audio"
|
||||
@@ -38,8 +39,20 @@ func NewStartScreen() *StartScreen {
|
||||
|
||||
func (s *StartScreen) Update() error {
|
||||
|
||||
touch.UpdateTouchIDs()
|
||||
|
||||
ids := touch.GetTouchIDs()
|
||||
var touched bool = false
|
||||
for _, id := range ids {
|
||||
touched = touch.IsTouchJustPressed(id)
|
||||
if touched {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyEnter) ||
|
||||
ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonCenterRight) {
|
||||
ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonCenterRight) ||
|
||||
touched {
|
||||
s.eHandler[EventCompleted]()
|
||||
if s.audioplayer.IsPlaying() {
|
||||
s.audioplayer.Close()
|
||||
|
||||
Reference in New Issue
Block a user