-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUnit.hpp
152 lines (131 loc) · 3.82 KB
/
Unit.hpp
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#pragma once
#include <glm/glm.hpp>
#include "Debug.hpp"
#include "Timer.hpp"
struct Unit {
static constexpr float GAUGE = .0004;
using vec_t = glm::vec3;
using loc_t = vec_t;
using real_t = float;
using time_t = Timer::time_t;
static real_t length(vec_t vec) { return glm::length(vec); }
Timer timer;
loc_t pos;
loc_t dest;
Unit *dest_unit=nullptr;
real_t moving_speed = 0.;
real_t facing = .0;
real_t facing_dest = .0;
const real_t facing_speed;
static constexpr int TIME_LOCKED_MOVE = 0;
Unit(vec_t pos={0, 0, 0}, real_t facing_speed=4*M_PI):
pos(pos), dest(pos), facing_speed(facing_speed)
{
timer.set_event(TIME_LOCKED_MOVE);
}
real_t height() const { return pos.z; }
real_t &height() { return pos.z; }
vec_t velocity() const {
vec_t dir(
dest.x - pos.x,
dest.y - pos.y,
0
);
/* printf("dir: %f %f %f\n", dir.x, dir.y, dir.z); */
if(length(dir) < .0001) return vec_t(0, 0, 0);
return moving_speed * dir / length(dir);
}
void idle(Timer &t) {
timer.set_time(t.current_time);
moving_speed = std::fmin(522.f * GAUGE, moving_speed);
if(dest_unit)dest=dest_unit->pos;
idle_facing();
idle_moving();
}
void move(loc_t location) {
if(!timer.timed_out(TIME_LOCKED_MOVE)) {
facing_dest = facing_angle(location);
return;
}
face(location);
dest = location;
}
void slide(loc_t location, time_t lock_dur) {
if(!timer.timed_out(TIME_LOCKED_MOVE))return;
stop();
dest = location;
timer.set_event(TIME_LOCKED_MOVE);
timer.set_timeout(TIME_LOCKED_MOVE, lock_dur);
}
void move(Unit &unit) {
dest_unit = &unit;
}
void face(float angle) {
stop();
facing_dest = angle;
}
float facing_angle(loc_t location) {
return atan2(location.y - pos.y, location.x - pos.x);
}
void face(loc_t location) {
face(facing_angle(location));
}
void stop() {
/* printf("stop dest: %f %f %f\n", dest.x, dest.y, dest.z); */
dest = pos;
if(dest_unit)dest_unit=nullptr;
}
void idle_facing() {
while(facing < -M_PI)facing += 2*M_PI;
while(facing > M_PI)facing -= 2*M_PI;
real_t face_diff = std::abs(facing - facing_dest);
while(face_diff >= 2*M_PI)face_diff -= 2*M_PI;
real_t timediff = timer.elapsed();
if(face_diff < .001)return;
real_t delta = facing_speed * timediff;
/* printf("facing: %f \\tendsto %f\n", facing, facing_dest); */
if(face_diff < M_PI) {
if(face_diff < std::abs(delta))facing=facing_dest;
else if(facing > facing_dest)facing -= delta;
else facing += delta;
} else {
if(2*M_PI - face_diff < std::abs(delta))facing=facing_dest;
else if(facing > facing_dest)facing += delta;
else facing -= delta;
}
}
vec_t point_offset(real_t offset, float angle) const {
return pos + offset * vec_t(
std::cos(angle),
std::sin(angle),
height()
);
}
vec_t point_offset(real_t offset) const {
return point_offset(offset, facing);
}
bool is_moving() const {
return length(dest - pos) > .0001;
}
void idle_moving() {
if(!is_moving())return;
/* printf("pos: %f %f %f\n", pos.x, pos.y, pos.z); */
real_t timediff = timer.elapsed();
auto dir = vec_t(dest.x - pos.x, dest.y - pos.y, 0);
/* printf("pos: %f %f %f\n", pos.x, pos.y, pos.z); */
/* printf("dest: %f %f %f\n", dest.x, dest.y, dest.z); */
/* printf("dir: %f %f %f\n", dir.x, dir.y, dir.z); */
/* printf("timediff: %f\n", timediff); */
/* printf("moving_speed: %f\n", moving_speed); */
real_t step = timediff * moving_speed;
if(length(dir) <= step) {
pos.x = dest.x;
pos.y = dest.y;
} else {
dir *= step / length(dir);
pos += dir;
/* printf("facing angle: %f\n", facing_dest); */
}
/* printf("pos: %f %f %f\n", pos.x, pos.y, pos.z); */
}
};