Sander Schobers
44aef25d34
Inversed zoom on projection (previously how much smaller the content would be, now it is the magnification).
186 lines
5.0 KiB
Go
186 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 = PtPtr(e.X, e.Y)
|
|
} else if !r.interact.mouseLeftDown && r.interact.mouseDrag != nil {
|
|
r.interact.mouseDrag = nil
|
|
}
|
|
}
|
|
case *sdl.MouseMotionEvent:
|
|
if r.project.windowRect.IsPointInside(e.X, e.Y) {
|
|
hover := r.project.screenToMap(e.X, e.Y)
|
|
r.hover = PtPtr(int32(Round32(hover.X)), 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 = PtPtr(e.X, e.Y)
|
|
}
|
|
case *sdl.MouseWheelEvent:
|
|
if r.hover != nil {
|
|
zoom := r.project.zoom
|
|
if e.Y < 0 && r.project.zoom > .25 {
|
|
zoom *= .5
|
|
} else if e.Y > 0 && r.project.zoom < 2 {
|
|
zoom *= 2
|
|
}
|
|
if zoom != r.project.zoom {
|
|
hover := r.hover.ToPtF()
|
|
r.project.center = hover.Sub(hover.Sub(r.project.center).Mul(r.project.zoom / zoom))
|
|
r.project.zoom = zoom
|
|
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(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})
|
|
// }
|
|
// }
|
|
}
|