-
Notifications
You must be signed in to change notification settings - Fork 1
/
rockets_grid.c
193 lines (158 loc) · 4.24 KB
/
rockets_grid.c
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
Direction
rotate_direction(Direction direction, int rotation)
{
int dir = (int)direction;
dir += rotation;
dir = (dir + 6) % 6;
return (Direction)dir;
}
GridV
gridV(int x, int y, int z)
{
return (GridV){.x = x, .y = y, .z = z};
}
int
gridV_eq(GridV a, GridV b)
{
return (a.x == b.x &&
a.y == b.y &&
a.z == b.z);
}
GridV
gridV_plus(GridV a, GridV b)
{
a.x += b.x;
a.y += b.y;
a.z += b.z;
return a;
}
GridV
gridV_minus(GridV a, GridV b)
{
a.x -= b.x;
a.y -= b.y;
a.z -= b.z;
return a;
}
int
gridV_distance(GridV a, GridV b)
{
return (abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z)) / 2;
}
int
gridV_magnitude(GridV v)
{
return gridV_distance(GRID_ZERO, v);
}
// @NOTE: This takes a float so you can do stuff like 0.5;
// You'll still get back ints so don't mess yourself up.
// @TODO: Could make this gridV_divide and take an int instead.
GridV
gridV_scale(GridV v, float n)
{
v.x = (int)(v.x * n);
v.y = (int)(v.y * n);
v.z = (int)(v.z * n);
return v;
}
// Rotate a grid vector counter clockwise around the hexagon.
GridV
gridV_rotate(GridV v, int rotation)
{
// Only rotating left for now.
int left_rotation = (rotation + 6) % 6;
// A left rotation is
//[ x,y,z] to [-y, -z, -x]
for (int i = 0; i < left_rotation; i++) {
GridV new_v = gridV(-v.y, -v.z, -v.x);
v = new_v;
}
return v;
}
// Get the unit (1 space) grid vector for a given direction.
GridV
gridV_for_direction(Direction direction)
{
switch(direction) {
case(UP):
return GRID_UP;
break;
case(LEFT_UP):
return GRID_LEFT_UP;
break;
case(LEFT_DOWN):
return GRID_LEFT_DOWN;
break;
case(DOWN):
return GRID_DOWN;
break;
case(RIGHT_DOWN):
return GRID_RIGHT_DOWN;
break;
case(RIGHT_UP):
return GRID_RIGHT_UP;
break;
}
}
GridV round_to_gridV(float x, float y, float z)
{
int rx = round(x);
int ry = round(y);
int rz = round(z);
float x_diff = abs((float)rx - x);
float y_diff = abs((float)ry - y);
float z_diff = abs((float)rz - z);
if (x_diff > y_diff &&
x_diff > z_diff) {
rx = -ry-rz;
} else if (y_diff > z_diff) {
ry = -rx-rz;
} else {
rz = -rx-ry;
}
return gridV(rx, ry, rz);
}
// Returns true if v is on grid.
// @TODO: Need a good way to get iteration bounds.
bool point_on_grid(HexagonGrid grid, GridV v)
{
return (v.y - v.z >= 0 &&
v.y - v.z < grid.rows*2 &&
v.x >= v.z + v.y &&
v.x < grid.columns);
}
// @TODO: This can be a matrix multiplication if I had matrixes. Figure out what the most common
// way to do matrix stuff in c is, and make sure it's something that can be SIMDized.
// @OPTOMIZE: If we gotta do this for tons of entities it would be good to pack all their positions
// together. Depends on if this is the most common operation or not.
// Watch that mike actin talk again.
V2 gridV_to_pixel(HexagonGrid grid, GridV v)
{
// Only do the math for valid points.
assert(v.x + v.y + v.z == 0);
float q = v.x;
float r = v.z;
V2 origin;
origin.x = grid.origin_x + 2*grid.hexagon_size/2.0;
origin.y = grid.origin_y - sqrt(3)*grid.hexagon_size/2.0;
float screen_x = q * 3.0/2.0 * grid.hexagon_size;
float screen_y = (r + q/2.0) * sqrt(3) * grid.hexagon_size;
V2 screen_coordinates = v2(screen_x, screen_y);
screen_coordinates = v2_plus(screen_coordinates, origin);
return screen_coordinates;
}
// @OPTOMIZE: Again if I'm doing lots of these I should pack them and have this function take
// an array so I'm not calculating all the extra stuff in the inner loop.
GridV pixel_to_gridV(HexagonGrid grid, V2 pixel)
{
V2 origin;
origin.x = grid.origin_x + 2*grid.hexagon_size/2.0;
origin.y = grid.origin_y - sqrt(3)*grid.hexagon_size/2.0;
pixel = v2_minus(pixel, origin);
float q = pixel.x * 2.0/3.0 / grid.hexagon_size;
float r = (-pixel.x / 3.0 + sqrt(3)/3.0 * pixel.y) / grid.hexagon_size;
float grid_x = q;
float grid_z = r;
float grid_y = -grid_x-grid_z;
return round_to_gridV(grid_x, grid_y, grid_z);
}