Brought in screen manager, minor refactor.

This commit is contained in:
2024-11-11 09:54:30 -05:00
parent 9130155999
commit 6f794b7bb2
21 changed files with 373 additions and 170 deletions

15
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "survive",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "main.go"
}
]
}

View File

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 682 B

After

Width:  |  Height:  |  Size: 682 B

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

76
assets/imagebank.go Normal file
View File

@@ -0,0 +1,76 @@
package assets
import (
"bytes"
"image"
"log"
_ "embed"
"github.com/hajimehoshi/ebiten/v2"
)
type AssetName string
const (
FlyEyeNormal AssetName = "FlyEyeNormal"
FlyEyeDamaged AssetName = "FlyEyeDamaged"
FlyEyeDying AssetName = "FlyEyeDying"
FlyEyeShadow AssetName = "FlyEyeShadow"
HeroNormal AssetName = "HeroNormal"
HeroDying AssetName = "HeroDying"
TileSet AssetName = "TileSet"
Altar AssetName = "Altar"
Weapon AssetName = "Weapon"
)
var (
ImageBank map[AssetName]*ebiten.Image
flyeyeImage *ebiten.Image
flyeyeImage2 *ebiten.Image
flyeyeImage3 *ebiten.Image
shadow *ebiten.Image
//go:embed fly-eye.png
flyeye_img []byte
//go:embed fly-eye2.png
flyeye_img2 []byte
//go:embed fly-eye3.png
flyeye_img3 []byte
//go:embed shadow.png
shadow_img []byte
//go:embed hero.png
hero_img []byte
//go:embed herodeath.png
herodeath_img []byte
//go:embed grasstile.png
tileset_img []byte
//go:embed altar.png
altar_img []byte
//go:embed weapon.png
weapon_img []byte
)
func LoadImages() {
ImageBank = make(map[AssetName]*ebiten.Image)
ImageBank[FlyEyeNormal] = LoadImagesFatal(flyeye_img)
ImageBank[FlyEyeDamaged] = LoadImagesFatal(flyeye_img2)
ImageBank[FlyEyeDying] = LoadImagesFatal(flyeye_img3)
ImageBank[FlyEyeShadow] = LoadImagesFatal(shadow_img)
ImageBank[HeroNormal] = LoadImagesFatal(hero_img)
ImageBank[HeroDying] = LoadImagesFatal(herodeath_img)
ImageBank[TileSet] = LoadImagesFatal(tileset_img)
ImageBank[Altar] = LoadImagesFatal(altar_img)
ImageBank[Weapon] = LoadImagesFatal(weapon_img)
}
func LoadImagesFatal(b []byte) *ebiten.Image {
img, _, err := image.Decode(bytes.NewReader(b))
if err != nil {
log.Fatal(err)
}
return ebiten.NewImageFromImage(img)
}

View File

Before

Width:  |  Height:  |  Size: 102 B

After

Width:  |  Height:  |  Size: 102 B

View File

Before

Width:  |  Height:  |  Size: 741 B

After

Width:  |  Height:  |  Size: 741 B

View File

