Android游戲開發(fā)學習之引擎用法實例詳解
本文實例講述了Android游戲開發(fā)學習之引擎用法。分享給大家供大家參考。具體如下:
汽車引擎是汽車的心臟,其決定了汽車的性能和穩(wěn)定性,是人們在購車時相當關注的。而游戲中的物理引擎就如汽車的引擎一樣,占據(jù)了非常重要的位置。一款好的物理引擎可以非常真實地模擬現(xiàn)實世界,使得游戲更加逼真,提供更好的娛樂體驗。
一、JBox2D簡介
JBox2D是開源物理引擎Box2D的Java版本,可以直接用于Android。由于JBox2D的圖形渲染使用的是Processing庫,因此在Android平臺上使用JBox2D時,圖形渲染工作只能自行開發(fā)。該引擎能夠根據(jù)開發(fā)人員設定的參數(shù),如重力、密度、摩擦系數(shù)和彈性系數(shù)等,自動地進行2D剛體物理運動的全方位模擬。
二、示例
1.小球彈跳進階版
在第1節(jié)中小球的下落、碰撞、彈起都是用代碼來維護的,下面使用物理引擎來實現(xiàn),并且加入了剛體之間的碰撞。
(1)常量類Constant
package box2d.bheap;
public class Constant {
public static final float RATE=10; //屏幕與現(xiàn)實世界的比例
public static final boolean DRAW_THREAD_FLAG=true; //繪制線程工作標識位
public static final float TIME_STEP=2.0f/60.0f; //模擬的頻率
public static final int ITERA=10; //迭代次數(shù)
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.*; //靜態(tài)導入
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 {
/**
* 創(chuàng)建矩形物體(顏色)
*/
public static MyRectColor createBox (
float x,
float y,
float halfWidth,
float halfHeight,
boolean isStatic, //是否為靜止的
World world,
int color
) {
PolygonDef shape=new PolygonDef(); //創(chuàng)建多邊形描述對象
if(isStatic) {
shape.density=0;
} else {
shape.density=1.0f;
}
shape.friction=0.0f; //設置摩擦系數(shù)
shape.restitution=0.6f; //設置能量損失率
shape.setAsBox(halfWidth/RATE, halfHeight/RATE);
BodyDef bodyDef=new BodyDef(); //創(chuàng)建剛體描述對象
bodyDef.position.set(x/RATE,y/RATE); //設置位置
Body bodyTemp=world.createBody(bodyDef); //在世界中創(chuàng)建剛體
bodyTemp.createShape(shape); //指定剛體形狀
bodyTemp.setMassFromShapes(); //設置物體質(zhì)量
return new MyRectColor(bodyTemp, halfWidth, halfHeight, color);
}
/**
* 創(chuàng)建圓形物體(顏色)
*/
public static MyCircleColor createCircle (
float x,
float y,
float radius,
World world,
int color
) {
CircleDef shape=new CircleDef(); //創(chuàng)建圓描述對象
shape.density=2; //設置密度
shape.friction=0.0f; //設置摩擦系數(shù)
shape.restitution=0.95f; //設置能量損失率
shape.radius=radius/RATE;//設置半徑
BodyDef bodyDef=new BodyDef(); //創(chuàng)建剛體描述對象
bodyDef.position.set(x/RATE,y/RATE); //設置位置
Body bodyTemp=world.createBody(bodyDef); //在世界中創(chuàng)建剛體
bodyTemp.createShape(shape); //指定剛體形狀
bodyTemp.setMassFromShapes(); //設置物體質(zhì)量
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;//創(chuàng)建 一個管理碰撞的世界
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();
//上下界,以屏幕的左上方為 原點,如果創(chuàng)建的剛體到達屏幕的邊緣的話,會停止模擬
worldAABB.lowerBound.set(-100.0f,-100.0f);
worldAABB.upperBound.set(100.0f, 100.0f);//注意這里使用的是現(xiàn)實世界的單位
Vec2 gravity = new Vec2(0.0f,10.0f);
boolean doSleep = true;
//創(chuàng)建世界
world = new World(worldAABB, gravity, doSleep);
//創(chuàng)建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);
//創(chuàng)建磚塊
//磚塊間距 行間距為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)
{
//左側(cè)藍木塊
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);
}
//右側(cè)藍木塊
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);
//創(chuàng)建球
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程序設計有所幫助。
- Android游戲源碼分享之2048
- Android 游戲開發(fā)之Canvas畫布的介紹及方法
- Android游戲開發(fā)實踐之人物移動地圖的平滑滾動處理
- 解析Android游戲中獲取電話狀態(tài)進行游戲暫?;蚶^續(xù)的解決方法
- Unity3D游戲引擎實現(xiàn)在Android中打開WebView的實例
- Android 游戲引擎libgdx 資源加載進度百分比顯示案例分析
- android游戲載入的activity跳轉(zhuǎn)到游戲主菜單的activity具體實現(xiàn)
- Android游戲開發(fā)學習①彈跳小球?qū)崿F(xiàn)方法
- 以一個著色游戲展開講解Android中區(qū)域圖像填色的方法
- 最常見的猜拳小游戲Android代碼實現(xiàn)
相關文章
Android開發(fā)之Animations動畫用法實例詳解
這篇文章主要介紹了Android開發(fā)之Animations動畫用法,結合實例形式詳細分析了Animations動畫的類型、組成、模式及對應的使用技巧,需要的朋友可以參考下2016-02-02
Android?Activity生命周期調(diào)用的理解
大家好。本篇文章主要講的是Android?Activity生命周期調(diào)用的理解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
Android自定義RadioGroupX實現(xiàn)多行多列布局
這篇文章主要為大家詳細介紹了Android自定義RadioGroupX實現(xiàn)多行多列布局,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Android項目實戰(zhàn)教程之高仿網(wǎng)易云音樂啟動頁實例代碼
這篇文章主要給大家介紹了關于Android項目實戰(zhàn)教程之高仿網(wǎng)易云音樂啟動頁的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2018-09-09

