Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android游戲開發學習之引擎用法實例詳解

Android游戲開發學習之引擎用法實例詳解

編輯:關於Android編程

本文實例講述了Android游戲開發學習之引擎用法。分享給大家供大家參考。具體如下:

汽車引擎是汽車的心髒,其決定了汽車的性能和穩定性,是人們在購車時相當關注的。而游戲中的物理引擎就如汽車的引擎一樣,占據了非常重要的位置。一款好的物理引擎可以非常真實地模擬現實世界,使得游戲更加逼真,提供更好的娛樂體驗。

一、JBox2D簡介

JBox2D是開源物理引擎Box2D的Java版本,可以直接用於Android。由於JBox2D的圖形渲染使用的是Processing庫,因此在Android平台上使用JBox2D時,圖形渲染工作只能自行開發。該引擎能夠根據開發人員設定的參數,如重力、密度、摩擦系數和彈性系數等,自動地進行2D剛體物理運動的全方位模擬。

二、示例

1.小球彈跳進階版

在第1節中小球的下落、碰撞、彈起都是用代碼來維護的,下面使用物理引擎來實現,並且加入了剛體之間的碰撞。

(1)常量類Constant

package box2d.bheap; 
public class Constant { 
  public static final float RATE=10; //屏幕與現實世界的比例 
  public static final boolean DRAW_THREAD_FLAG=true; //繪制線程工作標識位 
  public static final float TIME_STEP=2.0f/60.0f; //模擬的頻率 
  public static final int ITERA=10; //迭代次數 
  public static int SCREEN_WIDTH; //屏幕寬度 
  public static int SCREEN_HEIGHT; //屏幕高度 
}

(2)抽象類MyBody

該類為自定義的抽象類,是所有自定義剛體類的基類。由於JBox2D中的剛體類對象僅具有物理仿真計算的功能,並沒有提供Android平台下的繪制功能,直接使用不是很方便。因此,這裡定義了MyBody對自定義剛體的繪制及JBox2D物理仿真對象進行了封裝。

package box2d.bheap; 
import org.jbox2d.dynamics.Body; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
public abstract class MyBody { 
  Body body; //JBox2D物理引擎中的剛體  
  int color; //剛體的顏色 
  public abstract void drawSelf(Canvas canvas,Paint paint); //繪制的方法 
}

(3)圓形剛體類MyCircleColor

package box2d.bheap; 
import org.jbox2d.dynamics.Body; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.Paint.Style; 
import static box2d.bheap.Constant.*; //靜態導入 
public class MyCircleColor extends MyBody { 
  float radius; //圓形半徑 
  public MyCircleColor(Body body,float radius,int color) { 
    this.body=body; 
    this.radius=radius; 
    this.color=color; 
  } 
  @Override 
  public void drawSelf(Canvas canvas, Paint paint) { 
    paint.setColor(color&0xCFFFFFF); //設置顏色 
    float x=body.getPosition().x*RATE; 
    float y=body.getPosition().y*RATE; 
    canvas.drawCircle(x, y, radius, paint); //畫圓 
    paint.setStyle(Style.STROKE); //設置空心無填充 
    paint.setStrokeWidth(1); 
    paint.setColor(color); //畫邊 
    canvas.drawCircle(x, y, radius, paint); 
    paint.reset(); //恢復畫筆設置 
  } 
}

(4)矩形剛體類MyRectColor

package box2d.bheap; 
import static box2d.bheap.Constant.RATE; 
import org.jbox2d.dynamics.Body; 
import android.graphics.Canvas; 
import android.graphics.Matrix; 
import android.graphics.Paint; 
public class MyRectColor extends MyBody { 
  float halfWidth;//半寬 
  float halfHeight;//半高 
  public MyRectColor(Body body,float halfWidth,float halfHeight,int color) 
  { 
    this.body=body; 
    this.halfWidth=halfWidth; 
    this.halfHeight=halfHeight;    
    this.color=color; 
  } 
  public void drawSelf(Canvas canvas,Paint paint) 
  {      
    paint.setColor(color&0x8CFFFFFF);  
    float x=body.getPosition().x*RATE; 
    float y=body.getPosition().y*RATE; 
    float angle=body.getAngle(); 
    canvas.save(); 
    Matrix m1=new Matrix(); 
    m1.setRotate((float)Math.toDegrees(angle),x, y); 
    canvas.setMatrix(m1); 
    canvas.drawRect(x-halfWidth, y-halfHeight, x+halfWidth, y+halfHeight, paint);  
    paint.setStyle(Paint.Style.STROKE); 
    paint.setStrokeWidth(1);//設置線條寬度 
    paint.setColor(color); 
    canvas.drawRect(x-halfWidth, y-halfHeight, x+halfWidth, y+halfHeight, paint);  
    paint.reset();    
    canvas.restore(); 
  } 
}

