Sander Schobers
69c8ae72f3
Textures used to be 512x512px, cropped them to 128x160px. The width of the texture was first cropped to 130px and then resized to 128px (height was not resized).
185 lines
5.0 KiB
Go
185 lines
5.0 KiB
Go
package tins2020
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/veandco/go-sdl2/sdl"
|
|
)
|
|
|
|
type terrainRenderer struct {
|
|
terrain *Map
|
|
hover *Point
|
|
project projection
|
|
|
|
interact interaction
|
|
}
|
|
|
|
type interaction struct {
|
|
mousePos Point
|
|
mouseLeftDown bool
|
|
mouseDrag *Point
|
|
}
|
|
|
|
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}
|
|
} else if !r.interact.mouseLeftDown && r.interact.mouseDrag != nil {
|
|
r.interact.mouseDrag = nil
|
|
}
|
|
}
|
|
case *sdl.MouseMotionEvent:
|
|
if insideRect(e.X, e.Y, &r.project.windowRect) {
|
|
hover := r.project.screenToMap(e.X, e.Y)
|
|
r.hover = &Point{X: int32(Round32(hover.X)), Y: int32(Round32(hover.Y))}
|
|
} else {
|
|
r.hover = nil
|
|
}
|
|
if r.interact.mouseDrag != nil {
|
|
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.zoom *= .5
|
|
r.project.update(ctx.Renderer)
|
|
} else if e.Y < 0 && r.project.zoom < 4 {
|
|
r.project.zoom *= 2
|
|
r.project.update(ctx.Renderer)
|
|
}
|
|
case *sdl.WindowEvent:
|
|
if e.Event == sdl.WINDOWEVENT_RESIZED {
|
|
r.project.update(ctx.Renderer)
|
|
}
|
|
}
|
|
}
|
|
|
|
func insideRect(x, y int32, rect *sdl.Rect) bool {
|
|
return x >= rect.X && x < rect.X+rect.W && y >= rect.Y && y < rect.Y+rect.H
|
|
}
|
|
|
|
func insideRectPt(p Point, rect *sdl.Rect) bool { return insideRect(p.X, p.Y, rect) }
|
|
|
|
func (r *terrainRenderer) Render(ctx *Context) {
|
|
toTileTexture := func(x, y int32) *Texture {
|
|
temp := r.terrain.Temp.Value(x, y)
|
|
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)
|
|
}
|
|
|
|
toItemTexture := func(x, y int32) *Texture {
|
|
variant := r.terrain.Variant.Value(x, y)
|
|
_, ok := r.terrain.Flowers[Pt(x, y)]
|
|
if ok {
|
|
return variantToTexture("flower-poppy-%d", variant)
|
|
}
|
|
temp := r.terrain.Temp.Value(x, y)
|
|
humid := r.terrain.Humid.Value(x, y)
|
|
return toPropTexture(temp, humid, variant)
|
|
}
|
|
|
|
// horizontal: [0, 128) = 128
|
|
// vertical (tile): [96,160) = 64
|
|
// vertical (total): [0,160) = 160
|
|
|
|
r.project.visibleTiles(func(x, y int32, pos Point) {
|
|
text := toTileTexture(x, y)
|
|
rect := r.project.screenToTileRect(pos)
|
|
text.Copy(ctx.Renderer, rect)
|
|
|
|
if r.hover != nil && x == r.hover.X && y == r.hover.Y {
|
|
ctx.Textures.Texture("tile-hover").Copy(ctx.Renderer, rect)
|
|
}
|
|
})
|
|
|
|
r.project.visibleTiles(func(x, y int32, pos Point) {
|
|
text := toItemTexture(x, y)
|
|
if text == nil {
|
|
return
|
|
}
|
|
|
|
placeX, placeY := r.terrain.PlaceX.Value(x, y), r.terrain.PlaceY.Value(x, y)
|
|
pos = r.project.mapToScreenF(float32(x)-.2+float32(.9*placeX-.45), float32(y)-.2+float32(.9*placeY-.45))
|
|
text.Copy(ctx.Renderer, r.project.screenToTileRect(pos))
|
|
})
|
|
|
|
// gfx.RectangleColor(ctx.Renderer, r.project.windowRect.X, r.project.windowRect.Y, r.project.windowRect.X+r.project.windowRect.W, r.project.windowRect.Y+r.project.windowRect.H, sdl.Color{R: 255, A: 255})
|
|
// for y := int32(-40); y < 40; y++ {
|
|
// for x := int32(-40); x < 40; x++ {
|
|
// pos := r.project.mapToScreen(x, y)
|
|
// ctx.Fonts.Font("debug").RenderCopy(ctx.Renderer, fmt.Sprintf("(%d, %d)", x, y), pos, sdl.Color{R: 255, A: 255})
|
|
// }
|
|
// }
|
|
}
|