• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • J2ME 2D小游戲入門之旅(四) 加入子彈群,實現碰撞運算

    發表于:2007-07-01來源:作者:點擊數: 標簽:
    飛機類 游戲 中子彈是必不可少的,他們數量很多且充斥著整個屏幕,這些隨機或者有著一定AI的小物體,實現起來不是總那么容易,有時候你不得不考慮很多和效能有關的問題。我們之前定義了GameObject,很大程度上就是為了方便的重用Sprite,因為我們有很多的子彈
    飛機類游戲中子彈是必不可少的,他們數量很多且充斥著整個屏幕,這些隨機或者有著一定AI的小物體,實現起來不是總那么容易,有時候你不得不考慮很多和效能有關的問題。我們之前定義了GameObject,很大程度上就是為了方便的重用Sprite,因為我們有很多的子彈,不可能沒增加一個子彈都是一個Sprite,我需要共享同一個Sprite。我們通過繼承GameObject來實現。



    下面分析一下這個子彈類:

    它將繼承自GameObject;

    記錄子彈的個數;

    一個子彈的狀態數組,記錄各個子彈的類型type,位置x,y,速度vx,vy,是否存活alive等等。

    初始化子彈

    一個繪制方法,將子彈畫到屏幕上。

    一個碰撞檢測方法。



    好了先這樣吧,以下是我們子彈類的定義,注意這種思想——重用Sprite,這很重要。(這里參考了tony的很多設計)

    public class Bullets extends GameObject {

    private int[][] bullets;//子彈狀態數組

    private int bulletstotal;//數組的length

    private Random rnd;//隨機數

    public static final int BULLET_TYPE_LEFT=0;//子彈初始化的位置類型

    public static final int BULLET_TYPE_RIGHT=1;//分為上下左右四種

    public static final int BULLET_TYPE_TOP=2;

    public static final int BULLET_TYPE_BOTTOM=3;

    private int width,height;//屏幕的高和寬,用于隨機子彈位置



    public Bullets(Image img,int picwidth,int picheight,int bulletstotal,int width,int height) {

    super(img,picwidth,picheight);

    this.bulletstotal=bulletstotal;

    bullets=new int[bulletstotal][6];

    rnd=new Random();

    this.width=width;

    this.height=height;

    }



    public void initBullets(){//初始化子彈狀態數組

    for (int i = 0; i < bullets.length; i++) {

    initBullet(i);

    }

    }



    private void initBullet(int i) {//初始化index號子彈

    bullets[i][0] = (rnd.nextInt() & 0x7fffffff) % 4; //type

    bullets[i][5] = 1; //alive 1表示存活, 0表示死去

    switch (bullets[i][0]) {

    case BULLET_TYPE_LEFT:

    bullets[i][1] = -5;

    bullets[i][2] = (rnd.nextInt() & 0x7fffffff) % height;

    bullets[i][3] = (rnd.nextInt() & 0x7fffffff) % 3 + 1; //vx

    bullets[i][4] = (rnd.nextInt()) % 3; //vy

    break;

    case BULLET_TYPE_RIGHT:

    bullets[i][1] = width + 5;

    bullets[i][2] = (rnd.nextInt() & 0x7fffffff) % height;

    bullets[i][3] = ( (rnd.nextInt() & 0x7fffffff) % 3 + 1) * -1; //vx

    bullets[i][4] = (rnd.nextInt()) % 3; //vy

    break;

    case BULLET_TYPE_TOP:

    bullets[i][1] = (rnd.nextInt() & 0x7fffffff) % width;

    bullets[i][2] = -5;

    bullets[i][3] = (rnd.nextInt()) % 3; //vx

    bullets[i][4] = (rnd.nextInt() & 0x7fffffff) % 3 + 1; //vy

    break;

    case BULLET_TYPE_BOTTOM:

    bullets[i][1] = (rnd.nextInt() & 0x7fffffff) % width;

    bullets[i][2] = height + 5;

    bullets[i][3] = (rnd.nextInt()) % 3; //vx

    bullets[i][4] = ( (rnd.nextInt() & 0x7fffffff) % 3 + 1) * -1; //vy

    break;

    }

    }



    public void updata(int i){//根據速度更新i子彈下一楨的位置,碰壁反彈

    bullets[i][1]+=bullets[i][3];

    bullets[i][2]+=bullets[i][4];

    if(bullets[i][1]<-5 || bullets[i][1]>width+5){

    bullets[i][3]*=-1;

    }

    if(bullets[i][2]<-5 || bullets[i][2]>height+5){

    bullets[i][4]*=-1;

    }

    }



    private void paint(Graphics g,int i){//繪畫出第i個子彈

    updataspritepos(i);//更新位置

    sprite.paint(g);//繪畫Sprtie

    }



    public void paint(Graphics g) {//繪畫整個子彈組

    for (int i = 0; i < bullets.length; i++) {

    if(bullets[i][5]==0){//死去的子彈不繪畫

    continue;

    }

    sprite.setPosition(bullets[i][1],bullets[i][2]); //更新位置

    sprite.paint(g);

    }

    }



    public void refreshBullets(Sprite planesprite, boolean needcollision){//刷新字典數組的狀態,并作碰撞處理

    for (int i = 0; i < bullets.length; i++) {

    if(bullets[i][5]==0){ //死去的子彈不更新

    continue;

    }

    if(needcollision){//如果需要碰撞檢測

    if (isCollision(planesprite, i, 10)) {//如果碰撞,進行處理

    //System.out.println("collision ");

    Navigate.mc.gameover = true;

    Navigate.mc.explosion.sprite.setPosition(bullets[i][1] - 16,

    bullets[i][2] - 16);

    bullets[i][5] = 0;//殺死碰撞的子彈

    continue;

    }

    }

    updata(i);//更新狀態

    }

    }



    private boolean isCollision(Sprite sprite,int i,int range){

    //判斷是否碰撞

    //updataspritepos(i);

    //return sprite.collidesWith(this.sprite,true);

    boolean result=false;

    int planeXCenter=sprite.getX()+12;

    int planeYCenter=sprite.getY()+12;

    int bulletXCenter=bullets[i][1]+3;

    int bulletYCenter=bullets[i][2]+3;

    if(Math.abs(planeXCenter-bulletXCenter) < range){

    if (Math.abs(planeYCenter - bulletYCenter )< range) {

    result = true;

    }

    }

    return result;

    }



    private void updataspritepos(int i){//將sprite更新到i字彈的位置

    sprite.setPosition(bullets[i][1],bullets[i][2]);

    }



    /* no use now

    public void resetDeadBullet(){

    for (int i = 0; i < bullets.length; i++) {

    if(bullets[i][5]==0){//dead bullet

    initBullet(i);

    }

    }

    }

    */



    public void killbullets(Sprite planesprite,int range){殺死一定區域內的子彈

    for (int i = 0; i < bullets.length; i++) {

    if(bullets[i][5]!=0){//alive bullets

    if(isCollision(planesprite, i, range)){

    bullets[i][5]=0;

    initBullet(i);

    }

    }

    }

    }

    }

    子彈如何表示?

    首先我們用一個二維數組來記錄子彈的信息:

    bullets[i][0]表示子彈的類型,有上、下、左、右四種,分別表示子彈飛入屏幕前的四種位置;

    bullets[i][1]表示子彈的x坐標;

    bullets[i][2]表示子彈的y坐標

    bullets[i][3]表示子彈的x方向速度;

    bullets[i][4]表示子彈的y方向速度;

    bullets[i][5]表示子彈的存活狀態;



    子彈如何初始化?

    我們首先寫了一個初始化單個子彈的方法,然后便利數組調用initBullet (i);來更新整個狀態數組。



    子彈如何繪制?

    我們首先寫了一個繪制單個子彈的方法,然后便利數組調用paint(g,i);來繪制整個狀態數組。



    子彈如何碰撞?

    有很多種方法,其中sprite本身就提供了邊框碰撞檢測和基于像素的碰撞檢測。前者不太適合我們的游戲,我們的飛機是不規則物體,且飛行游戲對碰撞比較敏感;而后者的效率又得不到我們的信賴,所以我們是用一種半徑檢測,把飛機近似的看成圓,選取恰當的半徑,Math.abs(planeXCenter-bulletXCenter) < range則表明碰撞。

    碰撞看似簡單,其實是很復雜的問題,值得慶幸的是,二維碰撞相比三維碰撞簡單得多。一個小技巧是,寧可讓膨脹檢測半徑變小也不要他變得大——漏掉檢測,總比誤檢測要好得多。



    子彈更新?

    我們利用refreshBullets進行更新,這是主要邏輯部分。這個方法負責便利數組檢測碰撞,如果碰撞就將處于碰撞位置的子彈殺死,并作相應的處理,這里是結束游戲并爆炸飛機;否則更新子彈的位置。

    我們只是線性的遍歷整個的數組,進行碰撞檢測,之后是更新位置;但是這樣做有一個前提,就是碰撞檢測簡單而且處理部分也很簡單:在這個游戲中,碰撞檢測只是子彈群和飛機的檢測,碰撞檢測在游戲結束后就不執行了(通過控制boolean needcollision);而處理更是簡單了一些——直接結束了游戲。如果不是如此,比如處理后并不是簡單的結束游戲,我們就不得不設計的復雜一些??赡芫筒皇菍⑴鲎埠唵蔚囊燥w機為中心了。我們需要設計好游戲事件,設計好碰撞系統。

    如果碰撞本身比較復雜,或者子彈數量,種類增加時,我們線性的遍歷數組就不能總是對所有的子彈都檢測,可能屏幕需要分區,不處于一個區域的單位不檢測。

    總之當你想想你的1934時,將不在是想象著子彈,飛機什么的,你要思考一個系統。

    總結一下子彈類的公共接口:

    n Bullets(Image img,int picwidth,int picheight,int bulletstotal,int width,int height)構造函數

    n public void initBullets()初始化子彈數組

    n public void paint(Graphics g) paint子彈數組

    n public void refreshBullets(Sprite planesprite, boolean needcollision)更新子彈數組狀態,碰撞檢測、處理等邏輯工作的綜合

    n public void killbullets(Sprite planesprite,int range)//稍后解釋



    到此為止,我們的游戲已經初具規模了,下一步是加入效果類,嘿嘿有點意思了…



    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>