(5)生成剛體形狀的工具類Box2DUtil

package box2d.bheap; 
import static box2d.bheap.Constant.RATE; 
import org.jbox2d.collision.CircleDef; 
import org.jbox2d.collision.PolygonDef; 
import org.jbox2d.dynamics.Body; 
import org.jbox2d.dynamics.BodyDef; 
import org.jbox2d.dynamics.World; 
public class Box2DUtil { 
  /** 
   * 創建矩形物體(顏色) 
   */ 
  public static MyRectColor createBox ( 
      float x, 
      float y, 
      float halfWidth, 
      float halfHeight, 
      boolean isStatic, //是否為靜止的 
      World world, 
      int color 
  ) { 
    PolygonDef shape=new PolygonDef(); //創建多邊形描述對象 
    if(isStatic) { 
      shape.density=0; 
    } else { 
      shape.density=1.0f; 
    } 
    shape.friction=0.0f; //設置摩擦系數 
    shape.restitution=0.6f; //設置能量損失率 
    shape.setAsBox(halfWidth/RATE, halfHeight/RATE); 
    BodyDef bodyDef=new BodyDef(); //創建剛體描述對象 
    bodyDef.position.set(x/RATE,y/RATE); //設置位置 
    Body bodyTemp=world.createBody(bodyDef); //在世界中創建剛體 
    bodyTemp.createShape(shape); //指定剛體形狀 
    bodyTemp.setMassFromShapes(); //設置物體質量 
    return new MyRectColor(bodyTemp, halfWidth, halfHeight, color);
  } 
  /** 
   * 創建圓形物體(顏色) 
   */ 
  public static MyCircleColor createCircle ( 
      float x, 
      float y, 
      float radius, 
      World world, 
      int color 
  ) { 
    CircleDef shape=new CircleDef(); //創建圓描述對象 
    shape.density=2; //設置密度 
    shape.friction=0.0f; //設置摩擦系數 
    shape.restitution=0.95f; //設置能量損失率 
    shape.radius=radius/RATE;//設置半徑 
    BodyDef bodyDef=new BodyDef(); //創建剛體描述對象 
    bodyDef.position.set(x/RATE,y/RATE); //設置位置 
    Body bodyTemp=world.createBody(bodyDef); //在世界中創建剛體 
    bodyTemp.createShape(shape); //指定剛體形狀 
    bodyTemp.setMassFromShapes(); //設置物體質量 
    return new MyCircleColor(bodyTemp, radius, color); 
  } 
}

(6)顏色工具類ColorUtil

package box2d.bheap; 
public class ColorUtil { 
  static int[][] result=  
    { 
      {56,225,254},   
      {41,246,239}, 
      {34,244,197}, 
      {44,241,161}, 
      {65,239,106}, 
      {45,238,59}, 
      {73,244,51},   
      {99,233,58}, 
      {129,243,34}, 
      {142,245,44}, 
      {187,243,32}, 
      {232,250,28}, 
      {242,230,46}, 
      {248,196,51}, 
      {244,125,31}, 
      {247,88,46}, 
      {249,70,40}, 
      {249,70,40}, 
      {248,48,48}, 
      {250,30,30}, 
      {252,15,15}, 
      {255,0,0},  
    }; 
    public static int getColor(int index) 
    { 
      int[] rgb=result[index%result.length]; 
      int result=0xff000000; 
      result=result|(rgb[0]<<16); 
      result=result|(rgb[1]<<8); 
      result=result|(rgb[2]); 
      return result; 
    } 
}

