-
Notifications
You must be signed in to change notification settings - Fork 1
/
hero.go
135 lines (121 loc) · 2.66 KB
/
hero.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"github.com/faiface/pixel"
"github.com/faiface/pixel/pixelgl"
"golang.org/x/image/colornames"
)
type Hero struct {
Entity
velocity pixel.Vec
maxVel float64
accel float64
health, maxHealth float64
}
func NewHero(s *pixel.Sprite, pos pixel.Vec, maxVel, accel float64) *Hero {
e := NewEntity(s, pos)
return &Hero{
Entity: *e,
maxVel: maxVel,
accel: accel,
maxHealth: 100,
health: 100,
}
}
func (h *Hero) Damage(health float64) {
if h.Alive() {
h.health = pixel.Clamp(h.health+health, 0, h.maxHealth)
}
}
func (h *Hero) SlowDown(rate float64) {
h.velocity = h.velocity.Scaled(rate)
}
func (h *Hero) Alive() bool {
return h.health > 0
}
func (h *Hero) Update() {
pct := h.health / h.maxHealth * 100
switch {
case pct >= 80:
h.Color = colornames.White
case pct >= 60:
h.Color = colornames.Peachpuff
case pct >= 45:
h.Color = colornames.Rosybrown
case pct >= 30:
h.Color = colornames.Brown
case pct >= 10:
h.Color = colornames.Red
default:
h.Color = colornames.Purple
}
if !h.Alive() {
return
}
daccel := h.accel * engine.dt
dx := 0.0
if engine.win.Pressed(pixelgl.KeyA) {
dx = -daccel
} else if engine.win.Pressed(pixelgl.KeyD) {
dx = +daccel
} else {
// handle deceleration correctly, don't let it oscilate around 0.
if h.velocity.X >= daccel {
dx = -daccel
} else if h.velocity.X <= -daccel {
dx = +daccel
} else {
h.velocity.X = 0
}
}
h.velocity.X = pixel.Clamp(h.velocity.X+dx, -h.maxVel, h.maxVel)
dy := 0.0
if engine.win.Pressed(pixelgl.KeyS) {
dy = -daccel
} else if engine.win.Pressed(pixelgl.KeyW) {
dy = +daccel
} else {
if h.velocity.Y >= daccel {
dy = -daccel
} else if h.velocity.Y <= -daccel {
dy = +daccel
} else {
h.velocity.Y = 0
}
}
h.velocity.Y = pixel.Clamp(h.velocity.Y+dy, -h.maxVel, h.maxVel)
// limit diagonal speed
actualVel := h.velocity.Len()
if actualVel > h.maxVel {
h.velocity = h.velocity.Scaled(h.maxVel / actualVel)
}
delta := h.velocity.Scaled(engine.dt)
colWorld := h.AbsCollider()
walls := world.GetColliders(colWorld)
c := colWorld.Moved(delta)
for _, wall := range walls {
if collides(c, wall) {
// Try to zero movement on one of the axes and continue if there is no collision.
tdelta := delta
tdelta.Y = 0
c = colWorld.Moved(tdelta)
if !collides(c, wall) {
h.velocity.Y = 0
delta = tdelta
continue
}
tdelta = delta
tdelta.X = 0
c = colWorld.Moved(tdelta)
if !collides(c, wall) {
h.velocity.X = 0
delta = tdelta
continue
}
}
if delta == pixel.ZV {
// bail when velocity is zero
break
}
}
h.Pos = h.Pos.Add(delta)
}