2016年1月13日 星期三

SDL - Step7俄羅斯方塊


螢幕截圖:

#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<math.h>
#include"SDL/SDL.h"
#define height 400
#define width 400
#define speed 20
struct brick
{
 SDL_Rect a;
 int appearance;//the number of box
 struct brick *next;
};
typedef struct brick BRICK;
//方塊初始座標
int O[8]={80,100,100,80,20,20,0,0};
int I[8]={80,80,80,80,60,40,20,0};
int J[8]={100,80,80,80,0,40,20,0};
int L[8]={100,80,80,80,40,40,20,0};
int S[8]={100,100,80,80,40,20,20,0};
int Z[8]={80,80,100,100,40,20,20,0};
int T[8]={100,80,80,80,20,40,20,0};
void Create(int R[],int c);
void Button(void);
void Overlapping(void);
void Boundary(void);
void Correct(void);
void GameOver(void);
void JudgePositionAfterCorrect(void);
void Rotation(void);
void MoveToDown(BRICK *deliver);
void LeftAndRight(void);
void Drop(void);
void Cancellation(void);
BRICK *first,*current,*previous,*temp;
bool running=true,move=false,correcting=false,DN=false,LR=false,dropping=false;
int dx=20,dy=speed,number=0,acount=0,cycle=0,i,j,p,Cx,Cy,J1,I1,J2,I2,ee=0;
int main()
{
 printf("=======================\n");
 printf("= SPACE - high down   =\n");
 printf("= UP    - rotate      =\n");
 printf("= DOWN  - slow down   =\n");
 printf("= LEFT  - left        =\n");
 printf("= RIGHT - right       =\n");
 printf("=======================\n");
 SDL_Init(SDL_INIT_EVERYTHING);
 SDL_Surface* screen;
 screen=SDL_SetVideoMode(width,height,32,SDL_SWSURFACE);
 SDL_WM_SetCaption("---Tetris---",NULL);
 Uint32 bg=SDL_MapRGB(screen->format,0xff,0xff,0xff);//the color of background
 Uint32 bg1=SDL_MapRGB(screen->format,240,240,240);//the color of bacdground-1
 Uint32 color[7];//the color of box
 color[0]=SDL_MapRGB(screen->format,240,0,0);
 color[1]=SDL_MapRGB(screen->format,0,240,0);
 color[2]=SDL_MapRGB(screen->format,0,0,240);
 color[3]=SDL_MapRGB(screen->format,240,240,0);
 color[4]=SDL_MapRGB(screen->format,0,240,240);
 color[5]=SDL_MapRGB(screen->format,240,0,240);
 color[6]=SDL_MapRGB(screen->format,200,200,0);
 SDL_Rect ss[20][10];//the box of background
 for(i=0;i<20;i++)//set the value to the box of background
 {
  for(j=0;j<10;j++)
  {
   ss[i][j].x=j*20;
   ss[i][j].y=i*20;
   ss[i][j].w=20;
   ss[i][j].h=20;
  }
 }
 srand(time(NULL));
 //printf("Now Loading.......\n");
 //SDL_Delay(1000);
 while(running)
 { 
  if(cycle>0)Cancellation();
  if(move==false)//increase the box
  {
   p=rand()%7;
   if(p==0)Create(O,p);
   if(p==1)Create(I,p);
   if(p==2)Create(J,p);
   if(p==3)Create(L,p);
   if(p==4)Create(S,p);
   if(p==5)Create(Z,p);
   if(p==6)Create(T,p);
   GameOver();
   acount=0;
  }
  //Button();
  if(cycle%8==0)MoveToDown(first);
  if(LR)LeftAndRight();//if left or right was pushed
  if(DN)MoveToDown(first);//if down was pushed
  if(dropping)Drop();//if space was pushed
  //check the condition
  Overlapping();
  Boundary();
  if(correcting)Correct();
  //------------------------
  Overlapping();
  Boundary();
  //increase the box
  if(correcting)Correct();
  //------------------------
  JudgePositionAfterCorrect();
  //Display all box
  SDL_FillRect(screen,&screen->clip_rect,bg1);//background
  for(i=0;i<20;i++)//background
   for(j=0;j<10;j++)
    if(i%2==0&&j%2==1)
     SDL_FillRect(screen,&ss[i][j],bg);
    else if(i%2==1&&j%2==0)
     SDL_FillRect(screen,&ss[i][j],bg);
    else
     SDL_FillRect(screen,&ss[i][j],bg1);
  current=first;//the box
  while(current!=NULL)
  {
   if(current->appearance==0)SDL_FillRect(screen,&current->a,color[0]);
   if(current->appearance==1)SDL_FillRect(screen,&current->a,color[1]);
   if(current->appearance==2)SDL_FillRect(screen,&current->a,color[2]);
   if(current->appearance==3)SDL_FillRect(screen,&current->a,color[3]);
   if(current->appearance==4)SDL_FillRect(screen,&current->a,color[4]);
   if(current->appearance==5)SDL_FillRect(screen,&current->a,color[5]);
   if(current->appearance==6)SDL_FillRect(screen,&current->a,color[6]);
   current=current->next;
  }
  SDL_Flip(screen);
  SDL_Delay(120);//Delay
  cycle++;
  Button();
 }
 SDL_Quit();
}
void Button(void)
{
 SDL_Event event;
 while(SDL_PollEvent(&event))
 {
  switch(event.type)
  {
   case SDL_QUIT:
                  running=false;
                  break;
   case SDL_KEYDOWN:
                  switch(event.key.keysym.sym)
                  {
                     case SDLK_ESCAPE://Quit
                           running=false;
                           break;
     case SDLK_SPACE://Drop
      dropping=true;
      break;
     case SDLK_UP://rotation
      Rotation();
      break;
     case SDLK_DOWN:
      dy=20;
      DN=true;
      break;
     case SDLK_LEFT:
      dx=-20;
      LR=true;
      break;
     case SDLK_RIGHT:
      dx=20;
      LR=true;
      break;
    }
    break;
   case SDL_KEYUP:
    switch(event.key.keysym.sym)
    {
     case SDLK_DOWN:
      dy=speed;
      DN=false;
      break;
     case SDLK_LEFT:
      LR=false;
      break;
     case SDLK_RIGHT:
      LR=false;
      break;
    }
    break;
  }
 }
}
void Create(int R[],int c)
{ 
 //printf("-create-%d\n",number);
 int i; 
 for(i=0;i<4;i++)
 {
  current=(BRICK *)malloc(sizeof(BRICK));
  current->a.x=R[i];
  current->a.y=R[i+4];
  current->a.w=20;
  current->a.h=20;
  current->appearance=c;
  if(number==0&&i==0)
  {
   first=current;
   current->next=NULL;
   //previous=current;
  }
  else
  {
   current->next=first;
   first=current;
  }
 }
 number++;
 move=true;
}
void Overlapping(void)
{
 //printf("-Overlapping\n");
 current=first;
 i=0;
 while(i<4)
 {
  temp=first;
  for(j=0;j<4;j++)temp=temp->next;
  while(temp!=NULL)
   {
   if(current->a.y==temp->a.y)
   {
    if(current->a.x==temp->a.x)correcting=true;
   }
   temp=temp->next;
  }
  current=current->next;
  i++;
 }
}
void Boundary(void)
{
 //printf("--BottomAndBoundary\n");
 current=first;
 i=0;
 while(i<4)
 {
  if(current->a.x<0)correcting=true;
  if(current->a.x>200-current->a.w)correcting=true;
  current=current->next;
  i++;
 }
}
void Correct(void)
{
 //printf("Correct\n");
 current=first;
 for(j=0;j<4;j++)
 {
  current->a.x=current->a.x-dx;
  current=current->next;
 }
 correcting=false;
}
void GameOver(void)
{
 //Game over
 current=first;
 i=0;
 while(i<4)
 {
  temp=first;
  for(j=0;j<4;j++)temp=temp->next;
  while(temp!=NULL)
  {
   if(current->a.x==temp->a.x)
   {
    if(current->a.y==temp->a.y)running=false;
   }
   temp=temp->next;
  }
  current=current->next;
  i++;
 }
 if(running==false)printf("Game Over!!\n");
}
void JudgePositionAfterCorrect(void)
{
 current=first;
 i=0;
 while(i<4)
 {
  temp=first;
  for(j=0;j<4;j++)temp=temp->next;
  while(temp!=NULL)
  {
   if(current->a.x==temp->a.x)
   {
    if(current->a.y==temp->a.y-20)move=false;
   }
   temp=temp->next;
  }
  if(current->a.y>=400-current->a.h)
  {
   current->a.y=400-current->a.h;
   move=false;
  }
  current=current->next;
  i++;
 }
}
void Rotation(void)
{
 current=first; 
 J1=current->a.x;
 I1=current->a.y;
 switch(p)//find the center(Cx,Cy) of box
 {
  case 1:
   if(acount==0)
   {
    Cx=((J1+20)+J1)/2;
    Cy=((I1+80)+I1)/2;
   }
   if(acount==1)
   {
    Cx=((J1-60)+(J1+20))/2;
    Cy=((I1+20)+I1)/2;
   }
   if(acount==2)
   {
    Cx=((J1+20)+J1)/2;
    Cy=((I1-60)+(I1+20))/2;
   }
   if(acount==3)
   {
    Cx=((J1+80)+J1)/2;
    Cy=((I1+20)+I1)/2;
   }
   break;
  case 2:
  case 3:
  case 4:
  case 6:
   if(acount==0)
   {
    Cx=((J1+40)+J1)/2;
    Cy=((I1+60)+I1)/2;
   }
   if(acount==1)
   {
    Cx=((J1-40)+(J1+20))/2;
    Cy=((I1+40)+I1)/2;
   }
   if(acount==2)
   {
    Cx=J1;
    Cy=((I1-40)+(I1+20))/2;
   }
   if(acount==3)
   {
    Cx=((J1+60)+J1)/2;
    Cy=I1;
   }
   break;
  case 5:
   if(acount==0)
   {
    Cx=J1;
    Cy=((I1+60)+I1)/2;
   }
   if(acount==1)
   {
    Cx=((J1-40)+(J1+20))/2;
    Cy=I1;
   }
   if(acount==2)
   {
    Cx=((J1+40)+J1)/2;
    Cy=((I1-40)+(I1+20))/2;
   }
   if(acount==3)
   {
    Cx=((J1+60)+J1)/2;
    Cy=((I1+40)+I1)/2;
   }
   break;
 }
 i=0;//(J1,I1)->(J2,I2)
 while(i<4)
 {
  if(p==0)break;
  J1=current->a.x;
  I1=current->a.y;
  //J2=(J1-Cx)*cos(Theta)-(I1-Cy)*sin(Theta)+Cx
  //I2=(J1-Cx)*sin(Theta)+(I1-Cy)*cos(Theta)+Cy
  J2=(0-(I1-Cy)*1)+Cx;
  I2=((J1-Cx)*1)+Cy;
  //------------------------------
  if(acount>=2)current->a.x=J2-30;
  else
   current->a.x=J2-10;
  if(acount%2==0)current->a.y=I2-10;
  else
   current->a.y=I2+10;
  current=current->next;
  i++;
 }
 if(acount==3)acount=0;
 else
  acount++;
}
void MoveToDown(BRICK *deliver)
{
 i=0;
 while(i<4)
 {
  deliver->a.y=deliver->a.y+dy;
  deliver=deliver->next;
  i++;
 }
}
void LeftAndRight(void)
{
 current=first;
 i=0;
 while(i<4)
 {
  current->a.x=current->a.x+dx;
  current=current->next;
  i++;
 }
}
void Drop(void)
{
 while(1)
 {
  MoveToDown(first);
  JudgePositionAfterCorrect();
  if(move==false)break;
 }
 dropping=false;
}
void Cancellation(void)
{
 i=0;
 while(i<=380)
 { 
  current=first;
  for(j=0;j<4;j++)current=current->next;
  while(current!=NULL)
  {
   if(current->a.y==i)ee++;
   current=current->next;
  }
  if(ee==10)
  { 
   current=first;
   //for(j=0;j<4;j++)current=current->next;
   while(current!=NULL)//delete the node
   {
    if(current->a.y!=i)
    {
     temp=current;
     current=current->next;
    }
    else
    {
     temp->next=current->next;
     previous=current;
     current=current->next;
     free(previous);
    }
   }
   current=first;
   //for(j=0;j<4;j++)current=current->next;
   while(current!=NULL)
   {
    if(current->a.y<i)current->a.y=current >a.y+20;
    current=current->next;
   }
  }
  ee=0;
  i=i+20;
 }
}

沒有留言:

張貼留言