view trix/src/game.c @ 12:24d60bdea349

ClonneChannel
author prymula <prymula76@outlook.com>
date Thu, 08 Feb 2024 20:24:27 +0100
parents 2787f5e749ae
children
line wrap: on
line source

/* 
 * 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; l<k; l++) {
            /* jesli jest jakis klocek to wyskakuje z petli */
            if (field[i+1][25-l].type) break;
         }
//         printf ("  L: %d\n", l);
         
         /* gdy brak elementow na przedpolu mozna przesowac */
         if (k == l) {
             j=25;
            /* przesowa kolejno elementy ustawione pionowo oprocz 
               eksplozji i zanikniec */
            while (field[i][j].type && field[i][j].status != FADE) {
               
               field[i+1][j] = field[i][j];

               field[i][j].status = 0;
               field[i][j].type = NULL;
               --j;          
            }
         }
         
      }
   }
   
}


void start_game(void) {

   int done;
   char buffor[100]; 
   int i, j, x, y;
   int move=1; // zmienna odpowiedzialna za przesowanie elem. gornel listwy
   int over =-1; // zmienna odpowiedzialna za pojawienie sie napisu game over
   int virtual_level, level;
   int vis, drop_slat, pic;
   SDL_Rect srcrect, destrect;
   SDL_bool only_bomb = SDL_FALSE;
   
   /*
   struct data_levels data_level[10] = {
      {85, 200, 0},
      {90, 200, 0},
      {99, 150, 0},
      {99, 150, 0},
      {106, 150, 0},
      {111, 100, 0},
      {111, 150, 1},
      {111, 100, 1},
      {116, 150, 1},
      {116, 100, 1}};   
*/
	struct data_levels data_level[10] = {
      {85, 200, 0},
      {90, 200, 0},
      {99, 150, 0},
      {99, 150, 0},
      {106, 200, 0},
      {106, 150, 0},
      {85, 200, 1},
      {90, 200, 1},
      {99, 150, 1},
      {111, 100, 1}};   
 
   virtual_level = level = start_level;
   score = 0;
   srand(time(NULL));
   
   destrect = set_rect(0,0,screen->w,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);   

}