149 lines
2.8 KiB
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
|
|
}
|