@@ -1,8 +1,10 @@
package main
package elements
import "mover/gamedata"
type Explosion struct {
Radius float64
Origin Coordinates
Origin gamedata.Coordinates
cycle int
Active bool
}
@@ -27,7 +29,7 @@ func (e *Explosion) Update() {
}
func (e *Explosion) SetOrigin(origin Coordinates) {
func (e *Explosion) SetOrigin(origin gamedata.Coordinates) {
e.Origin = origin
}

View File

@@ -1,9 +1,9 @@
package main
package elements
import (
"bytes"
"image"
"log"
"mover/assets"
"mover/gamedata"
_ "embed"
"image/color"
@@ -12,15 +12,9 @@ import (
"github.com/hajimehoshi/ebiten/v2"
)
var (
heroImage *ebiten.Image
heroDeath *ebiten.Image
//go:embed hero.png
hero_img []byte
//go:embed herodeath.png
herodeath_img []byte
const (
MOVER_WIDTH = 48
MOVER_HEIGHT = 48
)
const (
@@ -34,28 +28,14 @@ const (
type HeroAction uint
func init() {
img, _, err := image.Decode(bytes.NewReader(hero_img))
if err != nil {
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 {
Sprite *ebiten.Image
Maks *ebiten.Image
MaksDest *ebiten.Image
Angle float64
Pos Coordinates
Origin Coordinates
Lastpos Coordinates
Pos gamedata.Coordinates
Origin gamedata.Coordinates
Lastpos gamedata.Coordinates
Action HeroAction
cycles int
Upgrade bool
@@ -93,7 +73,7 @@ func (m *Hero) SetAngle(a float64) {
m.Angle = a
}
func (m *Hero) SetOrigin(coords Coordinates) {
func (m *Hero) SetOrigin(coords gamedata.Coordinates) {
m.Origin = coords
m.Pos = coords
}
@@ -117,16 +97,16 @@ func (m *Hero) Draw() {
switch m.Action {
case HeroActionDefault:
m.Sprite.DrawImage(heroImage.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op)
m.Sprite.DrawImage(assets.ImageBank[assets.HeroNormal].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op)
case HeroActionDying:
m.Sprite.DrawImage(heroDeath.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op)
m.Sprite.DrawImage(assets.ImageBank[assets.HeroDying].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op)
if m.dyingcount >= 31 {
m.cycles = 0
m.Action++
}
case HeroActionExploding:
m.Sprite.DrawImage(heroDeath.SubImage(image.Rect(48*3, 0, 48*4, 48)).(*ebiten.Image), op)
m.Sprite.DrawImage(assets.ImageBank[assets.HeroDying].SubImage(image.Rect(48*3, 0, 48*4, 48)).(*ebiten.Image), op)
default:
}
}

View File

@@ -1,9 +1,9 @@
package main
package elements
import (
"bytes"
"image"
"log"
"mover/assets"
"mover/gamedata"
_ "embed"
"image/color"
@@ -12,22 +12,6 @@ import (
"github.com/hajimehoshi/ebiten/v2"
)
var (
flyeyeImage *ebiten.Image
flyeyeImage2 *ebiten.Image
flyeyeImage3 *ebiten.Image
shadow *ebiten.Image
//go:embed fly-eye.png
flyeye_img []byte
//go:embed fly-eye2.png
flyeye_img2 []byte
//go:embed fly-eye3.png
flyeye_img3 []byte
//go:embed shadow.png
shadow_img []byte
)
const (
MoverActionDefault = iota
MoverActionDamaged
@@ -39,39 +23,13 @@ const (
type MoverAction uint
func init() {
img, _, err := image.Decode(bytes.NewReader(flyeye_img))
if err != nil {
log.Fatal(err)
}
flyeyeImage = ebiten.NewImageFromImage(img)
img, _, err = image.Decode(bytes.NewReader(flyeye_img2))
if err != nil {
log.Fatal(err)
}
flyeyeImage2 = ebiten.NewImageFromImage(img)
img, _, err = image.Decode(bytes.NewReader(flyeye_img3))
if err != nil {
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 {
Sprite *ebiten.Image
Maks *ebiten.Image
MaksDest *ebiten.Image
Angle float64
Pos Coordinates
Origin Coordinates
Pos gamedata.Coordinates
Origin gamedata.Coordinates
Action MoverAction
cycles int
rotating bool
@@ -106,7 +64,7 @@ func (m *Mover) SetAngle(a float64) {
m.Angle = a
}
func (m *Mover) SetOrigin(coords Coordinates) {
func (m *Mover) SetOrigin(coords gamedata.Coordinates) {
m.Origin = coords
m.Pos = coords
}
@@ -126,18 +84,18 @@ func (m *Mover) Draw() {
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)
m.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeShadow], op)
m.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeNormal].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)
m.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeShadow], op)
m.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeDamaged].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
case MoverActionDying:
if (m.cycles/5)%2 == 0 {
m.MaksDest.DrawImage(flyeyeImage2.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
m.MaksDest.DrawImage(assets.ImageBank[assets.FlyEyeDamaged].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
op := &ebiten.DrawImageOptions{}
op.GeoM.Reset()
op.Blend = ebiten.BlendSourceAtop
@@ -145,14 +103,14 @@ func (m *Mover) Draw() {
m.Sprite.DrawImage(m.MaksDest, nil)
} else {
m.Sprite.DrawImage(flyeyeImage2.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
m.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeDamaged].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
}
if m.dyingcount >= 31 {
m.cycles = 0
m.SetHit()
}
case MoverActionExploding:
m.Sprite.DrawImage(flyeyeImage3.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
m.Sprite.DrawImage(assets.ImageBank[assets.FlyEyeDying].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
if idx == 3 {
m.SetHit()
}

View File

@@ -1,14 +1,17 @@
package main
package elements
import "math"
import (
"math"
"mover/gamedata"
)
type Projectile struct {
Pos Coordinates
Pos gamedata.Coordinates
Velocity float64
a float64
}
func NewProjectile(origin Coordinates, angle, velocity float64) *Projectile {
func NewProjectile(origin gamedata.Coordinates, angle, velocity float64) *Projectile {
return &Projectile{
Velocity: velocity,
a: angle,

View File

@@ -1,4 +1,4 @@
package main
package gamedata
type Coordinates struct {
X float64

16
gamedata/gameinfo.go Normal file
View File

@@ -0,0 +1,16 @@
package gamedata
type Area struct {
Width int
Height int
}
func (a *Area) Area() int {
return a.Height * a.Width
}
type GameInfo struct {
Name string
Version string
Dimensions Area
}

25
main.go
View File

@@ -1,8 +1,11 @@
package main
import (
"fmt"
"log"
"mover/assets"
"mover/gamedata"
"mover/screenmanager"
"mover/screens"
"github.com/hajimehoshi/ebiten/v2"
)
@@ -13,17 +16,23 @@ const (
)
func main() {
ver := "survive v0.10"
fmt.Println(ver)
moverGame := &Game{}
//moverGame := &Game{}
moverGame := screenmanager.NewManager()
moverGame.SetDimensions(gamedata.Area{Width: screenWidth, Height: screenHeight})
ebiten.SetWindowSize(screenWidth*1.5, screenHeight*1.5)
ebiten.SetWindowTitle(ver)
ebiten.SetWindowTitle(moverGame.Info.Name + ": v" + moverGame.Info.Version)
if err := ebiten.RunGame(moverGame); err != nil {
loadScreens(&moverGame)
if err := ebiten.RunGame(&moverGame); err != nil {
log.Fatal(err)
}
}
func loadScreens(m *screenmanager.Manager) {
assets.LoadImages()
m.AddScene(&screens.Game{})
m.ResetScenes()
}

136
screenmanager/manager.go Normal file
View File

@@ -0,0 +1,136 @@
package screenmanager
import (
"mover/gamedata"
"mover/screens"
"github.com/hajimehoshi/ebiten/v2"
)
const (
defaultWidth = 1024
defaultHeight = 768
)
type Manager struct {
Info gamedata.GameInfo
currentScene screens.Screen
currentSceneId uint
nextSceneId uint
screens []screens.Screen
internalerr error
}
// can be used to create default manager instance
func NewManager() Manager {
return Manager{
Info: gamedata.GameInfo{
Name: "survive",
Version: "0.12",
Dimensions: gamedata.Area{
Width: defaultWidth,
Height: defaultHeight,
},
},
currentSceneId: 0,
nextSceneId: 1,
internalerr: nil,
}
}
// ebitengine update proxy on behalf of current scene
func (m *Manager) Update() error {
if m.currentScene == nil {
return nil
}
err := m.currentScene.Update()
if err != nil {
return err
}
return m.internalerr
}
// shutdown application
func (m *Manager) Quit() {
m.internalerr = ebiten.Termination
}
// calls current scene's draw method if the currentscene is valid
func (m *Manager) Draw(screen *ebiten.Image) {
if m.currentScene != nil {
m.currentScene.Draw(screen)
}
}
// ebitengine proxy for layout
func (m *Manager) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
return m.Info.Dimensions.Width, m.Info.Dimensions.Height
}
// appends scene to the managed screens
func (m *Manager) AddScene(s screens.Screen) {
setDefaultHandlers(m, s)
s.SetDimensions(m.Info.Dimensions)
m.screens = append(m.screens, s)
}
// sets the default callback handlers for a given scene within manager
// Default Handling behaviours:
//
// reset: sets (scene, nextscene) to {0, 1}
// scene completion: sets (scene, nextscene) to {nextscene, nextscene+1}
// end game: shutdown groovy
//
// note: NOOP and RELOAD are purposefully not mapped; they are scene
// specific and should be mapped to by user of groovy
func setDefaultHandlers(m *Manager, s screens.Screen) {
s.SetEventHandler(screens.EventReset, func() { m.ResetScenes() })
s.SetEventHandler(screens.EventCompleted, func() { m.TransitionScene() })
s.SetEventHandler(screens.EventEndgame, func() { m.Quit() })
}
// we're going to reset the scene to the first one
func (m *Manager) ResetScenes() {
m.currentSceneId = 0
m.nextSceneId = 1
m.SetCurrentScene(0)
}
// sets the current scene, based on sceneindex n
// n > scenelist, quit
// otherwise, scene = n
func (m *Manager) SetCurrentScene(sceneId uint) {
if sceneId >= uint(len(m.screens)) {
m.Quit()
} else {
m.currentSceneId = sceneId
m.currentScene = m.screens[sceneId]
m.nextSceneId = m.currentSceneId + 1
}
}
// handle scene transition
func (m *Manager) TransitionScene() {
m.SetCurrentScene(m.nextSceneId)
}
// set new sceneId as the successor
func (m *Manager) SetNextScene(sceneId uint) {
m.nextSceneId = sceneId
}
// sets sene dimensions
func (m *Manager) SetDimensions(a gamedata.Area) {
m.Info.Dimensions = a
}
// report number of total screens
func (m *Manager) SceneCount() uint {
return uint(len(m.screens))
}
func (m *Manager) GetScene(sceneId uint) screens.Screen {
return m.screens[sceneId]
}

View File

@@ -1,14 +1,16 @@
package main
package screens
import (
"bytes"
"fmt"
"image"
"image/color"
"log"
"math"
"math/rand/v2"
"mover/assets"
"mover/elements"
"mover/fonts"
"mover/gamedata"
_ "embed"
@@ -23,19 +25,6 @@ const (
MOVER_HEIGHT = 48
)
var (
weaponImage *ebiten.Image
tilesetImage *ebiten.Image
altarImage *ebiten.Image
//go:embed grasstile.png
tileset_img []byte
//go:embed altar.png
altar_img []byte
//go:embed weapon.png
weapon_img []byte
)
type Game struct {
background *ebiten.Image
collisionMask *ebiten.Image
@@ -43,20 +32,21 @@ type Game struct {
heroCollisionMask *ebiten.Image
heroCollisionCpy *ebiten.Image
Pos Coordinates
dimensions gamedata.Area
Pos gamedata.Coordinates
Paused bool
initialized bool
gameover bool
reset bool
runtime float64
hero *Hero
projectiles map[int]*Projectile
explosion *Explosion
hero *elements.Hero
projectiles map[int]*elements.Projectile
explosion *elements.Explosion
score int
counter int
timer int
targets []*Mover
targets []*elements.Mover
gamepadIDsBuf []ebiten.GamepadID
gamepadIDs map[ebiten.GamepadID]struct{}
@@ -64,43 +54,23 @@ type Game struct {
//pressedButtons map[ebiten.GamepadID][]string
}
func init() {
img, _, err := image.Decode(bytes.NewReader(tileset_img))
if err != nil {
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)
img, _, err = image.Decode(bytes.NewReader(weapon_img))
if err != nil {
log.Fatal(err)
}
weaponImage = ebiten.NewImageFromImage(img)
}
func (g *Game) Initialize() {
origin := Coordinates{X: 640 / 2, Y: 480 / 2}
origin := gamedata.Coordinates{X: 640 / 2, Y: 480 / 2}
g.ConstructBackground()
g.hero = NewHero()
g.hero = elements.NewHero()
g.hero.SetOrigin(origin)
g.hero.ToggleRotate()
g.gameover = false
g.collisionMask = ebiten.NewImage(screenWidth, screenHeight)
g.projectileMask = ebiten.NewImage(screenWidth, screenHeight)
g.collisionMask = ebiten.NewImage(g.dimensions.Width, g.dimensions.Height)
g.projectileMask = ebiten.NewImage(g.dimensions.Width, g.dimensions.Height)
g.heroCollisionMask = ebiten.NewImage(MOVER_WIDTH, MOVER_HEIGHT)
g.heroCollisionCpy = ebiten.NewImage(MOVER_WIDTH, MOVER_HEIGHT)
g.explosion = NewExplosion()
g.explosion = elements.NewExplosion()
g.explosion.SetOrigin(origin)
g.score = 0
g.reset = false
@@ -116,7 +86,7 @@ func (g *Game) Initialize() {
g.timer = 0
g.runtime = 0.
g.projectiles = make(map[int]*Projectile)
g.projectiles = make(map[int]*elements.Projectile)
g.initialized = true
g.reset = false
@@ -184,7 +154,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
op.GeoM.Translate(0, -16)
op.GeoM.Rotate(g.hero.Angle)
op.GeoM.Translate(g.hero.Pos.X, g.hero.Pos.Y)
screen.DrawImage(weaponImage, op)
screen.DrawImage(assets.ImageBank[assets.Weapon], op)
//secondary/upgraded weapon sprite; in testing proves sort of distracting
/*
@@ -226,7 +196,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
}
func (g *Game) Layout(width, height int) (int, int) {
return screenWidth, screenHeight
return g.dimensions.Width, g.dimensions.Height
}
func (g *Game) CleanupTargets() {
@@ -234,7 +204,7 @@ func (g *Game) CleanupTargets() {
i := 0
for _, target := range g.targets {
//moving valid targets to the front of the slice
if target.Action < MoverActionDead {
if target.Action < elements.MoverActionDead {
g.targets[i] = target
i++
}
@@ -282,7 +252,7 @@ func (g *Game) StepGame() {
func (g *Game) SpawnEnemies() {
f := 40000 / (g.counter + 1)
if g.counter%f == 0 {
g.targets = append(g.targets, NewMover())
g.targets = append(g.targets, elements.NewMover())
x0 := rand.Float64() * 640
y0 := rand.Float64() * 480
@@ -290,15 +260,15 @@ func (g *Game) SpawnEnemies() {
switch quadrant {
case 0:
g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: x0, Y: -MOVER_HEIGHT})
g.targets[len(g.targets)-1].SetOrigin(gamedata.Coordinates{X: x0, Y: -MOVER_HEIGHT})
case 1:
g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: x0, Y: screenHeight + MOVER_HEIGHT})
g.targets[len(g.targets)-1].SetOrigin(gamedata.Coordinates{X: x0, Y: float64(g.dimensions.Height) + MOVER_HEIGHT})
case 2:
g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: -MOVER_WIDTH, Y: y0})
g.targets[len(g.targets)-1].SetOrigin(gamedata.Coordinates{X: -MOVER_WIDTH, Y: y0})
case 3:
g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: screenWidth + x0, Y: y0})
g.targets[len(g.targets)-1].SetOrigin(gamedata.Coordinates{X: float64(g.dimensions.Width) + x0, Y: y0})
default:
g.targets[len(g.targets)-1].SetOrigin(Coordinates{X: x0, Y: y0})
g.targets[len(g.targets)-1].SetOrigin(gamedata.Coordinates{X: x0, Y: y0})
fmt.Println("WTF " + string(quadrant))
}
@@ -319,7 +289,8 @@ func (g *Game) HandlePulseWaveUpdate() {
dy := target.Pos.Y - g.hero.Pos.Y
r := math.Sqrt(dx*dx + dy*dy)
if r >= g.explosion.Radius-5 && r <= g.explosion.Radius+5 && target.Action <= MoverActionDamaged && !target.Touched {
if r >= g.explosion.Radius-5 && r <= g.explosion.Radius+5 &&
target.Action <= elements.MoverActionDamaged && !target.Touched {
target.ToggleColor()
target.Touched = true
//target.SetHit()
@@ -344,7 +315,9 @@ func (g *Game) UpdateProjectiles() {
//compute projectile collisions
for _, target := range g.targets {
//first, boundary check
if p.Pos.X >= target.Pos.X-MOVER_WIDTH/2 && p.Pos.X <= target.Pos.X+MOVER_WIDTH/2 && p.Pos.Y >= target.Pos.Y-MOVER_HEIGHT/2 && p.Pos.Y <= target.Pos.Y+MOVER_HEIGHT/2 && target.Action == MoverActionDamaged {
if p.Pos.X >= target.Pos.X-MOVER_WIDTH/2 && p.Pos.X <= target.Pos.X+MOVER_WIDTH/2 &&
p.Pos.Y >= target.Pos.Y-MOVER_HEIGHT/2 && p.Pos.Y <= target.Pos.Y+MOVER_HEIGHT/2 &&
target.Action == elements.MoverActionDamaged {
//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
@@ -359,7 +332,7 @@ func (g *Game) UpdateProjectiles() {
g.collisionMask.DrawImage(target.Sprite, op)
//var pixels []byte = make([]byte, MOVER_WIDTH*MOVER_HEIGHT*4)
var pixels []byte = make([]byte, screenWidth*screenHeight*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 {
@@ -367,7 +340,7 @@ func (g *Game) UpdateProjectiles() {
delete(g.projectiles, k)
//target.ToggleColor()
target.SetHit()
//target.SetOrigin(Coordinates{X: rand.Float64() * 640, Y: rand.Float64() * 480})
//target.SetOrigin(gamedata.Coordinates{X: rand.Float64() * 640, Y: rand.Float64() * 480})
target.Hit = true
break
}
@@ -380,7 +353,7 @@ func (g *Game) UpdateProjectiles() {
func (g *Game) UpdateTargets() {
for _, target := range g.targets {
if !target.Hit && g.hero.Action < HeroActionDying {
if !target.Hit && g.hero.Action < elements.HeroActionDying {
dx := g.hero.Pos.X - target.Pos.X
dy := g.hero.Pos.Y - target.Pos.Y
angle := math.Atan2(dy, dx)
@@ -392,7 +365,9 @@ func (g *Game) UpdateTargets() {
}
//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 && g.hero.Action < HeroActionDying {
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 < elements.MoverActionDying && g.hero.Action < elements.HeroActionDying {
g.heroCollisionMask.Clear()
g.heroCollisionMask.DrawImage(g.hero.Sprite, nil)
@@ -428,10 +403,10 @@ func (g *Game) ResetTargetTouches() {
func (g *Game) AppendProjectiles() {
if g.counter%14 == 0 && ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonFrontBottomRight) {
g.projectiles[g.counter] = NewProjectile(Coordinates{X: g.hero.Pos.X, Y: g.hero.Pos.Y}, g.hero.Angle, 5.)
g.projectiles[g.counter] = elements.NewProjectile(gamedata.Coordinates{X: g.hero.Pos.X, Y: g.hero.Pos.Y}, g.hero.Angle, 5.)
if g.hero.Upgrade {
g.projectiles[g.counter+1] = NewProjectile(Coordinates{X: g.hero.Pos.X, Y: g.hero.Pos.Y}, g.hero.Angle+math.Pi, 5.)
g.projectiles[g.counter+1] = elements.NewProjectile(gamedata.Coordinates{X: g.hero.Pos.X, Y: g.hero.Pos.Y}, g.hero.Angle+math.Pi, 5.)
}
}
}
@@ -487,7 +462,7 @@ func (g *Game) UpdateHeroPosition() {
}
func (g *Game) ConstructBackground() {
g.background = ebiten.NewImage(screenWidth, screenHeight)
g.background = ebiten.NewImage(g.dimensions.Width, g.dimensions.Height)
BLOCK_SIZE := 32
for i := 0; i < 640/16; i++ {
@@ -505,7 +480,7 @@ func (g *Game) ConstructBackground() {
//translate for grid element we're painting
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(i)*16, float64(j)*16)
g.background.DrawImage(tilesetImage.SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op)
g.background.DrawImage(assets.ImageBank[assets.TileSet].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), op)
}
}
@@ -514,5 +489,13 @@ func (g *Game) ConstructBackground() {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(ax, ay)
g.background.DrawImage(altarImage, op)
g.background.DrawImage(assets.ImageBank[assets.Altar], op)
}
func (g *Game) SetDimensions(a gamedata.Area) {
g.dimensions = a
}
func (g *Game) SetEventHandler(e ScreenManagerEvent, f func()) {
}

25
screens/scene.go Normal file
View File

@@ -0,0 +1,25 @@
package screens
import (
"mover/gamedata"
"github.com/hajimehoshi/ebiten/v2"
)
type ScreenManagerEvent int
const (
EventNoop ScreenManagerEvent = iota
EventReset // reset to initial scene
EventLoad // loading elements
EventReload // reload current scene
EventCompleted // current scene has completed
EventEndgame // shutdown all scenes
)
type Screen interface {
Update() error
Draw(screen *ebiten.Image)
SetEventHandler(e ScreenManagerEvent, f func())
SetDimensions(a gamedata.Area)
}