diff --git a/assets/imagebank.go b/assets/imagebank.go index cadfdb6..a13b5b9 100644 --- a/assets/imagebank.go +++ b/assets/imagebank.go @@ -28,6 +28,7 @@ const ( Cloud ImgAssetName = "Cloud" Fireball ImgAssetName = "Fireball" Splash ImgAssetName = "Splash" + LaserBeam ImgAssetName = "LaserBeam" ) var ( @@ -63,6 +64,8 @@ var ( fireball_img []byte //go:embed splash.png splash_img []byte + //go:embed laserbeam.png + laserbeam_img []byte ) func LoadImages() { @@ -83,6 +86,7 @@ func LoadImages() { ImageBank[Cloud] = LoadImagesFatal(cloud_img) ImageBank[Fireball] = LoadImagesFatal(fireball_img) ImageBank[Splash] = LoadImagesFatal(splash_img) + ImageBank[LaserBeam] = LoadImagesFatal(laserbeam_img) } diff --git a/assets/laserbeam.png b/assets/laserbeam.png new file mode 100644 index 0000000..ce8e65e Binary files /dev/null and b/assets/laserbeam.png differ diff --git a/assets/splash.png b/assets/splash.png index e09a4a3..cb9d909 100644 Binary files a/assets/splash.png and b/assets/splash.png differ diff --git a/elements/laser.go b/elements/laser.go index 9b1f1ab..e9a5542 100644 --- a/elements/laser.go +++ b/elements/laser.go @@ -1,27 +1,30 @@ package elements import ( - "image/color" + "image" + "mover/assets" "mover/gamedata" "github.com/hajimehoshi/ebiten/v2" ) type Laser struct { - Sprite *ebiten.Image - position gamedata.Coordinates - angle float64 - cycle int - firing bool + Sprite *ebiten.Image + position gamedata.Coordinates + angle float64 + cycle int + firing bool + numcycles int } func NewLaser(pos gamedata.Coordinates, angle float64) *Laser { l := &Laser{ - Sprite: ebiten.NewImage(200, 20), - angle: angle, - cycle: 0, - position: pos, - firing: false, + Sprite: ebiten.NewImage(200, 20), + angle: angle, + cycle: 0, + position: pos, + firing: false, + numcycles: 5, } return l } @@ -33,7 +36,16 @@ func (l *Laser) Update() error { func (l *Laser) Draw() { 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 { diff --git a/gamedata/gameinputs.go b/gamedata/gameinputs.go index ac83dde..c4a4a0d 100644 --- a/gamedata/gameinputs.go +++ b/gamedata/gameinputs.go @@ -1,12 +1,13 @@ package gamedata type GameInputs struct { - XAxis float64 - YAxis float64 - ShotAngle float64 - Shot bool - Start bool - Charge bool - Quit bool - Reset bool + XAxis float64 + YAxis float64 + ShotAngle float64 + Shot bool + Start bool + Charge bool + Quit bool + Reset bool + CycleWeapon bool } diff --git a/gamedata/weapontype.go b/gamedata/weapontype.go new file mode 100644 index 0000000..d599c63 --- /dev/null +++ b/gamedata/weapontype.go @@ -0,0 +1,9 @@ +package gamedata + +type WeaponType int + +const ( + WeaponTypeGun = iota + WeaponTypeLaser + WeaponTypeMax +) diff --git a/gameelement/canvas.go b/gameelement/canvas.go index 5e5b5cb..2ba4b6e 100644 --- a/gameelement/canvas.go +++ b/gameelement/canvas.go @@ -10,6 +10,7 @@ import ( "mover/elements" "mover/fonts" "mover/gamedata" + "mover/weapons" "github.com/hajimehoshi/ebiten/v2" "github.com/hajimehoshi/ebiten/v2/text" @@ -43,6 +44,7 @@ type Canvas struct { gameover bool lasercoords []gamedata.Coordinates + holster *weapons.Holster } func NewCanvas(a gamedata.Area) *Canvas { @@ -63,6 +65,7 @@ func NewCanvas(a gamedata.Area) *Canvas { score: 0, runtime: 0., counter: 0, + holster: weapons.NewHolster(), } c.laserMask.Clear() c.eventmap = make(map[gamedata.GameEvent]func()) @@ -79,8 +82,8 @@ func (c *Canvas) Update() error { c.Initialize() } else { c.UpdateHero() + c.UpdateWeapons() c.UpdateProjectiles() - c.UpdateLaser() c.UpdateCharge() c.UpdateEnemies() c.SpawnEnemies() @@ -227,7 +230,6 @@ func (c *Canvas) UpdateHero() { if !c.gameover { c.UpdateHeroPosition() c.ComputeHeroCollisions() - c.AddProjectiles() } } @@ -275,31 +277,26 @@ func (c *Canvas) ComputeHeroCollisions() { func (c *Canvas) AddProjectiles() { //add new projectiles - /* - if c.lastInputs.Shot && c.counter%14 == 0 { - loc := gamedata.Coordinates{ - 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]() - } + if c.lastInputs.Shot && c.counter%14 == 0 { + loc := gamedata.Coordinates{ + X: c.hero.Pos.X, + Y: c.hero.Pos.Y, } - */ - if c.lastInputs.Shot { - c.laser.SetPosition(c.hero.Pos) - c.laser.SetAngle(c.lastInputs.ShotAngle) + 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]() + } + } } @@ -362,7 +359,11 @@ func (c *Canvas) UpdateProjectiles() { } 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) if c.lastInputs.Shot { 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 d = math.Abs(x1 - x0) 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 d = math.Abs(y1 - y0) 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 m0 := math.Tan(a) m1 := -1 / m0 @@ -838,9 +839,9 @@ func (c *Canvas) LaserAttempt4() { yi := xi*m0 - x0*m0 + y0 c.lasercoords[3] = gamedata.Coordinates{X: xi, Y: yi} 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 { @@ -857,7 +858,7 @@ func (c *Canvas) LaserAttempt4() { if c.eventmap[gamedata.GameEventTargetHit] != nil { 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] } + +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) + } + +} diff --git a/screens/primary.go b/screens/primary.go index 9acee33..647d862 100644 --- a/screens/primary.go +++ b/screens/primary.go @@ -155,6 +155,7 @@ func (p *Primary) CollectInputs() gamedata.GameInputs { gi.ShotAngle = math.Atan2(yaxis, xaxis) + gi.CycleWeapon = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonFrontTopRight) gi.Charge = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonRightStick) gi.Start = inpututil.IsStandardGamepadButtonJustPressed(0, ebiten.StandardGamepadButtonCenterRight) gi.Shot = ebiten.IsStandardGamepadButtonPressed(0, ebiten.StandardGamepadButtonFrontBottomRight) diff --git a/weapons/gun.go b/weapons/gun.go new file mode 100644 index 0000000..2e19939 --- /dev/null +++ b/weapons/gun.go @@ -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 +} diff --git a/weapons/holster.go b/weapons/holster.go new file mode 100644 index 0000000..ccd56dc --- /dev/null +++ b/weapons/holster.go @@ -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 + } + + } + +} diff --git a/weapons/laser.go b/weapons/laser.go new file mode 100644 index 0000000..dbd2d9e --- /dev/null +++ b/weapons/laser.go @@ -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 +} diff --git a/weapons/weapon.go b/weapons/weapon.go new file mode 100644 index 0000000..b0c46f5 --- /dev/null +++ b/weapons/weapon.go @@ -0,0 +1,9 @@ +package weapons + +import "mover/gamedata" + +type Weapon interface { + IsActive() bool + SetActivity(bool) + GetWeaponType() gamedata.WeaponType +}