-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmap.cpp
More file actions
293 lines (275 loc) · 10.8 KB
/
map.cpp
File metadata and controls
293 lines (275 loc) · 10.8 KB
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#include <string.h> //For memset()
#include "math.cpp"
#define B_WATER 0
#define B_STONE 1
#define B_GRASS 2
#define B_SAND 3
#define S_CAMPFIRE 3
const uint16_t MAP_W = 488, MAP_H = 488;
const uint32_t MAP_A = MAP_W * MAP_H;
//eeeeeeee eeeeeeee llaf ffssssbb
uint32_t map[MAP_W][MAP_H]; //00000000 00000000 00000000 00000000 - 0000000000000000 entity map id, 0000 RESERVED, 00 luminosity, 0 animated, 000 frame, 0000 sprite, 00 biome
uint64_t game_time = 0;
//Constants
const uint8_t GEN_ISLANDS = 5;
const uint16_t GEN_ISLAND_RAD_MIN = 48;
const uint16_t GEN_ISLAND_RAD_MAX = 64;
const uint8_t GEN_ISLAND_RES = 4; //'resolution' of an island - how many blobs make it up
const uint8_t GEN_VILLAGES = 64;
const uint16_t GEN_VILLAGE_RAD_MIN = 8;
const uint16_t GEN_VILLAGE_RAD_MAX = 16;
const uint16_t GEN_GROW_MAP = 4096;
const uint16_t MAP_GROW_SPEED = 128;
const uint16_t MAP_DEATH_SPEED = 32;
bool inBounds (uint16_t x, uint16_t y)
{
return x > 0 && x < MAP_W && y > 0 && y < MAP_H;
}
uint8_t getBiome (uint16_t x, uint16_t y) { if (inBounds(x, y)) {
return map[x][y] & 0x03;
} }
void setBiome (uint16_t x, uint16_t y, uint8_t b) { if (inBounds(x, y)) {
map[x][y] = (map[x][y] & 0xFFFFFFFC) | b;
} }
uint8_t getSprite (uint16_t x, uint16_t y) { if (inBounds(x, y)) {
return (map[x][y] & 0x3C) >> 2;
} }
void setSprite (uint16_t x, uint16_t y, uint8_t s) { if (inBounds(x, y)) {
map[x][y] = (map[x][y] & 0xFFFFFFC3) | (s << 2);
} }
uint8_t getFrame (uint16_t x, uint16_t y) { if (inBounds(x, y)) {
return (map[x][y] & 0x1C0) >> 6;
} }
void setFrame (uint16_t x, uint16_t y, uint8_t f) { if (inBounds(x, y)) {
map[x][y] = (map[x][y] & 0xFFFFFE3F) | (f << 6);
} }
bool getAnimated (uint16_t x, uint16_t y) { if (inBounds(x, y)) {
return (map[x][y] & 0x200) >> 9;
} }
void setAnimated (uint16_t x, uint16_t y, bool a) { if (inBounds(x, y)) {
map[x][y] = (map[x][y] & 0xFFFFFDFF) | (a << 9);
} }
uint8_t getLux (uint16_t x, uint16_t y) { if (inBounds(x, y)) {
return (map[x][y] & 0xC00) >> 10;
} }
void setLux (uint16_t x, uint16_t y, uint8_t l, bool append = false) { if (inBounds(x, y)) {
if (append) { if (getLux(x, y) > l) { return; } }
map[x][y] = (map[x][y] & 0xFFFFF3FF) | (l << 10);
} }
uint16_t getMapEntity (uint16_t x, uint16_t y) { if (inBounds(x, y)) {
return (map[x][y] & 0xFFFF0000) >> 16;
} }
void setMapEntity (uint16_t x, uint16_t y, uint16_t e) { if (inBounds(x, y)) {
map[x][y] = (map[x][y] & 0x0000FFFF) | (e << 16);
} }
bool isFoliage (uint8_t sprite_code)
{
switch (sprite_code) {
case 4: case 5: return true;
default: return false;
}
}
bool isSolid (uint8_t sprite_code)
{
switch (sprite_code) {
case 1: case 2: return true;
default: return false;
}
}
void pushCrate (uint16_t x, uint16_t y, double dx, double dy)
{
if (fabs(dx) > fabs(dy)) { dx = (dx > 0 ? 1 : -1); dy = 0; } else { dx = 0; dy = (dy > 0 ? 1 : -1); }
uint16_t px = x + int16_t(dx);
uint16_t py = y + int16_t(dy);
if (getSprite(x, y) == 1 && !getSprite(px, py) && getBiome(px, py) == B_STONE) {
setSprite(x, y, 0);
setSprite(px, py, 1);
}
}
void growMap (uint16_t grow_speed = MAP_GROW_SPEED, uint16_t death_speed = MAP_DEATH_SPEED);
void genMap ()
{
//Set map to water
memset(map, B_WATER, sizeof map);
//Generate islands
//Generated by randomly placing differently sized circles (blobs) in a group
for (uint8_t i = 0; i < GEN_ISLANDS; ++i) { //For each island
//Calc island size and pos
const uint16_t island_radius = ri(GEN_ISLAND_RAD_MIN, GEN_ISLAND_RAD_MAX);
uint16_t island_X, island_Y;
do {
random_coord(MAP_W, MAP_H, island_X, island_Y);
} while (island_X < island_radius || island_Y < island_radius || island_X > MAP_W - island_radius || island_Y > MAP_H - island_radius);
//Calc blob size and pos
uint16_t blob_X = island_X + ri(island_radius / 2, island_radius);
uint16_t blob_Y = island_Y + ri(island_radius / 2, island_radius);
for (uint8_t b = 0; b < GEN_ISLAND_RES; ++b) { //For each blob in the island
uint16_t blob_X = island_X + ri(-island_radius, island_radius);
uint16_t blob_Y = island_Y + ri(-island_radius, island_radius);
//Go through all angles from 0 to 2 * PI radians, in an ever-smaller circle (size), to fill the blob
float size = 1.0;
const float step = .005;
while (size > step) {
float r = size * island_radius;
for (float ang = 0; ang < 6.28; ang += .01) {
uint16_t x = blob_X + r * sinf(ang);
uint16_t y = blob_Y + r * cosf(ang);
//Place some land there
setBiome(x, y, B_GRASS);
}
size -= step;
}
//Go through all angles and add a coast of sand
for (float ang = 0; ang < 6.28; ang += .01) {
uint16_t x = blob_X + island_radius * sinf(ang);
uint16_t y = blob_Y + island_radius * cosf(ang);
//Place some land there
setBiome(x, y, B_SAND);
}
}
}
//Generate villages
for (uint8_t v = 0; v < GEN_VILLAGES; ++v) { //For each village
//Calc island size and pos
const uint16_t village_radius = ri(GEN_VILLAGE_RAD_MIN, GEN_VILLAGE_RAD_MAX);
uint16_t village_X, village_Y;
do {
random_coord(MAP_W, MAP_H, village_X, village_Y);
} while (getBiome(village_X, village_Y) != B_GRASS);
//Go through all angles from 0 to 2 * PI radians, in an ever-smaller circle (size), to fill the village biome
float size = 1.0;
const float step = .005;
while (size > step) {
float r = size * village_radius;
for (float ang = 0; ang < 6.28; ang += .01) {
uint16_t x = village_X + r * sinf(ang);
uint16_t y = village_Y + r * cosf(ang);
setBiome(x, y, B_STONE);
}
size -= step;
}
//Go through all angles and add a brick wall
for (float ang = 0; ang < 6.28; ang += .07) { //wide angle to cause some gaps
uint16_t x = village_X + village_radius * sinf(ang);
uint16_t y = village_Y + village_radius * cosf(ang);
setSprite(x, y, 2);
}
size -= step;
}
//En-masse
for (uint16_t y = 1; y < MAP_H - 1; ++y) {
for (uint16_t x = 1; x < MAP_W - 1; ++x) {
//Set animation properties (idk why I even have to do this)
setFrame(x, y, 0);
setAnimated(x, y, false);
//Prune strays
//Remove all brick walls surrounded by stone biome (where village blobs have overlapped)
if (getSprite(x, y) == 2 && getBiome(x+1, y) == B_STONE && getBiome(x-1, y) == B_STONE && getBiome(x, y+1) == B_STONE && getBiome(x, y-1) == B_STONE) {
setSprite(x, y, 0);
}
//Remove all sand not touching water (where island blobs have overlapped)
if (getBiome(x, y) == B_SAND) {
bool wet = false;
wet |= getBiome(x+1, y) == B_WATER;
wet |= getBiome(x-1, y) == B_WATER;
wet |= getBiome(x, y+1) == B_WATER;
wet |= getBiome(x, y-1) == B_WATER;
if (!wet) {
setBiome(x, y, B_GRASS);
}
}
uint8_t biome_code = getBiome(x, y);
if ( !getSprite(x, y) && (biome_code == B_STONE && rb(.05)) || (biome_code == B_GRASS && rb(.01))) {
//Add random fireplace and luminosity
setSprite(x, y, 3);
setAnimated(x, y, true);
setFrame(x, y, ri(0, 6));
setLux(x+0,y+0,3, true);
setLux(x+1,y+0,2, true);
setLux(x+2,y+0,1, true);
setLux(x+3,y+0,1, true);
setLux(x-1,y+0,2, true);
setLux(x-2,y+0,1, true);
setLux(x-3,y+0,1, true);
setLux(x+0,y+1,2, true);
setLux(x+1,y+1,2, true);
setLux(x+2,y+1,1, true);
setLux(x-1,y+1,2, true);
setLux(x-2,y+1,1, true);
setLux(x+0,y+2,1, true);
setLux(x+1,y+2,1, true);
setLux(x-1,y+2,1, true);
setLux(x+0,y+3,1, true);
setLux(x+0,y-1,2, true);
setLux(x+1,y-1,2, true);
setLux(x+2,y-1,1, true);
setLux(x-1,y-1,2, true);
setLux(x-2,y-1,1, true);
setLux(x+0,y-2,1, true);
setLux(x+0,y-3,1, true);
setLux(x+1,y-2,1, true);
setLux(x-1,y-2,1, true);
}
if (biome_code == B_STONE && rb(.05) && !getSprite(x, y)) {
setSprite(x, y, 1); //Random crate
}
//Add random foliage
else if (biome_code == B_GRASS) {
if (rb(0.025)) {
setSprite(x, y, 4);
//setAnimated(x, y, true);
} else if (rb(0.05)) {
setSprite(x, y, 5);
//setAnimated(x, y, true);
}
}
//Add random brick
if (rb(0.005) && getBiome(x, y) != B_WATER) {
setSprite(x, y, 2);
}
}
}
//Grow the map naturally for a bit
for (uint16_t g = 0; g < GEN_GROW_MAP; ++g) {
growMap();
}
}
void growMap (uint16_t grow_speed, uint16_t death_speed)
{
//Giveuth
for (uint16_t g = 0; g < grow_speed; ++g) {
//Select a random position on the map
uint16_t grow_X, grow_Y;
random_coord(MAP_W, MAP_H, grow_X, grow_Y);
uint8_t sprite_code = getSprite(grow_X, grow_Y);
//If it's growable, grow it
uint8_t spread = 0;
switch (sprite_code) {
case 4: spread = 1 * rb(.6); break;
case 5: spread = 2 * rb(1); break;
}
if (spread && getBiome(grow_X, grow_Y) == B_GRASS) {
grow_X += ri(-spread, spread);
grow_Y += ri(-spread, spread);
if (!getSprite(grow_X, grow_Y)) {
setSprite(grow_X, grow_Y, sprite_code);
}
}
}
//Takeuth awae
for (uint16_t d = 0; d < death_speed; ++d) {
//Select a random position on the map
uint16_t grow_X, grow_Y;
random_coord(MAP_W, MAP_H, grow_X, grow_Y);
uint8_t sprite_code = getSprite(grow_X, grow_Y);
//If it's killable, kill it
bool to_kill = 0;
switch (sprite_code) {
case 4: to_kill = rb(.3); break;
case 5: to_kill = rb(1); break;
}
if (to_kill) {
setSprite(grow_X, grow_Y, 0);
}
}
}