2012年11月13日 星期二

Midterm

Midterm 期中作品

1. 執行成果:

遊戲名稱:棒球轟不讓
遊戲方法:登入遊戲畫面點選開始遊戲按鈕,遊戲開始時玩家利用滑鼠搖動以及點擊控制球棒揮動角度,棒球會從投手位置投球出來,要打擊目標物為上方酒瓶,打中會加一分,沒打中不會扣分,時間限制為一分鐘。遊戲結束畫面會依分數有無達到規定跳出成功/失敗畫面。

Demo影片
成果截圖


 遊戲登入畫面點選開始遊戲按鈕(紅箭頭指向處)


 遊戲開始畫面,分別有clock時間軸來記錄時間grade記分板來記錄分數
bat球棒為玩家揮動控制ball棒球會從pitcher投手丟向bat球棒
wine酒瓶為要打擊的目標物


 遊戲結束畫面-闖關成功score分數>13分為遊戲成功


遊戲結束畫面-闖關失敗score分數<12分為遊戲失敗

2. 程式碼:

/*宣告放音樂函式*/
import ddf.minim.*;
import ddf.minim.analysis.*;
Minim minim;
AudioPlayer song;
PImage login,gamebg,win,lose,pitcher,bat,ball,wine1,wine2,wine3,clock;
PImage [] num = new PImage [10];
Timer timer,timer2;
int bg=1,s1=0,s2=0,s=0,score=0;
int lastTime=60;  //時間60秒
float wine1x=0,wine2x=100,wine3x=230,wine4x=300,wine5x=450,rect_x=0;
float bangangle=0;
float bx=480,vx=0,nx=0;
float by=150,vy=0,ny=0;
float x,y,a,b;
int state=0,stateBall;
float inner;
void setup() {
  size(640,500);  //視窗大小
  /*放音樂,音樂要儲存在processing檔案資料夾下*/
  minim = new Minim(this);
  song = minim.loadFile("baseball.mp3", 2048);
  /*載入圖片*/
  login = loadImage("login.jpg");
  gamebg = loadImage("gamebg.jpg");
  win = loadImage("win.jpg");
  lose = loadImage("lose.jpg");
  wine1 = loadImage("wine1.gif");
  wine2 = loadImage("wine2.gif");
  wine3 = loadImage("wine3.gif");
  pitcher = loadImage("pitcher.gif");
  ball = loadImage("ball.gif");
  bat = loadImage("bat.gif");
  clock = loadImage("clock.gif"); 
  for(int i=0;i<10;i++){
    num[i]=loadImage(""+i+".jpg");
  }
}
float sx=-3,sy=0.48;//error 1, not local variable
void ball(){  //球棒
   bx=bx+sx; by=by+sy;//error 3, need to modify (bx,by)
   if(bx>0&&state==0){
      //bx=bx+sx; by=by+sy;//error 3, need to modify (bx,by)
     if(bx<=150&&state==0){
       state=1;
       //println("state=1");
     }
      else if(bx<10&&state==0){
        bx+=480; by-=50;
      }
    }  
    if(state==1){
     inner=vx*sx+vy*sy;
      sx=2*(sx-2*inner*vx);
      sy=2*(sy-2*inner*vy);
      print(sx+"\n"+sy+"\n");
      state=2;//error 2, always collision
      stateBall=0;
    }
    if(bx>640||bx<0||by<0||by>448)
    { sx=-1*6+random(1); sy=(94+random(2))/100;
      bx=480; by=150;
      bx=bx+sx; by=by+sy;
      state=0;
    }
  image(ball,bx,by);
  //point(bx+25,by+25); //球棒中心點bx+25,by+25
//  print("bx:"+(bx+25)+" by:"+(by+25)+"\n");
//  print("dx:"+bx+" dy:"+by+"\n");  //球速向量dx,dy
}
void bat(){  //球棒
  pushMatrix();
    translate(150,350);
    rotate(bangangle);
    translate(-17,-180);
    image(bat,0,0,70,200);
    stroke(255,255,0);//Line color
    strokeWeight(10);//line size
    //line(17,0,17,200);//draw line
    stroke(255,0,0);//Line color
    //line(17,50,100,50);//球棒法線
  popMatrix();
  //point(150,350);
 // print("batangel:"+bangangle+"\n"); 
  vx=cos(bangangle);  //球棒向量vx,vy
  vy=sin(bangangle);
 // print("vx:"+vx+" vy:"+vy+"\n");
  nx=-2/vx;  //球棒法向量nx,ny
  ny=1/vy;
 // print("nx:"+nx+" ny:"+ny+"\n");  
  a=tan(bangangle);
  b=350-150*a;   
}
void winemove(){  //酒瓶移動
  if(wine1x<640){
    wine1x+=1;
    if(wine1x==640){
      wine1x-=640;
    }
    if(bx>=wine1x && bx<wine1x+50 && by<100 && stateBall==0)
     { s++; stateBall=1;}
  }
  image(wine1,wine1x,0);  
  if(wine2x<640){
     wine2x+=1;
     if(wine2x==640){
       wine2x-=640;
     }
     if(bx>=wine2x && bx<wine2x+50 && by<100 && stateBall==0)
     { s++; stateBall=1;}
  }
  image(wine2,wine2x,0);  
  if(wine3x<640){
    wine3x+=1;
    if(wine3x==640){
      wine3x-=640;
    }
    if(bx>=wine3x && bx<wine3x+50 && by<100 && stateBall==0)
     { s++; stateBall=1;}
  }
  image(wine3,wine3x,0); 
  if(wine4x<640){
    wine4x+=1;
     if(wine4x==640){
       wine4x-=640;
     }
     if(bx>=wine4x && bx<wine4x+50 && by<100 && stateBall==0)
     { s++; stateBall=1;}
  }
  image(wine1,wine4x,0);
  if(wine5x<640){
    wine5x+=1;
    if(wine5x==640){
      wine5x-=640;
    }
    if(bx>=wine5x && bx<wine5x+50 && by<100 && stateBall==0)
     { s++; stateBall=1;}
  }       
  image(wine2,wine5x,0);
}
void grade(){  //記分板
  s1=s%10; 
  image(num[s1],560,348,60,80); //個位數
  s2=s/10;
  image(num[s2],500,348,60,80); //十位數
}
void clock(){  //時間軸
  noStroke();
  fill(0);
  rect(0,448,640,52);
  image(clock,0,448,40,52);  //起點鐘
  image(clock,600,448,40,52);  //終點鐘
  //bug2-->下排時間軸不準確會有誤差!!(喊一秒)//bug1-->登入畫面時計時器便開始計時了!!
  lastTime=60-millis()/1000;
  if(lastTime>0){
    fill(255);
    rect_x+=0.16;
    rect(43,448,rect_x,600);
  }else if(lastTime<=0){
    fill(255);
    rect(43,448,rect_x,600);
  }
}
void draw() {
  if(bg==1){  //登入遊戲畫面 
     image(login,0,0,640,500);
     if(mousePressed && mouseX>=150 && mouseX<=500 && mouseY>=380 && mouseY<=500){
       image(gamebg,0,0);     
       bg=2;
       //print("進入遊戲\n");
     }
  } 
  if(bg==2){  //遊戲開始畫面
    song.play();  //音樂播放
    image(gamebg,0,0,640,448);
    image(pitcher,450,100);
    winemove();  //酒瓶移動
    grade(); //記分板
    clock();  //時間軸
    ball();   //棒球
    bat();  //球棒
    //print("a=  "+a+"\nb=  "+b+"\n");
    if(lastTime<=0){
      bg=3;
      if(s>=12){
        image(win,0,0,640,448);  //贏畫面
        grade();
      }else if(s<12){
        image(lose,0,0,640,448);  //輸畫面
        grade();
      } 
    }
  }
  //print("ny/nx="+ny/nx+"\n");
}
/*void keyPressed() {
  if (key==' ')  s++;
}*/
void mouseDragged()
{
  bangangle=1/2*PI-mouseX/150.0;  //球棒角度bangangle
}

3. 心得:

在做互動期中作品中遇到許多問題,有些有解決而有些無法如預期結果。我們不斷地努力測試和debug,經由這次期中作品知道自己有許多不足和加強的地方得再接再厲。
以下是遇到的問題與討論:
(1) 時間部分會有小小的誤差,從執行開始的登入畫面時間就開始計時了。
(2) 棒球和球棒部分是這次作品最大的問題,必須考慮球反彈的角度、速度等等,計算棒球和球棒的向量、法向量、斜率等等。這個部份讓我們頭痛好久,雖然還是有不足的地方。謝謝老師不厭其煩地教導。
(3) 程式碼部分寫起來有點混亂,可以再濃縮和整理。






沒有留言:

張貼留言