comparison trix/src/game.c @ 0:2787f5e749ae

INIT
author prymula <prymula76@outlook.com>
date Thu, 21 Sep 2023 22:33:57 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:2787f5e749ae
1 /*
2 * Trix - klikanie po klockach
3 * Przemysław R. Pietraszczyk
4 *
5 * paźdżiernik 2006 r.
6 *
7 * licencja: Public Domain
8 */
9
10 #include "trix.h"
11
12 #define X_SCORE_INSCRIPTION 10
13 #define X_LEVEL_INSCRIPTION 200
14 #define X_HISCORE_INSCRIPTION 340
15 #define Y_ALL_INSCRIPTION 0
16
17 #define X_HIGH_SLAT 1
18 #define Y_HIGH_SLAT 40
19 #define X_SIZE_HIGH_SLAT (screen->w)
20 #define Y_SIZE_HIGH_SLAT FIELD_SIZE
21
22 #define X_ACTION 1
23 #define Y_ACTION 60
24 #define X_SIZE_ACTION (screen->w)
25 #define Y_SIZE_ACTION (screen->h)
26
27 /*
28 // z trix.h begin
29 SDL_Surface * block[8];
30 SDL_Surface * explode;
31 SDL_Surface * bomb;
32 SDL_Surface * wall;
33 SDL_Surface * smoke;
34
35 SDL_Surface * net;
36 SDL_Surface * banner;
37 SDL_Surface * bg;
38 SDL_Surface * screen;
39 TTF_Font* font;
40
41 SDL_Renderer * renderer;
42 SDL_Texture * tex_screen;
43
44 SDL_Rect source, dest;
45 int use_net; // zmienna wyswietlania siatki
46 int start_level; // start gry od poziomu ...
47 int score;
48 int bonus; // nalicza premie
49
50 char * hifile; // path do hiscore
51
52
53 int use_net; // zmienna wyswietlania siatki
54 int start_level; // start gry od poziomu ...
55 int score;
56 int bonus; // nalicza premie
57
58 char * hifile; // path do hiscore
59 struct tab tab_hiscores[5];
60 char const catalogue[N_PIC][40];
61 // z trix.h end
62
63 */
64
65
66
67 static SDL_Surface * var_level_inscription;
68 static SDL_Surface * var_hiscore_inscription;
69
70 /* tablica struktur przechowuje pozycje kasowanych elementow */
71 static struct ghost gh[598];
72 static int gh_index;
73
74 SDL_Surface * prepare_text(int r, int b, int g, char *buffer);
75 void load_background(int n);
76 void print_inscription(char * buffor, int desx, int desy);
77 void draw_text (int x, int y, SDL_Surface * image);
78
79 void get_name_of_player(void);
80
81
82
83 /* sprawdza czy klocki nie osiagnely masymalnej wysokosci */
84 int behind_high(void) {
85
86 int i;
87
88 /* jesli znajdzie na szczycie jakis klocek o stalym statusie
89 zwraca prawde */
90 for (i=0; i<23; ++i) {
91 if (field[i][1].type && field[i][1].status == STAND)
92 return 1;
93 }
94
95 return 0;
96 }
97
98 /* zeruje strukture elementow */
99 void zero_field(void) {
100
101 int i, j;
102
103 for (j=0; j<26;++j) {
104 for (i=0; i<23;++i) {
105 field[i][j].type = NULL;
106 field[i][j].status=0;
107 }
108 }
109
110 }
111
112
113 void set_background(void) {
114
115 SDL_Rect srcrect, destrect;
116
117 destrect = set_rect(0, 0, bg->w, bg->h);
118 srcrect = set_rect(0,0, bg->w, bg->h);
119 SDL_BlitSurface(bg,&srcrect,screen,&destrect);
120 }
121
122 void set_net(void) {
123
124 SDL_Rect srcrect, destrect;
125
126 destrect = set_rect(0, 0, net->w, net->h);
127 srcrect = set_rect(0,0, net->w, net->h);
128 SDL_BlitSurface(net,&srcrect,screen,&destrect);
129 }
130
131
132 /* sprawdza czy na planszy sa jakies klocki */
133 int shortage_blocks(void) {
134
135 int i, j;
136
137 for (j=1; j<26; j++) {
138 for (i=0; i<23; i++) {
139 if (field[i][j].type) {
140 if (field[i][j].type == wall) continue;
141 else goto end;
142 }
143 }
144 }
145
146 end:
147 /* gdy brak klockow */
148 if (j==26 && i==23) {
149 printf ("brak klockow\n");
150 return 1;
151 }
152
153 /* gdy sa klocki */
154 return 0;
155
156
157 }
158
159
160 /* elementy zaczynaja opadac z gornej belki */
161 void drop_from_high_slat(void) {
162
163 int i;
164
165 for (i=22; i>=0; --i) {
166 field[i][0].status = DROP;
167 }
168 }
169
170 void set_element(int f, int x, int y) {
171
172 switch(f) {
173 // od 0 do 49 pustka
174 case 50 ... 64:
175 field[x][y].type = bomb;
176 break;
177 case 65 ... 73:
178 field[x][y].type = block[0];
179 break;
180 case 74 ... 80:
181 field[x][y].type = block[1];
182 break;
183 case 81 ... 85:
184 field[x][y].type = block[2];
185 break;
186 case 86 ... 90:
187 field[x][y].type = block[3];
188 break;
189 case 91 ... 99:
190 field[x][y].type = block[4];
191 break;
192 case 100 ... 106:
193 field[x][y].type = block[5];
194 break;
195 case 107 ... 111:
196 field[x][y].type = block[6];
197 break;
198 case 112 ... 116:
199 field[x][y].type = block[7];
200 break;
201 default:
202 field[x][y].type = NULL;
203 break;
204 }
205 }
206
207 /* wypelnia studnie elementami */
208 void fill_board(struct data_levels * dl) {
209
210 int x, y, f;
211
212 for (y=24; y>2; --y) {
213 for (x=0; x<23; ++x) {
214 label:
215 f=rand()%dl->max;
216 if (f<40) goto label;
217 set_element(f, x, y);
218
219 field[x][y].status = DROP;
220 }
221 }
222
223 }
224
225
226 /* gorna listwa */
227 void high_slat(struct data_levels * dl, SDL_bool only_bomb) {
228
229 int i, f;
230
231 /* przesuwamy klocki w prawo */
232 for (i=22; i>0; --i)
233 field[i][0] = field[i-1][0];
234
235 /* losujemy element dla pozycji 0,0 */
236 if (!only_bomb) f=rand()%dl->max;
237 else f=55;
238
239 set_element(f, 0, 0);
240
241 field[0][0].status = 0;
242
243 }
244
245 /* funkcja sprawdza status elementu i jesli
246 element opada to obniza element na planszy */
247 void drop_elements(void) {
248
249 int j, i;
250
251
252 for (j=25; j>=0; --j) {
253 for (i=0; i<23; ++i) {
254 if (field[i][j].status == DROP) {
255
256 /* jesli analizowana pozycja jest pusta */
257 if (!field[i][j+1].type) {
258 field[i][j+1] = field[i][j];
259
260
261 // wyzerowanie poprzedniej pozycji
262 field[i][j].status = 0;
263 field[i][j].type = NULL;
264
265 /* osiadlo na dnie */
266 if (j==24) {
267 field[i][j+1].status = STAND;
268 }
269 }
270 /* wprzeciwnym wypadku stawiamy element na
271 elemencie */
272 else {
273 field[i][j].status = STAND;
274 }
275
276
277
278
279 }
280 }
281 }
282
283 }
284
285 /* kasuje elementy po skasowaniu klockow badz wybuchu bomb */
286 void delete_elements(void) {
287
288 int x, y;
289
290 /* to musi byc przynajmniej para wiec mozna
291 tak sprawdzac */
292 if (gh_index) {
293
294 /* index jest o jeden wiekszy trzeba go zmnniejszyc */
295 gh_index--;
296
297 printf ("gh_index: %d\n", gh_index);
298
299 do {
300 /* kasowanie elementow po zniknieciu lub wybuchu */
301 field[gh[gh_index].x][gh[gh_index].y].type = NULL;
302 field[gh[gh_index].x][gh[gh_index].y].status = 0;
303
304 printf ("kasowanie x: %d y: %d\n", gh[gh_index].x, gh[gh_index].y);
305
306 x = gh[gh_index].x;
307 y = gh[gh_index].y - 1; // dotyczy elementu znajdujacego sie nad kasowanym elementem
308
309 // gh[gh_index].x = 0;
310 // gh[gh_index].y = 0;
311
312 /* zmiana statusu elementom znajdujacym sie wyzej
313 o ile nie znikaja */
314 while (y>1 && field[x][y].status == STAND) {
315 field[x][y].status = DROP;
316 --y;
317 }
318
319 }while(gh_index--);
320 gh_index = 0;
321 }
322 }
323
324
325
326
327 /* wyszukuje klocki o tym samym kolorze i zmienia je w dymek*/
328 void search_block(SDL_Surface * color, int x, int y) {
329
330 // printf ("s... type: %p color: %p x: %d y: %d\n", field[x][y].type, color, x, y);
331
332 if (field[x][y].type == color && field[x][y].status == STAND) {
333
334 printf ("Fade : %p color %p x: %d y: %d\n", field[x][y].type, color, x, y);
335
336 field[x][y].status = FADE;
337 field[x][y].type = smoke;
338 score++;
339 bonus++;
340
341 /* zapamietuje pozycje ktora trzeba bedzie pozniej skasowac */
342 // printf ("gh_index = %d\n", gh_index);
343 gh[gh_index].x = x;
344 gh[gh_index].y = y;
345 gh_index++;
346
347 /* nastepne klocki do sprawdzenia */
348 if (y<25) search_block(color, x, y+1);
349 if (y>1) search_block(color,x, y-1);
350 if (x>0) search_block(color, x-1, y);
351 if (x<22) search_block(color,x+1, y);
352
353
354 }
355
356 }
357
358 /* szuka pary do skasowania */
359 void pre_delete_block(int x, int y) {
360
361
362 // printf ("\npre_delete: %p x: %d y: %d \n\n", field[x][y].type, x, y);
363
364 /* szuka przynajmniej pary */
365 if (field[x][y].type == field[x][y+1].type ||
366 field[x][y].type == field[x][y-1].type ||
367 field[x][y].type == field[x+1][y].type ||
368 field[x][y].type == field[x-1][y].type && field[x][y].status == STAND) {
369
370
371 if (y<25) search_block(field[x][y].type, x, y+1);
372 if (y>1) search_block(field[x][y].type, x, y-1);
373 if (x>0) search_block(field[x][y].type, x-1, y);
374 if (x<22) search_block(field[x][y].type, x+1, y);
375
376 // raczej niepotrzebne juz
377 // field[x][y].status = FADE;
378 // field[x][y].type = smoke;
379
380 }
381
382
383 }
384 /* eksplozja elementow znajdujacych sie wokol bomb */
385 void power_strike (int x, int y){
386
387 if (field[x][y].type != bomb && field[x][y].status == STAND) {
388
389 field[x][y].status = FADE;
390 field[x][y].type = explode;
391
392 /* zapamietuje pozycje ktora trzeba bedzie pozniej skasowac */
393 gh[gh_index].x = x;
394 gh[gh_index].y = y;
395 gh_index++;
396 }
397
398 }
399
400 /* szuka bomb i dokonuje eksplozji */
401 void search_bomb(int x, int y) {
402
403 if (field[x][y].type == bomb && field[x][y].status == STAND) {
404
405 printf ("Fade : %p bomb %p x: %d y: %d\n", field[x][y].type, bomb, x, y);
406
407 field[x][y].status = FADE;
408 field[x][y].type = explode;
409
410 /* zapamietuje pozycje ktora trzeba bedzie pozniej skasowac */
411 gh[gh_index].x = x;
412 gh[gh_index].y = y;
413 gh_index++;
414
415 /* nastepne klocki do sprawdzenia */
416 if (y<25) search_bomb(x, y+1);
417 if (y>1) search_bomb(x, y-1);
418 if (x>0) search_bomb(x-1, y);
419 if (x<22) search_bomb(x+1, y);
420 if (x>0 && y>1) search_bomb(x-1, y-1);
421 if (x<22 && y>1) search_bomb(x+1, y-1);
422 if (x>0 && y<25) search_bomb(x-1, y+1);
423 if (x<22 && y<25) search_bomb(x+1, y+1);
424
425 /* sila razenia */
426 if (y<25) power_strike(x, y+1);
427 if (y>1) power_strike(x, y-1);
428 if (x>0) power_strike(x-1, y);
429 if (x<22) power_strike(x+1, y);
430 if (x>0 && y>1) power_strike(x-1, y-1);
431 if (x<22 && y>1) power_strike(x+1, y-1);
432 if (x>0 && y<25) power_strike(x-1, y+1);
433 if (x<22 && y<25) power_strike(x+1, y+1);
434
435
436 }
437
438 }
439
440 /* szuka pary bomb */
441 void pre_delete_bomb(int x, int y) {
442
443 /* szuka przynajmniej pary */
444 if (field[x][y].type == field[x][y+1].type ||
445 field[x][y].type == field[x][y-1].type ||
446 field[x][y].type == field[x+1][y].type ||
447 field[x][y].type == field[x-1][y].type && field[x][y].status == STAND) {
448
449
450 if (y<25) search_bomb(x, y+1);
451 if (y>1) search_bomb(x, y-1);
452 if (x>0) search_bomb(x-1, y);
453 if (x<22) search_bomb(x+1, y);
454
455 }
456 }
457
458 /* sprawdza czy mozna dosunac elemnty do prawej strony */
459 //void check_before_field(void) {
460 void on_the_right(void) {
461
462 int i,j,k,l;
463
464 for (i=21; i>=0; --i) {
465
466 /* jesli pole przed elementem jest puste */
467 if (!field[i+1][25].type && field[i][25].status == STAND) {
468
469 /* sprawdza jak wysoko siegaja kolocki */
470 k=0;
471 // while(field[i][25-k].type && field[i][25-k].status == STAND)k++;
472 while(field[i][25-k].type)k++;
473 ++k;
474
475 // printf (" K: %d\n", k);
476
477 /* sprawdza czy nie wystaja jakies klocki na przedpolu */
478 for (l=0; l<k; l++) {
479 /* jesli jest jakis klocek to wyskakuje z petli */
480 if (field[i+1][25-l].type) break;
481 }
482 // printf (" L: %d\n", l);
483
484 /* gdy brak elementow na przedpolu mozna przesowac */
485 if (k == l) {
486 j=25;
487 /* przesowa kolejno elementy ustawione pionowo oprocz
488 eksplozji i zanikniec */
489 while (field[i][j].type && field[i][j].status != FADE) {
490
491 field[i+1][j] = field[i][j];
492
493 field[i][j].status = 0;
494 field[i][j].type = NULL;
495 --j;
496 }
497 }
498
499 }
500 }
501
502 }
503
504
505 void start_game(void) {
506
507 int done;
508 char buffor[100];
509 int i, j, x, y;
510 int move=1; // zmienna odpowiedzialna za przesowanie elem. gornel listwy
511 int over =-1; // zmienna odpowiedzialna za pojawienie sie napisu game over
512 int virtual_level, level;
513 int vis, drop_slat, pic;
514 SDL_Rect srcrect, destrect;
515 SDL_bool only_bomb = SDL_FALSE;
516
517 /*
518 struct data_levels data_level[10] = {
519 {85, 200, 0},
520 {90, 200, 0},
521 {99, 150, 0},
522 {99, 150, 0},
523 {106, 150, 0},
524 {111, 100, 0},
525 {111, 150, 1},
526 {111, 100, 1},
527 {116, 150, 1},
528 {116, 100, 1}};
529 */
530 struct data_levels data_level[10] = {
531 {85, 200, 0},
532 {90, 200, 0},
533 {99, 150, 0},
534 {99, 150, 0},
535 {106, 200, 0},
536 {106, 150, 0},
537 {85, 200, 1},
538 {90, 200, 1},
539 {99, 150, 1},
540 {111, 100, 1}};
541
542 virtual_level = level = start_level;
543 score = 0;
544 srand(time(NULL));
545
546 destrect = set_rect(0,0,screen->w,screen->h);
547 SDL_FillRect(screen,&destrect,0);
548 //SDL_Flip(screen);
549
550
551 sprintf (buffor, "%d", tab_hiscores[0].score);
552 var_hiscore_inscription = (SDL_Surface *) prepare_text(255, 255, 255, buffor);
553
554 new_level:
555 bonus = 0;
556
557 sprintf(buffor, "%d", virtual_level);
558 var_level_inscription = (SDL_Surface *) prepare_text(255, 255, 255, buffor);
559
560 pic = rand()%N_PIC;
561 load_background(pic);
562
563
564 drop_slat = data_level[level-1].drop;
565 vis = 15;
566
567 /* ustawia murek */
568 if (data_level[level-1].wall) {
569 field[10][25].type = wall;
570 field[10][25].status = WALL;
571 }
572
573
574 /* wypelnia studnie elementami */
575 fill_board(&data_level[level-1]);
576
577 done = 0;
578 while (!done)
579 {
580
581
582
583
584 set_background();
585
586 if (use_net) set_net();
587
588 /* sprawdza czy na planszy sa jakies klocki */
589 if (shortage_blocks()) {
590 virtual_level++;
591 if (level < 10) level++;
592
593 SDL_FreeSurface(var_level_inscription);
594
595 score += bonus *3;
596 goto new_level;
597 }
598
599 delete_elements();
600
601
602 SDL_Event event;
603
604 /* Check for events */
605 while (SDL_PollEvent (&event))
606 {
607 switch (event.type)
608 {
609 case SDL_KEYDOWN:
610 printf("Nacini�o klawisz: %s\n",
611 SDL_GetKeyName(event.key.keysym.sym));
612
613 switch (event.key.keysym.sym) {
614 case SDLK_ESCAPE:
615 done = 1;
616 break;
617 case SDLK_b:
618 if (only_bomb) only_bomb=SDL_FALSE;
619 else only_bomb=SDL_TRUE;
620 break;
621 }
622 break;
623 case SDL_QUIT:
624 exit(0);
625 break;
626 case SDL_MOUSEMOTION:
627 // if (event.motion.state & SDL_BUTTON(1))
628 // printf("Ruch z pierwszym przyciskeim myszy\n");
629
630 // if (event.motion.state & SDL_BUTTON(2))
631 // printf("Ruch z drugim przyciskiem myszy\n");
632
633 // if (event.motion.state & SDL_BUTTON(3))
634 // printf("Ruch z trzecim przyciskiem myszy\n");
635
636 // printf("Przesuni�o myszk�o %d,%d\n",
637 // event.motion.xrel, event.motion.yrel);
638 case SDL_MOUSEBUTTONDOWN:
639 // printf("Nacini�o przycisk o numerze %d na "
640 // "punkcie o wsp�rz�nych %d,%d\n", event.button.button,
641 // event.button.x, event.button.y);
642
643
644 if (event.button.button &&
645 event.button.x >= X_HIGH_SLAT +1 &&
646 event.button.y >= Y_HIGH_SLAT &&
647 event.button.x <= X_SIZE_HIGH_SLAT &&
648 event.button.y <= (Y_SIZE_HIGH_SLAT + Y_HIGH_SLAT)) {
649
650 printf ("opadanie\n");
651 drop_from_high_slat();
652 move = 0;
653 drop_slat = data_level[level-1].drop;
654 }
655 else if (event.button.button &&
656 event.button.x >= X_ACTION &&
657 event.button.y >= Y_ACTION &&
658 event.button.x <= X_SIZE_ACTION &&
659 event.button.y <= Y_SIZE_ACTION) {
660
661 x=event.button.x/FIELD_SIZE;
662 y=event.button.y/FIELD_SIZE-2;
663
664 if (field[x][y].type == bomb)
665 pre_delete_bomb(x, y);
666 else if (field[x][y].type)
667 pre_delete_block(x, y);
668
669 }
670
671
672 }
673 }
674
675
676 drop_slat--;
677 /* gdy zero program sam zrzuca klocki z gornej listwy */
678 if (!drop_slat) {
679 drop_from_high_slat();
680 move = 0;
681 drop_slat = data_level[level-1].drop;
682 }
683
684
685 /* przesowa klocki na gornej listwie zapobiegajac przy okazji
686 opadaniu pod katem */
687 if (!only_bomb){
688 if (move) high_slat(&data_level[level-1], SDL_FALSE);
689 else move = 1;
690 }
691 else {
692 if (move) high_slat(&data_level[level-1], SDL_TRUE);
693 else move = 1;
694 }
695
696 /* przesowa elemnty do prawej strony */
697 on_the_right();
698
699 /* opuszcza elementy */
700 drop_elements();
701
702
703 // for (j=0; j<26; ++j) {
704 // for (i=0; i<23; ++i) {
705
706 // if (field[i][j].type)
707 // printf ("j: %d i: %d type: %p\n", j, i, field[i][j].type);
708 // }
709 // }
710 // printf("\n\n");
711
712
713
714 /* umieszczanie elementow na planszy */
715 srcrect = set_rect(0,0,FIELD_SIZE,FIELD_SIZE);
716 for (j=0; j<26; ++j) {
717 for (i=0; i<23; ++i) {
718
719 // if (field[i][j].type)
720 // printf ("j: %d i: %d type: %p\n", j, i, field[i][j].type);
721
722 destrect = set_rect(FIELD_SIZE * i,FIELD_SIZE * j+ 40, FIELD_SIZE, FIELD_SIZE);
723 SDL_BlitSurface(field[i][j].type,&srcrect, screen,&destrect);
724 }
725 }
726
727 // for (j=0; j<20; ++j) {
728 // for (i=0; i<23; ++i) {
729 // if (field[i][j].status == DROP) putchar('|');
730 // else if (field[i][j].status == STAND) putchar ('=');
731 // else if (field[i][j].status == 0) putchar(' ');
732 // }
733 // putchar('\n');
734 // }
735
736 /* przy rozpoczeciu poziomu wyswietla numer poziomu */
737 if (vis) {
738 sprintf (buffor, " LEVEL %d", virtual_level);
739 print_inscription(buffor, 190, 200);
740 vis -= 1;
741 }
742
743 /* sprawdza czy nie ma przepelnienia */
744 if (behind_high() && over == -1)
745 over = 15;
746 /* wyswietla napis game over */
747 if (!over)
748 done = 1;
749 else if (over > 0) {
750 strcpy(buffor, "GAME OVER");
751 print_inscription(buffor, 160, 200);
752 // SDL_UpdateRect(screen, 160, 200, 136, 32);
753 over -= 1;
754 }
755
756 sprintf (buffor, "%d", score);
757 print_inscription(buffor, 20, Y_ALL_INSCRIPTION);
758 draw_text(X_LEVEL_INSCRIPTION, Y_ALL_INSCRIPTION, var_level_inscription);
759 draw_text(X_HISCORE_INSCRIPTION, Y_ALL_INSCRIPTION, var_hiscore_inscription);
760
761 // printf ("wysokosc : %d \n", var_hiscore_inscription->h);
762
763 // SDL_Flip(screen);
764
765
766
767
768
769 dest = set_rect(0, 0, screen->w, screen->h);
770 //SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255));
771
772 source = set_rect(0, 0, screen->w, screen->h);
773
774 tex_screen = SDL_CreateTextureFromSurface(renderer, screen);
775 SDL_RenderClear ( renderer );
776 SDL_RenderCopy(renderer, tex_screen,&source,&dest);
777 SDL_RenderPresent(renderer);
778 SDL_DestroyTexture(tex_screen);
779
780
781
782
783
784 SDL_Delay(300);
785 }
786
787
788 /* sprawdza czy jest mozliwosc wpisu */
789 if (score > tab_hiscores[4].score) {
790 get_name_of_player();
791 }
792
793 zero_field();
794
795 /* czysci ekran przed powrotem do menu */
796 destrect = set_rect(0,0,screen->w,screen->h);
797 SDL_FillRect(screen,&destrect,0);
798 // SDL_Flip(screen);
799
800 source = set_rect(0, 0, screen->w, screen->h);
801 tex_screen = SDL_CreateTextureFromSurface(renderer, screen);
802 SDL_RenderClear ( renderer );
803 SDL_RenderCopy(renderer, tex_screen,&source,&dest);
804 SDL_RenderPresent(renderer);
805 SDL_DestroyTexture(tex_screen);
806
807 /* zwalnia pamiec po nieaktualnych obrazkach z liczbami */
808 SDL_FreeSurface(var_level_inscription);
809 SDL_FreeSurface(var_hiscore_inscription);
810
811 }
812
813