109 lines
2.6 KiB
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
|
|
}
|