Compare commits

..

No commits in common. "1cf13b0ec9656b101d30cbc21521de2e69f4429b" and "d6502c9080ec2d6fb4690bc9d360fbde8c0bd70e" have entirely different histories.

73 changed files with 70 additions and 339 deletions

View File

@ -1,72 +0,0 @@
package main
import (
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)
func atois(s ...string) ([]int, error) {
ints := make([]int, len(s))
for i, s := range s {
value, err := strconv.Atoi(s)
if err != nil {
return nil, fmt.Errorf("couldn't convert '%s' to a number; error: %v", s, err)
}
ints[i] = value
}
return ints, nil
}
func scanDir(dir string) ([]string, error) {
var files []string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if path == dir || info.IsDir() {
return nil
}
files = append(files, path)
return nil
})
if err != nil {
return nil, err
}
return files, nil
}
type point struct {
x, y int
}
func parsePoint(s string) (point, error) {
components := strings.Split(s, ",")
if len(components) != 2 {
return point{}, errors.New("expected two components separated by a comma")
}
ints, err := atois(components...)
if err != nil {
return point{}, err
}
return point{x: ints[0], y: ints[1]}, nil
}
type rect struct {
min, max point
}
func parseRect(s string) (rect, error) {
components := strings.Split(s, ",")
if len(components) != 4 {
return rect{}, errors.New("expected four components separated by a comma")
}
ints, err := atois(components...)
if err != nil {
return rect{}, err
}
return rect{min: point{x: ints[0], y: ints[1]}, max: point{x: ints[2], y: ints[3]}}, nil
}

View File

@ -1,25 +0,0 @@
package main
import (
"image"
"image/draw"
"github.com/nfnt/resize"
)
func crop(path string, crop rect, size *point) error {
src, err := decodeImage(path)
if err != nil {
return err
}
srcRect := image.Rect(crop.min.x, crop.min.y, crop.max.x, crop.max.y)
dstRect := image.Rect(0, 0, crop.max.x-crop.min.x, crop.max.y-crop.min.y)
dst := image.NewRGBA(dstRect)
draw.Draw(dst, dstRect, src, srcRect.Min, draw.Src)
if size == nil {
return encodePNG(path, dst)
}
resized := resize.Resize(uint(size.x), uint(size.y), dst, resize.Bilinear)
return encodePNG(path, resized)
}

View File

@ -1,29 +0,0 @@
package main
import (
"image"
"image/color"
)
func convertToGray(path string) error {
src, err := decodeImage(path)
if err != nil {
return err
}
bounds := src.Bounds()
dst := image.NewRGBA(bounds)
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
c := src.At(x, y)
rgba := color.NRGBAModel.Convert(c).(color.NRGBA)
if rgba.A > 0 {
gray := color.GrayModel.Convert(c).(color.Gray)
rgba.R, rgba.G, rgba.B = gray.Y, gray.Y, gray.Y
dst.Set(x, y, rgba)
} else {
dst.Set(x, y, c)
}
}
}
return encodePNG(path, dst)
}

View File

