Added weapon system. Animated laser.

This commit is contained in:
2024-11-21 16:26:25 -05:00
parent 75d464b5e2
commit 257318926d
12 changed files with 210 additions and 50 deletions

View File

@@ -28,6 +28,7 @@ const (
Cloud ImgAssetName = "Cloud" Cloud ImgAssetName = "Cloud"
Fireball ImgAssetName = "Fireball" Fireball ImgAssetName = "Fireball"
Splash ImgAssetName = "Splash" Splash ImgAssetName = "Splash"
LaserBeam ImgAssetName = "LaserBeam"
) )
var ( var (
@@ -63,6 +64,8 @@ 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
) )
func LoadImages() { func LoadImages() {
@@ -83,6 +86,7 @@ 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)
} }

BIN
assets/laserbeam.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 786 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 {

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"
@@ -43,6 +44,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 +65,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,8 +82,8 @@ func (c *Canvas) Update() error {
c.Initialize() c.Initialize()
} else { } else {
c.UpdateHero() c.UpdateHero()
c.UpdateWeapons()
c.UpdateProjectiles() c.UpdateProjectiles()
c.UpdateLaser()
c.UpdateCharge() c.UpdateCharge()
c.UpdateEnemies() c.UpdateEnemies()
c.SpawnEnemies() c.SpawnEnemies()
@@ -227,7 +230,6 @@ func (c *Canvas) UpdateHero() {
if !c.gameover { if !c.gameover {
c.UpdateHeroPosition() c.UpdateHeroPosition()
c.ComputeHeroCollisions() c.ComputeHeroCollisions()
c.AddProjectiles()
} }
} }
@@ -275,31 +277,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,7 +359,11 @@ func (c *Canvas) UpdateProjectiles() {
} }
func (c *Canvas) UpdateLaser() { func (c *Canvas) UpdateLaser() {
c.laser.Update()
if c.lastInputs.Shot {
c.laser.SetPosition(c.hero.Pos)
c.laser.SetAngle(c.lastInputs.ShotAngle)
}
c.laser.SetFiring(c.lastInputs.Shot) c.laser.SetFiring(c.lastInputs.Shot)
if c.lastInputs.Shot { if c.lastInputs.Shot {
c.laserMask.Clear() c.laserMask.Clear()
@@ -826,11 +827,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,9 +839,9 @@ 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 <= 50 && e.GetEnemyState() <= gamedata.EnemyStateHit {
@@ -857,7 +858,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 +885,23 @@ func (c *Canvas) CleanSplashes() {
c.splashes = c.splashes[:i] c.splashes = c.splashes[: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)
}
}

View File

@@ -155,6 +155,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
}

51
weapons/holster.go Normal file
View File

@@ -0,0 +1,51 @@
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) 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
for ok := false; !ok; {
nextwp := (h.activewp + 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
}