2023年11月2日 星期四

XX - Week08



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

EIGHTH

今天的重點是碰撞偵測,以馬力歐(Mario)為例


1.動者恆動
void setup(){
  size(400,400);
}
float x=200, y=200, vx=1, vy=1;
void draw(){
  ellipse(x, y, 10, 10);
  x += vx;
  y += vy;
}
註:有殘影的球x,y各別+1跑(往右下角跑)

2.用位置、速度、加速度來形成一個拋物線
void setup(){
  size(400,400);
}
float x=50, y=250, vx=2, vy=-20;
void draw(){
  ellipse(x, y, 10, 10);
  x += vx;
  y += vy;
  vy += 0.98;
}
註:利用重力將球往下拉

3.拋物線下來之後會落在y=350的地板上
void setup(){
  size(400,400);
}
float x=50, y=250, vx=2, vy=-20;
void draw(){
  x += vx;
  y += vy;
  vy += 0.98;//重力加速度
  if(y>350){//利用if判斷,看有沒有到地板 y=350位置
    y=350;;
  }
  ellipse(x, y, 10, 10);
}
註:掉到y=350會往右繼續運動


4.在原來的基礎上加上彈跳
void setup(){
  size(400,400);
}
float x=50, y=250, vx=2, vy=-20;
void draw(){
  x += vx;
  y += vy;
  vy += 0.98;//重力加速度
  if(y>350){//利用if判斷,看有沒有到地板 y=350位置
    y=350;
    vy = -vy * 0.5;//能量耗損、速度變慢
  }
  ellipse(x, y, 10, 10);
}
註:因為x也有耗損,所以可以加上vx = vx*0.7的耗損

5.做出一個馬力歐場景跟人物,並且利用鍵盤讓他能夠左右移動
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
}
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
}
註:此時還未能夠停止


6.讓馬力歐能夠停下、往上
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  marioY += vy;
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
}
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
  if(keyCode==UP) vy = -20;
}
void keyReleased(){
  if(keyCode==LEFT || keyCode==RIGHT) vx = 0;
}
註:加上keyReleased讓馬力歐能夠停下,這時候的跳還並未加上重力所以會直接往上跑


7.讓馬力歐能夠跳起來並且落在正確的地板上
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  if(flying){//如果在飛行中
    marioY += vy;//上下的位置會改變
    vy += 0.98;//重力加速度往下
    if(marioY >= 250){//碰到地板
      marioY = 250;//站在地板上
      flying = false;//不再飛行
    }
  }
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
}
boolean flying = false;//一開始沒有飛
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
  if(keyCode==UP && flying==false) {//如果沒有在飛的話才會飛
    vy = -20;
    flying = true;//開始飛行
  }
}
void keyReleased(){
  if(keyCode==LEFT || keyCode==RIGHT) vx = 0;
}
註:在flying狀態會有重力往下,以此來模擬跳



8.做出一個hitBox的函式,來做碰撞箱
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  if(flying){//如果在飛行中
    marioY += vy;//上下的位置會改變
    vy += 0.98;//重力加速度往下
    if(marioY >= 250){//碰到地板
      marioY = 250;//站在地板上
      flying = false;//不再飛行
    }
  }
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
  fill(229,119,42); rect(200,150,20,20);
  if(hitBox(200,150,20,20)){
    vy = 0;
    marioY = 150+20;
  }
}
boolean hitBox(int x, int y, int w, int h){
  if(x<marioX && marioX<x+w && y<marioY && marioY<y+h) return true;
  else return false;
}
boolean flying = false;//一開始沒有飛
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
  if(keyCode==UP && flying==false) {//如果沒有在飛的話才會飛
    vy = -20;
    flying = true;//開始飛行
  }
}
void keyReleased(){
  if(keyCode==LEFT || keyCode==RIGHT) vx = 0;
}
註:用判斷上下左右邊界來取決於是否要停止flying


