160 lines
4.0 KiB
Go
160 lines
4.0 KiB
Go
package mapgens
|
|
|
|
import (
|
|
"fmt"
|
|
"lab.zaar.be/thefish/alchemyst-go/engine/gamemap"
|
|
"lab.zaar.be/thefish/alchemyst-go/engine/types"
|
|
"lab.zaar.be/thefish/alchemyst-go/util"
|
|
)
|
|
|
|
//fixme move to config
|
|
var minRoomSize = 3
|
|
var maxRoomSize = 22
|
|
var maxrooms = 50
|
|
|
|
var fges = map[int]types.RectFill{
|
|
1: types.RectFill{
|
|
Top: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
Bottom: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
Left: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
Right: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
BottomLeft: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
BottomRight: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
TopLeft: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
TopRight: func() *gamemap.Tile { return gamemap.NewWall() },
|
|
Body: func() *gamemap.Tile { return gamemap.NewFloor() },
|
|
},
|
|
|
|
2: types.RectFill{
|
|
Top: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
Bottom: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
Left: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
Right: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
BottomLeft: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
BottomRight: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
TopLeft: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
TopRight: func() *gamemap.Tile { return gamemap.NewWaterTile() },
|
|
Body: func() *gamemap.Tile { return gamemap.NewDeepWaterTile() },
|
|
},
|
|
}
|
|
|
|
func DefaultGen(ctx util.ClientCtx,l *gamemap.Level) (*gamemap.Level, []*gamemap.Room) {
|
|
|
|
rng := util.NewRNG()
|
|
|
|
//load prefabs
|
|
pfLoader := gamemap.NewPrefabLoader(ctx)
|
|
pfRooms := pfLoader.PrefabRoomsList()
|
|
|
|
|
|
//fill with walls
|
|
for i := 0; i < l.W; i ++ {
|
|
for j := 0; j < l.H; j++ {
|
|
l.SetTileByXY(i, j, gamemap.NewWall())
|
|
}
|
|
}
|
|
|
|
rooms := make([]*gamemap.Room, 0)
|
|
|
|
for i := 0; i < maxrooms; i++ {
|
|
failed := false
|
|
var fillage types.RectFill
|
|
fillage = fges[rng.GetWeightedEntity(map[int]int{1: 10, 2: 1})]
|
|
var newRoom *gamemap.Room
|
|
if rng.Range(0, 5) == 1 {
|
|
//prefab
|
|
newRoom = &pfRooms[0]
|
|
} else {
|
|
newRoom = gamemap.NewRandomRectRoom(
|
|
rng,
|
|
rng.Range(minRoomSize, maxRoomSize),
|
|
rng.Range(minRoomSize, maxRoomSize),
|
|
fillage,
|
|
)
|
|
}
|
|
where := types.Coords{
|
|
rng.Range(1, l.W -2 - newRoom.W),
|
|
rng.Range(1, l.H - 2 - newRoom.H),
|
|
}
|
|
|
|
newRoom.MoveToCoords(where)
|
|
|
|
for _, otherRoom := range rooms {
|
|
if otherRoom.Intersects(newRoom.Rect) {
|
|
failed = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !failed {
|
|
rooms = append(rooms, newRoom)
|
|
}
|
|
|
|
//addStairs(rooms)
|
|
//itemize(rooms)
|
|
}
|
|
|
|
//build delannay graph from room center
|
|
|
|
//refine it to minimum spanning tree
|
|
|
|
//connect accordingly
|
|
for _, room := range rooms {
|
|
err := room.BlitToLevel(l)
|
|
if err != nil {
|
|
fmt.Printf("err: %v", err)
|
|
}
|
|
}
|
|
|
|
for idx, room := range rooms {
|
|
if idx > 0 {
|
|
connectRooms(l, room, rooms[idx-1], rng.Range(0, 1))
|
|
}
|
|
}
|
|
|
|
return l, rooms
|
|
}
|
|
|
|
func connectRooms(l *gamemap.Level, room, otherRoom *gamemap.Room, toss int) {
|
|
if toss == 0 {
|
|
digHTunnel(l, room.Center.X, otherRoom.Center.X, room.Center.Y)
|
|
digVTunnel(l, room.Center.Y, otherRoom.Center.Y, otherRoom.Center.X)
|
|
} else {
|
|
digVTunnel(l, room.Center.Y, otherRoom.Center.Y, room.Center.Y)
|
|
digHTunnel(l, room.Center.X, otherRoom.Center.X, otherRoom.Center.Y)
|
|
}
|
|
}
|
|
|
|
func digHTunnel(l *gamemap.Level, x1, x2, y int) {
|
|
var start, finish int
|
|
if x1 < x2 {
|
|
start = x1
|
|
finish = x2
|
|
} else {
|
|
start = x2
|
|
finish = x1
|
|
}
|
|
for i := start; i <= finish; i++ {
|
|
if l.InBounds(types.Coords{i, y}) {
|
|
l.SetTileByXY(i, y, gamemap.NewFloor())
|
|
//l.Tiles[i][y] = gamemap.NewFloor()
|
|
}
|
|
}
|
|
}
|
|
|
|
func digVTunnel(l *gamemap.Level, y1, y2, x int) {
|
|
var start, finish int
|
|
if y1 < y2 {
|
|
start = y1
|
|
finish = y2
|
|
} else {
|
|
start = y2
|
|
finish = y1
|
|
}
|
|
for i := start; i <= finish; i++ {
|
|
if l.InBounds(types.Coords{x, i}) {
|
|
l.SetTileByXY(x, i, gamemap.NewFloor())
|
|
}
|
|
}
|
|
}
|