(7)主控制類MyBox2dActivity

package box2d.bheap;    
import java.util.ArrayList; 
import java.util.Random; 
import org.jbox2d.collision.AABB;   
import org.jbox2d.common.Vec2;   
import org.jbox2d.dynamics.World;    
import android.app.Activity;   
import android.content.pm.ActivityInfo; 
import android.os.Bundle;   
import android.util.DisplayMetrics; 
import android.view.Window;   
import android.view.WindowManager;  
import static box2d.bheap.Constant.*; 
public class MyBox2dActivity extends Activity  
{   
  AABB worldAABB;//創建 一個管理碰撞的世界   
  World world; 
  Random random=new Random(); 
  //物體列表 
  ArrayList<MyBody> bl=new ArrayList<MyBody>(); 
  public void onCreate(Bundle savedInstanceState)  
  {   
    super.onCreate(savedInstanceState); 
    //設置為全屏 
    requestWindowFeature(Window.FEATURE_NO_TITLE);   
    getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,   
    WindowManager.LayoutParams. FLAG_FULLSCREEN);  
    //設置為橫屏模式 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
    //獲取屏幕尺寸 
    DisplayMetrics dm=new DisplayMetrics(); 
    getWindowManager().getDefaultDisplay().getMetrics(dm);  
    if(dm.widthPixels<dm.heightPixels) 
    { 
       SCREEN_WIDTH=dm.widthPixels; 
       SCREEN_HEIGHT=dm.heightPixels; 
    } 
    else 
    { 
      SCREEN_WIDTH=dm.heightPixels; 
      SCREEN_HEIGHT=dm.widthPixels;   
    } 
    worldAABB = new AABB();   
    //上下界,以屏幕的左上方為 原點,如果創建的剛體到達屏幕的邊緣的話,會停止模擬   
    worldAABB.lowerBound.set(-100.0f,-100.0f); 
    worldAABB.upperBound.set(100.0f, 100.0f);//注意這裡使用的是現實世界的單位   
    Vec2 gravity = new Vec2(0.0f,10.0f); 
    boolean doSleep = true; 
    //創建世界  
    world = new World(worldAABB, gravity, doSleep);      
    //創建4邊 
    final int kd=40;//寬度或高度 
    MyRectColor mrc=Box2DUtil.createBox(kd/4, SCREEN_HEIGHT/2, kd/4, SCREEN_HEIGHT/2, true,world,0xFFe6e4FF); 
    bl.add(mrc); 
    mrc=Box2DUtil.createBox(SCREEN_WIDTH-kd/4, SCREEN_HEIGHT/2, kd/4, SCREEN_HEIGHT/2, true,world,0xFFe6e4FF); 
    bl.add(mrc); 
    mrc=Box2DUtil.createBox(SCREEN_WIDTH/2, kd/4, SCREEN_WIDTH/2, kd/4, true,world,0xFFe6e4FF); 
    bl.add(mrc); 
    mrc=Box2DUtil.createBox(SCREEN_WIDTH/2, SCREEN_HEIGHT-kd/4, SCREEN_WIDTH/2, kd/4, true,world,0xFFe6e4FF); 
    bl.add(mrc); 
    //創建磚塊 
    //磚塊間距 行間距為20   模塊寬度為10 最多一行為9塊 
    final int bs=20; 
    final int bw=(int)((SCREEN_WIDTH-2*kd-11*bs)/18); 
    //============================================================
    for(int i=2;i<10;i++) 
    { 
      if((i%2)==0) 
      { 
        //左側藍木塊 
        for(int j=0;j<9-i;j++) 
        { 
          mrc=Box2DUtil.createBox 
          ( 
            kd/2+bs+bw/2+i*(kd+5)/2+j*(kd+5)+3, 
            SCREEN_HEIGHT+bw-i*(bw+kd)/2, 
            bw/2, 
            kd/2, 
            false, 
            world, 
            ColorUtil.getColor(Math.abs(random.nextInt())) 
          ); 
          bl.add(mrc); 
        } 
        //右側藍木塊 
        for(int j=0;j<9-i;j++) 
        { 
          mrc=Box2DUtil.createBox 
          ( 
            3*kd/2+bs-bw/2+i*(kd+5)/2+j*(kd+5)-3, 
            SCREEN_HEIGHT+bw-i*(bw+kd)/2, 
            bw/2, 
            kd/2, 
            false, 
            world, 
            ColorUtil.getColor(Math.abs(random.nextInt())) 
          ); 
          bl.add(mrc); 
        } 
      }   
      if((i%2)!=0) 
      { 
        for(int j=0;j<10-i;j++) 
        { 
          mrc=Box2DUtil.createBox 
          ( 
            kd/2+bs+kd/2+(i-1)*(kd+5)/2+j*(kd+5), 
            SCREEN_HEIGHT-(kd-bw)/2-(i-1)*(bw+kd)/2, 
            kd/2, 
            bw/2, 
            false, 
            world, 
            ColorUtil.getColor(Math.abs(random.nextInt())) 
          ); 
          bl.add(mrc); 
        } 
      } 
    } 
    mrc=Box2DUtil.createBox 
    ( 
      5*kd+bs+20, 
      SCREEN_HEIGHT-(kd+bw)*4-kd, 
      bw/2, 
      kd/2, 
      false, 
      world, 
      ColorUtil.getColor(Math.abs(random.nextInt())) 
    ); 
    bl.add(mrc); 
    //創建球 
    MyCircleColor ball=Box2DUtil.createCircle(SCREEN_WIDTH/2-24, kd, kd/2, world,ColorUtil.getColor(Math.abs(random.nextInt()))); 
    bl.add(ball); 
    ball.body.setLinearVelocity(new Vec2(0,50)); 
    GameView gv= new GameView(this);
    setContentView(gv);
  }
}