@ -4,7 +4,11 @@ import (
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"image"
"image/color"
"image/png"
"log" "log"
"os"
) )
func run() error { func run() error {
@ -29,52 +33,74 @@ func run() error {
flags := flag.NewFlagSet("gray", flag.ContinueOnError) flags := flag.NewFlagSet("gray", flag.ContinueOnError)
flags.Parse(args[1:]) flags.Parse(args[1:])
for _, path := range flags.Args() { for _, path := range flags.Args() {
err := convertToGray(path) err := gray(path)
if err != nil { if err != nil {
return fmt.Errorf("couldn't convert to grayscale of '%s'; error: %v", path, err) return fmt.Errorf("couldn't convert to grayscale of '%s'; error: %v", path, err)
} }
} }
case "crop": }
flags := flag.NewFlagSet("crop", flag.ContinueOnError) return nil
var rect string }
var resize string
var dir string
flags.StringVar(&rect, "crop", "", "sets the crop rectangle \"x1,y1,y1,y2\"")
flags.StringVar(&resize, "resize", "", "sets the target size, \"width,height\", if not specified the crop rectangle size is used")
flags.StringVar(&dir, "dir", "", "crops all images in the specified directory (recursively)")
flags.Parse(args[1:])
cropRect, err := parseRect(rect) func setAlpha(path string, alpha int) error {
if err != nil { src, err := os.Open(path)
return fmt.Errorf("crop rectangle is invalid: error: %v", err) if err != nil {
} return err
var size *point }
if len(resize) != 0 { defer src.Close()
p, err := parsePoint(resize) im, _, err := image.Decode(src)
if err != nil { if err != nil {
return fmt.Errorf("resize parameter is invalid: error: %v", err) return err
}
bounds := im.Bounds()
dst := image.NewNRGBA(bounds)
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
c := color.NRGBAModel.Convert(im.At(x, y)).(color.NRGBA)
if c.A > 0 {
c.A = uint8(alpha)
} }
size = &p dst.Set(x, y, c)
} }
}
return encodePNG(path, dst)
}
var files []string func gray(path string) error {
if len(dir) == 0 { src, err := os.Open(path)
files = flags.Args() if err != nil {
} else { return err
files, err = scanDir(dir) }
if err != nil { defer src.Close()
return fmt.Errorf("couldn't find files to crop; error: %v", err) im, _, err := image.Decode(src)
} if err != nil {
} return err
}
for _, path := range files { bounds := im.Bounds()
err := crop(path, cropRect, size) dst := image.NewRGBA(bounds)
if err != nil { for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
return fmt.Errorf("couldn't crop '%s'; error: %v", path, err) for x := bounds.Min.X; x < bounds.Max.X; x++ {
c := im.At(x, y)
rgba := color.NRGBAModel.Convert(c).(color.NRGBA)
if rgba.A > 0 {
gray := color.GrayModel.Convert(c).(color.Gray)
rgba.R, rgba.G, rgba.B = gray.Y, gray.Y, gray.Y
dst.Set(x, y, rgba)
} else {
dst.Set(x, y, c)
} }
} }
} }
return nil return encodePNG(path, dst)
}
func encodePNG(path string, im image.Image) error {
dst, err := os.Create(path)
if err != nil {
return err
}
defer dst.Close()
return png.Encode(dst, im)
} }
func main() { func main() {

View File

@ -1,29 +0,0 @@
package main
import (
"image"
"image/png"
"os"
)
func encodePNG(path string, im image.Image) error {
dst, err := os.Create(path)
if err != nil {
return err
}
defer dst.Close()
return png.Encode(dst, im)
}
func decodeImage(path string) (image.Image, error) {
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
im, _, err := image.Decode(f)
if err != nil {
return nil, err
}
return im, nil
}

View File

@ -1,25 +0,0 @@
package main
import (
"image"
"image/color"
)
func setAlpha(path string, alpha int) error {
src, err := decodeImage(path)
if err != nil {
return err
}
bounds := src.Bounds()
dst := image.NewNRGBA(bounds)
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
for x := bounds.Min.X; x < bounds.Max.X; x++ {
c := color.NRGBAModel.Convert(src.At(x, y)).(color.NRGBA)
if c.A > 0 {
c.A = uint8(alpha)
}
dst.Set(x, y, c)
}
}
return encodePNG(path, dst)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,55 +0,0 @@
package tins2020
import (
"errors"
"regexp"
"github.com/veandco/go-sdl2/sdl"
)
var hexColorRE = regexp.MustCompile(`^#?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})-?([0-9A-Fa-f]{2})?$`)
func HexColor(s string) (sdl.Color, error) {
match := hexColorRE.FindStringSubmatch(s)
if match == nil {
return sdl.Color{}, errors.New("invalid color format")
}
values, err := HexToInts(match[1:]...)
if err != nil {
return sdl.Color{}, err
}
a := 255
if len(match[4]) > 0 {
a = values[3]
}
return sdl.Color{R: uint8(values[0]), G: uint8(values[1]), B: uint8(values[2]), A: uint8(a)}, nil
}
func HexToInt(s string) (int, error) {
var i int
for _, c := range s {
i *= 16
if c >= '0' && c <= '9' {
i += int(c - '0')
} else if c >= 'A' && c <= 'F' {
i += int(c - 'A' + 10)
} else if c >= 'a' && c <= 'f' {
i += int(c - 'a' + 10)
} else {
return 0, errors.New("hex digit not supported")
}
}
return i, nil
}
func HexToInts(s ...string) ([]int, error) {
ints := make([]int, len(s))
for i, s := range s {
value, err := HexToInt(s)
if err != nil {
return nil, err
}
ints[i] = value
}
return ints, nil
}

View File

@ -1,33 +0,0 @@
package tins2020
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/veandco/go-sdl2/sdl"
)
func TestHexColor(t *testing.T) {
type test struct {
Hex string
Success bool
Expected sdl.Color
}
tests := []test{
test{Hex: "#AA3939", Success: true, Expected: sdl.Color{R: 170, G: 57, B: 57, A: 255}},
test{Hex: "AA3939", Success: true, Expected: sdl.Color{R: 170, G: 57, B: 57, A: 255}},
test{Hex: "#AA3939BB", Success: true, Expected: sdl.Color{R: 170, G: 57, B: 57, A: 187}},
test{Hex: "AG3939", Success: false, Expected: sdl.Color{}},
test{Hex: "AA3939A", Success: false, Expected: sdl.Color{}},
test{Hex: "AA39A", Success: false, Expected: sdl.Color{}},
}
for _, test := range tests {
color, err := HexColor(test.Hex)
if test.Success {
assert.Nil(t, err)
assert.Equal(t, color, test.Expected)
} else {
assert.NotNil(t, err)
}
}
}

View File

@ -8,20 +8,12 @@ import (
"opslag.de/schobers/fs/vfs" "opslag.de/schobers/fs/vfs"
) )
type TextAlignment int
const (
TextAlignmentLeft TextAlignment = iota
TextAlignmentCenter
TextAlignmentRight
)
type Font struct { type Font struct {
*ttf.Font *ttf.Font
} }
func (f *Font) Render(renderer *sdl.Renderer, text string, pos Point, color sdl.Color) (*Texture, error) { func (f *Font) Render(renderer *sdl.Renderer, text string, pos Point, color sdl.Color) (*Texture, error) {
surface, err := f.RenderUTF8Blended(text, color) surface, err := f.RenderUTF8Solid(text, color)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -33,24 +25,6 @@ func (f *Font) Render(renderer *sdl.Renderer, text string, pos Point, color sdl.
return texture, nil return texture, nil
} }
func (f *Font) RenderCopyAlign(renderer *sdl.Renderer, text string, pos Point, color sdl.Color, align TextAlignment) error {
texture, err := f.Render(renderer, text, pos, color)
if err != nil {
return err
}
defer texture.Destroy()
rect := texture.Rect()
switch align {
case TextAlignmentLeft:
texture.Copy(renderer, &sdl.Rect{X: pos.X, Y: pos.Y, W: rect.W, H: rect.H})
case TextAlignmentCenter:
texture.Copy(renderer, &sdl.Rect{X: pos.X - (rect.W / 2), Y: pos.Y, W: rect.W, H: rect.H})
case TextAlignmentRight:
texture.Copy(renderer, &sdl.Rect{X: pos.X - rect.W, Y: pos.Y, W: rect.W, H: rect.H})
}
return nil
}
func (f *Font) RenderCopy(renderer *sdl.Renderer, text string, pos Point, color sdl.Color) error { func (f *Font) RenderCopy(renderer *sdl.Renderer, text string, pos Point, color sdl.Color) error {
texture, err := f.Render(renderer, text, pos, color) texture, err := f.Render(renderer, text, pos, color)
if err != nil { if err != nil {

View File

@ -60,7 +60,7 @@ func (b *ButtonBar) Render(ctx *Context) {
for i, button := range b.Buttons { for i, button := range b.Buttons {
pos := Pt(b.Left, b.Top+int32(i)*buttonBarWidth) pos := Pt(b.Left, b.Top+int32(i)*buttonBarWidth)
texture := texture(button) texture := texture(button)
texture.Copy(ctx.Renderer, &sdl.Rect{X: pos.X, Y: pos.Y - 40, W: buttonBarWidth, H: 120}) texture.Copy(ctx.Renderer, &sdl.Rect{X: pos.X, Y: pos.Y, W: buttonBarWidth, H: buttonBarWidth})
if b.Hover == i { if b.Hover == i {
hoverTexture.Copy(ctx.Renderer, hoverTexture.RectOffset(pos)) hoverTexture.Copy(ctx.Renderer, hoverTexture.RectOffset(pos))
} }

View File

@ -21,7 +21,7 @@ type projection struct {
} }
func newProjection() projection { func newProjection() projection {
return projection{zoom: 1, tileScreenDelta: PtF(64, 32), tileScreenDeltaInv: PtF(1./64, 1./32)} return projection{zoom: 1, tileScreenDelta: PtF(65, 32), tileScreenDeltaInv: PtF(1./65, 1./32)}
} }
func (p *projection) mapToScreen(x, y int32) Point { func (p *projection) mapToScreen(x, y int32) Point {
@ -30,7 +30,7 @@ func (p *projection) mapToScreen(x, y int32) Point {
func (p *projection) mapToScreenF(x, y float32) Point { func (p *projection) mapToScreenF(x, y float32) Point {
translated := PtF(x-p.center.X, y-p.center.Y) 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)) 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) screenToMap(x, y int32) PointF { func (p *projection) screenToMap(x, y int32) PointF {
@ -55,9 +55,9 @@ func (p *projection) screenToTileRect(pos Point) *sdl.Rect {
func (p *projection) update(renderer *sdl.Renderer) { func (p *projection) update(renderer *sdl.Renderer) {
p.zoomInv = 1 / p.zoom p.zoomInv = 1 / p.zoom
p.tileScreenOffset = Pt(int32(p.zoomInv*64), int32(p.zoomInv*112)) p.tileScreenOffset = Pt(int32(p.zoomInv*256), int32(p.zoomInv*300))
p.tileScreenSize = Pt(int32(p.zoomInv*128), int32(p.zoomInv*160)) p.tileScreenSize = Pt(int32(p.zoomInv*512), int32(p.zoomInv*512))
p.tileFitScreenSize = Pt(int32(p.zoomInv*64), int32(p.zoomInv*32)) p.tileFitScreenSize = Pt(int32(p.zoomInv*65), int32(p.zoomInv*32))
windowW, windowH, err := renderer.GetOutputSize() windowW, windowH, err := renderer.GetOutputSize()
if err != nil { if err != nil {

View File

@ -149,9 +149,8 @@ func (r *terrainRenderer) Render(ctx *Context) {
return toPropTexture(temp, humid, variant) return toPropTexture(temp, humid, variant)
} }
// horizontal: [0, 128) = 128 // horizontal: [191, 321) = 130
// vertical (tile): [96,160) = 64 // vertical: [267,332) = 65
// vertical (total): [0,160) = 160
r.project.visibleTiles(func(x, y int32, pos Point) { r.project.visibleTiles(func(x, y int32, pos Point) {
text := toTileTexture(x, y) text := toTileTexture(x, y)