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

9 months ago
package game
import (
"fmt"
9 months ago
"os"
"strings"
9 months ago
"github.com/hajimehoshi/ebiten/v2/inpututil"
9 months ago
"code.rocketnine.space/tslocum/doctorlectro/asset"
"code.rocketnine.space/tslocum/doctorlectro/entity"
9 months ago
"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"
9 months ago
)
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!
`
9 months ago
type Game struct {
shownIntro bool
9 months ago
}
func NewGame() (*Game, error) {
g := &Game{}
g.reset()
9 months ago
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.
9 months ago
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())
9 months ago
gohan.AddSystem(system.NewWinSystem())
9 months ago
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
9 months ago
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))
}
}
}
}
9 months ago
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
}
9 months ago
if !world.ShownIntro && world.Tick == 0 {
world.SetMessage(strings.TrimSpace(introMessage))
9 months ago
world.ShownIntro = true
9 months ago
if !world.StartMuted {
asset.SoundMusic.Play()
}
}
9 months ago
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)
}