(8)顯示界面類GameView

package box2d.bheap;
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.view.SurfaceHolder; 
import android.view.SurfaceHolder.Callback; 
import android.view.SurfaceView; 
public class GameView extends SurfaceView implements Callback{ 
  MyBox2dActivity activity; 
  Paint paint; 
  DrawThread dt; 
  public GameView(MyBox2dActivity activity) { 
    super(activity); 
    this.activity=activity; 
    this.getHolder().addCallback(this);  
    paint =new Paint(); 
    paint.setAntiAlias(true); 
    dt=new DrawThread(this); 
    dt.start(); 
  } 
  public void onDraw(Canvas canvas) { 
    if(canvas==null) { 
      return ; 
    } 
    canvas.drawARGB(255, 255, 255, 255); //設置背景顏色白色 
    for (MyBody mb : activity.bl) { 
      mb.drawSelf(canvas, paint); 
    } 
  } 
  @Override 
  public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
  } 
  @Override 
  public void surfaceCreated(SurfaceHolder holder) { 
        repaint(); 
  } 
  @Override 
  public void surfaceDestroyed(SurfaceHolder holder) { 
  } 
  public void repaint() { 
    SurfaceHolder holder=this.getHolder(); 
    Canvas canvas=holder.lockCanvas(); 
    try { 
      synchronized(holder){ 
        onDraw(canvas); 
      } 
    } catch(Exception e){ 
      e.printStackTrace(); 
    } finally { 
      if(canvas!=null) { 
        holder.unlockCanvasAndPost(canvas);  
      } 
    } 
  } 
}

(9)繪制線程類DrawThread

package box2d.bheap; 
import static box2d.bheap.Constant.*; 
//繪制線程 
public class DrawThread extends Thread 
{ 
  GameView gv; 
  public DrawThread(GameView gv) 
  { 
    this.gv=gv; 
  } 
  @Override 
  public void run() 
  { 
    while(DRAW_THREAD_FLAG) 
    { 
      gv.activity.world.step(TIME_STEP, ITERA);//開始模擬 
      gv.repaint(); 
      try  
      { 
        Thread.sleep(20); 
      } catch (InterruptedException e)  
      { 
        e.printStackTrace(); 
      } 
    } 
  } 
}

希望本文所述對大家的jsp程序設計有所幫助。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved