package main import "time" import "image" import "git.tebibyte.media/sashakoshka/tomo" import "git.tebibyte.media/sashakoshka/tomo/canvas" type Game struct { *Raycaster running bool tickChan <- chan time.Time stopChan chan bool stamina float64 health float64 controlState ControlState onStatUpdate func () } func NewGame (world World, textures Textures) (game *Game) { game = &Game { Raycaster: NewRaycaster(world, textures), stopChan: make(chan bool), } game.Raycaster.OnControlStateChange (func (state ControlState) { game.controlState = state }) game.stamina = 0.5 game.health = 1 return } func (game *Game) DrawTo ( canvas canvas.Canvas, bounds image.Rectangle, onDamage func (image.Rectangle), ) { if canvas == nil { select { case game.stopChan <- true: default: } } else if !game.running { game.running = true go game.run() } game.Raycaster.DrawTo(canvas, bounds, onDamage) } func (game *Game) Stamina () float64 { return game.stamina } func (game *Game) Health () float64 { return game.health } func (game *Game) OnStatUpdate (callback func ()) { game.onStatUpdate = callback } func (game *Game) tick () { moved := false statUpdate := false speed := 0.07 if game.controlState.Sprint { speed = 0.16 } if game.stamina <= 0 { speed = 0 } if game.controlState.WalkForward { game.Walk(speed) moved = true } if game.controlState.WalkBackward { game.Walk(-speed) moved = true } if game.controlState.StrafeLeft { game.Strafe(-speed) moved = true } if game.controlState.StrafeRight { game.Strafe(speed) moved = true } if game.controlState.LookLeft { game.Rotate(-0.1) } if game.controlState.LookRight { game.Rotate(0.1) } if moved { game.stamina -= speed / 50 statUpdate = true } else if game.stamina < 1 { game.stamina += 0.005 statUpdate = true } if game.stamina > 1 { game.stamina = 1 } if game.stamina < 0 { game.stamina = 0 } tomo.Do(game.Draw) if statUpdate && game.onStatUpdate != nil { tomo.Do(game.onStatUpdate) } } func (game *Game) run () { ticker := time.NewTicker(time.Second / 30) game.tickChan = ticker.C for game.running { select { case <- game.tickChan: game.tick() case <- game.stopChan: ticker.Stop() } } }