2024-11-15 16:11:45 -05:00
|
|
|
package screens
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"math"
|
|
|
|
|
"mover/assets"
|
|
|
|
|
"mover/gamedata"
|
|
|
|
|
"mover/gameelement"
|
|
|
|
|
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2/audio"
|
|
|
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Primary struct {
|
|
|
|
|
events map[ScreenManagerEvent]func()
|
|
|
|
|
dimensions gamedata.Area
|
|
|
|
|
elements []gameelement.GameElement
|
|
|
|
|
gameevents map[gamedata.GameEvent]bool
|
|
|
|
|
|
|
|
|
|
paused bool
|
|
|
|
|
gameover bool
|
|
|
|
|
musicInitialized bool
|
|
|
|
|
|
|
|
|
|
audioplayer *audio.Player
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewPrimary() *Primary {
|
|
|
|
|
p := &Primary{
|
|
|
|
|
events: make(map[ScreenManagerEvent]func()),
|
|
|
|
|
paused: false,
|
|
|
|
|
gameover: false,
|
|
|
|
|
musicInitialized: false,
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-16 12:31:22 -05:00
|
|
|
gamearea := gamedata.Area{Width: 640, Height: 480}
|
|
|
|
|
|
|
|
|
|
//initialize our layer map
|
2024-11-15 16:11:45 -05:00
|
|
|
p.gameevents = make(map[gamedata.GameEvent]bool)
|
|
|
|
|
|
2024-11-16 12:31:22 -05:00
|
|
|
//create background layer
|
|
|
|
|
p.elements = append(p.elements, gameelement.NewBackground(gamearea))
|
2024-11-15 16:11:45 -05:00
|
|
|
|
2024-11-16 12:31:22 -05:00
|
|
|
//create canvas (game) layer
|
|
|
|
|
canvas := gameelement.NewCanvas(gamearea)
|
2024-11-15 16:11:45 -05:00
|
|
|
canvas.RegisterEvents(gamedata.GameEventPlayerDeath, p.EventHandlerPlayerDeath)
|
|
|
|
|
canvas.RegisterEvents(gamedata.GameEventCharge, p.EventHandlerCharge)
|
|
|
|
|
canvas.RegisterEvents(gamedata.GameEventNewShot, p.EventHandlerNewShot)
|
|
|
|
|
canvas.RegisterEvents(gamedata.GameEventTargetHit, p.EventHandlerTargetHit)
|
|
|
|
|
canvas.RegisterEvents(gamedata.GameEventExplosion, p.EventHandlerExplosion)
|
|
|
|
|
p.elements = append(p.elements, canvas)
|
|
|
|
|
|
2024-11-16 12:31:22 -05:00
|
|
|
//create foreground cloud layer
|
|
|
|
|
clouds := gameelement.NewCloudLayer(gamearea)
|
|
|
|
|
clouds.Initialize()
|
|
|
|
|
p.elements = append(p.elements, clouds)
|
|
|
|
|
|
2024-11-15 16:11:45 -05:00
|
|
|
return p
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) Update() error {
|
|
|
|
|
|
|
|
|
|
if !p.musicInitialized {
|
|
|
|
|
s := audio.NewInfiniteLoop(assets.SoundBank[assets.MainLoop], assets.SoundBank[assets.MainLoop].Length())
|
|
|
|
|
p.audioplayer, _ = audioContext.NewPlayer(s)
|
|
|
|
|
p.audioplayer.Play()
|
|
|
|
|
p.musicInitialized = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//collect all inputs
|
|
|
|
|
inputs := p.CollectInputs()
|
|
|
|
|
if inputs.Quit {
|
|
|
|
|
p.events[EventEndgame]()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if inputs.Reset {
|
|
|
|
|
p.Reset()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.ProcessEventAudio()
|
|
|
|
|
|
|
|
|
|
if inputs.Start {
|
|
|
|
|
if p.gameover {
|
|
|
|
|
p.Reset()
|
|
|
|
|
} else {
|
|
|
|
|
p.TogglePause()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//primary game loop, for each element pass along the inputs
|
|
|
|
|
//and process its update logic
|
|
|
|
|
if !p.paused {
|
|
|
|
|
for _, ge := range p.elements {
|
|
|
|
|
ge.SetInputs(inputs)
|
|
|
|
|
ge.Update()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) Draw(screen *ebiten.Image) {
|
|
|
|
|
//here we simply call each game elements draw function
|
|
|
|
|
//as a layer on top of each other
|
|
|
|
|
for _, ge := range p.elements {
|
|
|
|
|
ge.Draw(screen)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) SetEventHandler(e ScreenManagerEvent, f func()) {
|
|
|
|
|
p.events[e] = f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) SetDimensions(a gamedata.Area) {
|
|
|
|
|
p.dimensions = a
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) CollectInputs() gamedata.GameInputs {
|
|
|
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyQ) {
|
|
|
|
|
p.events[EventEndgame]()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gi := gamedata.GameInputs{}
|
|
|
|
|
|
|
|
|
|
//axes
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gi.XAxis = inpx
|
|
|
|
|
gi.YAxis = inpy
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gi.ShotAngle = math.Atan2(yaxis, xaxis)
|
|
|
|
|
|
|
|
|
|
gi.Charge = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonRightStick)
|
|
|
|
|
gi.Start = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonCenterRight)
|
|
|
|
|
gi.Shot = ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonFrontBottomRight)
|
|
|
|
|
gi.Quit = inpututil.IsKeyJustPressed(ebiten.KeyQ)
|
|
|
|
|
gi.Reset = inpututil.IsKeyJustPressed(ebiten.KeyR)
|
|
|
|
|
|
|
|
|
|
return gi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) TogglePause() {
|
|
|
|
|
p.paused = !p.paused
|
|
|
|
|
var player *audio.Player
|
|
|
|
|
if p.paused {
|
|
|
|
|
player = audioContext.NewPlayerFromBytes(assets.PauseIn)
|
|
|
|
|
p.audioplayer.Pause()
|
|
|
|
|
} else {
|
|
|
|
|
player = audioContext.NewPlayerFromBytes(assets.PauseOut)
|
|
|
|
|
p.audioplayer.Play()
|
|
|
|
|
}
|
|
|
|
|
player.Play()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) Reset() {
|
|
|
|
|
p.paused = false
|
|
|
|
|
p.gameover = false
|
|
|
|
|
|
|
|
|
|
for _, ge := range p.elements {
|
|
|
|
|
ge.Initialize()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) ProcessEventAudio() {
|
|
|
|
|
for event, occurred := range p.gameevents {
|
|
|
|
|
if occurred {
|
|
|
|
|
p.PlayAudio(event)
|
|
|
|
|
p.gameevents[event] = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) PlayAudio(e gamedata.GameEvent) {
|
|
|
|
|
switch e {
|
|
|
|
|
case gamedata.GameEventPlayerDeath:
|
|
|
|
|
player := audioContext.NewPlayerFromBytes(assets.HeroDeath)
|
|
|
|
|
player.Play()
|
|
|
|
|
case gamedata.GameEventCharge:
|
|
|
|
|
player := audioContext.NewPlayerFromBytes(assets.Magic)
|
|
|
|
|
player.Play()
|
|
|
|
|
case gamedata.GameEventNewShot:
|
|
|
|
|
player := audioContext.NewPlayerFromBytes(assets.Shot)
|
|
|
|
|
player.Play()
|
|
|
|
|
case gamedata.GameEventTargetHit:
|
|
|
|
|
player := audioContext.NewPlayerFromBytes(assets.TargetHit)
|
|
|
|
|
player.Play()
|
|
|
|
|
case gamedata.GameEventExplosion:
|
|
|
|
|
player := audioContext.NewPlayerFromBytes(assets.Splode)
|
|
|
|
|
player.Play()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) EventHandlerPlayerDeath() {
|
|
|
|
|
p.gameevents[gamedata.GameEventPlayerDeath] = true
|
|
|
|
|
p.gameover = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) EventHandlerCharge() {
|
|
|
|
|
p.gameevents[gamedata.GameEventCharge] = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) EventHandlerNewShot() {
|
|
|
|
|
p.gameevents[gamedata.GameEventNewShot] = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) EventHandlerTargetHit() {
|
|
|
|
|
p.gameevents[gamedata.GameEventTargetHit] = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (p *Primary) EventHandlerExplosion() {
|
|
|
|
|
p.gameevents[gamedata.GameEventExplosion] = true
|
|
|
|
|
}
|