2023年12月21日 星期四

Sangmo 互動技術 Week12

子彈彈道控制

利用ArrayList創建子彈,並給子彈座標,當人物移動時射出的子彈也會跟著修改彈道
範例程式碼:
ArrayList<PVector> bullet = new ArrayList<PVector>();
ArrayList<PVector> bulletV = new ArrayList<PVector>();///!重要

void setup(){
  size(600,600);
}
float x=250,y=450,vx=0,vy=1;
void draw(){
  background(255);
  fill(255,0,0);
  ellipse(x,y,30,30);
  for(int i =0;i<bullet.size();i++)
  {
      PVector p = bullet.get(i);
      p.add( bulletV.get(i) );
      fill(255,0,0);
      ellipse(p.x,p.y,8,8);
  }
}
void keyPressed(){
  if(key == ' '){
    bullet.add( new PVector(x,y) );
    bulletV.add(new PVector(vx,vy) );
  }
  if(keyCode == LEFT){
    vx=-1; vy=0;
  }
  if(keyCode == UP){
    vx=0; vy=-1;
  }
}
修改後人物移動子彈就不會轉彎了

使用Enemy和Bullet代替PVector,再用class定義Enemy和Bullet

PImage plImg, enImg;
ArrayList<Enemy> ens = new ArrayList<Enemy>();
ArrayList<Bullet> bullets = new ArrayList<Bullet>();
Player pl = new Player(600 , 400);  ///遊戲角色生成座標

void setup(){ 
  size(1200, 800);  ///畫面大小
  plImg = loadImage("player.png"); ///角色圖片
  enImg = loadImage("enemy.png"); ///敵人圖片
 
  for (int i = 0; i < 6; i++)   ///敵人生成人數(目前為三
  {
    ens.add(new Enemy());
  }
}

void draw(){
  background(0);
    pl.move();
    pl.drawApp(); ///繪畫人物

  for (int i = 0; i < bullets.size() ; i++){  ///產生子彈
    Bullet bullet = bullets.get(i);
    bullet.move();
    bullet.drawApp(); ///繪畫子彈

    for (int j =0; j < ens.size() ; j++){  ///產生敵人
      Enemy enemy = ens.get(j);
      if (bullet.bump(enemy)){  ///敵人碰觸子彈時消失
        ens.remove(j);
        bullet.reset();
      } 
    }

    if (bullet.buloutScreen()){
      bullets.remove(i);  ///離開畫面時消除子彈
      }
    }
    
      if (ens.size() < 3){  ///敵人數量上限
      ens.add(new Enemy());
    }    
    for (Enemy en : ens){ ///簡化寫法,也能改成 for (int i = 0; i < ens.size(); i++) {Enemy en = ens.get(i);}
      en.move();
      en.drawApp(); ///繪畫敵人
    }

    if (frameCount % 20 == 0){
      if (bullets.size() < 3)  ///子彈3發後子彈不在射擊
      { 
          bullets.add(new Bullet(pl.x,pl.y,pl.dv)); ///子彈生成會從角色開始
      }
    }
  }
  
void keyPressed()///鍵盤按下
{
  if (keyCode == LEFT){
    pl.left = true;
  }else if (keyCode == RIGHT){
    pl.right = true;
  }else if (keyCode == UP){
    pl.up = true;
  }else if (keyCode == DOWN){
    pl.down = true;
  }
}

void keyReleased()///鍵盤放開
{
   if (keyCode == LEFT){
    pl.left = false;
  }else if (keyCode == RIGHT){
    pl.right = false;
  }else if (keyCode == UP){
    pl.up = false;
  }else if (keyCode == DOWN){
    pl.down = false;
  }
}

class Player ///定義人物的屬性
{
  float x, y;
  int speed = 5;///移動速度
  int dv = 0; ///控制子彈方向
  boolean left, right, up, down;

  Player(float dx, float dy){
     x = dx;
     y = dy;
   }
   
  void move(){
    if (left){
      x -= speed;
      dv = 1;
    }
    if (right){
      x += speed;
      dv = 2;
    }
    if (up){
      y -= speed;
      dv = 3;
    }
    if (down){
      y += speed;
      dv = 4;
    }
  }

  void drawApp(){
    image(plImg, x-25, y-25, 50, 50);
  }
}

class Enemy ///定義敵人的屬性
{
  float x, y;
  float speed = 1;
  float dv;

   Enemy(float vx, float vy, int dir) 
  {
   x = vx;
   y = vy;
   dv = dir;
  }

  Enemy(){
    reset();
  }
  
  void move() ///移動時會以最短距離靠近角色
  {
    float angle = atan2(pl.y - y, pl.x - x);  ///計算玩家與敵人的角度
    x += cos(angle) * speed;
    y += sin(angle) * speed;
  }
  void drawApp() 
  {
    image(enImg, x, y, 50, 50);
  }

  void reset() 
  { 
     x = random(pl.x+400); ///隨機傳送敵人,並與玩家有一段距離
     y = random(pl.y+400);
  }
}


class Bullet ///定義子彈的屬性
{
  float x, y;
  float speed = 15; ///移動速度
  int dv;
  
  boolean bump(Enemy en) ///Enemy en為了檢查某個敵人是否被碰到
  {
    return dist(x, y, en.x+15, en.y+20)< 30;
  }
  
  boolean buloutScreen() 
  { 
    return (y < -10 || y > 810 || x < -10 || x > 1210);///子彈到畫面外,回傳讓子彈消失
  }
  
   Bullet(float vx, float vy, int dir) 
  {
   x = vx;
   y = vy;
   dv = dir;
  }

  void move() 
  {
   if (dv == 0){ ///未移動時子彈預設向上
      y -= speed;
    }else if (dv == 1){ ///向左
      x -= speed;
    }else if (dv == 2){ ///向右
      x += speed;
    } else if (dv == 3){ ///向上
      y -= speed;
    } else if (dv == 4){ ///向下
      y += speed;
    }
  }
  
  void drawApp() 
  {
    if(dv==3 || dv==4 || dv==0){
      fill(#F7C51E);
      ellipse(x, y, 6, 22); ///子彈外觀
    }
    else if(dv==1 || dv==2){
      fill(#F7C51E);
      ellipse(x, y, 22, 6); ///子彈外觀
    }
  }

  void reset(){  ///子彈消失後回到角色
    x = pl.x;
    y = pl.y;
  }
}

沒有留言:

張貼留言