/* * Trix - klikanie po klockach * Przemysław R. Pietraszczyk * * paźdżiernik 2006 r. * * licencja: Public Domain */ #include "trix.h" #define X_SCORE_INSCRIPTION 10 #define X_LEVEL_INSCRIPTION 200 #define X_HISCORE_INSCRIPTION 340 #define Y_ALL_INSCRIPTION 0 #define X_HIGH_SLAT 1 #define Y_HIGH_SLAT 40 #define X_SIZE_HIGH_SLAT (screen->w) #define Y_SIZE_HIGH_SLAT FIELD_SIZE #define X_ACTION 1 #define Y_ACTION 60 #define X_SIZE_ACTION (screen->w) #define Y_SIZE_ACTION (screen->h) /* // z trix.h begin SDL_Surface * block[8]; SDL_Surface * explode; SDL_Surface * bomb; SDL_Surface * wall; SDL_Surface * smoke; SDL_Surface * net; SDL_Surface * banner; SDL_Surface * bg; SDL_Surface * screen; TTF_Font* font; SDL_Renderer * renderer; SDL_Texture * tex_screen; SDL_Rect source, dest; int use_net; // zmienna wyswietlania siatki int start_level; // start gry od poziomu ... int score; int bonus; // nalicza premie char * hifile; // path do hiscore int use_net; // zmienna wyswietlania siatki int start_level; // start gry od poziomu ... int score; int bonus; // nalicza premie char * hifile; // path do hiscore struct tab tab_hiscores[5]; char const catalogue[N_PIC][40]; // z trix.h end */ static SDL_Surface * var_level_inscription; static SDL_Surface * var_hiscore_inscription; /* tablica struktur przechowuje pozycje kasowanych elementow */ static struct ghost gh[598]; static int gh_index; SDL_Surface * prepare_text(int r, int b, int g, char *buffer); void load_background(int n); void print_inscription(char * buffor, int desx, int desy); void draw_text (int x, int y, SDL_Surface * image); void get_name_of_player(void); /* sprawdza czy klocki nie osiagnely masymalnej wysokosci */ int behind_high(void) { int i; /* jesli znajdzie na szczycie jakis klocek o stalym statusie zwraca prawde */ for (i=0; i<23; ++i) { if (field[i][1].type && field[i][1].status == STAND) return 1; } return 0; } /* zeruje strukture elementow */ void zero_field(void) { int i, j; for (j=0; j<26;++j) { for (i=0; i<23;++i) { field[i][j].type = NULL; field[i][j].status=0; } } } void set_background(void) { SDL_Rect srcrect, destrect; destrect = set_rect(0, 0, bg->w, bg->h); srcrect = set_rect(0,0, bg->w, bg->h); SDL_BlitSurface(bg,&srcrect,screen,&destrect); } void set_net(void) { SDL_Rect srcrect, destrect; destrect = set_rect(0, 0, net->w, net->h); srcrect = set_rect(0,0, net->w, net->h); SDL_BlitSurface(net,&srcrect,screen,&destrect); } /* sprawdza czy na planszy sa jakies klocki */ int shortage_blocks(void) { int i, j; for (j=1; j<26; j++) { for (i=0; i<23; i++) { if (field[i][j].type) { if (field[i][j].type == wall) continue; else goto end; } } } end: /* gdy brak klockow */ if (j==26 && i==23) { printf ("brak klockow\n"); return 1; } /* gdy sa klocki */ return 0; } /* elementy zaczynaja opadac z gornej belki */ void drop_from_high_slat(void) { int i; for (i=22; i>=0; --i) { field[i][0].status = DROP; } } void set_element(int f, int x, int y) { switch(f) { // od 0 do 49 pustka case 50 ... 64: field[x][y].type = bomb; break; case 65 ... 73: field[x][y].type = block[0]; break; case 74 ... 80: field[x][y].type = block[1]; break; case 81 ... 85: field[x][y].type = block[2]; break; case 86 ... 90: field[x][y].type = block[3]; break; case 91 ... 99: field[x][y].type = block[4]; break; case 100 ... 106: field[x][y].type = block[5]; break; case 107 ... 111: field[x][y].type = block[6]; break; case 112 ... 116: field[x][y].type = block[7]; break; default: field[x][y].type = NULL; break; } } /* wypelnia studnie elementami */ void fill_board(struct data_levels * dl) { int x, y, f; for (y=24; y>2; --y) { for (x=0; x<23; ++x) { label: f=rand()%dl->max; if (f<40) goto label; set_element(f, x, y); field[x][y].status = DROP; } } } /* gorna listwa */ void high_slat(struct data_levels * dl, SDL_bool only_bomb) { int i, f; /* przesuwamy klocki w prawo */ for (i=22; i>0; --i) field[i][0] = field[i-1][0]; /* losujemy element dla pozycji 0,0 */ if (!only_bomb) f=rand()%dl->max; else f=55; set_element(f, 0, 0); field[0][0].status = 0; } /* funkcja sprawdza status elementu i jesli element opada to obniza element na planszy */ void drop_elements(void) { int j, i; for (j=25; j>=0; --j) { for (i=0; i<23; ++i) { if (field[i][j].status == DROP) { /* jesli analizowana pozycja jest pusta */ if (!field[i][j+1].type) { field[i][j+1] = field[i][j]; // wyzerowanie poprzedniej pozycji field[i][j].status = 0; field[i][j].type = NULL; /* osiadlo na dnie */ if (j==24) { field[i][j+1].status = STAND; } } /* wprzeciwnym wypadku stawiamy element na elemencie */ else { field[i][j].status = STAND; } } } } } /* kasuje elementy po skasowaniu klockow badz wybuchu bomb */ void delete_elements(void) { int x, y; /* to musi byc przynajmniej para wiec mozna tak sprawdzac */ if (gh_index) { /* index jest o jeden wiekszy trzeba go zmnniejszyc */ gh_index--; printf ("gh_index: %d\n", gh_index); do { /* kasowanie elementow po zniknieciu lub wybuchu */ field[gh[gh_index].x][gh[gh_index].y].type = NULL; field[gh[gh_index].x][gh[gh_index].y].status = 0; printf ("kasowanie x: %d y: %d\n", gh[gh_index].x, gh[gh_index].y); x = gh[gh_index].x; y = gh[gh_index].y - 1; // dotyczy elementu znajdujacego sie nad kasowanym elementem // gh[gh_index].x = 0; // gh[gh_index].y = 0; /* zmiana statusu elementom znajdujacym sie wyzej o ile nie znikaja */ while (y>1 && field[x][y].status == STAND) { field[x][y].status = DROP; --y; } }while(gh_index--); gh_index = 0; } } /* wyszukuje klocki o tym samym kolorze i zmienia je w dymek*/ void search_block(SDL_Surface * color, int x, int y) { // printf ("s... type: %p color: %p x: %d y: %d\n", field[x][y].type, color, x, y); if (field[x][y].type == color && field[x][y].status == STAND) { printf ("Fade : %p color %p x: %d y: %d\n", field[x][y].type, color, x, y); field[x][y].status = FADE; field[x][y].type = smoke; score++; bonus++; /* zapamietuje pozycje ktora trzeba bedzie pozniej skasowac */ // printf ("gh_index = %d\n", gh_index); gh[gh_index].x = x; gh[gh_index].y = y; gh_index++; /* nastepne klocki do sprawdzenia */ if (y<25) search_block(color, x, y+1); if (y>1) search_block(color,x, y-1); if (x>0) search_block(color, x-1, y); if (x<22) search_block(color,x+1, y); } } /* szuka pary do skasowania */ void pre_delete_block(int x, int y) { // printf ("\npre_delete: %p x: %d y: %d \n\n", field[x][y].type, x, y); /* szuka przynajmniej pary */ if (field[x][y].type == field[x][y+1].type || field[x][y].type == field[x][y-1].type || field[x][y].type == field[x+1][y].type || field[x][y].type == field[x-1][y].type && field[x][y].status == STAND) { if (y<25) search_block(field[x][y].type, x, y+1); if (y>1) search_block(field[x][y].type, x, y-1); if (x>0) search_block(field[x][y].type, x-1, y); if (x<22) search_block(field[x][y].type, x+1, y); // raczej niepotrzebne juz // field[x][y].status = FADE; // field[x][y].type = smoke; } } /* eksplozja elementow znajdujacych sie wokol bomb */ void power_strike (int x, int y){ if (field[x][y].type != bomb && field[x][y].status == STAND) { field[x][y].status = FADE; field[x][y].type = explode; /* zapamietuje pozycje ktora trzeba bedzie pozniej skasowac */ gh[gh_index].x = x; gh[gh_index].y = y; gh_index++; } } /* szuka bomb i dokonuje eksplozji */ void search_bomb(int x, int y) { if (field[x][y].type == bomb && field[x][y].status == STAND) { printf ("Fade : %p bomb %p x: %d y: %d\n", field[x][y].type, bomb, x, y); field[x][y].status = FADE; field[x][y].type = explode; /* zapamietuje pozycje ktora trzeba bedzie pozniej skasowac */ gh[gh_index].x = x; gh[gh_index].y = y; gh_index++; /* nastepne klocki do sprawdzenia */ if (y<25) search_bomb(x, y+1); if (y>1) search_bomb(x, y-1); if (x>0) search_bomb(x-1, y); if (x<22) search_bomb(x+1, y); if (x>0 && y>1) search_bomb(x-1, y-1); if (x<22 && y>1) search_bomb(x+1, y-1); if (x>0 && y<25) search_bomb(x-1, y+1); if (x<22 && y<25) search_bomb(x+1, y+1); /* sila razenia */ if (y<25) power_strike(x, y+1); if (y>1) power_strike(x, y-1); if (x>0) power_strike(x-1, y); if (x<22) power_strike(x+1, y); if (x>0 && y>1) power_strike(x-1, y-1); if (x<22 && y>1) power_strike(x+1, y-1); if (x>0 && y<25) power_strike(x-1, y+1); if (x<22 && y<25) power_strike(x+1, y+1); } } /* szuka pary bomb */ void pre_delete_bomb(int x, int y) { /* szuka przynajmniej pary */ if (field[x][y].type == field[x][y+1].type || field[x][y].type == field[x][y-1].type || field[x][y].type == field[x+1][y].type || field[x][y].type == field[x-1][y].type && field[x][y].status == STAND) { if (y<25) search_bomb(x, y+1); if (y>1) search_bomb(x, y-1); if (x>0) search_bomb(x-1, y); if (x<22) search_bomb(x+1, y); } } /* sprawdza czy mozna dosunac elemnty do prawej strony */ //void check_before_field(void) { void on_the_right(void) { int i,j,k,l; for (i=21; i>=0; --i) { /* jesli pole przed elementem jest puste */ if (!field[i+1][25].type && field[i][25].status == STAND) { /* sprawdza jak wysoko siegaja kolocki */ k=0; // while(field[i][25-k].type && field[i][25-k].status == STAND)k++; while(field[i][25-k].type)k++; ++k; // printf (" K: %d\n", k); /* sprawdza czy nie wystaja jakies klocki na przedpolu */ for (l=0; lw,screen->h); SDL_FillRect(screen,&destrect,0); //SDL_Flip(screen); sprintf (buffor, "%d", tab_hiscores[0].score); var_hiscore_inscription = (SDL_Surface *) prepare_text(255, 255, 255, buffor); new_level: bonus = 0; sprintf(buffor, "%d", virtual_level); var_level_inscription = (SDL_Surface *) prepare_text(255, 255, 255, buffor); pic = rand()%N_PIC; load_background(pic); drop_slat = data_level[level-1].drop; vis = 15; /* ustawia murek */ if (data_level[level-1].wall) { field[10][25].type = wall; field[10][25].status = WALL; } /* wypelnia studnie elementami */ fill_board(&data_level[level-1]); done = 0; while (!done) { set_background(); if (use_net) set_net(); /* sprawdza czy na planszy sa jakies klocki */ if (shortage_blocks()) { virtual_level++; if (level < 10) level++; SDL_FreeSurface(var_level_inscription); score += bonus *3; goto new_level; } delete_elements(); SDL_Event event; /* Check for events */ while (SDL_PollEvent (&event)) { switch (event.type) { case SDL_KEYDOWN: printf("Nacini�o klawisz: %s\n", SDL_GetKeyName(event.key.keysym.sym)); switch (event.key.keysym.sym) { case SDLK_ESCAPE: done = 1; break; case SDLK_b: if (only_bomb) only_bomb=SDL_FALSE; else only_bomb=SDL_TRUE; break; } break; case SDL_QUIT: exit(0); break; case SDL_MOUSEMOTION: // if (event.motion.state & SDL_BUTTON(1)) // printf("Ruch z pierwszym przyciskeim myszy\n"); // if (event.motion.state & SDL_BUTTON(2)) // printf("Ruch z drugim przyciskiem myszy\n"); // if (event.motion.state & SDL_BUTTON(3)) // printf("Ruch z trzecim przyciskiem myszy\n"); // printf("Przesuni�o myszk�o %d,%d\n", // event.motion.xrel, event.motion.yrel); case SDL_MOUSEBUTTONDOWN: // printf("Nacini�o przycisk o numerze %d na " // "punkcie o wsp�rz�nych %d,%d\n", event.button.button, // event.button.x, event.button.y); if (event.button.button && event.button.x >= X_HIGH_SLAT +1 && event.button.y >= Y_HIGH_SLAT && event.button.x <= X_SIZE_HIGH_SLAT && event.button.y <= (Y_SIZE_HIGH_SLAT + Y_HIGH_SLAT)) { printf ("opadanie\n"); drop_from_high_slat(); move = 0; drop_slat = data_level[level-1].drop; } else if (event.button.button && event.button.x >= X_ACTION && event.button.y >= Y_ACTION && event.button.x <= X_SIZE_ACTION && event.button.y <= Y_SIZE_ACTION) { x=event.button.x/FIELD_SIZE; y=event.button.y/FIELD_SIZE-2; if (field[x][y].type == bomb) pre_delete_bomb(x, y); else if (field[x][y].type) pre_delete_block(x, y); } } } drop_slat--; /* gdy zero program sam zrzuca klocki z gornej listwy */ if (!drop_slat) { drop_from_high_slat(); move = 0; drop_slat = data_level[level-1].drop; } /* przesowa klocki na gornej listwie zapobiegajac przy okazji opadaniu pod katem */ if (!only_bomb){ if (move) high_slat(&data_level[level-1], SDL_FALSE); else move = 1; } else { if (move) high_slat(&data_level[level-1], SDL_TRUE); else move = 1; } /* przesowa elemnty do prawej strony */ on_the_right(); /* opuszcza elementy */ drop_elements(); // for (j=0; j<26; ++j) { // for (i=0; i<23; ++i) { // if (field[i][j].type) // printf ("j: %d i: %d type: %p\n", j, i, field[i][j].type); // } // } // printf("\n\n"); /* umieszczanie elementow na planszy */ srcrect = set_rect(0,0,FIELD_SIZE,FIELD_SIZE); for (j=0; j<26; ++j) { for (i=0; i<23; ++i) { // if (field[i][j].type) // printf ("j: %d i: %d type: %p\n", j, i, field[i][j].type); destrect = set_rect(FIELD_SIZE * i,FIELD_SIZE * j+ 40, FIELD_SIZE, FIELD_SIZE); SDL_BlitSurface(field[i][j].type,&srcrect, screen,&destrect); } } // for (j=0; j<20; ++j) { // for (i=0; i<23; ++i) { // if (field[i][j].status == DROP) putchar('|'); // else if (field[i][j].status == STAND) putchar ('='); // else if (field[i][j].status == 0) putchar(' '); // } // putchar('\n'); // } /* przy rozpoczeciu poziomu wyswietla numer poziomu */ if (vis) { sprintf (buffor, " LEVEL %d", virtual_level); print_inscription(buffor, 190, 200); vis -= 1; } /* sprawdza czy nie ma przepelnienia */ if (behind_high() && over == -1) over = 15; /* wyswietla napis game over */ if (!over) done = 1; else if (over > 0) { strcpy(buffor, "GAME OVER"); print_inscription(buffor, 160, 200); // SDL_UpdateRect(screen, 160, 200, 136, 32); over -= 1; } sprintf (buffor, "%d", score); print_inscription(buffor, 20, Y_ALL_INSCRIPTION); draw_text(X_LEVEL_INSCRIPTION, Y_ALL_INSCRIPTION, var_level_inscription); draw_text(X_HISCORE_INSCRIPTION, Y_ALL_INSCRIPTION, var_hiscore_inscription); // printf ("wysokosc : %d \n", var_hiscore_inscription->h); // SDL_Flip(screen); dest = set_rect(0, 0, screen->w, screen->h); //SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 255, 255, 255)); source = set_rect(0, 0, screen->w, screen->h); tex_screen = SDL_CreateTextureFromSurface(renderer, screen); SDL_RenderClear ( renderer ); SDL_RenderCopy(renderer, tex_screen,&source,&dest); SDL_RenderPresent(renderer); SDL_DestroyTexture(tex_screen); SDL_Delay(300); } /* sprawdza czy jest mozliwosc wpisu */ if (score > tab_hiscores[4].score) { get_name_of_player(); } zero_field(); /* czysci ekran przed powrotem do menu */ destrect = set_rect(0,0,screen->w,screen->h); SDL_FillRect(screen,&destrect,0); // SDL_Flip(screen); source = set_rect(0, 0, screen->w, screen->h); tex_screen = SDL_CreateTextureFromSurface(renderer, screen); SDL_RenderClear ( renderer ); SDL_RenderCopy(renderer, tex_screen,&source,&dest); SDL_RenderPresent(renderer); SDL_DestroyTexture(tex_screen); /* zwalnia pamiec po nieaktualnych obrazkach z liczbami */ SDL_FreeSurface(var_level_inscription); SDL_FreeSurface(var_hiscore_inscription); }