/
MainGame.h
302 lines (229 loc) · 7.29 KB
/
MainGame.h
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
294
295
296
297
298
299
300
301
302
#include "TileType.h"
#include <Arduboy2.h>
Arduboy2 arduboy;
#include "GameSprites.h"
// Changes to make:
// - Create pause function on B button press and call drawMap function in it
// - Create functions toIso and toCart to go to and from Isometric/Cartesian
// - Draw new map tiles using toIso (and probably an enum due to how theyre stored in memory?)
class Vector {
public:
float x = 0;
float y = 0;
};
// The game camera, represented by the camera's top left coordinates
Vector camera;
// The dimensions of the screen
constexpr uint8_t screen_height = HEIGHT;
constexpr uint8_t screen_width = WIDTH;
// The centre coordinates of the screen
constexpr uint8_t viewport_center_height = screen_height / 2;
constexpr uint8_t viewport_center_width = screen_width / 2;
// The dimensions of the tiles
constexpr uint8_t tileWidth = 19;
constexpr uint8_t tileHeight = 9;
// The dimensions of the map
constexpr uint8_t mapHeight = 32;
constexpr uint8_t mapWidth = 32;
// A 2D array of tiles, represented with 'TileType'
TileType tileMap[mapHeight][mapWidth] {};
// Though it would be better to introduce a named function so you don’t forget what this code actually does:
inline uint8_t getSpriteHeight(const uint8_t * sprite)
{
return pgm_read_byte(&sprite[1]);
}
inline uint8_t getSpriteWidth(const uint8_t * sprite)
{
return pgm_read_byte(&sprite[0]);
}
TileType generateRandomBuildingTile()
{
constexpr uint8_t buildingMin = toTileIndex(TileType::building0);
constexpr uint8_t buildingMax = toTileIndex(TileType::building3);
return fromTileIndex(random(buildingMin, buildingMax));
}
//char city[32][32];
TileType building = generateRandomBuildingTile();
//Replace with fromTileIndex?
TileType road = fromTileIndex(5);
void fill(TileType tileType)
{
for(size_t y = 0; y < 32; ++y)
for(size_t x = 0; x < 32; ++x)
tileMap[y][x] = tileType;
}
void fillHorizontalLine(uint8_t x, uint8_t y, uint8_t width, TileType tileType)
{
for(size_t offset = 0; offset < width; ++offset)
if(x + offset < 32)
tileMap[y][x + offset] = tileType;
}
void fillVerticalLine(uint8_t x, uint8_t y, uint8_t height, TileType tileType)
{
for(size_t offset = 0; offset < height; ++offset)
if(y + offset < 32)
tileMap[y + offset][x] = tileType;
}
void generateHorizontalStep(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t depth);
void generateVerticalStep(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t depth);
void generateSubdivide(uint8_t depth)
{
fill(building);
generateVerticalStep(0, 0, 32, 32, depth);
}
void generateHorizontalStep(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t depth)
{
if(depth == 0)
return;
if(width < 2)
return;
if(height < 3)
return;
const uint8_t division = 1 + (rand() % (height - 2));
fillHorizontalLine(x, y + division, width, road);
const uint8_t upperY = y;
const uint8_t upperHeight = division;
const uint8_t lowerY = (y + division + 1);
const uint8_t lowerHeight = (height - division - 1);
generateVerticalStep(x, upperY, width, upperHeight, depth - 1);
generateVerticalStep(x, lowerY, width, lowerHeight, depth - 1);
}
void generateVerticalStep(uint8_t x, uint8_t y, uint8_t width, uint8_t height, uint8_t depth)
{
if(depth == 0)
return;
if(height < 2)
return;
if(width < 3)
return;
const uint8_t division = 1 + (rand() % (width - 2));
fillVerticalLine(x + division, y, height, road);
const uint8_t leftX = x;
const uint8_t leftWidth = division;
const uint8_t rightX = (x + division + 1);
const uint8_t rightWidth = (width - division - 1);
generateHorizontalStep(leftX, y, leftWidth, height, depth - 1);
generateHorizontalStep(rightX, y, rightWidth, height, depth - 1);
}
/*void print()
{
for(size_t y = 0; y < 32; ++y)
{
for(size_t x = 0; x < 32; ++x)
cout << tileMap[y][x];
cout << endl;
}
}
*/
/*int main()
{
generateSubdivide(6);
//print();
cin.get();
}
*/
/*
inline bool isWalkable(TileType tile)
{
switch (tile)
{
// Add cases for every
// kind of 'walkable' tile
case TileType::blankTile:
case TileType::roadTile:
return true;
// Assume anything that isn't in
// the above case list is not walkable
default:
return false;
}
}
*/
/*
uint8_t determineRoadType(uint8_t x, uint8_t y)
{
uint8_t roadType = 0;
if (((x + 1) < mapWidth) && isWalkable(tileMap[y][x + 1]))
roadType |= (1 << 0);
if ((x > 0) && isWalkable(tileMap[y][x - 1]))
roadType |= (1 << 1);
if (((y + 1) < mapHeight) && isWalkable(tileMap[y + 1][x]))
roadType |= (1 << 2);
if ((y > 0) && isWalkable(tileMap[y - 1][x]))
roadType |= (1 << 3);
return roadType;
}
*/
/*if isWalkable(tileMap[y][x])
{
TileType tileType = determineRoadType(y,x);
else TileType tileType = tileMap[y][x];
}
*/
void drawMiniMap()
{
for (uint8_t y = 0; y < mapHeight; ++y)
{
// Calculate the y position to draw the tile at, 6 is tile height
int16_t drawY = ((y * 6) - camera.y);
for (uint8_t x = 0; x < mapWidth; ++x)
{
// Calculate the x position to draw the tile at, 6 is tile width:
int16_t drawX = ((x * 6) - camera.x);
// Read the tile from the map.
TileType tileType = tileMap[y][x];
// Figure out the tile index.
uint8_t tileIndex = toTileIndex(tileType);
// Draw the tile at the calculated position.
Sprites::drawOverwrite(drawX, drawY, minimapTileSprites, tileIndex);
}
}
}
// Isometric map tiles
constexpr uint8_t const * tileSprites[]
{
building0,
building1,
building2,
building3,
blankTile,
roadTiles,
};
constexpr uint8_t const * tileMasks[]
{
building0_mask,
building1_mask,
building2_mask,
building3_mask,
//blank tile mask?
};
void drawIsoMap()
{
for (uint8_t tileY = 0; tileY < mapHeight; ++tileY)
{
for (uint8_t tileX = 0; tileX < mapWidth; ++tileX)
{
// Calculate the x position to draw the tile at.
const int16_t isometricX = (((tileX * tileWidth) / 2) - ((tileY * tileWidth) / 2));
const int16_t drawX = (isometricX - camera.x);
// Calculate the y position to draw the tile at.
const int16_t isometricY = (((tileX * tileHeight) / 2) + ((tileY * tileHeight) / 2));
const int16_t drawY = (isometricY - camera.y);
// TODO: Skip off-screen tiles
// Read the tile from the map.
const TileType tileType = tileMap[tileY][tileX];
// Figure out the tile index.
const uint8_t tileIndex = toTileIndex(tileType);
// Select the building sprite
const uint8_t * tileSprite = tileSprites[tileIndex];
// Select the building sprite mask
const uint8_t * tileMask = tileMasks[tileIndex];
// Get the sprite's height
const uint8_t spriteHeight = getSpriteHeight(tileSprite);
// Adjust the y position to account for the height of the sprite
const int16_t adjustedY = (drawY - (spriteHeight - tileHeight));
// Draw the tile at the calculated position.
Sprites::drawExternalMask(drawX, adjustedY, tileSprite, tileMask, 0, 0);
}
}
}