gwfc/internal/gwfc/Game.go

109 lines
2.6 KiB
Go

package gwfc
import (
"gwfc/data"
"math/rand"
"time"
"github.com/hajimehoshi/ebiten/v2"
"golang.org/x/exp/slices"
)
// Game is our game structure.
type Game struct {
Images map[string]*ebiten.Image
Map Map
cTiles [][2]int
stepRate int
tickDelay int
tileWidth int
tileHeight int
}
func (g *Game) Init() {
rand.Seed(time.Now().UnixMilli())
g.Images = make(map[string]*ebiten.Image)
g.stepRate = 0
data.Init()
for name, img := range data.Images {
// Assume tile size is same as first data Image.
if g.tileWidth == 0 || g.tileHeight == 0 {
g.tileWidth = img.Bounds().Dx()
g.tileHeight = img.Bounds().Dy()
}
g.Images[name] = ebiten.NewImageFromImage(img)
}
g.ResetMap()
ebiten.SetWindowSize(640, 480)
}
func (g *Game) ResetMap() {
// Size map according to 1/2 ebiten window.
w, h := ebiten.WindowSize()
g.Map.Size(w/2/g.tileWidth, h/2/g.tileHeight)
g.cTiles = [][2]int{{rand.Intn(g.Map.w), rand.Intn(g.Map.h)}}
}
func (g *Game) getRandomTile(s []string) string {
return s[rand.Intn(len(s))]
}
func (g *Game) iterFunc(c [2]int, t *Tile) {
types := g.Map.GetAdjacentTypes(c[0], c[1])
t.processed = true
if len(types) == 0 {
t.tile = g.getRandomTile([]string{"sand", "water", "grass", "saplings", "trees"})
} else if slices.Contains(types, "water") {
t.tile = g.getRandomTile([]string{"water", "sand"})
} else if slices.Contains(types, "sand") {
t.tile = g.getRandomTile([]string{"sand", "water", "grass"})
} else if slices.Contains(types, "grass") {
t.tile = g.getRandomTile([]string{"saplings", "grass", "sand"})
} else if slices.Contains(types, "trees") {
t.tile = g.getRandomTile([]string{"trees", "saplings", "grass"})
} else if slices.Contains(types, "saplings") {
t.tile = g.getRandomTile([]string{"trees", "saplings", "grass"})
} else {
t.tile = g.getRandomTile([]string{"sand", "water", "grass", "saplings", "trees"})
}
}
// Update updates the game state.
func (g *Game) Update() error {
if ebiten.IsKeyPressed(ebiten.KeyR) && len(g.cTiles) == 0 {
g.ResetMap()
}
if g.tickDelay > g.stepRate && len(g.cTiles) > 0 {
g.cTiles = g.Map.Iterate(g.cTiles, g.iterFunc)
g.tickDelay = 0
}
g.tickDelay++
return nil
}
// Draw draws the game state.
func (g *Game) Draw(screen *ebiten.Image) {
for x := range g.Map.tiles {
for y := range g.Map.tiles[x] {
if img, ok := g.Images[g.Map.tiles[x][y].tile]; ok {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64(x*g.tileWidth), float64(y*g.tileHeight))
screen.DrawImage(img, op)
}
}
}
}
// Layout does normal layout stuff.
func (g *Game) Layout(ow, oh int) (int, int) {
return 320, 240
}