summary refs log tree commit diff stats
path: root/gamestate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gamestate.cpp')
-rw-r--r--gamestate.cpp350
1 files changed, 350 insertions, 0 deletions
diff --git a/gamestate.cpp b/gamestate.cpp new file mode 100644 index 0000000..e82a786 --- /dev/null +++ b/gamestate.cpp
@@ -0,0 +1,350 @@
1#include "gamestate.h"
2#include <SDL_ttf.h>
3#include "util.h"
4#include "mazeoflife.h"
5
6class GameBoard {
7 public:
8 GameBoard(int level);
9 void tick(int playerx, int playery);
10 void render(SDL_Renderer* renderer);
11 bool isObstructed(int x, int y);
12
13 private:
14 int level;
15 bool blocks[WIDTH][HEIGHT];
16};
17
18class LoadGameState : public State {
19 public:
20 LoadGameState(int level);
21 State* operator() (SDL_Renderer* renderer);
22
23 private:
24 int level;
25};
26
27class PlayGameState : public State {
28 public:
29 PlayGameState(int level, GameBoard* board, int playerx, int playery);
30 State* operator() (SDL_Renderer* renderer);
31
32 private:
33 bool move(int x, int y);
34 int level;
35 GameBoard* board;
36 int playerx;
37 int playery;
38};
39
40void setRendererAliveColor(SDL_Renderer* renderer, int level)
41{
42 switch ((level/10)%5)
43 {
44 case 0: SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); break; // Black
45 case 1: SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); break; // Red
46 case 2: SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255); break; // Green
47 case 3: SDL_SetRenderDrawColor(renderer, 85, 85, 85, 255); break; // Dark Gray
48 case 4: SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255); break; // Magenta
49 }
50}
51
52void setRendererDeadColor(SDL_Renderer* renderer, int level)
53{
54 switch ((level/10)%5)
55 {
56 case 0: SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); break; // White
57 case 1: SDL_SetRenderDrawColor(renderer, 255, 192, 203, 255); break; // Pink
58 case 2: SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255); break; // Cyan
59 case 3: SDL_SetRenderDrawColor(renderer, 170, 170, 170, 255); break; // Light Gray
60 case 4: SDL_SetRenderDrawColor(renderer, 255, 128, 0, 255); break; // Orange
61 }
62}
63
64void incrementIfNeighbor(int x, int y, bool temp[WIDTH][HEIGHT], int* tick, int playerx, int playery)
65{
66 int nx = x;
67 int ny = y;
68
69 wrap(&x, &y);
70
71 if (!((nx!=x)&&(ny!=y)))
72 {
73 if ((temp[x][y])||((playerx==x)&&(playery==y))||((x==15)&&(y==15)))
74 {
75 ++*tick;
76 }
77 }
78}
79
80State* GameState::operator() (SDL_Renderer* renderer)
81{
82 return new LoadGameState(0);
83}
84
85LoadGameState::LoadGameState(int m_level)
86{
87 level = m_level;
88}
89
90State* LoadGameState::operator() (SDL_Renderer* renderer)
91{
92 // Randomly place the player in a corner
93 int playerx, playery;
94 switch (rand()%4)
95 {
96 case 0: playerx = 1; playery = 1; break;
97 case 1: playerx = 1; playery = HEIGHT-2; break;
98 case 2: playerx = WIDTH-2; playery = HEIGHT-2; break;
99 case 3: playerx = WIDTH-2; playery = 1; break;
100 }
101
102 // Display the level number
103 setRendererDeadColor(renderer, level);
104 SDL_RenderClear(renderer);
105
106 TTF_Font* font = loadFont(100);
107 SDL_Color fontColor = {0, 0, 0, 0};
108 char levelnum[8];
109 sprintf(levelnum, "%d", level);
110 SDL_Surface* dispsurf = TTF_RenderText_Solid(font, levelnum, fontColor);
111 SDL_Texture* disptext = SDL_CreateTextureFromSurface(renderer, dispsurf);
112 SDL_FreeSurface(dispsurf);
113
114 SDL_Rect pos;
115 SDL_QueryTexture(disptext, NULL, NULL, &pos.w, &pos.h);
116 pos.x = 240-(pos.w/2);
117 pos.y = 240-(pos.h/2);
118
119 SDL_RenderCopy(renderer, disptext, NULL, &pos);
120 SDL_RenderPresent(renderer);
121
122 // Do 50 gens of Conway
123 GameBoard* board = new GameBoard(level);
124 for (int i=0; i<50; i++)
125 {
126 board->tick(playerx, playery);
127 }
128
129 // Wait a bit
130 SDL_Delay(500);
131
132 // Start the level
133 return new PlayGameState(level, board, playerx, playery);
134}
135
136PlayGameState::PlayGameState(int m_level, GameBoard* m_board, int m_playerx, int m_playery)
137{
138 level = m_level;
139 board = m_board;
140 playerx = m_playerx;
141 playery = m_playery;
142}
143
144State* PlayGameState::operator() (SDL_Renderer* renderer)
145{
146 SDL_Event e;
147
148 for (;;)
149 {
150 // Tick board
151 board->tick(playerx, playery);
152
153 // Paint board
154 board->render(renderer);
155
156 // Paint event
157 SDL_Rect block;
158 block.w = 16;
159 block.h = 16;
160 block.x = 15*16;
161 block.y = 15*16;
162 SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
163 SDL_RenderFillRect(renderer, &block);
164
165 // Paint player
166 block.x = playerx*16;
167 block.y = playery*16;
168 SDL_SetRenderDrawColor(renderer, 255, 255, 0, 255);
169 SDL_RenderFillRect(renderer, &block);
170
171 SDL_RenderPresent(renderer);
172
173 while (SDL_PollEvent(&e))
174 {
175 if (e.type == SDL_QUIT)
176 {
177 return NULL;
178 } else if (e.type == SDL_KEYDOWN)
179 {
180 switch (e.key.keysym.sym)
181 {
182 case SDLK_LEFT:
183 if (move(playerx-1, playery))
184 {
185 return new LoadGameState(level+1);
186 } else {
187 break;
188 }
189
190 case SDLK_RIGHT:
191 if (move(playerx+1, playery))
192 {
193 return new LoadGameState(level+1);
194 } else {
195 break;
196 }
197
198 case SDLK_UP:
199 if (move(playerx, playery-1))
200 {
201 return new LoadGameState(level+1);
202 } else {
203 break;
204 }
205
206 case SDLK_DOWN:
207 if (move(playerx, playery+1))
208 {
209 return new LoadGameState(level+1);
210 } else {
211 break;
212 }
213 }
214 }
215 }
216 }
217}
218
219bool PlayGameState::move(int x, int y)
220{
221 wrap(&x, &y);
222
223 // Are we at the event?
224 if ((x==15)&&(y==15))
225 {
226 return true;
227 }
228
229 // Can we even go there?
230 if (!board->isObstructed(x,y))
231 {
232 playerx = x;
233 playery = y;
234 }
235
236 return false;
237}
238
239GameBoard::GameBoard(int m_level)
240{
241 level = m_level;
242
243 for (int y=0; y<HEIGHT; y++)
244 {
245 for (int x=0; x<WIDTH; x++)
246 {
247 blocks[x][y] = false;
248
249 switch (level/10+1)
250 {
251 case 1:
252 if ((x>13)&&(x<17)&&(y>13)&&(y<17))
253 {
254 blocks[x][y] = rand() % 2;
255 }
256 break;
257 case 2:
258 case 3:
259 if ((x>12)&&(x<18)&&(y>12)&&(y<18))
260 {
261 blocks[x][y] = rand() % 2;
262 }
263 break;
264 case 4:
265 case 5:
266 if ((x>11)&&(x<19)&&(y>11)&&(y<19))
267 {
268 blocks[x][y] = rand() % 2;
269 }
270 break;
271 default:
272 blocks[x][y] = rand() % 2;
273 }
274 }
275 }
276
277 blocks[15][15] = false;
278}
279
280void GameBoard::tick(int playerx, int playery)
281{
282 bool temp[WIDTH][HEIGHT];
283 int x,y;
284 for (x=0;x<WIDTH;x++)
285 {
286 for (y=0;y<HEIGHT;y++)
287 {
288 temp[x][y] = blocks[x][y];
289 }
290 }
291
292 for (x=0;x<WIDTH;x++)
293 {
294 for (y=0;y<HEIGHT;y++)
295 {
296 if ((x==15)&&(y==15))
297 {
298 continue;
299 }
300
301 int neighbors = 0;
302
303 incrementIfNeighbor(x-1,y-1,temp,&neighbors, playerx, playery);
304 incrementIfNeighbor(x-1,y,temp,&neighbors, playerx, playery);
305 incrementIfNeighbor(x-1,y+1,temp,&neighbors, playerx, playery);
306 incrementIfNeighbor(x,y-1,temp,&neighbors, playerx, playery);
307 incrementIfNeighbor(x,y+1,temp,&neighbors, playerx, playery);
308 incrementIfNeighbor(x+1,y-1,temp,&neighbors, playerx, playery);
309 incrementIfNeighbor(x+1,y,temp,&neighbors, playerx, playery);
310 incrementIfNeighbor(x+1,y+1,temp,&neighbors, playerx, playery);
311
312 if (temp[x][y])
313 {
314 blocks[x][y] = ((neighbors >= 1) && (neighbors <= 4));
315 } else {
316 blocks[x][y] = (neighbors == 3);
317 }
318 }
319 }
320}
321
322void GameBoard::render(SDL_Renderer* renderer)
323{
324 SDL_Rect block;
325 block.w = 16;
326 block.h = 16;
327
328 for (int y=0; y<HEIGHT; y++)
329 {
330 for (int x=0; x<WIDTH; x++)
331 {
332 block.x = x*16;
333 block.y = y*16;
334
335 if (blocks[x][y])
336 {
337 setRendererAliveColor(renderer, level);
338 } else {
339 setRendererDeadColor(renderer, level);
340 }
341
342 SDL_RenderFillRect(renderer, &block);
343 }
344 }
345}
346
347bool GameBoard::isObstructed(int x, int y)
348{
349 return blocks[x][y];
350}