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
120
121
122
123
124
125
126
|
package main
import (
"github.com/hajimehoshi/ebiten/v2"
"log"
"image"
_ "image/png"
)
type Tilemap struct {
tilesImage *ebiten.Image
surfaces []*ebiten.Image
mapWidth int
tileSize int
layers [][]int
collisions []image.Rectangle
}
// take in map coord and make it real life coord
func (t *Tilemap) Translate(x, y int) (int, int) {
return x * t.tileSize, y*t.tileSize
}
func (* Tilemap) Update() error {
return nil
}
func (tm * Tilemap) Draw(screen *ebiten.Image, x, y float32) {
for _, surf := range tm.surfaces {
ShadowDraw(screen, surf, x, y, 1.0)
}
}
func (tm *Tilemap) UpdateSurface() {
w := tm.tilesImage.Bounds().Dx()
tileXCount := w / tileSize
tm.surfaces = make([]*ebiten.Image, len(tm.layers))
// Draw each tile with each DrawImage call.
// As the source images of all DrawImage calls are always same,
// this rendering is done very efficiently.
// For more detail, see https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#Image.DrawImage
for idx, l := range tm.layers {
tm.surfaces[idx] = ebiten.NewImage(tm.mapWidth*tm.tileSize, len(l)/tm.mapWidth*tm.tileSize)
for i, t := range l {
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(float64((i%tm.mapWidth)*tm.tileSize), float64((i/tm.mapWidth)*tm.tileSize))
sx := (t % tileXCount) * tileSize
sy := (t / tileXCount) * tileSize
tm.surfaces[idx].DrawImage(tm.tilesImage.SubImage(image.Rect(sx, sy, sx+tileSize, sy+tileSize)).(*ebiten.Image), op)
}
}
//ebitenutil.DebugPrint(screen, fmt.Sprintf("TPS: %0.2f", ebiten.ActualTPS()))
}
func NewTilemap(layers [][]int, mapWidth int) Tilemap {
tilemap := Tilemap{
tileSize: 16,
mapWidth: 25,
}
tilemap.layers = layers
var err error
tilemap.tilesImage = tilesImage
if err != nil {
log.Fatal(err)
}
tilemap.CalculateCollisions()
return tilemap
}
func (tm * Tilemap) CalculateCollisions() {
for i, t := range tm.layers[0] {
if t != 0 {
x := i%tm.mapWidth * tm.tileSize
y := i/tm.mapWidth * tm.tileSize
w, h := tm.tileSize, tm.tileSize
rect := image.Rect(x, y, x+w, y+h)
tm.collisions = append(tm.collisions, rect)
}
}
}
func Collide(r1 image.Rectangle, r2 image.Rectangle) bool {
return ! ( r2.Min.X >= r1.Max.X || r2.Max.X <= r1.Min.X || r2.Min.Y >= r1.Max.Y || r2.Max.Y <= r1.Min.Y)
}
func (t * Tilemap) Collide(x, y, width, height int) bool {
r1 := image.Rect(
x,
y,
x+width,
y+height,
)
for _, r2 := range t.collisions {
if ! ( r2.Min.X >= r1.Max.X || r2.Max.X <= r1.Min.X || r2.Min.Y >= r1.Max.Y || r2.Max.Y <= r1.Min.Y) {
return true
}
}
return false
}
func (t * Tilemap) CollideObject(object *GameObject) bool {
width := object.image.Bounds().Dx()
height := object.image.Bounds().Dy()
x := int(object.x)
y := int(object.y)
return t.Collide(x, y, width, height)
}
|