You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.2 KiB
156 lines
3.2 KiB
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) |
|
}
|
|
|