这篇文章主要介绍了Android游戏开发学习之引擎用法,较为详细的分析了Android游戏开发中所常用的JBox2D引擎功能及相关使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
本文实例讲述了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程序设计有所帮助。
新闻热点
疑难解答