Real-time strategy (RTS) video game
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

165 lines
4.3 KiB

package world
import (
"image/color"
"math/rand"
"github.com/hajimehoshi/ebiten/v2"
)
const MapSize = 128
const tileDivisions = 4
const numTiles = MapSize * MapSize * tileDivisions * tileDivisions
func environmentTile(r, g, b uint8) *ebiten.Image {
img := ebiten.NewImage(TileSizeEnvironment, TileSizeEnvironment)
img.Fill(color.RGBA{r, g, b, 255})
return img
}
var (
lightBlueTile1 = environmentTile(174, 208, 218)
lightBlueTile2 = environmentTile(203, 234, 229)
lightBlueTile3 = environmentTile(154, 202, 206)
lightBlueTiles = []*ebiten.Image{lightBlueTile1, lightBlueTile1, lightBlueTile2, lightBlueTile2, lightBlueTile2, lightBlueTile2, lightBlueTile2, lightBlueTile2, lightBlueTile2, lightBlueTile3}
mediumBlueTile1 = environmentTile(0, 38, 117)
mediumBlueTile2 = environmentTile(9, 69, 131)
mediumBlueTile3 = environmentTile(25, 71, 148)
mediumBlueTiles = []*ebiten.Image{mediumBlueTile1, mediumBlueTile2, mediumBlueTile3}
darkBlueTile1 = environmentTile(0, 9, 88)
darkBlueTile2 = environmentTile(2, 3, 67)
darkBlueTile3 = environmentTile(0, 0, 72)
darkBlueTiles = []*ebiten.Image{darkBlueTile1, darkBlueTile1, darkBlueTile2, darkBlueTile3}
redTile1 = environmentTile(109, 5, 0)
redTile2 = environmentTile(135, 13, 8)
redTile3 = environmentTile(118, 0, 6)
redTiles = []*ebiten.Image{redTile1, redTile1, redTile2, redTile3}
)
func NewGameMap(seed int64) []Tile {
r := rand.New(rand.NewSource(seed))
tiles := make([]Tile, numTiles)
{
tx, ty := float64(0), float64(0)
for i := range tiles {
tiles[i].X, tiles[i].Y = tx, ty
tiles[i].Walkable = true
tx++
if tx == MapSize*4 {
tx = 0
ty++
}
}
}
for x := 0.0; x < MapSize; x++ {
for y := 0.0; y < MapSize; y++ {
index := TileIndex(x, y)
tiles[index].Sprite = lightBlueTiles[r.Intn(len(lightBlueTiles))]
}
}
setWalkable := func(tx, ty float64, walkable bool) {
tileIndexes := PathTilesAtMapTile(tx, ty)
for _, index := range tileIndexes {
tiles[index].Walkable = walkable
}
}
numMediumBlue := r.Intn(10) + 7
for i := 0; i < numMediumBlue; i++ {
bx, by := float64(r.Intn(132)-4), float64(r.Intn(132)-4)
bSizeX := float64(r.Intn(TileSize) + 7)
bSizeY := float64(r.Intn(TileSize) + 7)
for offsetX := 0.0; offsetX < bSizeX; offsetX++ {
for offsetY := 0.0; offsetY < bSizeY; offsetY++ {
tx, ty := bx+offsetX, by+offsetY
index := TileIndex(tx, ty)
if index == -1 {
continue
}
setWalkable(tx, ty, false)
tiles[index].Sprite = mediumBlueTiles[r.Intn(len(mediumBlueTiles))]
}
}
}
numDarkBlue := r.Intn(7) + 4
for i := 0; i < numDarkBlue; i++ {
bx, by := float64(r.Intn(132)-4), float64(r.Intn(132)-4)
bSizeX := float64(r.Intn(12) + 7)
bSizeY := float64(r.Intn(12) + 7)
for offsetX := 0.0; offsetX < bSizeX; offsetX++ {
for offsetY := 0.0; offsetY < bSizeY; offsetY++ {
tx, ty := bx+offsetX, by+offsetY
index := TileIndex(tx, ty)
if index == -1 {
continue
}
setWalkable(tx, ty, false)
tiles[index].Sprite = darkBlueTiles[r.Intn(len(darkBlueTiles))]
}
}
}
numStreaks := r.Intn(3) + 5
for i := 0; i < numStreaks; i++ {
bx, by := float64(r.Intn(132)-4), float64(r.Intn(132)-4)
vertical := r.Intn(2) == 0
bSize := float64(rand.Intn(14) + 32)
for offset := 0.0; offset < bSize; offset++ {
var tx, ty float64
if vertical {
tx, ty = bx, by+offset
} else {
tx, ty = bx+offset, by
}
index := TileIndex(tx, ty)
if index == -1 || !tiles[index].Walkable {
continue
}
setWalkable(tx, ty, false)
tiles[index].Sprite = redTiles[r.Intn(len(redTiles))]
}
}
return tiles
}
func PathTileIndex(x, y float64) int {
if x < 0 || y < 0 || x >= MapSize*tileDivisions || y >= MapSize*tileDivisions {
return -1
}
return int(y*MapSize*tileDivisions) + int(x)
}
func TileIndex(x, y float64) int {
if x < 0 || y < 0 || x >= MapSize || y >= MapSize {
return -1
}
return int(y*tileDivisions*MapSize*tileDivisions) + int(x*tileDivisions)
}
func ValidXY(x, y int) bool {
return x >= 0 && y >= 0 && x < MapSize && y < MapSize
}
func PathTilesAtMapTile(tx, ty float64) []int {
pi := TileIndex(tx, ty)
tiles := make([]int, 16)
i := 0
for offsetY := 0; offsetY < 4; offsetY++ {
for offsetX := 0; offsetX < 4; offsetX++ {
tiles[i] = pi + (offsetY * MapSize * 4) + offsetX
i++
}
}
return tiles
}