diff --git a/main.go b/main.go index 7d86e990e5d09da1af41eb85e0784164ed11bc82..45d0c18732f76f042fac01f7c32469f3757cb614 100644 --- a/main.go +++ b/main.go @@ -2,17 +2,55 @@ package main import ( "image/color" + "time" "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/inpututil" ) // Game holds the top-level state for the Ebitengine run loop. type Game struct { - ship Ship + ship Ship + walk map[[2]int]bool + crew []Crew + selectedCrew int + lastTime time.Time } -// Update advances simulation; nothing to do in this milestone. +// Update advances simulation by dt seconds and handles input. func (g *Game) Update() error { + if g.lastTime.IsZero() { + g.lastTime = time.Now() + return nil + } + dt := time.Since(g.lastTime).Seconds() + g.lastTime = time.Now() + if dt > 0.1 { + dt = 0.1 + } + + for i := range g.crew { + updateCrew(&g.crew[i], dt) + } + + if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { + cx, cy := ebiten.CursorPosition() + tx, ty := cx/TilePx, cy/TilePx + + for i := range g.crew { + if g.crew[i].TileX == tx && g.crew[i].TileY == ty { + g.selectedCrew = i + return nil + } + } + + if g.selectedCrew >= 0 && g.walk[[2]int{tx, ty}] { + from := [2]int{g.crew[g.selectedCrew].TileX, g.crew[g.selectedCrew].TileY} + g.crew[g.selectedCrew].Path = bfsPath(g.walk, from, [2]int{tx, ty}) + g.crew[g.selectedCrew].MoveT = 0 + } + } + return nil } @@ -20,6 +58,9 @@ // Draw renders the whole frame. func (g *Game) Draw(screen *ebiten.Image) { screen.Fill(color.RGBA{10, 15, 25, 255}) drawShip(screen, g.ship) + for i, c := range g.crew { + drawCrew(screen, c, i == g.selectedCrew) + } } // Layout fixes the virtual resolution; the window scales to fit. @@ -28,9 +69,12 @@ return VirtualW, VirtualH } func main() { + ship := NewPlayerShip() + walk := walkableTiles(ship) + crew := NewStartingCrew() ebiten.SetWindowSize(1280, 720) ebiten.SetWindowTitle("ftl-shape") - if err := ebiten.RunGame(&Game{ship: NewPlayerShip()}); err != nil { + if err := ebiten.RunGame(&Game{ship: ship, walk: walk, crew: crew, selectedCrew: -1}); err != nil { panic(err) } } diff --git a/render.go b/render.go index a81cbcdd5b4fd5e613d2e4fe2faf2140dfc53e04..878c778e6f2382ec4484a1807d63310503f3cb4b 100644 --- a/render.go +++ b/render.go @@ -64,3 +64,26 @@ // Label: a few pixels inside the top-left corner. ebitenutil.DebugPrintAt(screen, r.Name, int(x)+3, int(y)+2) } + +const CrewRadius = 6 + +var white = color.RGBA{255, 255, 255, 255} + +func drawCrew(screen *ebiten.Image, c Crew, selected bool) { + var fx, fy float64 + if len(c.Path) > 0 { + fx = float64(c.TileX) + (float64(c.Path[0][0])-float64(c.TileX))*c.MoveT + fy = float64(c.TileY) + (float64(c.Path[0][1])-float64(c.TileY))*c.MoveT + } else { + fx = float64(c.TileX) + fy = float64(c.TileY) + } + px := float32(fx*TilePx + TilePx/2) + py := float32(fy*TilePx + TilePx/2) + + vector.DrawFilledCircle(screen, px, py, CrewRadius, c.Color, true) + if selected { + vector.StrokeCircle(screen, px, py, CrewRadius+1, 1, white, true) + } + ebitenutil.DebugPrintAt(screen, string(c.Initial), int(px)-2, int(py)-5) +}