krampus19/cmd/tilewarp/tilewarp.go

149 lines
2.8 KiB
Go

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
}