From c4fc256c19dabbb002c5393a8d3548b26efe953f Mon Sep 17 00:00:00 2001 From: Sander Schobers Date: Sun, 29 Dec 2019 12:52:37 +0100 Subject: [PATCH] Added tool to warp tiles. --- cmd/tilewarp/tilewarp.go | 148 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 cmd/tilewarp/tilewarp.go diff --git a/cmd/tilewarp/tilewarp.go b/cmd/tilewarp/tilewarp.go new file mode 100644 index 0000000..ec465f7 --- /dev/null +++ b/cmd/tilewarp/tilewarp.go @@ -0,0 +1,148 @@ +package main + +import ( + "image" + "image/color" + "image/png" + "log" + "os" +) + +func main() { + err := run() + if err != nil { + log.Fatal(err) + } +} + +func loadPNG(path string) (image.Image, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + return png.Decode(f) +} + +func storePNG(path string, im image.Image) error { + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + return png.Encode(f, im) +} + +type warpFn func(image.Image) image.Image + +func warp(path string, warp warpFn) error { + im, err := loadPNG(path) + if err != nil { + return err + } + warped := warp(im) + return storePNG(path, warped) +} + +type warpTile struct { + im image.Image + + right int + farRight int + top int + farTop int + + src tile + dst tile + + yOffset int +} + +type tile struct { + width int + height int +} + +func (w warpTile) ColorModel() color.Model { return w.im.ColorModel() } + +func (w warpTile) Bounds() image.Rectangle { + bounds := w.im.Bounds() + bounds.Max.Y = bounds.Dy() * w.dst.height / w.src.height + return bounds +} + +func (w warpTile) At(x, y int) color.Color { + offset := image.Point{} + for x >= w.dst.width { + x -= w.dst.width + offset.X += w.src.width + } + for y >= w.dst.height { + y -= w.dst.height + offset.Y += w.src.height + } + y += w.yOffset + + if y >= w.top && x < w.right { + return w.im.At(x+offset.X, y-6*30+offset.Y) + } + + isTopSide := func() bool { + if y >= w.top { + return false + } + if x < w.right { + return true + } + sideX := w.farRight - (w.farRight-w.right)*(y-w.farTop)/(w.top-w.farTop) + return x < sideX + } + if isTopSide() { + srcY := w.farTop + (6*40)*(y-w.farTop)/(w.top-w.farTop) + return w.im.At(x+offset.X, srcY+offset.Y) + } + srcY := y - (6*30)*(w.farRight-x)/(w.farRight-w.right) + srcBottom := 6 * 160 + if srcY > srcBottom { + srcY = srcBottom + } + return w.im.At(x+offset.X, srcY+offset.Y) +} + +func run() error { + warp("../krampus19/res/tile_lava_brick.png", func(im image.Image) image.Image { + return &warpTile{ + im: im, + dst: tile{width: 6 * 170, height: 6 * 190}, + src: tile{width: 6 * 170, height: 6 * 160}, + right: 6 * 110, + farRight: 6 * 160, + top: 6 * 80, + farTop: 6 * 10, + } + }) + warp("../krampus19/res/tile_magma.png", func(im image.Image) image.Image { + return &warpTile{ + im: im, + dst: tile{width: 6 * 170, height: 6 * 190}, + src: tile{width: 6 * 170, height: 6 * 160}, + right: 6 * 110, + farRight: 6 * 160, + top: 6 * 100, + farTop: 6 * 30, + } + }) + warp("../krampus19/res/entity_brick.png", func(im image.Image) image.Image { + return &warpTile{ + im: im, + dst: tile{width: 6 * 170, height: 6 * 190}, + src: tile{width: 6 * 170, height: 6 * 160}, + yOffset: 18, + right: 6 * 100, + farRight: 6 * 150, + top: 6 * 100, + farTop: 6 * 30, + } + }) + return nil +}