Pull world gen out into interface

This commit is contained in:
Marc Di Luzio 2020-07-19 13:41:47 +01:00
parent 4f1a9c2c2b
commit 1eba9a8652
2 changed files with 84 additions and 44 deletions

View file

@ -6,7 +6,6 @@ import (
"github.com/mdiluz/rove/pkg/maths"
"github.com/mdiluz/rove/proto/roveapi"
"github.com/ojrac/opensimplex-go"
)
// chunk represents a fixed square grid of tiles
@ -34,29 +33,23 @@ type chunkBasedAtlas struct {
// ChunkSize is the x/y dimensions of each square chunk
ChunkSize int `json:"chunksize"`
// terrainNoise describes the noise function for the terrain
terrainNoise opensimplex.Noise
// terrainNoise describes the noise function for the terrain
objectNoise opensimplex.Noise
// worldGen is the internal world generator
worldGen WorldGen
}
const (
noiseSeed = 1024
terrainNoiseScale = 6
objectNoiseScale = 3
noiseSeed = 1024
)
// NewChunkAtlas creates a new empty atlas
func NewChunkAtlas(chunkSize int) Atlas {
// Start up with one chunk
a := chunkBasedAtlas{
ChunkSize: chunkSize,
Chunks: make([]chunk, 1),
LowerBound: maths.Vector{X: 0, Y: 0},
UpperBound: maths.Vector{X: chunkSize, Y: chunkSize},
terrainNoise: opensimplex.New(noiseSeed),
objectNoise: opensimplex.New(noiseSeed),
ChunkSize: chunkSize,
Chunks: make([]chunk, 1),
LowerBound: maths.Vector{X: 0, Y: 0},
UpperBound: maths.Vector{X: chunkSize, Y: chunkSize},
worldGen: NewNoiseWorldGen(noiseSeed),
}
// Initialise the first chunk
a.populate(0)
@ -105,31 +98,15 @@ func (a *chunkBasedAtlas) populate(chunk int) {
origin := a.chunkOriginInWorldSpace(chunk)
for i := 0; i < a.ChunkSize; i++ {
for j := 0; j < a.ChunkSize; j++ {
loc := maths.Vector{X: origin.X + i, Y: origin.Y + j}
// Get the terrain noise value for this location
t := a.terrainNoise.Eval2(float64(origin.X+i)/terrainNoiseScale, float64(origin.Y+j)/terrainNoiseScale)
var tile roveapi.Tile
switch {
case t > 0.5:
tile = roveapi.Tile_Gravel
case t > 0.05:
tile = roveapi.Tile_Sand
default:
tile = roveapi.Tile_Rock
}
c.Tiles[j*a.ChunkSize+i] = byte(tile)
// Set the tile
c.Tiles[j*a.ChunkSize+i] = byte(a.worldGen.GetTile(loc))
// Get the object noise value for this location
o := a.objectNoise.Eval2(float64(origin.X+i)/objectNoiseScale, float64(origin.Y+j)/objectNoiseScale)
var obj = roveapi.Object_ObjectUnknown
switch {
case o > 0.6:
obj = roveapi.Object_RockLarge
case o > 0.5:
obj = roveapi.Object_RockSmall
}
if obj != roveapi.Object_ObjectUnknown {
c.Objects[j*a.ChunkSize+i] = Object{Type: roveapi.Object(obj)}
// Set the object
obj := a.worldGen.GetObject(loc)
if obj.Type != roveapi.Object_ObjectUnknown {
c.Objects[j*a.ChunkSize+i] = obj
}
}
}
@ -236,12 +213,11 @@ func (a *chunkBasedAtlas) worldSpaceToChunkWithGrow(v maths.Vector) int {
// Create the new empty atlas
newAtlas := chunkBasedAtlas{
ChunkSize: a.ChunkSize,
LowerBound: lower,
UpperBound: upper,
Chunks: make([]chunk, size.X*size.Y),
terrainNoise: a.terrainNoise,
objectNoise: a.objectNoise,
ChunkSize: a.ChunkSize,
LowerBound: lower,
UpperBound: upper,
Chunks: make([]chunk, size.X*size.Y),
worldGen: a.worldGen,
}
// Log that we're resizing

64
pkg/atlas/worldgen.go Normal file
View file

@ -0,0 +1,64 @@
package atlas
import (
"github.com/mdiluz/rove/pkg/maths"
"github.com/mdiluz/rove/proto/roveapi"
"github.com/ojrac/opensimplex-go"
)
// WorldGen describes a world gen algorythm
type WorldGen interface {
// GetTile generates a tile for a location
GetTile(v maths.Vector) roveapi.Tile
// GetObject generates an object for a location
GetObject(v maths.Vector) Object
}
// NoiseWorldGen returns a noise based world generator
type NoiseWorldGen struct {
// terrainNoise describes the noise function for the terrain
terrainNoise opensimplex.Noise
// terrainNoise describes the noise function for the terrain
objectNoise opensimplex.Noise
}
// NewNoiseWorldGen creates a new noise based world generator
func NewNoiseWorldGen(seed int64) WorldGen {
return &NoiseWorldGen{
terrainNoise: opensimplex.New(seed),
objectNoise: opensimplex.New(seed),
}
}
const (
terrainNoiseScale = 6
objectNoiseScale = 3
)
// GetTile returns the chosen tile at a location
func (g *NoiseWorldGen) GetTile(v maths.Vector) roveapi.Tile {
t := g.terrainNoise.Eval2(float64(v.X)/terrainNoiseScale, float64(v.Y)/terrainNoiseScale)
switch {
case t > 0.5:
return roveapi.Tile_Gravel
case t > 0.05:
return roveapi.Tile_Sand
default:
return roveapi.Tile_Rock
}
}
// GetObject returns the chosen object at a location
func (g *NoiseWorldGen) GetObject(v maths.Vector) Object {
o := g.objectNoise.Eval2(float64(v.X)/objectNoiseScale, float64(v.Y)/objectNoiseScale)
var obj = roveapi.Object_ObjectUnknown
switch {
case o > 0.6:
obj = roveapi.Object_RockLarge
case o > 0.5:
obj = roveapi.Object_RockSmall
}
return Object{Type: roveapi.Object(obj)}
}