-
Notifications
You must be signed in to change notification settings - Fork 5
/
brick.go
117 lines (100 loc) · 2.5 KB
/
brick.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
package main
import (
"github.com/quasilyte/ge"
"github.com/quasilyte/ge/gesignal"
"github.com/quasilyte/ge/physics"
"github.com/quasilyte/gmath"
)
const brickDefaultWidth float64 = 64
const brickShardWidth float64 = 8
const brickShardHeight float64 = 8
type brick struct {
scene *ge.Scene
body physics.Body
sprite *ge.Sprite
scale float64
hp float64
shapeHeight float64
EventDestroyed gesignal.Event[gesignal.Void]
}
func newBrick(scale float64, rotation gmath.Rad, pos gmath.Vec) *brick {
b := &brick{hp: 4, scale: scale, shapeHeight: 32}
b.body.InitRotatedRect(b, brickDefaultWidth*scale, 32*scale)
b.body.Rotation = rotation
b.body.Pos = pos
return b
}
func newCircleBrick(scale float64, pos gmath.Vec) *brick {
b := &brick{
hp: 3,
scale: scale,
shapeHeight: brickDefaultWidth,
}
b.body.InitCircle(b, 32*scale)
b.body.Pos = pos
return b
}
func (b *brick) Init(scene *ge.Scene) {
b.scene = scene
if b.body.IsCircle() {
b.sprite = scene.NewSprite(ImageBrickCircle)
} else {
b.sprite = scene.NewSprite(ImageBrickRect)
b.sprite.Rotation = &b.body.Rotation
}
b.sprite.FrameWidth = brickDefaultWidth
b.sprite.Pos.Base = &b.body.Pos
b.sprite.SetScale(b.scale, b.scale)
scene.AddGraphics(b.sprite)
scene.AddBody(&b.body)
}
func (b *brick) Hit(hitPos gmath.Vec) bool {
b.hp--
b.sprite.FrameOffset.X += brickDefaultWidth
if b.hp <= 0 {
b.scene.Audio().PlaySound(AudioBrickDestroyed)
b.Destroy()
return true
}
for i := 0; i < 3; i++ {
shardPos := hitPos.Add(gmath.Vec{X: float64(i*8) - 8})
shard := newBrickShard(shardPos)
b.scene.AddObject(shard)
}
b.scene.Audio().PlaySound(AudioBrickHit)
return false
}
func (b *brick) IsDisposed() bool { return b.body.IsDisposed() }
func (b *brick) Update(delta float64) {}
func (b *brick) Dispose() {
b.body.Dispose()
b.sprite.Dispose()
}
func (b *brick) Destroy() {
width := brickDefaultWidth * b.scale
height := b.shapeHeight * b.scale
offset := gmath.Vec{
X: b.body.Pos.X - width/2,
Y: b.body.Pos.Y - height/2,
}
startX := float64(0)
startY := float64(0)
if b.body.IsCircle() {
startX = 8
startY = 8
width -= 8
height -= 8
}
for y := startY; y < height; y += 8 {
for x := startX; x < width; x += 8 {
unrotatedPos := offset.Add(gmath.Vec{X: x, Y: y})
center := b.body.Pos
diff := unrotatedPos.Sub(center)
rotatedPos := diff.Rotated(b.body.Rotation).Add(center)
shard := newBrickShard(rotatedPos)
b.scene.AddObject(shard)
}
}
b.EventDestroyed.Emit(gesignal.Void{})
b.Dispose()
}