From 1d65d0046e06de74ae9bff4f42a581c497d69f55 Mon Sep 17 00:00:00 2001 From: iegod Date: Sat, 16 Nov 2024 12:31:22 -0500 Subject: [PATCH] Cloud layer. --- assets/cloud.png | Bin 0 -> 4172 bytes assets/imagebank.go | 4 ++ elements/cloud.go | 62 ++++++++++++++++++++++ elements/enemies.go | 1 + elements/flyeye.go | 6 +++ elements/flygoblin.go | 12 +++-- gameelement/canvas.go | 17 +++--- gameelement/cloudlayer.go | 109 ++++++++++++++++++++++++++++++++++++++ screens/primary.go | 15 ++++-- 9 files changed, 214 insertions(+), 12 deletions(-) create mode 100644 assets/cloud.png create mode 100644 elements/cloud.go create mode 100644 gameelement/cloudlayer.go diff --git a/assets/cloud.png b/assets/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..c8283c4a059913047dec316160c9d455fb7c98b3 GIT binary patch literal 4172 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 KaM!H^j{P0YlJklH literal 0 HcmV?d00001 diff --git a/assets/imagebank.go b/assets/imagebank.go index 6c7291c..5e7b7db 100644 --- a/assets/imagebank.go +++ b/assets/imagebank.go @@ -25,6 +25,7 @@ const ( Weapon ImgAssetName = "Weapon" WormDamaged ImgAssetName = "WormDamaged" Worm ImgAssetName = "WormDefault" + Cloud ImgAssetName = "Cloud" ) var ( @@ -54,6 +55,8 @@ var ( worm_img []byte //go:embed wormdefault.png wormdefault_img []byte + //go:embed cloud.png + cloud_img []byte ) func LoadImages() { @@ -71,6 +74,7 @@ func LoadImages() { ImageBank[Weapon] = LoadImagesFatal(weapon_img) ImageBank[WormDamaged] = LoadImagesFatal(worm_img) ImageBank[Worm] = LoadImagesFatal(wormdefault_img) + ImageBank[Cloud] = LoadImagesFatal(cloud_img) } diff --git a/elements/cloud.go b/elements/cloud.go new file mode 100644 index 0000000..f690605 --- /dev/null +++ b/elements/cloud.go @@ -0,0 +1,62 @@ +package elements + +import ( + "math" + "mover/assets" + "mover/gamedata" + + "github.com/hajimehoshi/ebiten/v2" +) + +type Cloud struct { + Sprite *ebiten.Image + position gamedata.Coordinates + angle float64 + velocity float64 + Alpha float64 +} + +func NewCloud(a gamedata.Area, angle, velocity float64) *Cloud { + c := &Cloud{ + Sprite: ebiten.NewImage(a.Width, a.Height), + angle: angle, //rand.Float64() * (math.Pi * 2), + velocity: velocity, + } + return c +} + +func (c *Cloud) Update() error { + + c.position.X += c.velocity * math.Cos(c.angle) + c.position.Y += c.velocity * math.Sin(c.angle) + return nil +} + +func (c *Cloud) Draw() { + c.Sprite.Clear() + //c.Sprite.Fill(color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}) + //c.Sprite.Fill(color.White) + + cloudsprite := assets.ImageBank[assets.Cloud] + + spritex := cloudsprite.Bounds().Dx() + spritey := cloudsprite.Bounds().Dy() + + cloudx := c.Sprite.Bounds().Dx() + cloudy := c.Sprite.Bounds().Dy() + + scalex := float64(cloudx) / float64(spritex) + scaley := float64(cloudy) / float64(spritey) + + op := &ebiten.DrawImageOptions{} + op.GeoM.Scale(scalex, scaley) + c.Sprite.DrawImage(assets.ImageBank[assets.Cloud], op) +} + +func (c *Cloud) SetPosition(p gamedata.Coordinates) { + c.position = p +} + +func (c *Cloud) GetPosition() gamedata.Coordinates { + return c.position +} diff --git a/elements/enemies.go b/elements/enemies.go index fe79954..f4b553d 100644 --- a/elements/enemies.go +++ b/elements/enemies.go @@ -23,4 +23,5 @@ type Enemies interface { ExplosionInitiated() bool SetExplosionInitiated() Health() int + MaxHealth() int } diff --git a/elements/flyeye.go b/elements/flyeye.go index e963a67..717f3ca 100644 --- a/elements/flyeye.go +++ b/elements/flyeye.go @@ -163,5 +163,11 @@ func (f *FlyEye) SetExplosionInitiated() { } func (f *FlyEye) Health() int { + //health bars reserved for special enemies, flyeye is a one + //hitter so returning zero ensure no health bar is rendered return 0 } + +func (f *FlyEye) MaxHealth() int { + return 1 +} diff --git a/elements/flygoblin.go b/elements/flygoblin.go index 894898b..5e51cfb 100644 --- a/elements/flygoblin.go +++ b/elements/flygoblin.go @@ -9,6 +9,10 @@ import ( "github.com/hajimehoshi/ebiten/v2" ) +const ( + FG_MAXHEALTH = 100 +) + type FlyGoblin struct { Sprite *ebiten.Image Maks *ebiten.Image @@ -18,10 +22,8 @@ type FlyGoblin struct { state gamedata.EnemyState cycle int health int - dyingcount int damageduration int right bool - hit bool touched bool toggle bool sploding bool @@ -33,7 +35,7 @@ func NewFlyGoblin() *FlyGoblin { Sprite: ebiten.NewImage(96, 96), Maks: ebiten.NewImage(96, 96), MaksDest: ebiten.NewImage(96, 96), - health: 100, + health: FG_MAXHEALTH, damageduration: 0, } fg.Maks.Fill(color.White) @@ -176,3 +178,7 @@ func (f *FlyGoblin) SetExplosionInitiated() { func (f *FlyGoblin) Health() int { return f.health } + +func (f *FlyGoblin) MaxHealth() int { + return FG_MAXHEALTH +} diff --git a/gameelement/canvas.go b/gameelement/canvas.go index febe3f6..921aa8b 100644 --- a/gameelement/canvas.go +++ b/gameelement/canvas.go @@ -4,6 +4,7 @@ import ( "fmt" "image/color" "math" + "math/rand/v2" "mover/assets" "mover/elements" "mover/fonts" @@ -50,6 +51,7 @@ func NewCanvas(a gamedata.Area) *Canvas { goblinspawned: false, score: 0, runtime: 0., + counter: 0, } c.eventmap = make(map[gamedata.GameEvent]func()) return c @@ -70,9 +72,9 @@ func (c *Canvas) Update() error { c.UpdateCharge() c.UpdateEnemies() c.CleanupTargets() - + c.counter++ } - c.counter++ + return nil } @@ -105,7 +107,7 @@ func (c *Canvas) Draw(drawimg *ebiten.Image) { if e.Health() > 0 { x0 := e.GetPosition().X - float64(e.GetSprite().Bounds().Dx()) y0 := e.GetPosition().Y - 2/3.*float64(e.GetSprite().Bounds().Dy()) - vector.DrawFilledRect(c.Sprite, float32(x0), float32(y0), 204, 12, color.Black, true) + vector.DrawFilledRect(c.Sprite, float32(x0), float32(y0), float32(e.MaxHealth())*2+4, 12, color.Black, true) vector.DrawFilledRect(c.Sprite, float32(x0+2), float32(y0+2), float32(e.Health())*2, 8, color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff}, true) } } @@ -351,7 +353,8 @@ func (c *Canvas) UpdateEnemies() { e.Update() } if !c.gameover { - /* + + if !c.goblinspawned { //spawn new enemies f := 40000 / (c.counter + 1) @@ -376,13 +379,15 @@ func (c *Canvas) UpdateEnemies() { newenemy.SetTarget(c.hero.Pos) c.enemies = append(c.enemies, newenemy) - }*/ + } + } - if !c.goblinspawned { + if !c.goblinspawned && c.counter > 1200 { newfg := elements.NewFlyGoblin() c.enemies = append(c.enemies, newfg) c.goblinspawned = true } + } } diff --git a/gameelement/cloudlayer.go b/gameelement/cloudlayer.go new file mode 100644 index 0000000..2fde433 --- /dev/null +++ b/gameelement/cloudlayer.go @@ -0,0 +1,109 @@ +package gameelement + +import ( + "math" + "math/rand/v2" + "mover/elements" + "mover/gamedata" + + "github.com/hajimehoshi/ebiten/v2" +) + +type CloudLayer struct { + Sprite *ebiten.Image + clouds []*elements.Cloud + dimensions gamedata.Area + cycle int +} + +func NewCloudLayer(a gamedata.Area) *CloudLayer { + c := &CloudLayer{ + Sprite: ebiten.NewImage(a.Width, a.Height), + cycle: 0, + dimensions: a, + } + return c +} + +func (c *CloudLayer) SetInputs(gamedata.GameInputs) { +} + +func (c *CloudLayer) Update() error { + c.cycle++ + + for _, cloud := range c.clouds { + cloud.Update() + + cpos := cloud.GetPosition() + if cpos.X > float64(c.dimensions.Width)+float64(cloud.Sprite.Bounds().Dx()) { + dx := -float64(cloud.Sprite.Bounds().Dx()) + cloud.SetPosition(gamedata.Coordinates{X: dx, Y: cloud.GetPosition().Y}) + } + if cpos.X < -float64(cloud.Sprite.Bounds().Dx()) { + dx := float64(c.dimensions.Width + cloud.Sprite.Bounds().Dx()) + cloud.SetPosition(gamedata.Coordinates{X: dx, Y: cloud.GetPosition().Y}) + } + if cpos.Y > float64(c.dimensions.Height)+float64(cloud.Sprite.Bounds().Dy()) { + dy := -float64(cloud.Sprite.Bounds().Dy()) + cloud.SetPosition(gamedata.Coordinates{X: cloud.GetPosition().X, Y: dy}) + } + if cpos.Y < -float64(cloud.Sprite.Bounds().Dy()) { + dy := float64(c.dimensions.Height + cloud.Sprite.Bounds().Dy()) + cloud.SetPosition(gamedata.Coordinates{X: cloud.GetPosition().X, Y: dy}) + } + } + + return nil +} + +func (c *CloudLayer) Draw(drawimg *ebiten.Image) { + c.Sprite.Clear() + + for _, cloud := range c.clouds { + cloud.Draw() + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(cloud.GetPosition().X, cloud.GetPosition().Y) + op.ColorScale.ScaleAlpha(float32(cloud.Alpha)) + c.Sprite.DrawImage(cloud.Sprite, op) + } + + drawimg.DrawImage(c.Sprite, nil) +} + +func (c *CloudLayer) Initialize() { + + //cull previous cloud layer + for i := 0; i < len(c.clouds); i++ { + c.clouds[i] = nil + } + c.clouds = c.clouds[:0] + + numclouds := rand.IntN(20) + angle := rand.Float64() * math.Pi * 2 + + for i := 0; i < numclouds; i++ { + + a := gamedata.Area{ + Height: rand.IntN(c.dimensions.Width/2) + 1, + Width: rand.IntN(c.dimensions.Height/2) + 1, + } + + velocity := rand.Float64() * 3 + //velocity := 0. + + newcloud := elements.NewCloud(a, angle, velocity) + + newcloud.Alpha = rand.Float64() / 2 + + newcloud.SetPosition(gamedata.Coordinates{ + X: rand.Float64() * float64(c.dimensions.Width), + Y: rand.Float64() * float64(c.dimensions.Height), + }) + + c.clouds = append(c.clouds, newcloud) + } +} + +func (c *CloudLayer) RegisterEvents(e gamedata.GameEvent, f func()) { + +} diff --git a/screens/primary.go b/screens/primary.go index 9c6e771..8175caf 100644 --- a/screens/primary.go +++ b/screens/primary.go @@ -32,19 +32,28 @@ func NewPrimary() *Primary { musicInitialized: false, } + gamearea := gamedata.Area{Width: 640, Height: 480} + + //initialize our layer map p.gameevents = make(map[gamedata.GameEvent]bool) - p.elements = append(p.elements, gameelement.NewBackground(gamedata.Area{Width: 640, Height: 480})) + //create background layer + p.elements = append(p.elements, gameelement.NewBackground(gamearea)) - canvas := gameelement.NewCanvas(gamedata.Area{Width: 640, Height: 480}) + //create canvas (game) layer + canvas := gameelement.NewCanvas(gamearea) 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) + //create foreground cloud layer + clouds := gameelement.NewCloudLayer(gamearea) + clouds.Initialize() + p.elements = append(p.elements, clouds) + return p }