2020-05-09 11:55:37 +00:00
|
|
|
package tins2020
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/veandco/go-sdl2/sdl"
|
|
|
|
)
|
|
|
|
|
|
|
|
type terrainRenderer struct {
|
2020-05-10 18:44:20 +00:00
|
|
|
game *Game
|
2020-05-09 11:55:37 +00:00
|
|
|
terrain *Map
|
2020-05-09 22:19:44 +00:00
|
|
|
hover *Point
|
2020-05-09 11:55:37 +00:00
|
|
|
project projection
|
|
|
|
|
2020-05-10 18:44:20 +00:00
|
|
|
drag Drageable
|
2020-05-09 11:55:37 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 18:44:20 +00:00
|
|
|
type Drageable struct {
|
|
|
|
start *Point
|
|
|
|
dragged bool
|
2020-05-09 11:55:37 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 18:44:20 +00:00
|
|
|
func (d *Drageable) Cancel() { d.start = nil }
|
|
|
|
|
|
|
|
func (d *Drageable) IsDragging() bool { return d.start != nil }
|
|
|
|
|
|
|
|
func (d *Drageable) HasDragged() bool { return d.dragged }
|
|
|
|
|
|
|
|
func (d *Drageable) Move(p Point) Point {
|
|
|
|
delta := p.Sub(*d.start)
|
|
|
|
d.start = &p
|
|
|
|
d.dragged = true
|
|
|
|
return delta
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Drageable) Start(p Point) {
|
|
|
|
d.start = &p
|
|
|
|
d.dragged = false
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewTerrainRenderer(game *Game) Control {
|
|
|
|
return &terrainRenderer{game: game, terrain: game.Terrain, project: newProjection()}
|
2020-05-09 11:55:37 +00:00
|
|
|
}
|
|
|
|
|
2020-05-10 15:16:18 +00:00
|
|
|
func (r *terrainRenderer) Arrange(ctx *Context, _ Rectangle) {
|
|
|
|
r.project.update(ctx.Renderer)
|
|
|
|
}
|
|
|
|
|
2020-05-09 11:55:37 +00:00
|
|
|
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:
|
2020-05-10 15:16:18 +00:00
|
|
|
if r.project.windowInteractRect.IsPointInside(e.X, e.Y) {
|
2020-05-10 18:44:20 +00:00
|
|
|
switch e.Button {
|
|
|
|
case sdl.BUTTON_LEFT:
|
|
|
|
down := e.Type == sdl.MOUSEBUTTONDOWN
|
|
|
|
if down && !r.drag.IsDragging() {
|
|
|
|
r.drag.Start(Pt(e.X, e.Y))
|
|
|
|
} else if !down && r.drag.IsDragging() {
|
|
|
|
r.drag.Cancel()
|
|
|
|
}
|
|
|
|
if e.Type == sdl.MOUSEBUTTONUP && !r.drag.HasDragged() {
|
|
|
|
pos := r.project.screenToMapInt(e.X, e.Y)
|
|
|
|
r.game.UserClickedTile(pos)
|
|
|
|
}
|
|
|
|
case sdl.BUTTON_RIGHT:
|
|
|
|
if e.Type == sdl.MOUSEBUTTONDOWN {
|
|
|
|
r.game.CancelTool()
|
2020-05-10 15:16:18 +00:00
|
|
|
}
|
2020-05-09 11:55:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case *sdl.MouseMotionEvent:
|
2020-05-10 15:16:18 +00:00
|
|
|
if r.project.windowInteractRect.IsPointInside(e.X, e.Y) {
|
2020-05-10 18:44:20 +00:00
|
|
|
hover := r.project.screenToMapInt(e.X, e.Y)
|
|
|
|
r.hover = &hover
|
2020-05-09 22:19:44 +00:00
|
|
|
} else {
|
|
|
|
r.hover = nil
|
|
|
|
}
|
2020-05-10 18:44:20 +00:00
|
|
|
if r.drag.IsDragging() {
|
|
|
|
delta := r.drag.Move(Pt(e.X, e.Y))
|
|
|
|
r.project.center = r.project.center.Sub(r.project.screenToMapRel(delta.X, delta.Y))
|
2020-05-09 11:55:37 +00:00
|
|
|
r.project.update(ctx.Renderer)
|
|
|
|
}
|
|
|
|
case *sdl.MouseWheelEvent:
|
2020-05-10 10:40:44 +00:00
|
|
|
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
|
2020-05-10 10:21:51 +00:00
|
|
|
r.project.update(ctx.Renderer)
|
|
|
|
}
|
2020-05-09 11:55:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *terrainRenderer) Render(ctx *Context) {
|
2020-05-09 20:50:11 +00:00
|
|
|
toTileTexture := func(x, y int32) *Texture {
|
|
|
|
temp := r.terrain.Temp.Value(x, y)
|
2020-05-09 11:55:37 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2020-05-09 17:34:43 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2020-05-10 08:56:20 +00:00
|
|
|
// horizontal: [0, 128) = 128
|
|
|
|
// vertical (tile): [96,160) = 64
|
|
|
|
// vertical (total): [0,160) = 160
|
2020-05-09 11:55:37 +00:00
|
|
|
|
2020-05-09 14:48:39 +00:00
|
|
|
r.project.visibleTiles(func(x, y int32, pos Point) {
|
2020-05-09 20:50:11 +00:00
|
|
|
text := toTileTexture(x, y)
|
2020-05-09 14:48:39 +00:00
|
|
|
rect := r.project.screenToTileRect(pos)
|
2020-05-10 15:16:18 +00:00
|
|
|
text.CopyResize(ctx.Renderer, rect)
|
2020-05-09 20:50:11 +00:00
|
|
|
|
2020-05-09 22:19:44 +00:00
|
|
|
if r.hover != nil && x == r.hover.X && y == r.hover.Y {
|
2020-05-10 15:16:18 +00:00
|
|
|
ctx.Textures.Texture("tile-hover").CopyResize(ctx.Renderer, rect)
|
2020-05-09 20:50:11 +00:00
|
|
|
}
|
2020-05-09 14:48:39 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
r.project.visibleTiles(func(x, y int32, pos Point) {
|
2020-05-09 17:34:43 +00:00
|
|
|
text := toItemTexture(x, y)
|
2020-05-09 14:48:39 +00:00
|
|
|
if text == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
placeX, placeY := r.terrain.PlaceX.Value(x, y), r.terrain.PlaceY.Value(x, y)
|
2020-05-09 20:50:11 +00:00
|
|
|
pos = r.project.mapToScreenF(float32(x)-.2+float32(.9*placeX-.45), float32(y)-.2+float32(.9*placeY-.45))
|
2020-05-10 15:16:18 +00:00
|
|
|
text.CopyResize(ctx.Renderer, r.project.screenToTileRect(pos))
|
2020-05-09 14:48:39 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
// 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})
|
|
|
|
// }
|
|
|
|
// }
|
2020-05-09 11:55:37 +00:00
|
|
|
}
|