首页 > 系统 > Android > 正文

Android游戏开发学习之引擎用法实例详解

2020-04-11 11:23:23
字体:
来源:转载
供稿:网友

本文实例讲述了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程序设计有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表