2024年1月14日 星期日

Sangmo 互動技術Week18

總程式碼:加了音樂

import processing.sound.*;

SoundFile main;
SoundFile gameover;
SoundFile gamemu;
SoundFile run;
SoundFile go;




PImage plImg, enImg, mainuiImg;
PImage stbuttonImg1,stbuttonImg2,mainpic1,failimg,endimg; ///第一張圖剩下外框
PImage map1,map2,map3;
PImage gunA,gunB,gunC,gunD,gunE,gunF;

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

boolean look = false;

boolean mStarted = false;
boolean mover  = false;
boolean mgame = false;




long Tim;
int state=0;
int killedEnemies = 0;
int klevel= 0;
int shootspeed=20; ///射擊速度
int damageb=10; ///射擊子彈傷害
int playerlevel = 0;

int a=0,b=0,c=0,d=0;
int e=0,f=0,j=0,k=0;

int startT;
int Time;
int T=0,t=0,A=0,B=0;
int Y=5;

void setup(){ 
  size(1200, 800);  ///畫面大小
  frameRate(80);
  main = new SoundFile(this,"main.mp3");
  gamemu = new SoundFile(this,"gamemu.mp3");
  gameover = new SoundFile(this,"gameover.mp3");
  run = new SoundFile(this,"click.mp3");
  go = new SoundFile(this,"ru.mp3");
  
  
  startT = millis();
  stbuttonImg1 = loadImage("start1.png"); ///開始按鈕
  stbuttonImg2 = loadImage("start.png");   
  mainpic1 = loadImage("Paintmain.png");
  mainuiImg = loadImage("mainUI.png");  ///畫面圖片
  failimg = loadImage("fail.png");
  endimg = loadImage("end.png");
  map1 = loadImage("snow.png");
  map2 = loadImage("desert.png");
  map3 = loadImage("prison.png");
  plImg = loadImage("player.png"); ///角色圖片
  enImg = loadImage("enemy.png"); ///敵人圖片
  gunA = loadImage("gunA.png");
  gunB = loadImage("gunB.png");
  gunC = loadImage("gunC.png");
  gunD = loadImage("gunD.png");
  gunE = loadImage("gunE.png");
  gunF = loadImage("gunF.png");
  
 
  for (int i = 0; i < 3; i++)   ///開始敵人生成人數(目前為三
  {
    ens.add(new Enemy());
  }
}

void draw(){
  if (state==0 && !mStarted) {
    // 開始播放音樂
    main.play();
    mStarted = true;
  }
  if (state !=0 && mStarted){
    mStarted = false;
  }
  
  if(pl.health==2){ 
    gamemu.stop();
    gameover.play();
  }
  
  
  if(state == 0){ ///開始畫面
    StartScreen();
  }
  if(state == 5){
    chooseScreen();
  }
  
  
  if(state==1 || state == 6 ||state == 7){ ///遊戲畫面
    GameScreen();
    Timer();
    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)){  ///敵人碰觸高穿透子彈時消失
        if (enemy.health <= 0) {
          ens.remove(j);
          killedEnemies++; ///觸發用
          klevel++; ///顯示等級用,最終擊殺敵人數
        }
      }
    }
    if (bullet.buloutScreen()){
      bullets.remove(i);  ///離開畫面時消除子彈
      }
    }

      if (ens.size() < 5+playerlevel){  ///敵人數量上限
      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 % shootspeed == 0 && state ==1 || frameCount % shootspeed == 0 && state == 6 || frameCount % shootspeed == 0 && state == 7){
      if (bullets.size() < 10)  ///子彈3發後子彈不在射擊
      {
          bullets.add(new Bullet(pl.x,pl.y,pl.dv,damageb)); ///子彈生成屬性(x,y,速度,傷害) 會從角色開始
      }
    }
    PFont font = createFont("微軟正黑體 Bold",30);
    textFont(font);
    fill(#585454);
    text("玩家武器",50,50);
    if(e>0)image(gunA,50,55,120,100);
    if(f>0)image(gunB,50,55,120,100);
    if(j>0)image(gunC,50,55,120,100);
    if(k>0)image(gunE,50,55,120,100);
    fill(#FC3838);
    text("玩家血量"+pl.health,1000,50);
  }
  if(state==2 )EndScreen(); ///結束畫面
  if(state == 9 )choosegun(); ///選擇槍械
  if (killedEnemies % Y ==0 && killedEnemies>0) {
    state += 10;
  }
  if(state==11 || state==16 || state==17){ //升級介面
    levelmenu();
  }
  if(state==1&& look==true || state==6&& look==true || state==7 && look==true){
    skill();
  }
}

