2023年11月30日 星期四

XX - Week12

 


=========================================================================

TWELTH


先看看Tetris的英文維基百科

先利用rect()+for迴圈畫出背景的格子

照著老師說的利用陣列迴圈if判斷來畫出俄羅斯方塊每個的形狀
註:利用陣列(座標)的技巧可以簡化程式碼

旋轉,原本的打算是直接做旋轉,但後來老師有提醒不要直接做旋轉,所以我就先
使用陣列搭配迴圈做做看旋轉的部分

也順便做了碰到網格的偵測,在旋轉偵測那邊卡了一陣子

控制:目前只有方向鍵能夠控制(上是旋轉)
int CurrentPos[] = new int[2];//當前的形狀
void setup(){
  size(600, 750);
  background(0);
  Current = new Shapes();
  //目前的Tetris
  CurrentPos[0] = 4;//左右,方塊的起始位置
  CurrentPos[1] = 0;//下降,方塊的起始位置
}
int down = 0;
void draw(){
  //Shapes.ShowNext();
  Grid();
  displayCurrent();
  
  down++;//下降
  if (down > 20) {
    down = 0;//直到0
    CurrentPos[1]++;
  }
  StopEmpty();
}
int StopShapes[][] = new int[10][20];
public void Grid(){
  for(int x = 0; x < 10; x++) {
    for(int y = 0; y < 20; y++) {
      //停下來的Tetris
      if(StopShapes[x][y] == 0) fill(100);
      else if(StopShapes[x][y] == 1) fill(#AE5FE0);//紫
      else if(StopShapes[x][y] == 2) fill(#FA980F);//橘
      else if(StopShapes[x][y] == 3) fill(#E7F000);//黃
      else if(StopShapes[x][y] == 4) fill(#4FC104);//綠
      else if(StopShapes[x][y] == 5) fill(#258BF5);//藍
      else if(StopShapes[x][y] == 6) fill(#E30000);//紅
      else fill(#FA65C6);//粉
      rect(x*30+50, y*30+50, 26, 26, 5);
    }
  }
}
Shapes Current = new Shapes();
class Shapes {//形狀
  int [][] shape = new int[4][2];
  int tetris = 0;
  
  public Shapes() {
    tetris = int(random(1, 8));//random 選擇1-8狀態來隨機選擇圖形
    //先選擇圖形
    if(tetris == 1) {//直線
      shape[1][0] =  1;
      shape[2][0] = -1;
      shape[3][0] = -2;
    }
    else if(tetris == 2) {//方塊
      shape[1][0] = 1;
      shape[2][1] = 1;
      shape[3][0] = 1;
      shape[3][1] = 1;
    }
    else if(tetris == 3) {//右L
      shape[1][0] =  1;
      shape[2][0] = -1;
      shape[3][0] =  1;
      shape[3][1] = -1;
    }
    else if(tetris == 4) {//左L
      shape[1][0] =  1;
      shape[2][0] = -1;
      shape[3][0] = -1;
      shape[3][1] = -1;
    }
    else if(tetris == 5) {//左閃電
      shape[1][0] = -1;
      shape[2][1] = -1;
      shape[3][0] =  1;
      shape[3][1] = -1;
    }
    else if(tetris == 6) {//右閃電
      shape[1][0] =  1;
      shape[2][1] = -1;
      shape[3][0] = -1;
      shape[3][1] = -1;
    }
    else{//小T
      shape[1][0] =  1;
      shape[2][0] = -1;
      shape[3][1] = -1;
    }
  }
  /*public void ShowNext(){
    
  }*/
  //後來做旋轉
  public void Rotate() {
    for(int i = 0; i < 4; i++) {
      if(tetris==2) break;//方塊不做旋轉,會往上跑
      int temp = shape[i][0];
      shape[i][0] = shape[i][1];
      shape[i][1] = -temp;
    }
  }
  public int getShapeX(int i) {
    return shape[i][0];
  }
  public int getShapeY(int i) {
    return shape[i][1];
  }
  //左右 上下
  //X
  public int MaxRight() {
    int i = 0;
    for(int j = 0; j < 4; j++) {
      if(shape[j][0] > shape[i][0]) i = j;
    }
    return shape[i][0];
  }
  public int MinLeft() {
    int i = 0;
    for(int j = 0; j < 4; j++) {
      if(shape[j][0] < shape[i][0]) i = j;
    }
    return shape[i][0];
  }
  //Y
  public int MaxUp() {
    int i = 0;
    for(int j = 0; j < 4; j++) {
      if(shape[j][1] > shape[i][1]) i = j;
    }
    return shape[i][1];
  }
  public int MinDown() {
    int i = 0;
    for(int j = 0; j < 4; j++) {
      if(shape[j][1] < shape[i][1]) i = j;
    }
    return shape[i][1];
  }
  public int getColor() {
    return tetris;
  }
}
void displayCurrent() {
  //正在下落的Tetris
  if(Current.getColor() == 0) fill(100);
  else if (Current.getColor() == 1) fill(#D7A7F7);//淺紫
  else if (Current.getColor() == 2) fill(#F5C56A);//淺橘
  else if (Current.getColor() == 3) fill(#F7FAB1);//淺黃
  else if (Current.getColor() == 4) fill(#95E584);//淺綠
  else if (Current.getColor() == 5) fill(#B8CBFA);//淺藍
  else if (Current.getColor() == 6) fill(#FAB8B8);//淺紅
  else fill(#FFDBF2);//淺粉
 
  for(int i = 0; i < 4; i++) {
    if((Current.getShapeY(i)+CurrentPos[1]) >= 0) {
//目前要下降所以先用getShapeY+CurrentPos[1] 因為CurrentPos[1]是跟著down一起++
      rect((Current.getShapeX(i)+CurrentPos[0])*30+50, (Current.getShapeY(i)+CurrentPos[1])*30+50, 26, 26, 5);
      //    getShapeX,CurrentPos[0]一組                 getShapeY,CurrentPos[1]一組
      //跟著Grid的rect同樣參數
    }
  }
}
void keyPressed() {//控制 上(旋轉)下左右
  if (keyCode == DOWN) {
    CurrentPos[1]++;//下落++
    StopEmpty();
  }
  if (keyCode == LEFT) {
    boolean stop = false;
    for (int i = 0; i < 4; i++) {
      if ((Current.getShapeX(i)+CurrentPos[0]) >=1) {//判斷到左邊界
      //目前要左橫移所以先用getShapeX+CurrentPos[0] 
        if ((Current.getShapeY(i)+CurrentPos[1]) <=18 && (Current.getShapeY(i)+CurrentPos[1]) >=1) {
          //下降最多到18 最少1
          if (StopShapes[Current.getShapeX(i)+CurrentPos[0]-1][Current.getShapeY(i)+CurrentPos[1]] !=0){
          //  StopShapes[x][y]
              stop = true;
          }
        }
      }
      else stop = true;
    }
    if (!stop) CurrentPos[0]--;//持續判斷是否stop是true 不是的話就可-- 往左邊移動
  }
  if (keyCode == RIGHT) {
    boolean stop = false;
    for (int i = 0; i < 4; i++) {
      if ((Current.getShapeX(i)+CurrentPos[0]) <= 8) {//判斷到右邊界
      //目前要右橫移所以先用getShapeX+CurrentPos[0] 
        if ( (Current.getShapeY(i)+CurrentPos[1]) <=18 && (Current.getShapeY(i)+CurrentPos[1]) >=1) {
          //下降最多到18 最少1
          if (StopShapes[Current.getShapeX(i)+CurrentPos[0]][Current.getShapeY(i)+CurrentPos[1]] != 0){
          //  StopShapes[x][y]
            stop = true;
          }
        }
      }
      else stop = true;
    }
    if (!stop) CurrentPos[0]++;//持續判斷是否stop是true 不是的話就可++ 往右邊移動
  }
  if (keyCode == UP) {//旋轉
    Current.Rotate();//呼叫Shapes裡的Rotate
    //防止旋轉時會超出邊框
    if(Current.MinLeft()+CurrentPos[0] < 0){
      CurrentPos[0]=-Current.MinLeft();
    }
    if(Current.MaxRight()+CurrentPos[0] > 9){
      CurrentPos[0]=-Current.MaxRight()+9;
    }
    if(Current.MinDown()+CurrentPos[1] < 0){
      CurrentPos[1]=-Current.MinDown();
    }
    if(Current.MaxUp()+CurrentPos[1] > 19){
      CurrentPos[1]=-Current.MaxUp()+19;
    }
  }
  /*if(keyCode == 32){// 空白鍵 立即下降
    //目前想法:下降速度超快 or 直接到底
    //還在想
    
  }*/
}
//boolean state = false;
public void StopEmpty() {
  boolean stop = false;
  for(int i = 0; i < 4; i++) {
    if(Current.getShapeY(i)+CurrentPos[1] <= 18) {
      if(StopShapes[Current.getShapeX(i)+CurrentPos[0]][Current.getShapeY(i)+CurrentPos[1]+1] != 0) {
        //StopShapes[x][y]                                         i=3,ShapeY(i)=-1,       所以至少要+1變回0
        stop = true;
      }
    }
  }
  if (Current.MaxUp()+CurrentPos[1] == 19 || stop) {
      //
    for(int i = 0; i < 4; i++) {
      //抓目前顏色
      StopShapes[(Current.getShapeX(i)+CurrentPos[0])][(Current.getShapeY(i)+CurrentPos[1])] = Current.getColor();
    }
    for(int y = 0; y < 20; y++) {
      boolean empty = true;
      for(int x = 0; x < 10; x++) {
        if(StopShapes[x][y] == 0){
          empty = false;
        }
      }
      if(empty){
        for(int y2 = y-1; y2 > -1; y2--) {
          for(int x = 0; x < 10; x++) {
            StopShapes[x][y2+1] = StopShapes[x][y2];
          }
        }
      }
    }
    
  //因stop or empty
    Current = new Shapes(); 
    CurrentPos[0] = 4;
    CurrentPos[1] = 0;
   
    displayCurrent();
    //state=true;
  }
}



沒有留言:

張貼留言