]> git.r.bdr.sh - rbdr/pico-engine/blob - game_overwatch.cpp
32e9ad1d77bd9df7e8dfb9ee2e79762127893909
[rbdr/pico-engine] / game_overwatch.cpp
1 #include "stdafx.h"
2
3
4 Game_overwatch::Game_overwatch(){
5 //Initialize our population
6 head = NULL;
7 population = 0;
8 }
9
10
11 void Game_overwatch::move_out(Actor *npc){
12
13 //Moving out means killing a citizen from the citizen linked list.
14
15 citizen *curr, *prev;
16 prev = NULL;
17
18 for(curr=head;curr!=NULL;prev=curr,curr=curr->next){
19 if (curr->val == npc) {
20 if (prev == NULL) {
21 head = curr->next;
22 std::cout << "I have deleted an NPC from the top!\n";
23 } else {
24 prev->next = curr->next;
25 std::cout << "I have deleted an NPC from the middle!\n";
26 }
27
28 delete curr;
29
30 }
31 }
32 population--;
33 }
34
35 void Game_overwatch::move_in(Actor * npc){
36 //Moving in means adding a citizen to the linkd list.
37
38 citizen *curr;
39 curr = new citizen;
40 curr->val = npc;
41 curr->next = head;
42 head=curr;
43 population++;
44 }
45
46 int Game_overwatch::get_population(){
47 return population;
48 }
49
50 void Game_overwatch::draw(SDL_Surface *viewport, Map *mainmap){
51
52 //Generic draw function, iterates over the list and draws
53 //each one of them.
54
55 //NOTE: Further along it may be wise to allow Lua scripts to
56 // override the draw function and just call curr->draw();
57
58 citizen *curr;
59 curr = head;
60 while (curr != NULL){
61 Gfx::drawsurface(curr->val->get_clip_x(),curr->val->get_clip_y(),
62 curr->val->get_w(),curr->val->get_h(),
63 curr->val->get_sprite(),
64 curr->val->get_x()-mainmap->get_sx(),curr->val->get_y()-mainmap->get_sy(),
65 viewport);
66 curr = curr->next;
67 }
68 }
69
70 void Game_overwatch::act(SDL_Surface *viewport, Map *mainmap, bool keys[323]){
71
72 //Iterates over the list and runs the "act" function from the lua script.
73
74 citizen *curr;
75 curr = head;
76 while (curr != NULL){
77 curr->val->move();
78 handleinput(curr->val, keys);
79
80 //do the lua thing.
81 curr->val->SelectScriptFunction ("act");
82 curr->val->Go ();
83
84 curr = curr->next;
85 }
86 }
87
88 void Game_overwatch::handleinput(Actor *actor, bool keys[323]){
89
90 //Right now these actions just map keys to variables the scripts can use
91 //In the future it will be wise to abstract the keys to what they do
92 //Also, take into account gamepads.
93 //Preferably, let lua handle this somehow.
94
95 if(keys[SDLK_LEFT]){
96 if(leftkey == 0){
97 leftkey = SDL_GetTicks();
98 }
99 }else{
100 leftkey = 0;
101 }
102
103 if(keys[SDLK_RIGHT]){
104
105 if(rightkey == 0){
106 rightkey = SDL_GetTicks();
107 }
108 }else{
109 rightkey = 0;
110 }
111
112 if(keys[SDLK_z]){
113 if(zkey == 0){
114 zkey = SDL_GetTicks();
115 }
116 }else{
117 zkey = 0;
118 }
119
120 if(keys[SDLK_x]){
121 if(xkey == 0){
122 xkey = SDL_GetTicks();
123 }
124 }else{
125 xkey = 0;
126 }
127
128 if(keys[SDLK_c]){
129 if(ckey == 0){
130 ckey = SDL_GetTicks();
131 }
132 }else{
133 ckey = 0;
134 }
135
136 actor->set_leftkey(leftkey);
137 actor->set_rightkey(rightkey);
138 actor->set_zkey(zkey);
139 actor->set_xkey(xkey);
140 actor->set_ckey(ckey);
141 }
142
143 void Game_overwatch::animate(){
144 //Iterate and run the animate method.
145
146 citizen *curr;
147 curr = head;
148 while (curr != NULL){
149 curr->val->animate();
150 curr = curr->next;
151 }
152 }
153
154 void Game_overwatch::check_collisions(Map *mainmap){
155 citizen *curr, *others;
156
157 bool collided = false;
158 curr = head;
159 others = head->next;
160 Actor *ac1, *ac2;
161
162 //now check everyone. Never with itself.
163 //It does line collisions, not corner collisions.
164
165 while (curr != NULL){
166 ac1 = curr->val;
167 while (others != NULL) {
168 ac2 = others->val;
169 collided = false;
170 if (curr->val != others->val) {
171 if(Game_overwatch::line_colliding(ac1->get_x(), ac1->get_w(),
172 ac1->get_y(), ac1->get_h(),
173 ac2->get_x(), ac2->get_w(),
174 ac2->get_y(), ac2->get_h(),
175 UP)){
176
177 ac2->set_collision(true, DOWN);
178 ac2->set_speed(ac1->get_ownspeed());
179 ac2->set_vertical_speed(ac2->get_vertical_speed()+ac1->get_vertical_speed());
180
181 ac1->set_collision(true, UP);
182 collided = true;
183 }
184 if(Game_overwatch::line_colliding(ac1->get_x(), ac1->get_w(),
185 ac1->get_y(), ac1->get_h(),
186 ac2->get_x(), ac2->get_w(),
187 ac2->get_y(), ac2->get_h(),
188 DOWN)){
189
190 ac2->set_collision(true, UP);
191 ac1->set_collision(true, DOWN);
192 collided = true;
193 }
194 if(Game_overwatch::line_colliding(ac1->get_x(), ac1->get_w(),
195 ac1->get_y(), ac1->get_h(),
196 ac2->get_x(), ac2->get_w(),
197 ac2->get_y(), ac2->get_h(),
198 LEFT)){
199
200 ac2->set_collision(true, RIGHT);
201 ac1->set_collision(true, LEFT);
202 collided = true;
203 }
204 if(Game_overwatch::line_colliding(ac1->get_x(), ac1->get_w(),
205 ac1->get_y(), ac1->get_h(),
206 ac2->get_x(), ac2->get_w(),
207 ac2->get_y(), ac2->get_h(),
208 RIGHT)){
209
210 ac2->set_collision(true, LEFT);
211 ac1->set_collision(true, RIGHT);
212 collided = true;
213 }
214 }
215
216 others = others->next;
217 if(collided){
218 collision_callback(ac1, ac2);
219 }
220
221 }
222
223 curr = curr->next;
224 if (curr != NULL){
225 others = curr->next;
226 }
227 }
228 }
229
230 void Game_overwatch::collision_callback(Actor *ac1, Actor *ac2){
231
232 std::cout << "The collision has called ";
233
234 if (ac1->get_enemy() == WEAPON && !ac2->get_dying()) {
235 if (ac2->get_enemy() == EVIL) {
236 ac1->set_dying(true);
237 ac2->set_dying(true);
238
239
240 std::cout << "And the shot has destroyed the enemy.";
241 }
242 }
243
244 if (ac1->get_enemy() == SUPEREVIL) {
245 ac2->set_dying(true);
246 std::cout << "And the shot has destroyed the enemy.";
247 }
248
249 if (ac1->get_controllable()) {
250 if (ac2->get_enemy() == EVIL) {
251 ac1->set_dying(true);
252
253
254 std::cout << "And the enemy has destroyed the main actor.";
255 }
256 }
257
258 if (ac1->get_enemy() == EVIL) {
259 if (ac2->get_controllable()) {
260 ac2->set_dying(true);
261
262
263 std::cout << "And the enemy has destroyed the main actor.";
264 }
265 }
266
267
268 std::cout << "\n";
269 }
270
271
272 bool Game_overwatch::line_colliding(int x1, int w1, int y1, int h1, int x2, int w2, int y2, int h2, int direction){
273 switch (direction) {
274 case UP:
275 if (y1 <= y2+h2 && y1 >= y2+(h2/2) &&
276 ((x1 > x2 && x1 < x2+w2) ||
277 (x1+w1 > x2 && x1+w2 < x2+w2))) {
278 std::cout << "Foo' is collidin' top\n";
279 return true;
280 }
281 break;
282 case DOWN:
283 if (y1+h1 >= y2 && y1+h1 <= y2+(h2/2) &&
284 ((x1 > x2 && x1 < x2+w2) ||
285 (x1+w1 > x2 && x1+w2 < x2+w2))) {
286 std::cout << "Foo' is collidin' bottom\n";
287 return true;
288 }
289 break;
290 case LEFT:
291 if (x1 <= x2+w2 && x1 >= x2+(w2/2) &&
292 ((y1 > y2 && y1 < y2+h2) ||
293 (y1+h1 > y2 && y1+h1 < y2+h2))) {
294 std::cout << "Foo' is collidin' left\n";
295 return true;
296 }
297 break;
298 case RIGHT:
299 if (x1+w1 >= x2 && x1+w1 <= x2+(w2/2) &&
300 ((y1 > y2 && y1 < y2+h2) ||
301 (y1+h1 > y2 && y1+h1 < y2+h2))) {
302 std::cout << "Foo' is collidin' right\n";
303 return true;
304 }
305 break;
306 }
307
308 return false;
309 }
310
311 void Game_overwatch::handlephysics(Map *mainmap, int ticks1, int ticks2){
312 citizen *curr;
313 curr = head;
314 while (curr != NULL){
315
316 //some are not affected by physics.
317 if(curr->val->get_physics()){
318 //can it fall?
319 if(curr->val->can_move(DOWN, curr->val->get_x(), curr->val->get_y())){
320
321 //change sprite to its jump.
322 switch(curr->val->get_oldclip()){
323 case 1:
324 curr->val->set_clip_y(curr->val->get_h()*0);
325 break;
326 case 2:
327 curr->val->set_clip_y(curr->val->get_h()*3);
328 break;
329 }
330
331 //start the fall process
332 if(curr->val->get_falltime() == 0){
333 curr->val->set_falltime(.5);
334 }else{
335 curr->val->set_falltime(curr->val->get_falltime()+(ticks2-ticks1)/1000);
336 }
337
338 }else{
339
340 //stop falling.
341 curr->val->set_clip_y(curr->val->get_h()*curr->val->get_oldclip());
342 curr->val->set_falltime(0);
343 if(curr->val->get_vertical_speed() > 0){
344 curr->val->set_vertical_speed(0);
345 }
346 }
347
348 //check for top collision
349 if( !curr->val->can_move(UP, curr->val->get_x(), curr->val->get_y()) && curr->val->get_vertical_speed() < 0){
350 curr->val->set_vertical_speed(0);
351 }
352
353 //Avoid falling through the ground
354 while(!curr->val->can_move(DOWN, curr->val->get_x(), curr->val->get_y()+curr->val->get_vertical_speed()) && curr->val->get_vertical_speed() > 0){
355 curr->val->set_vertical_speed( curr->val->get_vertical_speed() - 1 );
356 }
357
358 //V=Vo+at
359 curr->val->set_vertical_speed( curr->val->get_vertical_speed() + (GRAVITY*curr->val->get_falltime()));
360
361 //translate.
362 curr->val->set_y( curr->val->get_y() + curr->val->get_vertical_speed());
363 }
364
365 //NEXT
366 curr = curr->next;
367 }
368 }
369
370 void Game_overwatch::reset_collisions(){
371 citizen *curr;
372 curr = head;
373 while (curr != NULL){
374 curr->val->set_collision(false, LEFT);
375 curr->val->set_collision(false, RIGHT);
376 curr->val->set_collision(false, DOWN);
377 curr->val->set_collision(false, UP);
378 curr = curr->next;
379 }
380 }
381
382 void Game_overwatch::dieloop(){
383
384 //The kill loop:
385 // Every frame, we find out who needs to be killed
386 // We kill them all.
387
388 citizen *curr;
389 curr = head;
390 while (curr != NULL){
391 bool killthis = false;
392 if ( curr->val->get_dying() ){
393 killthis = true;
394 }
395
396 if (killthis){
397 Actor *victim = curr->val;
398 curr = curr->next;
399 this->kill(victim);
400 }else{
401 curr = curr->next;
402 }
403 }
404 }
405
406 void Game_overwatch::kill(Actor *actor){
407
408 //This should probably delegate to the lua die function
409 //So it can animate/change states.
410
411 if ( actor->get_controllable() ){
412 actor->set_x(50);
413 actor->set_y(100);
414 actor->set_dying(false);
415 }else{
416 delete actor;
417 actor = NULL;
418 }
419 }