103 lines
2.4 KiB
Go
103 lines
2.4 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"image"
|
||
|
"os"
|
||
|
|
||
|
"github.com/faiface/pixel"
|
||
|
"github.com/faiface/pixel/pixelgl"
|
||
|
|
||
|
_ "image/png"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
windowWidth = 800
|
||
|
windowHeight = 800
|
||
|
// sprite tiles are squared, 64x64 size
|
||
|
tileSize = 64
|
||
|
f = 0 // floor identifier
|
||
|
w = 1 // wall identifier
|
||
|
)
|
||
|
|
||
|
var levelData = [][]uint{
|
||
|
{f, f, f, f, f, f}, // This row will be rendered in the lower left part of the screen (closer to the viewer)
|
||
|
{w, f, f, f, f, w},
|
||
|
{w, f, f, f, f, w},
|
||
|
{w, f, f, f, f, w},
|
||
|
{w, f, f, f, f, w},
|
||
|
{w, w, w, w, w, w}, // And this in the upper right
|
||
|
}
|
||
|
var win *pixelgl.Window
|
||
|
var offset = pixel.V(400, 325)
|
||
|
var floorTile, wallTile *pixel.Sprite
|
||
|
|
||
|
func loadPicture(path string) (pixel.Picture, error) {
|
||
|
file, err := os.Open(path)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
defer file.Close()
|
||
|
img, _, err := image.Decode(file)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return pixel.PictureDataFromImage(img), nil
|
||
|
}
|
||
|
|
||
|
func run() {
|
||
|
var err error
|
||
|
|
||
|
cfg := pixelgl.WindowConfig{
|
||
|
Title: "Isometric demo",
|
||
|
Bounds: pixel.R(0, 0, windowWidth, windowHeight),
|
||
|
VSync: true,
|
||
|
}
|
||
|
win, err = pixelgl.NewWindow(cfg)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
pic, err := loadPicture("castle.png")
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
wallTile = pixel.NewSprite(pic, pixel.R(0, 448, tileSize, 512))
|
||
|
floorTile = pixel.NewSprite(pic, pixel.R(0, 128, tileSize, 192))
|
||
|
|
||
|
depthSort()
|
||
|
|
||
|
for !win.Closed() {
|
||
|
win.Update()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Draw level data tiles to window, from farthest to closest.
|
||
|
// In order to achieve the depth effect, we need to render tiles up to down, being lower
|
||
|
// closer to the viewer (see painter's algorithm). To do that, we need to process levelData in reverse order,
|
||
|
// so its first row is rendered last, as OpenGL considers its origin to be in the lower left corner of the display.
|
||
|
func depthSort() {
|
||
|
for x := len(levelData) - 1; x >= 0; x-- {
|
||
|
for y := len(levelData[x]) - 1; y >= 0; y-- {
|
||
|
isoCoords := cartesianToIso(pixel.V(float64(x), float64(y)))
|
||
|
mat := pixel.IM.Moved(offset.Add(isoCoords))
|
||
|
// Not really needed, just put to show bigger blocks
|
||
|
mat = mat.ScaledXY(win.Bounds().Center(), pixel.V(2, 2))
|
||
|
tileType := levelData[x][y]
|
||
|
if tileType == f {
|
||
|
floorTile.Draw(win, mat)
|
||
|
} else {
|
||
|
wallTile.Draw(win, mat)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func cartesianToIso(pt pixel.Vec) pixel.Vec {
|
||
|
return pixel.V((pt.X-pt.Y)*(tileSize/2), (pt.X+pt.Y)*(tileSize/4))
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
pixelgl.Run(run)
|
||
|
}
|