void GameScreen()
{
    if(state==1)image(map1,0,0);///遊戲場景
    if(state == 6)image(map2,0,0);
    if(state == 7)image(map3,0,0);
}

void Timer() { 
  Time = (millis() - startT) ; ///顯示時間,可以根據需要調整位置和樣式
  A=Time/1000;
  t=(Time/1000)%60; ///秒
  T=Time/60000;
}


void levelmenu() {
  noLoop();///暫停遊戲主畫面,顯示提升選項
  fill(255);
  rect(340, 100, 500, 500,28);  ///顯示選項框

  // 顯示提升選項
  fill(0);
  PFont font = createFont("微軟正黑體 Bold",40);
  textFont(font);
  fill(#A9E4FA);
  textSize(40);
  text("點擊選擇升級項目", 450, 150);
  
  fill(#7AAFF7);
  textSize(30); 

  text("移動速度Lv."+ a, 500, 250);
  
  fill(#F78484);
  textSize(30);
  text("增加傷害Lv."+ b , 500, 325);
  
  fill(#3B39F5);
  textSize(30); 
  text("射擊速度Lv."+ c, 500, 400);
  
  fill(#FFD80F);
  textSize(30); 
  text("射擊距離Lv."+ d, 500, 475);
  
  fill(#FF270F);
  textSize(30); 
  text("補血瓶", 500, 550);
}

void skill(){
  fill(#81D8FA);
  rect(450, 10, 300, 100,28);
  textSize(20);
  fill(0);
  text("移動速度:"+pl.speed,520,30);
  text("射擊傷害:"+damageb,520,60);
  text("射擊距離:"+pl.space +"格",520,90);
}
void resetS(){
  t=0;
  T=0;
  Y=5;
  pl.speed = 3;
  pl.health = 100;
  pl.space = 200;
  damageb = 10;
  shootspeed = 20;
  a=0;b=0;c=0;d=0;  
}


void chooseScreen()
{
  image(mainuiImg,0,0);
  fill(255);
  PFont font = createFont("微軟正黑體 Bold",40);
  textFont(font);
  text("地圖選擇",525,100);
  text("雪地",150,200);
  image(map1,100,250,200,200);
  fill(#FABD21);
  text("沙漠",550,200);
  image(map2,500,250,200,200);
  fill(#9D9B97);
  text("監獄",950,200);
  image(map3,900,250,200,200);
  
  fill(#A7DAFF);
  text("遊戲操作",500,550);
  fill(#43A9F5);
  text("玩家移動",50,600);
  text("上 : W鍵  "+"下 : S鍵  "+"左 : A鍵  "+"右 : D鍵  ",300,600);
  fill(#FC8787);
  textSize(20);
  text("射擊方向和移動方向相同",350,630);
  textFont(font);
  fill(#43A9F5);
  text("射擊方向反轉 : 空白鍵",300,690);
  text("屬性顯示 : TAB鍵",300,740);
  
  
  if (mouseX > 100 && mouseX < 300 && mouseY > 250 && mouseY < 450)tint(#95948F, 255);
  image(map1,100,250,200,200);
  noTint();
  if (mouseX > 500 && mouseX < 700 && mouseY > 250 && mouseY < 450)tint(#95948F, 255);
  image(map2,500,250,200,200);
  noTint();
  if (mouseX > 900 && mouseX < 1100 && mouseY > 250 && mouseY < 450)tint(#95948F, 255);
  image(map3,900,250,200,200);
  noTint();  
}

void choosegun(){
  background(#EAC566);
  
  fill(#52514C);
  PFont font = createFont("微軟正黑體 Bold",40);
  PFont font2 = createFont("微軟正黑體 Bold",20);
  textFont(font);
  fill(0);
  text("選擇槍械",525,100);
  fill(#1102F0);
  text("半自動步槍",50,220);
  text("自動步槍",320,220);
  text("衝鋒槍",680,220);
  text("狙擊步槍",950,220);
  fill(0);
  
  image(gunA,50,250,200,150); ///滑鼠移過去時會跑出槍械有什麼功能 
  if(mouseX > 50 && mouseX < 250 && mouseY > 250 && mouseY < 400){
    tint(#95948F, 255);
    image(gunA,50,250,200,150);
    noTint();
  }
  if(state==9 && mouseX > 50 && mouseX < 250 && mouseY > 250 && mouseY < 400){
    fill(255);
    rect(400,475,400,300,28);
    fill(0);
    textFont(font2);
    text("射擊速度稍微降低", 420,500);
    fill(#F77F7F);
    text("傷害稍微提升", 420,520);
    fill(0);
    text("玩家速度  "+pl.speed,420,600);
    text("玩家血量  "+pl.health,420,630);
    text("射擊傷害  15",420,660);
    text("射擊速度  每秒1.5發子彈",420,690);
    text("射擊距離  "+pl.space,420,720);
  }
  
  image(gunB,320,250,200,150);
  if(mouseX > 320 && mouseX < 520 && mouseY > 250 && mouseY < 400){
    tint(#95948F, 255);
    image(gunB,320,250,200,150);
    noTint();
  }
  if(state==9 && mouseX > 320 && mouseX < 520 && mouseY > 250 && mouseY < 400){
    fill(255);
    rect(400,475,400,300,28);
    fill(0);
    textFont(font2);
    text("屬性平均發展", 420,500);
    fill(#F77F7F);
    text("擊殺首個敵人時 立即獲得升級點", 420,520);
    fill(0);
    text("玩家速度  5",420,600);
    text("玩家血量  "+pl.health,420,630);
    text("射擊傷害  "+damageb,420,660);
    text("射擊速度  每秒3發子彈",420,690);
    text("射擊距離  "+pl.space,420,720);
  }
  image(gunC,680,250,200,150);
  if(mouseX > 680 && mouseX < 880 && mouseY > 250 && mouseY < 400){
    tint(#95948F, 255);
    image(gunC,680,250,200,150);
    noTint();
  }
  if(state==9 && mouseX > 680 && mouseX < 880 && mouseY > 250 && mouseY < 400){
    fill(255);
    rect(400,475,400,300,28);
    fill(0);
    textFont(font2);
    text("射擊距離與槍械傷害降低", 420,500);
    fill(#F77F7F);
    text("玩家速度與射擊速度皆大幅提升", 420,520);
    fill(0);
    text("玩家速度  5",420,600);
    text("玩家血量  "+pl.health,420,630);
    text("射擊傷害  8",420,660);
    text("射擊速度  每秒6發子彈",420,690);
    text("射擊距離  150.0",420,720);
  }
  image(gunE,950,250,200,150);
  if(mouseX > 950 && mouseX < 1050 && mouseY > 250 && mouseY < 400){
    tint(#95948F, 255);
    image(gunE,950,250,200,150);
    noTint();
  }
  if(state==9 && mouseX > 950 && mouseX < 1050 && mouseY > 250 && mouseY < 400){
    fill(255);
    rect(400,475,400,300,28);
    fill(0);
    textFont(font2);
    text("玩家血量與玩家速度與射擊速度降低", 420,500);
    fill(#F77F7F);
    text("射擊距離與槍械傷害大幅提升", 420,520);
    fill(0);
    text("玩家速度  2",420,600);
    text("玩家血量  50",420,630);
    text("射擊傷害  30",420,660);
    text("射擊速度  每秒1發子彈",420,690);
    text("射擊距離  500.0",420,720);
  }
}
void EndScreen(){
  image(mainuiImg,340,100,500,500);
  image(failimg,350,200,200,200);
  PFont font3 = createFont("Times New Roman",40);
  textFont(font3);
  fill(#F55454);
  text("F - A - I - L",540,200);
  PFont font = createFont("微軟正黑體 Bold",40);
  textFont(font);
  fill(255);
  text("玩家等級:"+playerlevel,550,300);
  text("時間:"+T+"分"+t+"秒",550,350);
  text("擊殺數:"+klevel,550,400);
  image(endimg,660,550,150,40);
  if(state==2 && mouseX > 660 && mouseX < 810 && mouseY > 550 && mouseY < 600){
    tint(#95948F, 255);
    image(endimg,660,550,150,40);
    noTint();
  }
}

void StartScreen()
{
  background(255);
  image(mainuiImg,0,0,width, height);
  image(mainpic1,415,100,400, 200); ///美觀主畫面用
  image(stbuttonImg1, 450, 450, 300, 100);///(x座標,y座標,寬度,高度)
  if (mouseX > 450 && mouseX < 730 && mouseY > 450 && mouseY < 560)tint(#95948F, 255);// 透明度(顏色,透明度(0 為完全透明,255 為完全不透明))
  image(stbuttonImg2, 434, 445, 327, 110);
  noTint();
}

void mousePressed()
{
  if (state == 0 && mouseX > 450 && mouseX < 730 && mouseY > 450 && mouseY < 560)
  {
    state = 9;///start畫面
    run.play();
    main.stop();
  }
  if(state==2 && mouseX > 660 && mouseX < 810 && mouseY > 550 && mouseY < 600){
    state = 0;
    resetS();
    run.play();
  }
  
  if(state==9 && mouseX > 50 && mouseX < 250 && mouseY > 250 && mouseY < 400){
    damageb= 15;
    shootspeed = 50;
    e++;
  }
  if(state==9 && mouseX > 320 && mouseX < 520 && mouseY > 250 && mouseY < 400){
    shootspeed = 25;
    killedEnemies = 1;
    f++;
  }
  if(state==9 && mouseX > 680 && mouseX < 880 && mouseY > 250 && mouseY < 400){
    shootspeed = 16;
    pl.speed = 4;
    damageb= 8;
    pl.space = 150;
    j++;
  }
  if(state==9 && mouseX > 950 && mouseX < 1050 && mouseY > 250 && mouseY < 400){
    shootspeed = 60;
    pl.speed = 1;
    damageb = 30;
    pl.space = 500;
    pl.health = 50;
    k++;
  }
 
  if(state==9 && mouseX > 50 && mouseX < 250 && mouseY > 250 && mouseY < 400)go.play();
  if(state==9 && mouseX > 320 && mouseX < 520 && mouseY > 250 && mouseY < 400)go.play();
  if(state==9 && mouseX > 680 && mouseX < 880 && mouseY > 250 && mouseY < 400)go.play();
  if(state==9 && mouseX > 950 && mouseX < 1050 && mouseY > 250 && mouseY < 400)go.play();
  
  if (state == 5 && mouseX > 100 && mouseX < 300 && mouseY > 250 && mouseY < 450){state = 1;startT=millis();gamemu.play();}///choose畫面
  if (state == 5 && mouseX > 500 && mouseX < 700 && mouseY > 250 && mouseY < 450){state = 6;startT=millis();gamemu.play();}
  if (state == 5 && mouseX > 900 && mouseX < 1100 && mouseY > 250 && mouseY < 450){state = 7;startT=millis();gamemu.play();}
  
    
  if (state > 10 && mouseX > 500 && mouseX < 500+150 && mouseY > 250-30 && mouseY < 250+20){ ///移動速度
    go.play();
    a++;
    Y += 1;
    playerlevel++;
    pl.speed += 1; 
    state -= 10;
    killedEnemies = 0;
    loop();
  }
  if (state > 10 && mouseX > 500 && mouseX < 500+150 && mouseY > 325-30 && mouseY < 325+20){ ///增加傷害
    go.play();
    b++;
    Y += 1;
    playerlevel++;
    damageb += 10;
    state -= 10;
    killedEnemies = 0;
    loop();
  }
  if (state > 10 && mouseX > 500 && mouseX < 500+150 && mouseY > 400-30 && mouseY < 400+20){ ///射擊速度
    go.play();
    c++;
    Y += 1;
    playerlevel++;
    shootspeed -= 2;
    state -= 10;
    killedEnemies = 0;
    loop();
  }
  if (state > 10 && mouseX > 500 && mouseX < 500+150 && mouseY > 475-30 && mouseY < 475+20){ ///射擊距離
    go.play();
    d++;
    Y += 1;
    playerlevel++;
    pl.space += 30;
    state -= 10;
    killedEnemies = 0;
    loop();
  } 
  if (state > 10 && mouseX > 500 && mouseX < 500+150 && mouseY > 550-30 && mouseY < 550+20){ ///玩家血量
    go.play();
    Y +=1 ;
    pl.health += 30;
    state -= 10;
    killedEnemies = 0;
    loop();
  }
}

void mouseReleased()
{
  if(state==9 && mouseX > 50 && mouseX < 250 && mouseY > 250 && mouseY < 400)state=5;
  if(state==9 && mouseX > 320 && mouseX < 520 && mouseY > 250 && mouseY < 400)state=5;
  if(state==9 && mouseX > 680 && mouseX < 880 && mouseY > 250 && mouseY < 400)state=5;
  if(state==9 && mouseX > 950 && mouseX < 1050 && mouseY > 250 && mouseY < 400)state=5;
}
void keyPressed()///鍵盤按下 空白鍵切換子彈射擊反方向
{
  if (key == TAB) {
  look=true;
  }
  if (key == 'A' || key == 'a'){
    pl.left = true;
  }else if (key == 'D' || key == 'd'){
    pl.right = true;
  }else if (key == 'W' || key == 'w'){
    pl.up = true;
  }else if (key == 'S' || key == 's'){
    pl.down = true;
  }else if (key == ' ') {
    pl.change = !pl.change; // 切換射擊方向
  }
}

void keyReleased()///鍵盤放開
{
  if (key == TAB) {
  look= false;
  }
   if (key == 'A' || key == 'a'){
    pl.left = false;
  }else if (key == 'D' || key == 'd'){
    pl.right = false;
  }else if (key == 'W' || key == 'w'){
    pl.up = false;
  }else if (key == 'S' || key == 's'){
    pl.down = false;
  }
}


玩家/敵人/子彈程式碼

class Player  ///定義人物屬性 week12
{
  float x, y;
  int speed = 3;///移動速度
  int dv = 0; ///控制子彈方向
  boolean left, right, up, down,skill;
  boolean change = false;
  int health = 100;
  float space = 200;
  

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


  void drawApp(){
    fill(255); ///血條顏色為白色
    rect(x , y-15, health * 0.5, 5);  ///血條的長度為 health * 0.5
    image(plImg, x, y, 50, 60);
  }
}

class Enemy ///定義敵人的屬性 week12
{
  float x, y;
  float speed = 1;
  int health = 50;
  float Endv;
  
   Enemy(float vx, float vy, int dir) 
  {
   x = vx;
   y = vy;
   Endv = dir;
  }

  Enemy(){
    reset();
  }
  
  void move() ///移動時會以最短距離靠近角色
  {
    float angle = atan2(pl.y - y, pl.x - x);  ///計算玩家與敵人的角度
    x += cos(angle) * speed;
    y += sin(angle) * speed;
    
    if (dist(x, y, pl.x, pl.y) < 40) {
      pl.health -= 1;
      if(pl.health<1)state = 2;
    }
  }
  
  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 = 30; ///移動速度
  float damage = 10;
  int dv;
  
  
  boolean bump(Enemy en) ///Enemy en為了檢查某個敵人是否被碰到(故此不能與class Enemy分開)
  {
    if(dist(x,y,en.x,en.y)< 30){
      en.health -= damage;
      return true;
  }
  return false;
  }
  
  boolean buloutScreen() 
  { 
    return (y < pl.y- pl.space || y > pl.y+pl.space || x < pl.x-pl.space || x > pl.x+pl.space);///子彈範圍
  }
  
   Bullet(float vx, float vy, int dir,float damagebullet) ///預設子彈屬性
  {
   x = vx;
   y = vy;
   if (pl.change) {
      dv = (dir + 2) % 8;  ///方向反轉
    } else {
      dv = dir;
    }
   damage = damagebullet;
  }

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

沒有留言:

張貼留言