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 }