You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
3.2 KiB
Go
157 lines
3.2 KiB
Go
package game
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/asset"
|
|
|
|
"code.rocketnine.space/tslocum/doctorlectro/entity"
|
|
"code.rocketnine.space/tslocum/doctorlectro/level"
|
|
"code.rocketnine.space/tslocum/doctorlectro/system"
|
|
"code.rocketnine.space/tslocum/doctorlectro/world"
|
|
"code.rocketnine.space/tslocum/gohan"
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
"github.com/jakecoffman/cp"
|
|
)
|
|
|
|
const introMessage = `
|
|
DOCTOR LECTRO, THE MAD SCIENTIST, HAS TAKEN
|
|
CHARGE OF EARTH'S MAGNETIC POLES!
|
|
|
|
ANIMALS, ELECTRONICS, AND HAIRSTYLES ACROSS
|
|
THE GLOBE ARE IN GRAVE DANGER!
|
|
|
|
STOP DOCTOR LECTRO BEFORE IT IS TOO LATE!
|
|
`
|
|
|
|
type Game struct {
|
|
shownIntro bool
|
|
}
|
|
|
|
func NewGame() (*Game, error) {
|
|
g := &Game{}
|
|
g.reset()
|
|
g.addSystems()
|
|
|
|
return g, nil
|
|
}
|
|
|
|
// addSystems adds all systems to the game. Systems run in the order they are
|
|
// added in. Systems do not run in parallel.
|
|
func (g *Game) addSystems() {
|
|
gohan.AddSystem(system.NewPhysicsSystem())
|
|
gohan.AddSystem(system.NewPlayerMoveSystem())
|
|
gohan.AddSystem(system.NewMovementSystem())
|
|
for layer := world.LayerPlatform; layer <= world.LayerDefault; layer++ {
|
|
gohan.AddSystem(system.NewRenderSystem(layer))
|
|
}
|
|
gohan.AddSystem(system.NewRenderMessageSystem())
|
|
gohan.AddSystem(system.NewWinSystem())
|
|
gohan.AddSystem(system.NewRenderDebugTextSystem())
|
|
}
|
|
|
|
func (g *Game) reset() {
|
|
for _, e := range gohan.AllEntities() {
|
|
e.Remove()
|
|
}
|
|
|
|
world.GameOver = false
|
|
world.Tick = 0
|
|
|
|
world.CanJump = false
|
|
world.CanMagnetize = false
|
|
world.CanFire = false
|
|
world.CanDoubleJump = false
|
|
|
|
world.LastFire = 0
|
|
|
|
world.MetalRects = nil
|
|
world.HazardRects = nil
|
|
|
|
world.Clinging = false
|
|
|
|
world.LastWalkDirL = true
|
|
world.LastWalkDirU = true
|
|
|
|
world.Space = cp.NewSpace()
|
|
world.Space.Iterations = 1
|
|
world.Space.SetGravity(cp.Vector{0, world.Gravity})
|
|
|
|
world.Player = entity.NewPlayer()
|
|
|
|
level.LoadMap()
|
|
|
|
if world.Give != "" {
|
|
for _, ability := range strings.Split(world.Give, ",") {
|
|
switch strings.ToLower(ability) {
|
|
case "jump":
|
|
world.CanJump = true
|
|
case "magnetize":
|
|
world.CanMagnetize = true
|
|
case "fire":
|
|
world.CanFire = true
|
|
case "switch":
|
|
world.CanDoubleJump = true
|
|
default:
|
|
panic(fmt.Sprintf("unknown ability to give player: %s", ability))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
|
|
return world.ScreenWidth, world.ScreenHeight
|
|
}
|
|
|
|
func (g *Game) Update() error {
|
|
if ebiten.IsWindowBeingClosed() {
|
|
g.Exit()
|
|
return nil
|
|
}
|
|
|
|
if world.ResetGame {
|
|
g.reset()
|
|
world.ResetGame = false
|
|
}
|
|
|
|
if inpututil.IsKeyJustPressed(ebiten.KeyM) {
|
|
if asset.SoundMusic.IsPlaying() {
|
|
asset.SoundMusic.Pause()
|
|
} else {
|
|
asset.SoundMusic.Play()
|
|
}
|
|
}
|
|
|
|
if world.MessageText != "" {
|
|
if ebiten.IsKeyPressed(ebiten.KeyEnter) {
|
|
world.MessageText = ""
|
|
}
|
|
return nil
|
|
}
|
|
|
|
if !world.ShownIntro && world.Tick == 0 {
|
|
world.SetMessage(strings.TrimSpace(introMessage))
|
|
world.ShownIntro = true
|
|
|
|
if !world.StartMuted {
|
|
asset.SoundMusic.Play()
|
|
}
|
|
}
|
|
return gohan.Update()
|
|
}
|
|
|
|
func (g *Game) Draw(screen *ebiten.Image) {
|
|
err := gohan.Draw(screen)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func (g *Game) Exit() {
|
|
os.Exit(0)
|
|
}
|