diff --git a/go.mod b/go.mod index 1d7e099..2182bf8 100644 --- a/go.mod +++ b/go.mod @@ -13,4 +13,5 @@ require ( golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 // indirect + golang.org/x/text v0.3.7 // indirect ) diff --git a/go.sum b/go.sum index 46494ee..258d393 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/internal/gwfc/Game.go b/internal/gwfc/Game.go index cb7776d..61602f4 100644 --- a/internal/gwfc/Game.go +++ b/internal/gwfc/Game.go @@ -3,12 +3,19 @@ package gwfc import ( crand "crypto/rand" "encoding/binary" + "fmt" "gwfc/data" + "image/color" "log" "math/rand" "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/examples/resources/fonts" + "github.com/hajimehoshi/ebiten/v2/inpututil" + "github.com/hajimehoshi/ebiten/v2/text" "golang.org/x/exp/slices" + "golang.org/x/image/font" + "golang.org/x/image/font/opentype" ) // Game is our game structure. @@ -21,14 +28,32 @@ type Game struct { tickDelay int tileWidth int tileHeight int + processing bool + mode int + font font.Face + showText bool } func (g *Game) Init() { + ebiten.SetMaxTPS(500) ebiten.SetWindowSize(1280, 720) ebiten.SetWindowResizable(true) + // Load our font + tt, err := opentype.Parse(fonts.MPlus1pRegular_ttf) + if err != nil { + log.Fatal(err) + } + + const dpi = 72 + g.font, err = opentype.NewFace(tt, &opentype.FaceOptions{ + Size: 10, + DPI: dpi, + Hinting: font.HintingFull, + }) + var b [8]byte - _, err := crand.Read(b[:]) + _, err = crand.Read(b[:]) if err != nil { log.Fatal(err) } @@ -64,6 +89,14 @@ func (g *Game) ResetMap() { x, y := rand.Intn(g.Map.w), rand.Intn(g.Map.h) g.cTiles = append(g.cTiles, [2]int{x, y}) } + // ehh... + if g.mode == 1 { + for _, c := range g.cTiles { + t := g.Map.Get(c[0], c[1]) + g.iterFunc(c, t) + } + } + g.processing = true } func (g *Game) getRandomTile(s []string) string { @@ -81,6 +114,7 @@ func (g *Game) getMatchingValidAdjacentTiles(x, y int, s string) []string { t := g.Map.Get(x+x2, y+y2) if t != nil { + t.waveValue-- neighbors = append(neighbors, t) } } @@ -108,15 +142,48 @@ func (g *Game) iterFunc(c [2]int, t *Tile) { types := g.getMatchingValidAdjacentTiles(c[0], c[1], t.tile) t.processed = true t.tile = g.getRandomTile(types) + t.value = 1 } // Update updates the game state. func (g *Game) Update() error { - if ebiten.IsKeyPressed(ebiten.KeyR) && len(g.cTiles) == 0 { + if inpututil.IsKeyJustPressed(ebiten.KeyM) { + if g.mode == 0 { + g.mode = 1 + } else if g.mode == 1 { + g.mode = 0 + } g.ResetMap() } - if g.tickDelay > g.stepRate && len(g.cTiles) > 0 { - g.cTiles = g.Map.Iterate(g.cTiles, g.iterFunc) + if inpututil.IsKeyJustPressed(ebiten.KeyR) { + g.ResetMap() + } + if inpututil.IsKeyJustPressed(ebiten.KeyMinus) { + if g.stepRate > 0 { + g.stepRate-- + } + } else if inpututil.IsKeyJustPressed(ebiten.KeyEqual) { + if g.stepRate < 100 { + g.stepRate++ + } + } + if inpututil.IsKeyJustPressed(ebiten.KeyT) { + g.showText = !g.showText + } + if g.tickDelay > g.stepRate { + if g.mode == 0 { + if len(g.cTiles) == 0 { + g.processing = false + } else { + g.cTiles = g.Map.Iterate(g.cTiles, g.iterFunc) + } + } else if g.mode == 1 { + if c, t := g.Map.getBestTile(); t == nil { + g.processing = false + } else { + g.iterFunc(c, t) + } + } g.tickDelay = 0 } g.tickDelay++ @@ -125,19 +192,25 @@ func (g *Game) Update() error { // Draw draws the game state. func (g *Game) Draw(screen *ebiten.Image) { + tw := g.tileWidth * 2 + th := g.tileHeight * 2 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)) + op.GeoM.Scale(2, 2) + op.GeoM.Translate(float64(x*tw), float64(y*th)) screen.DrawImage(img, op) } + if g.showText { + text.Draw(screen, fmt.Sprintf("%d", g.Map.tiles[x][y].waveValue), g.font, x*tw+tw/4, y*th+th/2, color.White) + } } } } // Layout does normal layout stuff. func (g *Game) Layout(ow, oh int) (int, int) { - return ow / 2, oh / 2 + return ow, oh } diff --git a/internal/gwfc/Map.go b/internal/gwfc/Map.go index b68b708..39e3137 100644 --- a/internal/gwfc/Map.go +++ b/internal/gwfc/Map.go @@ -16,7 +16,9 @@ func (m *Map) Size(w, h int) { for x := range m.tiles { m.tiles[x] = make([]*Tile, h) for y := range m.tiles[x] { - m.tiles[x][y] = &Tile{} + m.tiles[x][y] = &Tile{ + waveValue: 4, + } } } m.w = w @@ -88,3 +90,22 @@ func (m *Map) Iterate(tiles [][2]int, f func(c [2]int, t *Tile)) [][2]int { } return next } + +func (m *Map) getBestTile() (lowestCoord [2]int, lowestTile *Tile) { + var lowestValue = 9 + for x := range m.tiles { + for y := range m.tiles[x] { + if !m.tiles[x][y].processed { + if lowestValue > m.tiles[x][y].waveValue { + if lowestValue <= 1 { + return + } + lowestValue = m.tiles[x][y].waveValue + lowestCoord = [2]int{x, y} + lowestTile = m.tiles[x][y] + } + } + } + } + return +} diff --git a/internal/gwfc/Tile.go b/internal/gwfc/Tile.go index 0bffb2d..672864d 100644 --- a/internal/gwfc/Tile.go +++ b/internal/gwfc/Tile.go @@ -4,4 +4,5 @@ type Tile struct { tile string processed bool value interface{} + waveValue int }