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).
91 lines
3.0 KiB
Go
91 lines
3.0 KiB
Go
package tins2020
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/veandco/go-sdl2/sdl"
|
|
)
|
|
|
|
type projection struct {
|
|
center PointF
|
|
zoom float32
|
|
zoomInv float32
|
|
|
|
windowRect sdl.Rect
|
|
tileScreenDelta PointF
|
|
tileScreenDeltaInv PointF
|
|
tileScreenOffset Point
|
|
tileScreenSize Point
|
|
tileFitScreenSize Point
|
|
windowCenter Point
|
|
}
|
|
|
|
func newProjection() projection {
|
|
return projection{zoom: 1, tileScreenDelta: PtF(64, 32), tileScreenDeltaInv: PtF(1./64, 1./32)}
|
|
}
|
|
|
|
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)*64*p.zoomInv), p.windowCenter.Y+int32((translated.X+translated.Y)*32*p.zoomInv))
|
|
}
|
|
|
|
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) 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) screenToTileFitRect(pos Point) *sdl.Rect {
|
|
return &sdl.Rect{X: pos.X - p.tileFitScreenSize.X, Y: pos.Y - p.tileFitScreenSize.Y, W: 2 * p.tileFitScreenSize.X, H: 2 * p.tileFitScreenSize.Y}
|
|
}
|
|
|
|
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 (p *projection) update(renderer *sdl.Renderer) {
|
|
p.zoomInv = 1 / p.zoom
|
|
|
|
p.tileScreenOffset = Pt(int32(p.zoomInv*64), int32(p.zoomInv*112))
|
|
p.tileScreenSize = Pt(int32(p.zoomInv*128), int32(p.zoomInv*160))
|
|
p.tileFitScreenSize = Pt(int32(p.zoomInv*64), int32(p.zoomInv*32))
|
|
|
|
windowW, windowH, err := renderer.GetOutputSize()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
p.windowCenter = Pt(windowW/2, windowH/2)
|
|
p.windowRect = sdl.Rect{X: buttonBarWidth, Y: 0, W: windowW - 2*buttonBarWidth, H: windowH - 0}
|
|
}
|
|
|
|
func (p *projection) visibleTiles(action func(int32, int32, Point)) {
|
|
topLeft := p.screenToMap(p.windowRect.X, p.windowRect.Y)
|
|
topRight := p.screenToMap(p.windowRect.X+p.windowRect.W, p.windowRect.Y)
|
|
bottomLeft := p.screenToMap(p.windowRect.X, p.windowRect.Y+p.windowRect.H)
|
|
bottomRight := p.screenToMap(p.windowRect.X+p.windowRect.W, p.windowRect.Y+p.windowRect.H)
|
|
minY, maxY := int32(Floor32(topRight.Y)), int32(Ceil32(bottomLeft.Y))
|
|
minX, maxX := int32(Floor32(topLeft.X)), int32(Ceil32(bottomRight.X))
|
|
for y := minY; y <= maxY; y++ {
|
|
for x := minX; x <= maxX; x++ {
|
|
pos := p.mapToScreen(x, y)
|
|
rectFit := p.screenToTileFitRect(pos)
|
|
if rectFit.X+rectFit.W < p.windowRect.X || rectFit.Y+rectFit.H < p.windowRect.Y {
|
|
continue
|
|
}
|
|
if rectFit.X > p.windowRect.X+p.windowRect.W || rectFit.Y > p.windowRect.Y+p.windowRect.H {
|
|
break
|
|
}
|
|
action(x, y, pos)
|
|
}
|
|
}
|
|
}
|