9.將碰撞箱做得更好,並且能先站方塊在上面
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  if(flying){//如果在飛行中
    marioY += vy;//上下的位置會改變
    vy += 0.98;//重力加速度往下
    if(marioY >= 250){//碰到地板
      marioY = 250;//站在地板上
      flying = false;//不再飛行
    }
  }
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
  fill(229,119,42); rect(200,150,20,20);
  if(hitBox(200,150,20,20)){
    if(vy>0){
      marioY = 150 - 10;
      flying = false;
    }
    else {
      vy = 0;
      marioY = 150+20+10;
    }
  }
}
boolean hitBox(int x, int y, int w, int h){
  if(x-7<marioX && marioX<x+w+7 && y-10<marioY && marioY<y+h+10) return true;
  else return false;
}
boolean flying = false;//一開始沒有飛
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
  if(keyCode==UP && flying==false) {//如果沒有在飛的話才會飛
    vy = -20;
    flying = true;//開始飛行
  }
}
void keyReleased(){
  if(keyCode==LEFT || keyCode==RIGHT) vx = 0;
}
註:vy>0就會停止flying往下掉。如果vy=0就可以站在方塊上,但此時站上了會掉不下來


10.最後讓馬力歐能夠順利掉落到地板,並且能撞到方塊
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  if(flying){//如果在飛行中
    marioY += vy;//上下的位置會改變
    vy += 0.98;//重力加速度往下
    if(marioY >= 250){//碰到地板
      marioY = 250;//站在地板上
      flying = false;//不再飛行
    }
  }
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
  fill(229,119,42); rect(200,150,20,20);
  if(hitBox(200,150,20,20)){
    if(vy>0){
      marioY = 150 - 10;
      flying = false;
      stand_box = true;
    }
    else {
      vy = 0;
      marioY = 150+20+10;
    }
  }
  if(stand_box==true && flying==false && leaveBox(200,150,20,20)){
    stand_box = false;
    flying = true;
    vy = 0;
  }
}
boolean leaveBox(int x, int y, int w, int h){
  if(x-7>marioX || marioX>x+w+7) return true;
  else return false;
}
boolean hitBox(int x, int y, int w, int h){
  if(x-7<marioX && marioX<x+w+7 && y-10<marioY && marioY<y+h+10) return true;
  else return false;
}
boolean flying = false, stand_box=false;//一開始沒有飛
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
  if(keyCode==UP && flying==false) {//如果沒有在飛的話才會飛
    vy = -20;
    flying = true;//開始飛行
  }
}
void keyReleased(){
  if(keyCode==LEFT || keyCode==RIGHT) vx = 0;
}
註:利用跟hitbox寫出邏輯相反的leaveBox,在這之中要判斷flying與否跟stand_box與否

11.發明了一個drawAndTextBox,可以利用for迴圈來做出多個方塊
void setup(){
  size(400,400);
}
float marioX=50, marioY=250, vx=0, vy=0;
void draw(){
  background(108,137,255);
  marioX += vx;
  if(flying){//如果在飛行中
    marioY += vy;//上下的位置會改變
    vy += 0.98;//重力加速度往下
    if(marioY >= 250){//碰到地板
      marioY = 250;//站在地板上
      flying = false;//不再飛行
    }
  }
  fill(255,0,0); ellipse(marioX, marioY, 15, 25);
  fill(229,119,42); rect(0,260,400,150);
  drawAndTextBox(100,150,20,20);
  drawAndTextBox(200,150,20,20);
  drawAndTextBox(300,150,20,20);
}
void drawAndTextBox(int x, int y, int w, int h){
  fill(229,119,42); rect(x, y, w, h);
  if(hitBox(x, y, w, h)){
    if(vy>0){
      marioY = y - 10;
      flying = false;
      stand_box = true;
    }
    else {
      vy = 0;
      marioY = y+h+10;
    }
  }
  if(stand_box==true && flying==false && leaveBox(x, y, w, h)){
    stand_box = false;
    flying = true;
    vy = 0;
  }
}
boolean leaveBox(int x, int y, int w, int h){
  if(x-7>marioX || marioX>x+w+7) return true;
  else return false;
}
boolean hitBox(int x, int y, int w, int h){
  if(x-7<marioX && marioX<x+w+7 && y-10<marioY && marioY<y+h+10) return true;
  else return false;
}
boolean flying = false, stand_box=false;//一開始沒有飛
void keyPressed(){
  if(keyCode==RIGHT) vx = 2;
  if(keyCode==LEFT) vx = -2;
  if(keyCode==UP && flying==false) {//如果沒有在飛的話才會飛
    vy = -20;
    flying = true;//開始飛行
    stand_box = false;//現在有2個變數,都要處理
  }
}
void keyReleased(){
  if(keyCode==LEFT || keyCode==RIGHT) vx = 0;
}
註:為了能夠複製多個方塊所以做出一個函式能夠呼叫,只要呼交函式並定義參數就可以設置了

沒有留言:

張貼留言