Cloud layer.

This commit is contained in:
2024-11-16 12:31:22 -05:00
parent fd46346346
commit 1d65d0046e
9 changed files with 214 additions and 12 deletions

BIN
assets/cloud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -25,6 +25,7 @@ const (
Weapon ImgAssetName = "Weapon" Weapon ImgAssetName = "Weapon"
WormDamaged ImgAssetName = "WormDamaged" WormDamaged ImgAssetName = "WormDamaged"
Worm ImgAssetName = "WormDefault" Worm ImgAssetName = "WormDefault"
Cloud ImgAssetName = "Cloud"
) )
var ( var (
@@ -54,6 +55,8 @@ var (
worm_img []byte worm_img []byte
//go:embed wormdefault.png //go:embed wormdefault.png
wormdefault_img []byte wormdefault_img []byte
//go:embed cloud.png
cloud_img []byte
) )
func LoadImages() { func LoadImages() {
@@ -71,6 +74,7 @@ func LoadImages() {
ImageBank[Weapon] = LoadImagesFatal(weapon_img) ImageBank[Weapon] = LoadImagesFatal(weapon_img)
ImageBank[WormDamaged] = LoadImagesFatal(worm_img) ImageBank[WormDamaged] = LoadImagesFatal(worm_img)
ImageBank[Worm] = LoadImagesFatal(wormdefault_img) ImageBank[Worm] = LoadImagesFatal(wormdefault_img)
ImageBank[Cloud] = LoadImagesFatal(cloud_img)
} }

62
elements/cloud.go Normal file
View File

@@ -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
}

View File

@@ -23,4 +23,5 @@ type Enemies interface {
ExplosionInitiated() bool ExplosionInitiated() bool
SetExplosionInitiated() SetExplosionInitiated()
Health() int Health() int
MaxHealth() int
} }

View File

@@ -163,5 +163,11 @@ func (f *FlyEye) SetExplosionInitiated() {
} }
func (f *FlyEye) Health() int { 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 return 0
} }
func (f *FlyEye) MaxHealth() int {
return 1
}

View File

@@ -9,6 +9,10 @@ import (
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
) )
const (
FG_MAXHEALTH = 100
)
type FlyGoblin struct { type FlyGoblin struct {
Sprite *ebiten.Image Sprite *ebiten.Image
Maks *ebiten.Image Maks *ebiten.Image
@@ -18,10 +22,8 @@ type FlyGoblin struct {
state gamedata.EnemyState state gamedata.EnemyState
cycle int cycle int
health int health int
dyingcount int
damageduration int damageduration int
right bool right bool
hit bool
touched bool touched bool
toggle bool toggle bool
sploding bool sploding bool
@@ -33,7 +35,7 @@ func NewFlyGoblin() *FlyGoblin {
Sprite: ebiten.NewImage(96, 96), Sprite: ebiten.NewImage(96, 96),
Maks: ebiten.NewImage(96, 96), Maks: ebiten.NewImage(96, 96),
MaksDest: ebiten.NewImage(96, 96), MaksDest: ebiten.NewImage(96, 96),
health: 100, health: FG_MAXHEALTH,
damageduration: 0, damageduration: 0,
} }
fg.Maks.Fill(color.White) fg.Maks.Fill(color.White)
@@ -176,3 +178,7 @@ func (f *FlyGoblin) SetExplosionInitiated() {
func (f *FlyGoblin) Health() int { func (f *FlyGoblin) Health() int {
return f.health return f.health
} }
func (f *FlyGoblin) MaxHealth() int {
return FG_MAXHEALTH
}

View File

@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"image/color" "image/color"
"math" "math"
"math/rand/v2"
"mover/assets" "mover/assets"
"mover/elements" "mover/elements"
"mover/fonts" "mover/fonts"
@@ -50,6 +51,7 @@ func NewCanvas(a gamedata.Area) *Canvas {
goblinspawned: false, goblinspawned: false,
score: 0, score: 0,
runtime: 0., runtime: 0.,
counter: 0,
} }
c.eventmap = make(map[gamedata.GameEvent]func()) c.eventmap = make(map[gamedata.GameEvent]func())
return c return c
@@ -70,9 +72,9 @@ func (c *Canvas) Update() error {
c.UpdateCharge() c.UpdateCharge()
c.UpdateEnemies() c.UpdateEnemies()
c.CleanupTargets() c.CleanupTargets()
}
c.counter++ c.counter++
}
return nil return nil
} }
@@ -105,7 +107,7 @@ func (c *Canvas) Draw(drawimg *ebiten.Image) {
if e.Health() > 0 { if e.Health() > 0 {
x0 := e.GetPosition().X - float64(e.GetSprite().Bounds().Dx()) x0 := e.GetPosition().X - float64(e.GetSprite().Bounds().Dx())
y0 := e.GetPosition().Y - 2/3.*float64(e.GetSprite().Bounds().Dy()) 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) 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() e.Update()
} }
if !c.gameover { if !c.gameover {
/*
if !c.goblinspawned {
//spawn new enemies //spawn new enemies
f := 40000 / (c.counter + 1) f := 40000 / (c.counter + 1)
@@ -376,13 +379,15 @@ func (c *Canvas) UpdateEnemies() {
newenemy.SetTarget(c.hero.Pos) newenemy.SetTarget(c.hero.Pos)
c.enemies = append(c.enemies, newenemy) c.enemies = append(c.enemies, newenemy)
}*/ }
}
if !c.goblinspawned { if !c.goblinspawned && c.counter > 1200 {
newfg := elements.NewFlyGoblin() newfg := elements.NewFlyGoblin()
c.enemies = append(c.enemies, newfg) c.enemies = append(c.enemies, newfg)
c.goblinspawned = true c.goblinspawned = true
} }
} }
} }

109
gameelement/cloudlayer.go Normal file
View File

@@ -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()) {
}

View File

@@ -32,19 +32,28 @@ func NewPrimary() *Primary {
musicInitialized: false, musicInitialized: false,
} }
gamearea := gamedata.Area{Width: 640, Height: 480}
//initialize our layer map
p.gameevents = make(map[gamedata.GameEvent]bool) 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.GameEventPlayerDeath, p.EventHandlerPlayerDeath)
canvas.RegisterEvents(gamedata.GameEventCharge, p.EventHandlerCharge) canvas.RegisterEvents(gamedata.GameEventCharge, p.EventHandlerCharge)
canvas.RegisterEvents(gamedata.GameEventNewShot, p.EventHandlerNewShot) canvas.RegisterEvents(gamedata.GameEventNewShot, p.EventHandlerNewShot)
canvas.RegisterEvents(gamedata.GameEventTargetHit, p.EventHandlerTargetHit) canvas.RegisterEvents(gamedata.GameEventTargetHit, p.EventHandlerTargetHit)
canvas.RegisterEvents(gamedata.GameEventExplosion, p.EventHandlerExplosion) canvas.RegisterEvents(gamedata.GameEventExplosion, p.EventHandlerExplosion)
p.elements = append(p.elements, canvas) p.elements = append(p.elements, canvas)
//create foreground cloud layer
clouds := gameelement.NewCloudLayer(gamearea)
clouds.Initialize()
p.elements = append(p.elements, clouds)
return p return p
} }