diff --git a/cmd/tins2020/res/images/cactus_short_NE.png b/cmd/tins2020/res/images/cactus_short_NE.png new file mode 100644 index 0000000..868501b Binary files /dev/null and b/cmd/tins2020/res/images/cactus_short_NE.png differ diff --git a/cmd/tins2020/res/images/cactus_short_NW.png b/cmd/tins2020/res/images/cactus_short_NW.png new file mode 100644 index 0000000..519219a Binary files /dev/null and b/cmd/tins2020/res/images/cactus_short_NW.png differ diff --git a/cmd/tins2020/res/images/cactus_short_SE.png b/cmd/tins2020/res/images/cactus_short_SE.png new file mode 100644 index 0000000..2fdd423 Binary files /dev/null and b/cmd/tins2020/res/images/cactus_short_SE.png differ diff --git a/cmd/tins2020/res/images/cactus_short_SW.png b/cmd/tins2020/res/images/cactus_short_SW.png new file mode 100644 index 0000000..5fcd84c Binary files /dev/null and b/cmd/tins2020/res/images/cactus_short_SW.png differ diff --git a/cmd/tins2020/res/images/cactus_tall_NE.png b/cmd/tins2020/res/images/cactus_tall_NE.png new file mode 100644 index 0000000..56f8228 Binary files /dev/null and b/cmd/tins2020/res/images/cactus_tall_NE.png differ diff --git a/cmd/tins2020/res/images/cactus_tall_NW.png b/cmd/tins2020/res/images/cactus_tall_NW.png new file mode 100644 index 0000000..3ce288d Binary files /dev/null and b/cmd/tins2020/res/images/cactus_tall_NW.png differ diff --git a/cmd/tins2020/res/images/cactus_tall_SE.png b/cmd/tins2020/res/images/cactus_tall_SE.png new file mode 100644 index 0000000..e358c89 Binary files /dev/null and b/cmd/tins2020/res/images/cactus_tall_SE.png differ diff --git a/cmd/tins2020/res/images/cactus_tall_SW.png b/cmd/tins2020/res/images/cactus_tall_SW.png new file mode 100644 index 0000000..4aa12fd Binary files /dev/null and b/cmd/tins2020/res/images/cactus_tall_SW.png differ diff --git a/cmd/tins2020/res/images/grass_NE.png b/cmd/tins2020/res/images/grass_NE.png new file mode 100644 index 0000000..df6feaa Binary files /dev/null and b/cmd/tins2020/res/images/grass_NE.png differ diff --git a/cmd/tins2020/res/images/grass_NW.png b/cmd/tins2020/res/images/grass_NW.png new file mode 100644 index 0000000..1aaf997 Binary files /dev/null and b/cmd/tins2020/res/images/grass_NW.png differ diff --git a/cmd/tins2020/res/images/grass_SE.png b/cmd/tins2020/res/images/grass_SE.png new file mode 100644 index 0000000..30793dd Binary files /dev/null and b/cmd/tins2020/res/images/grass_SE.png differ diff --git a/cmd/tins2020/res/images/grass_SW.png b/cmd/tins2020/res/images/grass_SW.png new file mode 100644 index 0000000..6901057 Binary files /dev/null and b/cmd/tins2020/res/images/grass_SW.png differ diff --git a/cmd/tins2020/res/images/grass_leafs_NE.png b/cmd/tins2020/res/images/grass_leafs_NE.png new file mode 100644 index 0000000..475ae3c Binary files /dev/null and b/cmd/tins2020/res/images/grass_leafs_NE.png differ diff --git a/cmd/tins2020/res/images/grass_leafs_NW.png b/cmd/tins2020/res/images/grass_leafs_NW.png new file mode 100644 index 0000000..ba7a9f2 Binary files /dev/null and b/cmd/tins2020/res/images/grass_leafs_NW.png differ diff --git a/cmd/tins2020/res/images/grass_leafs_SE.png b/cmd/tins2020/res/images/grass_leafs_SE.png new file mode 100644 index 0000000..ae728ea Binary files /dev/null and b/cmd/tins2020/res/images/grass_leafs_SE.png differ diff --git a/cmd/tins2020/res/images/grass_leafs_SW.png b/cmd/tins2020/res/images/grass_leafs_SW.png new file mode 100644 index 0000000..ca22418 Binary files /dev/null and b/cmd/tins2020/res/images/grass_leafs_SW.png differ diff --git a/cmd/tins2020/res/images/plant_bushLarge_NE.png b/cmd/tins2020/res/images/plant_bushLarge_NE.png new file mode 100644 index 0000000..62b7c4a Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushLarge_NE.png differ diff --git a/cmd/tins2020/res/images/plant_bushLarge_NW.png b/cmd/tins2020/res/images/plant_bushLarge_NW.png new file mode 100644 index 0000000..3260225 Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushLarge_NW.png differ diff --git a/cmd/tins2020/res/images/plant_bushLarge_SE.png b/cmd/tins2020/res/images/plant_bushLarge_SE.png new file mode 100644 index 0000000..a78294a Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushLarge_SE.png differ diff --git a/cmd/tins2020/res/images/plant_bushLarge_SW.png b/cmd/tins2020/res/images/plant_bushLarge_SW.png new file mode 100644 index 0000000..1fe2d3d Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushLarge_SW.png differ diff --git a/cmd/tins2020/res/images/plant_bushSmall_NE.png b/cmd/tins2020/res/images/plant_bushSmall_NE.png new file mode 100644 index 0000000..d5c4025 Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushSmall_NE.png differ diff --git a/cmd/tins2020/res/images/plant_bushSmall_NW.png b/cmd/tins2020/res/images/plant_bushSmall_NW.png new file mode 100644 index 0000000..5e58d5b Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushSmall_NW.png differ diff --git a/cmd/tins2020/res/images/plant_bushSmall_SE.png b/cmd/tins2020/res/images/plant_bushSmall_SE.png new file mode 100644 index 0000000..5e58d5b Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushSmall_SE.png differ diff --git a/cmd/tins2020/res/images/plant_bushSmall_SW.png b/cmd/tins2020/res/images/plant_bushSmall_SW.png new file mode 100644 index 0000000..d5c4025 Binary files /dev/null and b/cmd/tins2020/res/images/plant_bushSmall_SW.png differ diff --git a/cmd/tins2020/res/images/dirt.png b/cmd/tins2020/res/images/tile_dirt.png similarity index 100% rename from cmd/tins2020/res/images/dirt.png rename to cmd/tins2020/res/images/tile_dirt.png diff --git a/cmd/tins2020/res/images/grass.png b/cmd/tins2020/res/images/tile_grass.png similarity index 100% rename from cmd/tins2020/res/images/grass.png rename to cmd/tins2020/res/images/tile_grass.png diff --git a/cmd/tins2020/res/images/snow.png b/cmd/tins2020/res/images/tile_snow.png similarity index 100% rename from cmd/tins2020/res/images/snow.png rename to cmd/tins2020/res/images/tile_snow.png diff --git a/cmd/tins2020/res/images/tree_fat_NE.png b/cmd/tins2020/res/images/tree_fat_NE.png new file mode 100644 index 0000000..f35a819 Binary files /dev/null and b/cmd/tins2020/res/images/tree_fat_NE.png differ diff --git a/cmd/tins2020/res/images/tree_fat_NW.png b/cmd/tins2020/res/images/tree_fat_NW.png new file mode 100644 index 0000000..66861e8 Binary files /dev/null and b/cmd/tins2020/res/images/tree_fat_NW.png differ diff --git a/cmd/tins2020/res/images/tree_fat_SE.png b/cmd/tins2020/res/images/tree_fat_SE.png new file mode 100644 index 0000000..66861e8 Binary files /dev/null and b/cmd/tins2020/res/images/tree_fat_SE.png differ diff --git a/cmd/tins2020/res/images/tree_fat_SW.png b/cmd/tins2020/res/images/tree_fat_SW.png new file mode 100644 index 0000000..f35a819 Binary files /dev/null and b/cmd/tins2020/res/images/tree_fat_SW.png differ diff --git a/cmd/tins2020/res/images/tree_pineDefaultA_NE.png b/cmd/tins2020/res/images/tree_pineDefaultA_NE.png new file mode 100644 index 0000000..50781cf Binary files /dev/null and b/cmd/tins2020/res/images/tree_pineDefaultA_NE.png differ diff --git a/cmd/tins2020/res/images/tree_pineDefaultA_NW.png b/cmd/tins2020/res/images/tree_pineDefaultA_NW.png new file mode 100644 index 0000000..5fd449a Binary files /dev/null and b/cmd/tins2020/res/images/tree_pineDefaultA_NW.png differ diff --git a/cmd/tins2020/res/images/tree_pineDefaultA_SE.png b/cmd/tins2020/res/images/tree_pineDefaultA_SE.png new file mode 100644 index 0000000..74678b2 Binary files /dev/null and b/cmd/tins2020/res/images/tree_pineDefaultA_SE.png differ diff --git a/cmd/tins2020/res/images/tree_pineDefaultA_SW.png b/cmd/tins2020/res/images/tree_pineDefaultA_SW.png new file mode 100644 index 0000000..d40bac6 Binary files /dev/null and b/cmd/tins2020/res/images/tree_pineDefaultA_SW.png differ diff --git a/cmd/tins2020/terrainrenderer.go b/cmd/tins2020/terrainrenderer.go deleted file mode 100644 index bea8915..0000000 --- a/cmd/tins2020/terrainrenderer.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - "github.com/veandco/go-sdl2/sdl" - "opslag.de/schobers/tins2020" -) - -type terrainRenderer struct { - terrain *tins2020.Map - center tins2020.PointF - zoom float32 -} - -func newTerrainRenderer(terrain *tins2020.Map) *terrainRenderer { - return &terrainRenderer{terrain: terrain} -} - -func (r *terrainRenderer) Render(ctx *tins2020.Context) { - tempToTexture := func(temp float64) *tins2020.Texture { - if temp < .2 { - return ctx.Textures.Texture("snow") - } - if temp > .8 { - return ctx.Textures.Texture("dirt") - } - return ctx.Textures.Texture("grass") - } - - // horizontal: [191, 321) = 130 - // vertical: [267,332) = 65 - - for y := int32(0); y < 10; y++ { - left := -y * 65 - top := y * 32 - for x := int32(0); x < 10; x++ { - temp := r.terrain.Temp.Value(int(x), int(y)) - text := tempToTexture(temp) - text.Copy(ctx.Renderer, &sdl.Rect{X: left + x*65, Y: top + x*32, W: 512, H: 512}) - } - } -} diff --git a/cmd/tins2020/tins2020.go b/cmd/tins2020/tins2020.go index 56e67b5..49d77f9 100644 --- a/cmd/tins2020/tins2020.go +++ b/cmd/tins2020/tins2020.go @@ -28,7 +28,7 @@ func run() error { } defer sdl.Quit() - logSDLVersion() + // logSDLVersion() if err := ttf.Init(); err != nil { return err @@ -69,24 +69,66 @@ func run() error { return err } err = ctx.Textures.Load( - "dirt", "images/dirt.png", - "grass", "images/grass.png", - "snow", "images/snow.png", + "tile-dirt", "images/tile_dirt.png", + "tile-grass", "images/tile_grass.png", + "tile-snow", "images/tile_snow.png", + + "cactus-small-1", "images/cactus_short_NE.png", + "cactus-small-2", "images/cactus_short_NW.png", + "cactus-small-3", "images/cactus_short_SW.png", + "cactus-small-4", "images/cactus_short_SE.png", + + "cactus-tall-1", "images/cactus_tall_NE.png", + "cactus-tall-2", "images/cactus_tall_NW.png", + "cactus-tall-3", "images/cactus_tall_SW.png", + "cactus-tall-4", "images/cactus_tall_SE.png", + + "tree-fat-1", "images/tree_fat_NE.png", + "tree-fat-2", "images/tree_fat_NW.png", + "tree-fat-3", "images/tree_fat_SW.png", + "tree-fat-4", "images/tree_fat_SE.png", + + "tree-pine-1", "images/tree_pineDefaultA_NE.png", + "tree-pine-2", "images/tree_pineDefaultA_NW.png", + "tree-pine-3", "images/tree_pineDefaultA_SW.png", + "tree-pine-4", "images/tree_pineDefaultA_SE.png", + + "grass-small-1", "images/grass_NE.png", + "grass-small-2", "images/grass_NW.png", + "grass-small-3", "images/grass_SW.png", + "grass-small-4", "images/grass_SE.png", + + "grass-leafs-1", "images/grass_leafs_NE.png", + "grass-leafs-2", "images/grass_leafs_NW.png", + "grass-leafs-3", "images/grass_leafs_SW.png", + "grass-leafs-4", "images/grass_leafs_SE.png", + + "bush-small-1", "images/plant_bushSmall_NE.png", + "bush-small-2", "images/plant_bushSmall_NW.png", + "bush-small-3", "images/plant_bushSmall_SW.png", + "bush-small-4", "images/plant_bushSmall_SE.png", + + "bush-large-1", "images/plant_bushLarge_NE.png", + "bush-large-2", "images/plant_bushLarge_NW.png", + "bush-large-3", "images/plant_bushLarge_SW.png", + "bush-large-4", "images/plant_bushLarge_SE.png", ) if err != nil { return err } game := tins2020.NewGame() - tr := newTerrainRenderer(game.Terrain) + control := tins2020.NewTerrainRenderer(game.Terrain) + err = control.Init(ctx) + if err != nil { + return err + } - running := true - for running { + for { for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() { switch e := event.(type) { case *sdl.QuitEvent: - println("Quit") - running = false + ctx.Quit() break case *sdl.WindowEvent: switch e.Event { @@ -94,17 +136,22 @@ func run() error { x, y := window.GetPosition() ctx.Settings.Window.Location = &tins2020.Point{X: x, Y: y} } + case *sdl.KeyboardEvent: + switch e.Keysym.Sym { + case sdl.K_ESCAPE: + ctx.Quit() + } } + control.Handle(ctx, event) + } + + if ctx.ShouldQuit { + break } renderer.SetDrawColor(0, 0, 0, 255) renderer.Clear() - // renderer.SetDrawColor(255, 0, 0, 255) - // renderer.FillRect(&sdl.Rect{0, 0, 200, 200}) - // ctx.Textures.Texture("grass").Copy(renderer, &sdl.Rect{X: 200, Y: 100, W: 456, H: 356}) - // ctx.Textures.Texture("dirt").Copy(renderer, &sdl.Rect{X: 143, Y: 122, W: 456, H: 356}) - // ctx.Textures.Texture("snow").Copy(renderer, &sdl.Rect{X: 257, Y: 122, W: 456, H: 356}) - tr.Render(ctx) + control.Render(ctx) renderer.Present() } return nil diff --git a/context.go b/context.go index a903a74..b61b152 100644 --- a/context.go +++ b/context.go @@ -6,11 +6,12 @@ import ( ) type Context struct { - Renderer *sdl.Renderer - Fonts Fonts - Resources Resources - Textures Textures - Settings Settings + Renderer *sdl.Renderer + Fonts Fonts + Resources Resources + Textures Textures + Settings Settings + ShouldQuit bool } func NewContext(res *rice.Box) (*Context, error) { @@ -26,15 +27,17 @@ func NewContext(res *rice.Box) (*Context, error) { return ctx, nil } -func (c *Context) Init(renderer *sdl.Renderer) { - c.Renderer = renderer - c.Fonts.Init(c.Resources.Copy()) - c.Textures.Init(renderer, c.Resources.Copy()) -} - func (c *Context) Destroy() { c.Fonts.Destroy() c.Resources.Destroy() c.Textures.Destroy() c.Settings.Store() } + +func (c *Context) Init(renderer *sdl.Renderer) { + c.Renderer = renderer + c.Fonts.Init(c.Resources.Copy()) + c.Textures.Init(renderer, c.Resources.Copy()) +} + +func (c *Context) Quit() { c.ShouldQuit = true } diff --git a/game.go b/game.go index 1225279..61db4d8 100644 --- a/game.go +++ b/game.go @@ -13,33 +13,69 @@ type Game struct { } type Map struct { - Temp *NoiseMap - Humid *NoiseMap + Temp NoiseMap + Humid NoiseMap + Variant NoiseMap + PlaceX NoiseMap // displacement map of props + PlaceY NoiseMap } -type NoiseMap struct { +type NoiseMap interface { + Value(x, y int32) float64 +} + +func NewNoiseMap(seed int64) NoiseMap { + return &noiseMap{ + noise: noise.NewPerlin(seed), + alpha: 2, + beta: 4, + harmonics: 2, + } +} + +func NewRandomNoiseMap(seed int64) NoiseMap { + return &randomNoiseMap{noise.NewPerlin(seed)} +} + +type noiseMap struct { noise *noise.Perlin alpha, beta float64 harmonics int } -func NewNoiseMap(seed int64) *NoiseMap { - return &NoiseMap{ - noise: noise.NewPerlin(seed), - alpha: 2, - beta: 2.13, - harmonics: 4, +func clipNormalized(x float64) float64 { + if x < 0 { + return 0 } + if x > 1 { + return 1 + } + return x } -func (m *NoiseMap) Value(x, y int) float64 { - return m.noise.Noise2D(float64(x), float64(y), m.alpha, m.beta, m.harmonics) +// Value generates the noise value for an x/y pair. The range of the output is approximately [-1.325825214,1.325825214] (for 4 harmonics). +func (m *noiseMap) Value(x, y int32) float64 { + value := m.noise.Noise2D(float64(x)*.01, float64(y)*.01, m.alpha, m.beta, m.harmonics)*.565 + .5 + return clipNormalized(value) +} + +type randomNoiseMap struct { + *noise.Perlin +} + +// Value generates the noise value for an x/y pair. The range of the output is approximately [-1.325825214,1.325825214] (for 4 harmonics). +func (m randomNoiseMap) Value(x, y int32) float64 { + value := m.Noise2D(float64(x)*.53, float64(y)*.53, 1.01, 2, 2)*.5 + .5 + return clipNormalized(value) } func NewGame() *Game { terrain := &Map{ - Temp: NewNoiseMap(rand.Int63()), - Humid: NewNoiseMap(rand.Int63()), + Temp: NewNoiseMap(rand.Int63()), + Humid: NewNoiseMap(rand.Int63()), + Variant: NewRandomNoiseMap(rand.Int63()), + PlaceX: NewRandomNoiseMap(rand.Int63()), + PlaceY: NewRandomNoiseMap(rand.Int63()), } return &Game{ Terrain: terrain, @@ -48,10 +84,6 @@ func NewGame() *Game { } } -type PointF struct { - X, Y float32 -} - type Flower struct { Location PointF } diff --git a/point.go b/point.go index 66a5f0b..4eb3018 100644 --- a/point.go +++ b/point.go @@ -1,6 +1,18 @@ package tins2020 type Point struct { - X int32 - Y int32 + X, Y int32 } + +func (p Point) Add(q Point) Point { return Pt(p.X+q.X, p.Y+q.Y) } + +type PointF struct { + X, Y float32 +} + +func (p PointF) Add(q PointF) PointF { return PtF(p.X+q.X, p.Y+q.Y) } + +func (p PointF) Sub(q PointF) PointF { return PtF(p.X-q.X, p.Y-q.Y) } + +func Pt(x, y int32) Point { return Point{x, y} } +func PtF(x, y float32) PointF { return PointF{x, y} } diff --git a/renderer.go b/renderer.go new file mode 100644 index 0000000..7d35246 --- /dev/null +++ b/renderer.go @@ -0,0 +1,9 @@ +package tins2020 + +import "github.com/veandco/go-sdl2/sdl" + +type Control interface { + Init(*Context) error + Handle(*Context, sdl.Event) + Render(*Context) +} diff --git a/terrainrenderer.go b/terrainrenderer.go new file mode 100644 index 0000000..2971e67 --- /dev/null +++ b/terrainrenderer.go @@ -0,0 +1,225 @@ +package tins2020 + +import ( + "fmt" + "log" + + "opslag.de/schobers/geom" + + "github.com/veandco/go-sdl2/sdl" +) + +type terrainRenderer struct { + terrain *Map + hover PointF + project projection + + interact interaction +} + +type interaction struct { + mousePos Point + mouseLeftDown bool + mouseDrag *Point +} + +type projection struct { + center PointF + zoom float32 + zoomInv float32 + + tileScreenDelta PointF + tileScreenDeltaInv PointF + tileScreenOffset Point + tileScreenSize Point + windowCenter Point +} + +func newProjection() projection { + return projection{zoom: 1, tileScreenDelta: PtF(65, 32), tileScreenDeltaInv: PtF(1./65, 1./32)} +} + +func (p *projection) update(renderer *sdl.Renderer) { + p.zoomInv = 1 / p.zoom + + p.tileScreenOffset = Pt(int32(p.zoomInv*256), int32(p.zoomInv*300)) + p.tileScreenSize = Pt(int32(p.zoomInv*512), int32(p.zoomInv*512)) + + windowW, windowH, err := renderer.GetOutputSize() + if err != nil { + log.Fatal(err) + } + p.windowCenter = Pt(windowW/2, windowH/2) +} + +func (p *projection) mapToScreen(x, y int32) Point { + return p.mapToScreenF(float32(x), float32(y)) +} + +func (p *projection) mapToScreenF(x, y float32) Point { + translated := PtF(x-p.center.X, y-p.center.Y) + return Pt(p.windowCenter.X+int32((translated.X-translated.Y)*65*p.zoomInv), p.windowCenter.Y+int32((translated.X+translated.Y)*32*p.zoomInv)) +} + +func (p *projection) screenToMapRel(x, y int32) PointF { + normX := p.zoom * float32(x) + normY := p.zoom * float32(y) + return PtF(.5*(p.tileScreenDeltaInv.X*normX+p.tileScreenDeltaInv.Y*normY), .5*(-p.tileScreenDeltaInv.X*normX+p.tileScreenDeltaInv.Y*normY)) +} + +func (p *projection) screenToMap(x, y int32) PointF { + pos := p.screenToMapRel(x-p.windowCenter.X, y-p.windowCenter.Y) + return p.center.Add(pos) +} + +func (p *projection) screenToTileRect(pos Point) *sdl.Rect { + return &sdl.Rect{X: pos.X - p.tileScreenOffset.X, Y: pos.Y - p.tileScreenOffset.Y, W: p.tileScreenSize.X, H: p.tileScreenSize.Y} +} + +func NewTerrainRenderer(terrain *Map) Control { + return &terrainRenderer{terrain: terrain, project: newProjection()} +} + +func (r *terrainRenderer) Init(ctx *Context) error { + r.project.update(ctx.Renderer) + return nil +} + +func (r *terrainRenderer) Handle(ctx *Context, event sdl.Event) { + switch e := event.(type) { + case *sdl.MouseButtonEvent: + if e.Button == sdl.BUTTON_LEFT { + r.interact.mouseLeftDown = e.Type == sdl.MOUSEBUTTONDOWN + if r.interact.mouseLeftDown && r.interact.mouseDrag == nil { + r.interact.mouseDrag = &Point{e.X, e.Y} + fmt.Println("Drag start", r.interact.mouseDrag) + } else if !r.interact.mouseLeftDown && r.interact.mouseDrag != nil { + fmt.Println("Drag end", r.interact.mouseDrag) + r.interact.mouseDrag = nil + } + } + case *sdl.MouseMotionEvent: + r.hover = r.project.screenToMap(e.X, e.Y) + if r.interact.mouseDrag != nil { + fmt.Println("Dragging...", r.project.center) + r.project.center = r.project.center.Sub(r.project.screenToMapRel(e.X-r.interact.mouseDrag.X, e.Y-r.interact.mouseDrag.Y)) + r.project.update(ctx.Renderer) + r.interact.mouseDrag = &Point{e.X, e.Y} + } + case *sdl.MouseWheelEvent: + if e.Y > 0 { + r.project.zoom *= .5 + r.project.update(ctx.Renderer) + } else if e.Y < 0 { + r.project.zoom *= 2 + r.project.update(ctx.Renderer) + } + case *sdl.WindowEvent: + if e.Event == sdl.WINDOWEVENT_RESIZED { + r.project.update(ctx.Renderer) + } + } +} + +func (r *terrainRenderer) Render(ctx *Context) { + toTileTexture := func(temp, humid float64) *Texture { + if temp < .35 { + return ctx.Textures.Texture("tile-snow") + } + if temp > .65 { + return ctx.Textures.Texture("tile-dirt") + } + return ctx.Textures.Texture("tile-grass") + } + + variantToInt := func(variant float64) int { + if variant < .25 { + return 1 + } + if variant < .5 { + return 2 + } + if variant < .75 { + return 3 + } + if variant < 1 { + return 4 + } + return -1 + } + + variantToTexture := func(format string, variant float64) *Texture { + textName := fmt.Sprintf(format, variantToInt(variant)) + return ctx.Textures.Texture(textName) + } + + stretch := func(x, from, to float64) float64 { return (x - from) * 1 / (to - from) } + + toPropTexture := func(temp, humid, variant float64) *Texture { + if temp < .35 { + if humid < .2 { + return nil + } else if humid < .7 { + return variantToTexture("bush-small-%d", variant*5) + } + return variantToTexture("tree-pine-%d", variant*5) + } + if temp > .65 { + if humid < .2 { + return nil + } + if humid < .7 { + return variantToTexture("cactus-short-%d", variant*7) + } + return variantToTexture("cactus-tall-%d", variant*2) + } + if humid < .2 { + return nil + } + multiplier := 1 - stretch(humid, 0.2, 1) + if variant < .5 { + return variantToTexture("tree-fat-%d", stretch(variant, 0, .5)*multiplier*3) + } else if variant < .8 { + return variantToTexture("grass-small-%d", stretch(variant, .5, .8)*multiplier*2) + } + return variantToTexture("bush-large-%d", stretch(variant, .8, 1)*multiplier) + } + + // horizontal: [191, 321) = 130 + // vertical: [267,332) = 65 + + hover := Pt(int32(geom.Round32(r.hover.X)), int32(geom.Round32(r.hover.Y))) + for y := int32(-100); y < 100; y++ { + for x := int32(-100); x < 100; x++ { + if x == hover.X && y == hover.Y { + continue + } + temp := r.terrain.Temp.Value(x, y) + humid := r.terrain.Humid.Value(x, y) + text := toTileTexture(temp, humid) + pos := r.project.mapToScreen(x, y) + text.Copy(ctx.Renderer, r.project.screenToTileRect(pos)) + } + } + + for y := int32(-100); y < 100; y++ { + for x := int32(-100); x < 100; x++ { + variant := r.terrain.Variant.Value(x, y) + if variant < -1 || variant > 1 { + continue + } + + temp := r.terrain.Temp.Value(x, y) + humid := r.terrain.Humid.Value(x, y) + text := toPropTexture(temp, humid, variant) + if text == nil { + continue + } + + placeX, placeY := r.terrain.PlaceX.Value(x, y), r.terrain.PlaceY.Value(x, y) + pos := r.project.mapToScreenF(float32(x)-.2+float32(.8*placeX-.4), float32(y)-.2+float32(.8*placeY-.4)) + + text.Copy(ctx.Renderer, r.project.screenToTileRect(pos)) + } + } +}