Compare commits

..

4 Commits

Author SHA1 Message Date
63eafe036a Added a rain layer for atmosphere. 2024-11-23 01:13:55 -05:00
253c708d45 Added weapon drops and collection. New laser item asset. 2024-11-22 17:57:16 -05:00
b3a8ef8c0f Housekeeping. 2024-11-21 16:35:36 -05:00
257318926d Added weapon system. Animated laser. 2024-11-21 16:26:25 -05:00
20 changed files with 652 additions and 51 deletions

View File

@@ -28,6 +28,9 @@ const (
Cloud ImgAssetName = "Cloud" Cloud ImgAssetName = "Cloud"
Fireball ImgAssetName = "Fireball" Fireball ImgAssetName = "Fireball"
Splash ImgAssetName = "Splash" Splash ImgAssetName = "Splash"
LaserBeam ImgAssetName = "LaserBeam"
ItemLaser ImgAssetName = "ItemLaser"
RainSplash ImgAssetName = "RainSplash"
) )
var ( var (
@@ -63,6 +66,12 @@ var (
fireball_img []byte fireball_img []byte
//go:embed splash.png //go:embed splash.png
splash_img []byte splash_img []byte
//go:embed laserbeam.png
laserbeam_img []byte
//go:embed item-laser.png
itemlaser_img []byte
//go:embed rain-splash.png
rainsplash_img []byte
) )
func LoadImages() { func LoadImages() {
@@ -83,6 +92,9 @@ func LoadImages() {
ImageBank[Cloud] = LoadImagesFatal(cloud_img) ImageBank[Cloud] = LoadImagesFatal(cloud_img)
ImageBank[Fireball] = LoadImagesFatal(fireball_img) ImageBank[Fireball] = LoadImagesFatal(fireball_img)
ImageBank[Splash] = LoadImagesFatal(splash_img) ImageBank[Splash] = LoadImagesFatal(splash_img)
ImageBank[LaserBeam] = LoadImagesFatal(laserbeam_img)
ImageBank[ItemLaser] = LoadImagesFatal(itemlaser_img)
ImageBank[RainSplash] = LoadImagesFatal(rainsplash_img)
} }

BIN
assets/item-laser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

BIN
assets/laserbeam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 B

BIN
assets/rain-splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 B

After

Width:  |  Height:  |  Size: 615 B

View File

@@ -1,27 +1,30 @@
package elements package elements
import ( import (
"image/color" "image"
"mover/assets"
"mover/gamedata" "mover/gamedata"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
) )
type Laser struct { type Laser struct {
Sprite *ebiten.Image Sprite *ebiten.Image
position gamedata.Coordinates position gamedata.Coordinates
angle float64 angle float64
cycle int cycle int
firing bool firing bool
numcycles int
} }
func NewLaser(pos gamedata.Coordinates, angle float64) *Laser { func NewLaser(pos gamedata.Coordinates, angle float64) *Laser {
l := &Laser{ l := &Laser{
Sprite: ebiten.NewImage(200, 20), Sprite: ebiten.NewImage(200, 20),
angle: angle, angle: angle,
cycle: 0, cycle: 0,
position: pos, position: pos,
firing: false, firing: false,
numcycles: 5,
} }
return l return l
} }
@@ -33,7 +36,16 @@ func (l *Laser) Update() error {
func (l *Laser) Draw() { func (l *Laser) Draw() {
l.Sprite.Clear() l.Sprite.Clear()
l.Sprite.Fill(color.White) //l.Sprite.Fill(color.White)
idx := (l.cycle / 4) % l.numcycles
x0 := 0
y0 := 20 * idx
x1 := 200
y1 := y0 + 20
l.Sprite.DrawImage(assets.ImageBank[assets.LaserBeam].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
} }
func (l *Laser) GetPosition() gamedata.Coordinates { func (l *Laser) GetPosition() gamedata.Coordinates {

46
elements/raindrop.go Normal file
View File

@@ -0,0 +1,46 @@
package elements
import (
"image/color"
"math/rand/v2"
"mover/gamedata"
"github.com/hajimehoshi/ebiten/v2"
)
type RainDrop struct {
Sprite *ebiten.Image
position gamedata.Coordinates
cycle int
}
func NewRainDrop() *RainDrop {
rd := &RainDrop{
Sprite: ebiten.NewImage(2, 10),
cycle: rand.IntN(30),
}
return rd
}
func (rd *RainDrop) Update() error {
rd.position.Y += 5
rd.cycle++
return nil
}
func (rd *RainDrop) Draw() {
rd.Sprite.Clear()
rd.Sprite.Fill(color.White)
}
func (rd *RainDrop) GetPosition() gamedata.Coordinates {
return rd.position
}
func (rd *RainDrop) SetPosition(pos gamedata.Coordinates) {
rd.position = pos
}
func (rd *RainDrop) Expired() bool {
return rd.cycle > 30
}

58
elements/rainsplash.go Normal file
View File

@@ -0,0 +1,58 @@
package elements
import (
"image"
"math/rand/v2"
"mover/assets"
"mover/gamedata"
"github.com/hajimehoshi/ebiten/v2"
)
type RainSplash struct {
Sprite *ebiten.Image
position gamedata.Coordinates
cycle int
counter int
}
func NewRainSplash() *RainSplash {
rd := &RainSplash{
Sprite: ebiten.NewImage(10, 4),
cycle: rand.IntN(4),
counter: 0,
}
return rd
}
func (rd *RainSplash) Update() error {
rd.counter++
rd.cycle++
return nil
}
func (rd *RainSplash) Draw() {
rd.Sprite.Clear()
//rd.Sprite.Fill(color.White)
idx := (rd.cycle / 8) % 4
x0 := idx * 10
y0 := 0
x1 := x0 + 10
y1 := 4
rd.Sprite.DrawImage(assets.ImageBank[assets.RainSplash].SubImage(image.Rect(x0, y0, x1, y1)).(*ebiten.Image), nil)
}
func (rd *RainSplash) GetPosition() gamedata.Coordinates {
return rd.position
}
func (rd *RainSplash) SetPosition(pos gamedata.Coordinates) {
rd.position = pos
}
func (rd *RainSplash) Expired() bool {
return rd.counter > 30
}

View File

@@ -77,6 +77,26 @@ func (sp *Splash) Draw() {
sp.Sprite.DrawImage(assets.ImageBank[assets.Splash], op) sp.Sprite.DrawImage(assets.ImageBank[assets.Splash], op)
} }
for i := 0; i < 5; i++ {
percent := float64(5-i) / 5
a := 9.8
time := float64(sp.cycle) / 8
v0 := 10.
dy := 1/2.*a*math.Pow(time-float64(i), 2) - v0*time
dx := -float64(sp.cycle)
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(-48/2, -48/2)
op.GeoM.Scale(percent, percent)
op.GeoM.Rotate(-float64(sp.cycle) / (math.Pi * 4))
op.GeoM.Translate(SPLASH_DIM/2, SPLASH_DIM/2)
op.GeoM.Translate(dx, dy)
sp.Sprite.DrawImage(assets.ImageBank[assets.Splash], op)
op.GeoM.Translate(-2*dx, 0)
sp.Sprite.DrawImage(assets.ImageBank[assets.Splash], op)
}
} }
func (sp *Splash) GetPosition() gamedata.Coordinates { func (sp *Splash) GetPosition() gamedata.Coordinates {

66
elements/weapondrop.go Normal file
View File

@@ -0,0 +1,66 @@
package elements
import (
"math"
"mover/assets"
"mover/gamedata"
"github.com/hajimehoshi/ebiten/v2"
)
type WeaponDrop struct {
Sprite *ebiten.Image
position gamedata.Coordinates
weapontype gamedata.WeaponType
cycle int
collected bool
}
func NewWeaponDrop(wt gamedata.WeaponType) *WeaponDrop {
wp := &WeaponDrop{
Sprite: ebiten.NewImage(32, 32),
weapontype: wt,
cycle: 0,
collected: false,
}
return wp
}
func (wp *WeaponDrop) SetPosition(pos gamedata.Coordinates) {
wp.position = pos
}
func (wp *WeaponDrop) GetPosition() gamedata.Coordinates {
return wp.position
}
func (wp *WeaponDrop) GetWeaponType() gamedata.WeaponType {
return wp.weapontype
}
func (wp *WeaponDrop) Update() error {
wp.cycle++
return nil
}
func (wp *WeaponDrop) Draw() {
wp.Sprite.Clear()
dy := 2 * math.Sin(float64(wp.cycle)/(math.Pi*2))
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(0, dy)
switch wp.weapontype {
case gamedata.WeaponTypeLaser:
wp.Sprite.DrawImage(assets.ImageBank[assets.ItemLaser], op)
}
}
func (wp *WeaponDrop) SetCollected(c bool) {
wp.collected = c
}
func (wp *WeaponDrop) IsCollected() bool {
return wp.collected
}

View File

@@ -1,12 +1,13 @@
package gamedata package gamedata
type GameInputs struct { type GameInputs struct {
XAxis float64 XAxis float64
YAxis float64 YAxis float64
ShotAngle float64 ShotAngle float64
Shot bool Shot bool
Start bool Start bool
Charge bool Charge bool
Quit bool Quit bool
Reset bool Reset bool
CycleWeapon bool
} }

9
gamedata/weapontype.go Normal file
View File

@@ -0,0 +1,9 @@
package gamedata
type WeaponType int
const (
WeaponTypeGun = iota
WeaponTypeLaser
WeaponTypeMax
)

View File

@@ -10,6 +10,7 @@ import (
"mover/elements" "mover/elements"
"mover/fonts" "mover/fonts"
"mover/gamedata" "mover/gamedata"
"mover/weapons"
"github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/text" "github.com/hajimehoshi/ebiten/v2/text"
@@ -34,6 +35,7 @@ type Canvas struct {
counter int counter int
score int score int
splashes []*elements.Splash splashes []*elements.Splash
wpdrops []*elements.WeaponDrop
hero *elements.Hero hero *elements.Hero
charge *elements.Explosion charge *elements.Explosion
goblin *elements.FlyGoblin goblin *elements.FlyGoblin
@@ -43,6 +45,7 @@ type Canvas struct {
gameover bool gameover bool
lasercoords []gamedata.Coordinates lasercoords []gamedata.Coordinates
holster *weapons.Holster
} }
func NewCanvas(a gamedata.Area) *Canvas { func NewCanvas(a gamedata.Area) *Canvas {
@@ -63,6 +66,7 @@ func NewCanvas(a gamedata.Area) *Canvas {
score: 0, score: 0,
runtime: 0., runtime: 0.,
counter: 0, counter: 0,
holster: weapons.NewHolster(),
} }
c.laserMask.Clear() c.laserMask.Clear()
c.eventmap = make(map[gamedata.GameEvent]func()) c.eventmap = make(map[gamedata.GameEvent]func())
@@ -79,14 +83,16 @@ func (c *Canvas) Update() error {
c.Initialize() c.Initialize()
} else { } else {
c.UpdateHero() c.UpdateHero()
c.UpdateWeaponDrops()
c.UpdateWeapons()
c.UpdateProjectiles() c.UpdateProjectiles()
c.UpdateLaser()
c.UpdateCharge() c.UpdateCharge()
c.UpdateEnemies() c.UpdateEnemies()
c.SpawnEnemies() c.SpawnEnemies()
c.CleanupTargets() c.CleanupTargets()
c.UpdateSplashes() c.UpdateSplashes()
c.CleanSplashes() c.CleanSplashes()
c.CleanupDrops()
c.counter++ c.counter++
} }
@@ -132,6 +138,14 @@ func (c *Canvas) Draw(drawimg *ebiten.Image) {
} }
} }
//draw weapon drops
for _, drop := range c.wpdrops {
drop.Draw()
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(drop.GetPosition().X-float64(drop.Sprite.Bounds().Dx())/2, drop.GetPosition().Y-float64(drop.Sprite.Bounds().Dy())/2)
c.Sprite.DrawImage(drop.Sprite, op)
}
//draw enemies //draw enemies
for _, e := range c.enemies { for _, e := range c.enemies {
e.Draw() e.Draw()
@@ -209,6 +223,7 @@ func (c *Canvas) Initialize() {
c.InitializeHero() c.InitializeHero()
c.CleanSplashes() c.CleanSplashes()
c.ResetWeaponDrops()
c.enemies = c.enemies[:0] c.enemies = c.enemies[:0]
c.gameover = false c.gameover = false
c.initialized = true c.initialized = true
@@ -220,6 +235,9 @@ func (c *Canvas) Initialize() {
//temporary //temporary
c.hero.Action = elements.HeroActionDefault c.hero.Action = elements.HeroActionDefault
c.holster.SetActiveWeapon(gamedata.WeaponTypeGun)
c.laser.SetFiring(false)
} }
func (c *Canvas) UpdateHero() { func (c *Canvas) UpdateHero() {
@@ -227,7 +245,6 @@ func (c *Canvas) UpdateHero() {
if !c.gameover { if !c.gameover {
c.UpdateHeroPosition() c.UpdateHeroPosition()
c.ComputeHeroCollisions() c.ComputeHeroCollisions()
c.AddProjectiles()
} }
} }
@@ -275,31 +292,26 @@ func (c *Canvas) ComputeHeroCollisions() {
func (c *Canvas) AddProjectiles() { func (c *Canvas) AddProjectiles() {
//add new projectiles //add new projectiles
/*
if c.lastInputs.Shot && c.counter%14 == 0 {
loc := gamedata.Coordinates{ if c.lastInputs.Shot && c.counter%14 == 0 {
X: c.hero.Pos.X,
Y: c.hero.Pos.Y,
}
angle := c.lastInputs.ShotAngle
velocity := 5.
c.projectiles = append(c.projectiles, elements.NewProjectile(loc, angle, velocity))
if c.hero.Upgrade {
c.projectiles = append(c.projectiles, elements.NewProjectile(loc, angle+math.Pi, velocity))
}
if c.eventmap[gamedata.GameEventNewShot] != nil {
c.eventmap[gamedata.GameEventNewShot]()
}
loc := gamedata.Coordinates{
X: c.hero.Pos.X,
Y: c.hero.Pos.Y,
} }
*/ angle := c.lastInputs.ShotAngle
if c.lastInputs.Shot { velocity := 5.
c.laser.SetPosition(c.hero.Pos)
c.laser.SetAngle(c.lastInputs.ShotAngle) c.projectiles = append(c.projectiles, elements.NewProjectile(loc, angle, velocity))
if c.hero.Upgrade {
c.projectiles = append(c.projectiles, elements.NewProjectile(loc, angle+math.Pi, velocity))
}
if c.eventmap[gamedata.GameEventNewShot] != nil {
c.eventmap[gamedata.GameEventNewShot]()
}
} }
} }
@@ -362,9 +374,14 @@ func (c *Canvas) UpdateProjectiles() {
} }
func (c *Canvas) UpdateLaser() { func (c *Canvas) UpdateLaser() {
c.laser.Update()
c.laser.SetFiring(c.lastInputs.Shot) c.laser.SetFiring(c.lastInputs.Shot)
if c.lastInputs.Shot { if c.lastInputs.Shot {
c.laser.SetPosition(c.hero.Pos)
c.laser.SetAngle(c.lastInputs.ShotAngle)
c.laserMask.Clear() c.laserMask.Clear()
lpos := c.laser.GetPosition() lpos := c.laser.GetPosition()
op := &ebiten.DrawImageOptions{} op := &ebiten.DrawImageOptions{}
@@ -531,6 +548,16 @@ func (c *Canvas) CleanupTargets() {
// remove dead targets by iterating over all targets // remove dead targets by iterating over all targets
i := 0 i := 0
for _, e := range c.enemies { for _, e := range c.enemies {
//compute odds for dropping an item on dead enemies
if e.GetEnemyState() == elements.MoverActionDead {
if rand.Float64() > 0.98 {
drop := elements.NewWeaponDrop(gamedata.WeaponTypeLaser)
drop.SetPosition(e.GetPosition())
c.wpdrops = append(c.wpdrops, drop)
}
}
//moving valid targets to the front of the slice //moving valid targets to the front of the slice
if e.GetEnemyState() < elements.MoverActionDead && if e.GetEnemyState() < elements.MoverActionDead &&
!(e.GetPosition().X < -640*2 || e.GetPosition().X > 640*2 || !(e.GetPosition().X < -640*2 || e.GetPosition().X > 640*2 ||
@@ -826,11 +853,11 @@ func (c *Canvas) LaserAttempt4() {
if math.Abs(math.Mod(a, math.Pi)) == math.Pi/2 { // Check for vertical beam if math.Abs(math.Mod(a, math.Pi)) == math.Pi/2 { // Check for vertical beam
d = math.Abs(x1 - x0) d = math.Abs(x1 - x0)
c.lasercoords[3] = gamedata.Coordinates{X: x0, Y: y1} // Align on x-axis c.lasercoords[3] = gamedata.Coordinates{X: x0, Y: y1} // Align on x-axis
fmt.Printf("vertical beam\n") //fmt.Printf("vertical beam\n")
} else if math.Tan(a) == 0 { // Check for horizontal beam } else if math.Tan(a) == 0 { // Check for horizontal beam
d = math.Abs(y1 - y0) d = math.Abs(y1 - y0)
c.lasercoords[3] = gamedata.Coordinates{X: x1, Y: y0} // Align on y-axis c.lasercoords[3] = gamedata.Coordinates{X: x1, Y: y0} // Align on y-axis
fmt.Printf("horizontal beam\n") //fmt.Printf("horizontal beam\n")
} else { // General case } else { // General case
m0 := math.Tan(a) m0 := math.Tan(a)
m1 := -1 / m0 m1 := -1 / m0
@@ -838,11 +865,11 @@ func (c *Canvas) LaserAttempt4() {
yi := xi*m0 - x0*m0 + y0 yi := xi*m0 - x0*m0 + y0
c.lasercoords[3] = gamedata.Coordinates{X: xi, Y: yi} c.lasercoords[3] = gamedata.Coordinates{X: xi, Y: yi}
d = math.Sqrt(math.Pow(x1-xi, 2) + math.Pow(y1-yi, 2)) d = math.Sqrt(math.Pow(x1-xi, 2) + math.Pow(y1-yi, 2))
fmt.Printf("%f \n", d) //fmt.Printf("%f \n", d)
} }
fmt.Printf("%f \n", a) //fmt.Printf("%f \n", a)
if d <= 50 && e.GetEnemyState() <= gamedata.EnemyStateHit { if d <= float64(e.GetSprite().Bounds().Dx()) && e.GetEnemyState() <= gamedata.EnemyStateHit {
if IsPixelColliding(c.laserMask, e.GetSprite(), if IsPixelColliding(c.laserMask, e.GetSprite(),
image.Pt(0, 0), image.Pt(0, 0),
@@ -857,7 +884,7 @@ func (c *Canvas) LaserAttempt4() {
if c.eventmap[gamedata.GameEventTargetHit] != nil { if c.eventmap[gamedata.GameEventTargetHit] != nil {
c.eventmap[gamedata.GameEventTargetHit]() c.eventmap[gamedata.GameEventTargetHit]()
} }
fmt.Println("laser'd") //fmt.Println("laser'd")
} }
} }
} }
@@ -884,3 +911,78 @@ func (c *Canvas) CleanSplashes() {
c.splashes = c.splashes[:i] c.splashes = c.splashes[:i]
} }
func (c *Canvas) CleanupDrops() {
i := 0
for _, drop := range c.wpdrops {
if !drop.IsCollected() {
c.wpdrops[i] = drop
i++
}
}
for j := i; j < len(c.wpdrops); j++ {
c.wpdrops[j] = nil
}
c.wpdrops = c.wpdrops[:i]
}
func (c *Canvas) UpdateWeapons() {
if !c.gameover {
//check for weapon inputs
if c.lastInputs.CycleWeapon {
c.holster.CycleWeapon()
}
//now let's update some shit based on the weapon
switch c.holster.GetActiveWeapon().GetWeaponType() {
case gamedata.WeaponTypeGun:
c.AddProjectiles()
case gamedata.WeaponTypeLaser:
c.UpdateLaser()
}
} else {
c.laser.SetFiring(false)
}
}
func (c *Canvas) UpdateWeaponDrops() {
//do we have any drops? let's calculate the chances
//
for _, drop := range c.wpdrops {
drop.Update()
//has the hero collided with any? add to holster
//boundary box collision check
if c.hero.Pos.X >= drop.GetPosition().X-float64(drop.Sprite.Bounds().Dx())/2 &&
c.hero.Pos.X <= drop.GetPosition().X+float64(drop.Sprite.Bounds().Dx())/2 &&
c.hero.Pos.Y >= drop.GetPosition().Y-float64(drop.Sprite.Bounds().Dy())/2 &&
c.hero.Pos.Y <= drop.GetPosition().Y+float64(drop.Sprite.Bounds().Dy())/2 {
//fmt.Println("hero trying to pick up weapon maybe")
if IsPixelColliding(
c.hero.Sprite,
drop.Sprite,
image.Pt(int(c.hero.Pos.X), int(c.hero.Pos.Y)),
image.Pt(int(drop.GetPosition().X), int(drop.GetPosition().Y)),
) {
fmt.Println("weapon acquired")
drop.SetCollected(true)
c.holster.AddWeapon(weapons.NewLaser())
}
}
}
}
func (c *Canvas) ResetWeaponDrops() {
for i := range c.wpdrops {
c.wpdrops[i] = nil
}
c.wpdrops = c.wpdrops[:0]
c.holster = weapons.NewHolster()
}

149
gameelement/rainlayer.go Normal file
View File

@@ -0,0 +1,149 @@
package gameelement
import (
"math/rand/v2"
"mover/elements"
"mover/gamedata"
"github.com/hajimehoshi/ebiten/v2"
)
type RainLayer struct {
Sprite *ebiten.Image
lastInputs gamedata.GameInputs
raindrops []*elements.RainDrop
nextsplashes []gamedata.Coordinates
rainsplashes []*elements.RainSplash
dimensions gamedata.Area
cycle int
}
func NewRainLayer(a gamedata.Area) *RainLayer {
rl := &RainLayer{
Sprite: ebiten.NewImage(a.Width, a.Height),
dimensions: a,
}
for i := 0; i < 50; i++ {
nrd := elements.NewRainDrop()
nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(a.Width), Y: rand.Float64() * float64(a.Height)})
rl.raindrops = append(rl.raindrops, nrd)
}
for i := 0; i < 50; i++ {
nrd := elements.NewRainSplash()
nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(a.Width), Y: rand.Float64() * float64(a.Height)})
rl.rainsplashes = append(rl.rainsplashes, nrd)
}
return rl
}
func (r *RainLayer) SetInputs(inputs gamedata.GameInputs) {
r.lastInputs = inputs
}
func (r *RainLayer) Update() error {
r.UpdateDrops()
r.UpdateSplashes()
r.cycle++
return nil
}
func (r *RainLayer) Draw(drawimg *ebiten.Image) {
r.Sprite.Clear()
for _, drop := range r.raindrops {
drop.Draw()
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(drop.GetPosition().X, drop.GetPosition().Y)
op.ColorScale.ScaleAlpha(0.5)
r.Sprite.DrawImage(drop.Sprite, op)
}
for _, drop := range r.rainsplashes {
drop.Draw()
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(drop.GetPosition().X, drop.GetPosition().Y)
op.ColorScale.ScaleAlpha(0.5)
r.Sprite.DrawImage(drop.Sprite, op)
}
drawimg.DrawImage(r.Sprite, nil)
}
func (r *RainLayer) Initialize() {
}
func (r *RainLayer) RegisterEvents(e gamedata.GameEvent, f func()) {
}
func (r *RainLayer) UpdateDrops() {
i := 0
for _, drop := range r.raindrops {
drop.Update()
if !drop.Expired() {
r.raindrops[i] = drop
i++
} else {
r.nextsplashes = append(r.nextsplashes, drop.GetPosition())
}
}
var j int = i
var newdrops int = 0
for ; j < len(r.raindrops); j++ {
r.raindrops[j] = nil
}
newdrops = len(r.raindrops) - i
r.raindrops = r.raindrops[:i]
for k := 0; k < newdrops; k++ {
nrd := elements.NewRainDrop()
nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(r.dimensions.Width), Y: rand.Float64() * float64(r.dimensions.Height)})
r.raindrops = append(r.raindrops, nrd)
}
}
func (r *RainLayer) UpdateSplashes() {
i := 0
for _, drop := range r.rainsplashes {
drop.Update()
if !drop.Expired() {
r.rainsplashes[i] = drop
i++
}
}
var j int = i
//var newdrops int = 0
for ; j < len(r.rainsplashes); j++ {
r.rainsplashes[j] = nil
}
//newdrops = len(r.rainsplashes) - i
r.rainsplashes = r.rainsplashes[:i]
/*
for k := 0; k < newdrops; k++ {
nrd := elements.NewRainSplash()
nrd.SetPosition(gamedata.Coordinates{X: rand.Float64() * float64(r.dimensions.Width), Y: rand.Float64() * float64(r.dimensions.Height)})
r.rainsplashes = append(r.rainsplashes, nrd)
}*/
for _, splashloc := range r.nextsplashes {
nrd := elements.NewRainSplash()
nrd.SetPosition(splashloc)
r.rainsplashes = append(r.rainsplashes, nrd)
}
r.nextsplashes = r.nextsplashes[:0]
}

View File

@@ -26,7 +26,7 @@ func NewManager() Manager {
return Manager{ return Manager{
Info: gamedata.GameInfo{ Info: gamedata.GameInfo{
Name: "survive", Name: "survive",
Version: "0.30", Version: "0.34",
Dimensions: gamedata.Area{ Dimensions: gamedata.Area{
Width: defaultWidth, Width: defaultWidth,
Height: defaultHeight, Height: defaultHeight,

View File

@@ -50,6 +50,11 @@ func NewPrimary() *Primary {
canvas.RegisterEvents(gamedata.GameEventFireball, p.EventHandlerFireball) canvas.RegisterEvents(gamedata.GameEventFireball, p.EventHandlerFireball)
p.elements = append(p.elements, canvas) p.elements = append(p.elements, canvas)
//rainlayer
rain := gameelement.NewRainLayer(gamearea)
rain.Initialize()
p.elements = append(p.elements, rain)
//create foreground cloud layer //create foreground cloud layer
clouds := gameelement.NewCloudLayer(gamearea) clouds := gameelement.NewCloudLayer(gamearea)
clouds.Initialize() clouds.Initialize()
@@ -155,6 +160,7 @@ func (p *Primary) CollectInputs() gamedata.GameInputs {
gi.ShotAngle = math.Atan2(yaxis, xaxis) gi.ShotAngle = math.Atan2(yaxis, xaxis)
gi.CycleWeapon = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonFrontTopRight)
gi.Charge = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonRightStick) gi.Charge = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonRightStick)
gi.Start = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonCenterRight) gi.Start = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonCenterRight)
gi.Shot = ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonFrontBottomRight) gi.Shot = ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonFrontBottomRight)

26
weapons/gun.go Normal file
View File

@@ -0,0 +1,26 @@
package weapons
import "mover/gamedata"
type Gun struct {
active bool
}
func NewGun() *Gun {
g := &Gun{
active: false,
}
return g
}
func (g *Gun) IsActive() bool {
return g.active
}
func (g *Gun) SetActivity(active bool) {
g.active = active
}
func (g *Gun) GetWeaponType() gamedata.WeaponType {
return gamedata.WeaponTypeGun
}

59
weapons/holster.go Normal file
View File

@@ -0,0 +1,59 @@
package weapons
import "mover/gamedata"
type Holster struct {
activewp gamedata.WeaponType
guns map[gamedata.WeaponType]Weapon
}
func NewHolster() *Holster {
holster := &Holster{
guns: make(map[gamedata.WeaponType]Weapon),
activewp: gamedata.WeaponTypeGun,
}
holster.AddWeapon(NewGun())
//holster.AddWeapon(NewLaser())
return holster
}
func (h *Holster) SetActiveWeapon(wt gamedata.WeaponType) {
_, ok := h.guns[wt]
if ok {
h.activewp = wt
}
}
func (h *Holster) GetActiveWeapon() Weapon {
return h.guns[h.activewp]
}
func (h *Holster) GetActiveWeaponType() gamedata.WeaponType {
return h.guns[h.activewp].GetWeaponType()
}
func (h *Holster) AddWeapon(w Weapon) {
_, ok := h.guns[w.GetWeaponType()]
if !ok {
h.guns[w.GetWeaponType()] = w
}
}
func (h *Holster) CycleWeapon() {
//no weapons, nothing to do
if len(h.guns) == 0 {
return
}
//keep searching until we find the next weapon that exists
var nextwp gamedata.WeaponType = h.activewp
for ok := false; !ok; {
nextwp = (nextwp + 1) % gamedata.WeaponTypeMax
_, ok = h.guns[nextwp]
if ok {
h.activewp = nextwp
}
}
}

26
weapons/laser.go Normal file
View File

@@ -0,0 +1,26 @@
package weapons
import "mover/gamedata"
type Laser struct {
active bool
}
func NewLaser() *Laser {
l := &Laser{
active: false,
}
return l
}
func (g *Laser) IsActive() bool {
return g.active
}
func (g *Laser) SetActivity(active bool) {
g.active = active
}
func (g *Laser) GetWeaponType() gamedata.WeaponType {
return gamedata.WeaponTypeLaser
}

9
weapons/weapon.go Normal file
View File

@@ -0,0 +1,9 @@
package weapons
import "mover/gamedata"
type Weapon interface {
IsActive() bool
SetActivity(bool)
GetWeaponType() gamedata.WeaponType
}