一.發射子彈與簡單碰撞
發射子彈其實就只是在角色的位置繪製圖片或形狀模擬子彈的樣子,再將子彈重複執行往上移動,但我自己覺得既然都要模擬發射物了,目標是一定要有的,於是我想了一下碰撞的原理。
現在有A跟B兩個矩形,分別有最大最小X座標。
若A往前移動與B重疊的話,則A的最大X會大於B的最小X:A_maxX > B_minX
反過來則是B的最小X會大於A的最大X:B_minX > A_maxX
Y軸則同理。
1.宣告
- PImage player,monster,boom; //宣告玩家、怪物、爆炸特效的圖片
- int []x = {0,0,0,0,0,0,0,0}; //子彈的X座標
- int []y = {0,0,0,0,0,0,0,0}; //子彈的Y座標
- int n = 0; //目前的發射次數
- int cd = 0; //每顆子彈的間隔時間
- int posX = 134,posY = 450; //玩家的座標
- float MposX = 100,MposY = 24; //怪物的座標
- int ifcollision = 0; //是否有碰撞(會解釋)
- int timing1 = 0,timing2 = 0; //兩個計時器
- int looking = 0; //控制怪物目前的左右移動方向
2.設定
- void setup()
- {
- size(300,500); //視窗大小
- player = loadImage("player.png"); //讀取玩家圖片
- monster = loadImage("monster.png"); //讀取怪物圖片
- boom = loadImage("boom.png"); //讀取爆炸特效圖片
- }
3.偵測碰撞的函數
這邊需要稍微解釋一下,我自己覺得最簡單的碰撞判斷,基本上就是以X和Y座標去做比較,達到條件就輸出結果,解釋如下:
若A往前移動與B重疊的話,則A的最大X會大於B的最小X:A_maxX > B_minX
反過來則是B的最小X會大於A的最大X:B_minX > A_maxX
Y軸則同理。
- void Collision(float posX,float posY) //自訂義的函數名稱,輸入浮點數posX和posY
- {
- //以下分為兩塊,上面為邊長為15的子彈
- float minX1 = posX - 15 / 2; //最小X為自身中心X減掉邊長除2
- float maxX1 = posX + 15 / 2; //最大X為自身中心X加上邊長除2
- float minY1 = posY - 15 / 2; //同X軸
- float maxY1 = posY + 15 / 2;
- //計算方式都一樣,下面為怪物的
- float minX2 = MposX - 33 / 2;
- float maxX2 = MposX + 33 / 2;
- float minY2 = MposY - 24 / 2;
- float maxY2 = MposY + 24 / 2;
- //將上面圖文解釋的條件全部加上去的總條件,必須達成以下全部條件才會回傳
- if (minX1 > minX2 && maxX2 > minX1 && maxY1 > minY2 && maxY2 > minY1)
- {
- ifcollision++; //達成條件,回傳1
- }
- }
4.描繪
- void draw()
- {
- background(0); //黑色背景
- for (int i = 0;i < 8;i++) //發射子彈
- {
- square(x[i],y[i],15); //子彈為15X15的正方形
- y[i] -= 8; //重複往上移動8
- Collision(x[i],y[i]); //用函數判斷碰撞
- }
- image(player,posX,posY,33,24); //繪製玩家圖片
- //以下為繪製怪物圖片的條件
- if (ifcollision == 0) //如果沒有被子彈打到的話
- {
- if (looking == 0 && timing1 < 50) //看右邊和計時器1小於50
- {
- MposX += 2; //怪物往右邊移動2
- timing1++; //計時器開始計時
- if (timing1 == 50) looking = 1; //如果計了50次,則轉向左邊
- }
- else if (looking == 1) //如果轉向了左邊
- {
- MposX -= 2; //怪物往左邊移動2
- timing1--; //計時器開始倒數
- if (timing1 == 0) looking = 0; //如果倒數完了,既怪物已回到原點,則轉向右邊
- }
- image(monster,MposX,MposY,33,24); //如果沒有被子彈打到的話,繪製怪物圖片
- }
- else //如果被子彈打到的話
- {
- if (timing2 < 100) //計時器最多計時100次
- {
- if (timing2 % 20 > 10) image(boom,MposX,MposY,33,24); //繪製爆炸特效
- timing2++; //計時一次
- }
- }
- if (keyPressed && keyCode == RIGHT) //按右鍵往右走
- {
- if ((posX + 5) < 267) posX += 5;
- }
- if (keyPressed && keyCode == LEFT) //按左鍵往左走
- {
- if ((posX - 5) > 0) posX -= 5;
- }
- if (cd > 0) cd--; //使用過子彈的話,則進行冷卻時間倒數
- }
4.鍵盤按壓
- void keyPressed()
- {
- if (key == 'z' && cd == 0) //如果按了鍵盤上的Z鍵且子彈沒有進入冷卻時間
- {
- x[n] = posX + 8; //以玩家的座標為基準往上發射
- y[n] = posY - 5;
- n = (n+1)%8; //回收子彈
- cd = 10; //進入CD時間
- }
- }
5.最後成品
二.心得感想
雖然老師目前教的部分不多,但其實真的以目前所教過的東西就可以延伸成一個簡易的小遊戲,不過我認為應該還有更好的方式去縮短程式碼,程式最重要的不是寫得出來樣子,最重要的是要節省不必要的計算、減少計算的負擔。
























































