-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathtile.go
119 lines (98 loc) · 3.12 KB
/
tile.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package tilepix
import (
"fmt"
"math"
"github.com/gopxl/pixel"
)
/*
_____ _ _
|_ _(_) |___
| | | | / -_)
|_| |_|_\___|
*/
// Tile is a TMX file structure which holds a Tiled tile.
type Tile struct {
ID ID `xml:"id,attr"`
Image *Image `xml:"image"`
// ObjectGroup is set if objects have been added to individual sprites in Tiled.
ObjectGroup *ObjectGroup `xml:"objectgroup,omitempty"`
// parentMap is the map which contains this object
parentMap *Map
}
func (t *Tile) String() string {
return fmt.Sprintf("Tile{ID: %d}", t.ID)
}
func (t *Tile) setParent(m *Map) {
t.parentMap = m
if t.Image != nil {
t.Image.setParent(m)
}
}
// DecodedTile is a convenience struct, which stores the decoded data from a Tile.
type DecodedTile struct {
ID ID
Tileset *Tileset
HorizontalFlip bool
VerticalFlip bool
DiagonalFlip bool
Nil bool
sprite *pixel.Sprite
transform pixel.Matrix
// parentMap is the map which contains this object
parentMap *Map
}
// Draw will draw the tile to the target provided. This will calculate the sprite from the provided tileset and set the
// DecodedTiles' internal `sprite` property; this is so it is only calculated the first time.
func (t *DecodedTile) Draw(ind, columns, numRows int, ts *Tileset, target pixel.Target, offset pixel.Vec) {
if t.IsNil() {
return
}
if t.sprite == nil {
t.setSprite(columns, numRows, ts)
// Calculate the framing for the tile within its tileset's source image
pos := t.Position(ind, ts)
transform := pixel.IM.Moved(pos)
if t.DiagonalFlip {
transform = transform.Rotated(pos, math.Pi/2)
transform = transform.ScaledXY(pos, pixel.V(1, -1))
}
if t.HorizontalFlip {
transform = transform.ScaledXY(pos, pixel.V(-1, 1))
}
if t.VerticalFlip {
transform = transform.ScaledXY(pos, pixel.V(1, -1))
}
t.transform = transform
}
t.sprite.Draw(target, t.transform.Moved(offset))
}
// Position returns the relative game position.
func (t DecodedTile) Position(ind int, ts *Tileset) pixel.Vec {
gamePos := indexToGamePos(ind, t.parentMap.Width, t.parentMap.Height)
return gamePos.ScaledXY(pixel.V(float64(ts.TileWidth), float64(ts.TileHeight))).Add(pixel.V(float64(ts.TileWidth), float64(ts.TileHeight)).Scaled(0.5))
}
func (t *DecodedTile) String() string {
return fmt.Sprintf("DecodedTile{ID: %d, Is nil: %t}", t.ID, t.Nil)
}
// IsNil returns whether this tile is nil. If so, it means there is nothing set for the tile, and should be skipped in
// drawing.
func (t *DecodedTile) IsNil() bool {
return t.Nil
}
func (t *DecodedTile) setParent(m *Map) {
t.parentMap = m
}
func (t *DecodedTile) setSprite(columns, numRows int, ts *Tileset) {
if t.IsNil() {
return
}
if t.sprite == nil {
// Calculate the framing for the tile within its tileset's source image
x, y := tileIDToCoord(t.ID, columns, numRows)
iX := float64(x)*float64(ts.TileWidth) + float64(ts.Margin+ts.Spacing*(x-1))
fX := iX + float64(ts.TileWidth)
iY := float64(y)*float64(ts.TileHeight) + float64(ts.Margin+ts.Spacing*(y-1))
fY := iY + float64(ts.TileHeight)
t.sprite = pixel.NewSprite(ts.setSprite(), pixel.R(iX, iY, fX, fY))
}
}