Skip to content

Instantly share code, notes, and snippets.

@guregu
Last active October 14, 2015 22:42
Show Gist options
  • Save guregu/48e6b50e70fad59049c0 to your computer and use it in GitHub Desktop.
Save guregu/48e6b50e70fad59049c0 to your computer and use it in GitHub Desktop.
engi + tiled
package tiled
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"github.com/guregu/eng"
)
const tilesetName = "tileset/%s"
type Map struct {
Width int `json:"width"`
Height int `json:"height"`
TileWidth int `json:"tilewidth"`
TileHeight int `json:"tileheight"`
Layers []Layer `json:"layers"`
Tilesets []Tileset `json:"tilesets"`
Tiles map[int]*engi.Region
}
func (m *Map) setup() {
added := make(map[string]struct{})
for _, ts := range m.Tilesets {
if _, exists := added[ts.Name]; exists {
continue
}
added[ts.Name] = struct{}{}
for gid, r := range ts.Tiles() {
m.Tiles[gid] = r
}
}
}
type Layer struct {
Data []int `json:"data"` // TileIDs
X int `json:"x"`
Y int `json:"y"`
Width int `json:"width"`
Height int `json:"height"`
Visible bool `json:"visible"`
Name string `json:"name"`
NextObjectID int `json:"nextobjectid"` // ??
Opacity int `json:"opacity"` // ??
Type string `json:"type"` // ??
Objects []Object `json:"objects"`
}
type Object struct {
ID int
Name string
Properties map[string]string
Rotation float64
Type string
Visible bool
X, Y float32
Height, Width float32
}
type Tileset struct {
FirstGID int `json:"firstgid"`
Image string `json:"image"`
ImageHeight int `json:"imageheight"`
ImageWidth int `json:"imagewidth"`
Margin int `json:"margin"`
Spacing int `json:"spacing"`
TileHeight int `json:"tileheight"`
TileWidth int `json:"tilewidth"`
Name string `json:"name"`
}
func (ts Tileset) Tiles() map[int]*engi.Region {
tiles := make(map[int]*engi.Region)
gid := ts.FirstGID
tex := ts.Texture()
w := (ts.ImageWidth - ts.Margin) / (ts.TileWidth + ts.Spacing)
h := (ts.ImageHeight - ts.Margin) / (ts.TileHeight + ts.Spacing)
for y := 0; y < h; y++ {
for x := 0; x < w; x++ {
u := ts.Margin + (ts.TileWidth+ts.Spacing)*x
v := ts.Margin + (ts.TileHeight+ts.Spacing)*y
r := engi.NewRegion(tex, u, v, ts.TileWidth, ts.TileHeight)
tiles[gid] = r
gid++
}
}
return tiles
}
func (ts Tileset) Texture() *engi.Texture {
name := fmt.Sprintf(tilesetName, ts.Name)
return engi.Files.Image(name)
}
func Load(r io.Reader, tilesetPath string) (m Map, err error) {
err = json.NewDecoder(r).Decode(&m)
if err != nil {
return
}
m.Tiles = make(map[int]*engi.Region)
added := make(map[string]struct{})
for _, ts := range m.Tilesets {
name := fmt.Sprintf(tilesetName, ts.Name)
if _, exists := added[name]; exists {
continue
}
added[name] = struct{}{}
file := filepath.Base(ts.Image)
fmt.Println("loading", filepath.Join(tilesetPath, file))
engi.Files.Add(name, filepath.Join(tilesetPath, file))
}
engi.Files.Load(func() {
m.setup()
})
return
}
func LoadFile(path, tilesetPath string) (m Map, err error) {
f, err := os.Open(path)
if err != nil {
return Map{}, err
}
defer f.Close()
return Load(f, tilesetPath)
}
@guregu
Copy link
Author

guregu commented Apr 13, 2015

Here's how you actually draw the map:

    for z, layer := range game.Map.Layers {
        if !layer.Visible {
            continue
        }
        for i, gid := range layer.Data {
            x := layer.X + i%layer.Width
            y := layer.Y + i/layer.Width
            tx := float32(x * game.Map.TileWidth)
            ty := float32(y * game.Map.TileHeight)

            r := game.Map.Tiles[gid]
            game.batch.Draw(r, tx, ty, 0, 0, 1, 1, 0, 0xffffff, 1)
        }
        _ = z // TODO ;)
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment