首页 > 系统 > Android > 正文

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

2019-10-24 20:35:58
字体:
来源:转载
供稿:网友

这篇文章主要介绍了Android游戏开发学习之引擎用法,较为详细的分析了Android游戏开发中所常用的JBox2D引擎功能及相关使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下

本文实例讲述了Android游戏开发学习之引擎用法。分享给大家供大家参考。具体如下:

汽车引擎是汽车的心脏,其决定了汽车的性能和稳定性,是人们在购车时相当关注的。而游戏中的物理引擎就如汽车的引擎一样,占据了非常重要的位置。一款好的物理引擎可以非常真实地模拟现实世界,使得游戏更加逼真,提供更好的娱乐体验。

一、JBox2D简介

JBox2D是开源物理引擎Box2D的Java版本,可以直接用于Android。由于JBox2D的图形渲染使用的是Processing库,因此在Android平台上使用JBox2D时,图形渲染工作只能自行开发。该引擎能够根据开发人员设定的参数,如重力、密度、摩擦系数和弹性系数等,自动地进行2D刚体物理运动的全方位模拟。

二、示例

1.小球弹跳进阶版

在第1节中小球的下落、碰撞、弹起都是用代码来维护的,下面使用物理引擎来实现,并且加入了刚体之间的碰撞。

(1)常量类Constant

 

 
  1. package box2d.bheap;  
  2. public class Constant {  
  3. public static final float RATE=10; //屏幕与现实世界的比例  
  4. public static final boolean DRAW_THREAD_FLAG=true//绘制线程工作标识位  
  5. public static final float TIME_STEP=2.0f/60.0f; //模拟的频率  
  6. public static final int ITERA=10; //迭代次数  
  7. public static int SCREEN_WIDTH; //屏幕宽度  
  8. public static int SCREEN_HEIGHT; //屏幕高度  

(2)抽象类MyBody

该类为自定义的抽象类,是所有自定义刚体类的基类。由于JBox2D中的刚体类对象仅具有物理仿真计算的功能,并没有提供Android平台下的绘制功能,直接使用不是很方便。因此,这里定义了MyBody对自定义刚体的绘制及JBox2D物理仿真对象进行了封装。

 

 
  1. package box2d.bheap;  
  2. import org.jbox2d.dynamics.Body;  
  3. import android.graphics.Canvas;  
  4. import android.graphics.Paint;  
  5. public abstract class MyBody {  
  6. Body body; //JBox2D物理引擎中的刚体  
  7. int color; //刚体的颜色  
  8. public abstract void drawSelf(Canvas canvas,Paint paint); //绘制的方法  

(3)圆形刚体类MyCircleColor

 

 
  1. package box2d.bheap;  
  2. import org.jbox2d.dynamics.Body;  
  3. import android.graphics.Canvas;  
  4. import android.graphics.Paint;  
  5. import android.graphics.Paint.Style;  
  6. import static box2d.bheap.Constant.*; //静态导入  
  7. public class MyCircleColor extends MyBody {  
  8. float radius; //圆形半径  
  9. public MyCircleColor(Body body,float radius,int color) {  
  10. this.body=body;  
  11. this.radius=radius;  
  12. this.color=color;  
  13. }  
  14. @Override 
  15. public void drawSelf(Canvas canvas, Paint paint) {  
  16. paint.setColor(color&0xCFFFFFF); //设置颜色  
  17. float x=body.getPosition().x*RATE;  
  18. float y=body.getPosition().y*RATE;  
  19. canvas.drawCircle(x, y, radius, paint); //画圆  
  20. paint.setStyle(Style.STROKE); //设置空心无填充  
  21. paint.setStrokeWidth(1);  
  22. paint.setColor(color); //画边  
  23. canvas.drawCircle(x, y, radius, paint);  
  24. paint.reset(); //恢复画笔设置  
  25. }  

(4)矩形刚体类MyRectColor

 

 
  1. package box2d.bheap;  
  2. import static box2d.bheap.Constant.RATE;  
  3. import org.jbox2d.dynamics.Body;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Matrix;  
  6. import android.graphics.Paint;  
  7. public class MyRectColor extends MyBody {  
  8. float halfWidth;//半宽  
  9. float halfHeight;//半高  
  10. public MyRectColor(Body body,float halfWidth,float halfHeight,int color)  
  11. {  
  12. this.body=body;  
  13. this.halfWidth=halfWidth;  
  14. this.halfHeight=halfHeight;  
  15. this.color=color;  
  16. }  
  17. public void drawSelf(Canvas canvas,Paint paint)  
  18. {  
  19. paint.setColor(color&0x8CFFFFFF);  
  20. float x=body.getPosition().x*RATE;  
  21. float y=body.getPosition().y*RATE;  
  22. float angle=body.getAngle();  
  23. canvas.save();  
  24. Matrix m1=new Matrix();  
  25. m1.setRotate((float)Math.toDegrees(angle),x, y);  
  26. canvas.setMatrix(m1);  
  27. canvas.drawRect(x-halfWidth, y-halfHeight, x+halfWidth, y+halfHeight, paint);  
  28. paint.setStyle(Paint.Style.STROKE);  
  29. paint.setStrokeWidth(1);//设置线条宽度  
  30. paint.setColor(color);  
  31. canvas.drawRect(x-halfWidth, y-halfHeight, x+halfWidth, y+halfHeight, paint);  
  32. paint.reset();  
  33. canvas.restore();  
  34. }  

(5)生成刚体形状的工具类Box2DUtil

 

 
  1. package box2d.bheap;  
  2. import static box2d.bheap.Constant.RATE;  
  3. import org.jbox2d.collision.CircleDef;  
  4. import org.jbox2d.collision.PolygonDef;  
  5. import org.jbox2d.dynamics.Body;  
  6. import org.jbox2d.dynamics.BodyDef;  
  7. import org.jbox2d.dynamics.World;  
  8. public class Box2DUtil {  
  9. /**  
  10. * 创建矩形物体(颜色)  
  11. */ 
  12. public static MyRectColor createBox (  
  13. float x,  
  14. float y,  
  15. float halfWidth,  
  16. float halfHeight,  
  17. boolean isStatic, //是否为静止的  
  18. World world,  
  19. int color  
  20. ) {  
  21. PolygonDef shape=new PolygonDef(); //创建多边形描述对象  
  22. if(isStatic) {  
  23. shape.density=0;  
  24. else {  
  25. shape.density=1.0f;  
  26. }  
  27. shape.friction=0.0f; //设置摩擦系数  
  28. shape.restitution=0.6f; //设置能量损失率  
  29. shape.setAsBox(halfWidth/RATE, halfHeight/RATE);  
  30. BodyDef bodyDef=new BodyDef(); //创建刚体描述对象  
  31. bodyDef.position.set(x/RATE,y/RATE); //设置位置  
  32. Body bodyTemp=world.createBody(bodyDef); //在世界中创建刚体  
  33. bodyTemp.createShape(shape); //指定刚体形状  
  34. bodyTemp.setMassFromShapes(); //设置物体质量  
  35. return new MyRectColor(bodyTemp, halfWidth, halfHeight, color); 
  36. }  
  37. /**  
  38. * 创建圆形物体(颜色)  
  39. */ 
  40. public static MyCircleColor createCircle (  
  41. float x,  
  42. float y,  
  43. float radius,  
  44. World world,  
  45. int color  
  46. ) {  
  47. CircleDef shape=new CircleDef(); //创建圆描述对象  
  48. shape.density=2; //设置密度  
  49. shape.friction=0.0f; //设置摩擦系数  
  50. shape.restitution=0.95f; //设置能量损失率  
  51. shape.radius=radius/RATE;//设置半径  
  52. BodyDef bodyDef=new BodyDef(); //创建刚体描述对象  
  53. bodyDef.position.set(x/RATE,y/RATE); //设置位置  
  54. Body bodyTemp=world.createBody(bodyDef); //在世界中创建刚体  
  55. bodyTemp.createShape(shape); //指定刚体形状  
  56. bodyTemp.setMassFromShapes(); //设置物体质量  
  57. return new MyCircleColor(bodyTemp, radius, color);  
  58. }  

(6)颜色工具类ColorUtil

 

 
  1. package box2d.bheap;  
  2. public class ColorUtil {  
  3. static int[][] result=  
  4. {  
  5. {56,225,254},  
  6. {41,246,239},  
  7. {34,244,197},  
  8. {44,241,161},  
  9. {65,239,106},  
  10. {45,238,59},  
  11. {73,244,51},  
  12. {99,233,58},  
  13. {129,243,34},  
  14. {142,245,44},  
  15. {187,243,32},  
  16. {232,250,28},  
  17. {242,230,46},  
  18. {248,196,51},  
  19. {244,125,31},  
  20. {247,88,46},  
  21. {249,70,40},  
  22. {249,70,40},  
  23. {248,48,48},  
  24. {250,30,30},  
  25. {252,15,15},  
  26. {255,0,0},  
  27. };  
  28. public static int getColor(int index)  
  29. {  
  30. int[] rgb=result[index%result.length];  
  31. int result=0xff000000;  
  32. result=result|(rgb[0]<<16);  
  33. result=result|(rgb[1]<<8);  
  34. result=result|(rgb[2]);  
  35. return result;  
  36. }  

(7)主控制类MyBox2dActivity

 

 
  1. package box2d.bheap;  
  2. import java.util.ArrayList;  
  3. import java.util.Random;  
  4. import org.jbox2d.collision.AABB;  
  5. import org.jbox2d.common.Vec2;  
  6. import org.jbox2d.dynamics.World;  
  7. import android.app.Activity;  
  8. import android.content.pm.ActivityInfo;  
  9. import android.os.Bundle;  
  10. import android.util.DisplayMetrics;  
  11. import android.view.Window;  
  12. import android.view.WindowManager;  
  13. import static box2d.bheap.Constant.*;  
  14. public class MyBox2dActivity extends Activity  
  15. {  
  16. AABB worldAABB;//创建 一个管理碰撞的世界  
  17. World world;  
  18. Random random=new Random();  
  19. //物体列表  
  20. ArrayList<MyBody> bl=new ArrayList<MyBody>();  
  21. public void onCreate(Bundle savedInstanceState)  
  22. {  
  23. super.onCreate(savedInstanceState);  
  24. //设置为全屏  
  25. requestWindowFeature(Window.FEATURE_NO_TITLE);  
  26. getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN ,  
  27. WindowManager.LayoutParams. FLAG_FULLSCREEN);  
  28. //设置为横屏模式  
  29. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  
  30. //获取屏幕尺寸  
  31. DisplayMetrics dm=new DisplayMetrics();  
  32. getWindowManager().getDefaultDisplay().getMetrics(dm);  
  33. if(dm.widthPixels<dm.heightPixels)  
  34. {  
  35. SCREEN_WIDTH=dm.widthPixels;  
  36. SCREEN_HEIGHT=dm.heightPixels;  
  37. }  
  38. else 
  39. {  
  40. SCREEN_WIDTH=dm.heightPixels;  
  41. SCREEN_HEIGHT=dm.widthPixels;  
  42. }  
  43. worldAABB = new AABB();  
  44. //上下界,以屏幕的左上方为 原点,如果创建的刚体到达屏幕的边缘的话,会停止模拟  
  45. worldAABB.lowerBound.set(-100.0f,-100.0f);  
  46. worldAABB.upperBound.set(100.0f, 100.0f);//注意这里使用的是现实世界的单位  
  47. Vec2 gravity = new Vec2(0.0f,10.0f);  
  48. boolean doSleep = true;  
  49. //创建世界  
  50. world = new World(worldAABB, gravity, doSleep);  
  51. //创建4边  
  52. final int kd=40;//宽度或高度  
  53. MyRectColor mrc=Box2DUtil.createBox(kd/4, SCREEN_HEIGHT/2, kd/4, SCREEN_HEIGHT/2, true,world,0xFFe6e4FF);  
  54. bl.add(mrc);  
  55. mrc=Box2DUtil.createBox(SCREEN_WIDTH-kd/4, SCREEN_HEIGHT/2, kd/4, SCREEN_HEIGHT/2, true,world,0xFFe6e4FF);  
  56. bl.add(mrc);  
  57. mrc=Box2DUtil.createBox(SCREEN_WIDTH/2, kd/4, SCREEN_WIDTH/2, kd/4, true,world,0xFFe6e4FF);  
  58. bl.add(mrc);  
  59. mrc=Box2DUtil.createBox(SCREEN_WIDTH/2, SCREEN_HEIGHT-kd/4, SCREEN_WIDTH/2, kd/4, true,world,0xFFe6e4FF);  
  60. bl.add(mrc);  
  61. //创建砖块  
  62. //砖块间距 行间距为20 模块宽度为10 最多一行为9块  
  63. final int bs=20;  
  64. final int bw=(int)((SCREEN_WIDTH-2*kd-11*bs)/18);  
  65. //============================================================ 
  66. for(int i=2;i<10;i++)  
  67. {  
  68. if((i%2)==0)  
  69. {  
  70. //左侧蓝木块  
  71. for(int j=0;j<9-i;j++)  
  72. {  
  73. mrc=Box2DUtil.createBox  
  74. (  
  75. kd/2+bs+bw/2+i*(kd+5)/2+j*(kd+5)+3,  
  76. SCREEN_HEIGHT+bw-i*(bw+kd)/2,  
  77. bw/2,  
  78. kd/2,  
  79. false,  
  80. world,  
  81. ColorUtil.getColor(Math.abs(random.nextInt()))  
  82. );  
  83. bl.add(mrc);  
  84. }  
  85. //右侧蓝木块  
  86. for(int j=0;j<9-i;j++)  
  87. {  
  88. mrc=Box2DUtil.createBox  
  89. (  
  90. 3*kd/2+bs-bw/2+i*(kd+5)/2+j*(kd+5)-3,  
  91. SCREEN_HEIGHT+bw-i*(bw+kd)/2,  
  92. bw/2,  
  93. kd/2,  
  94. false,  
  95. world,  
  96. ColorUtil.getColor(Math.abs(random.nextInt()))  
  97. );  
  98. bl.add(mrc);  
  99. }  
  100. }  
  101. if((i%2)!=0)  
  102. {  
  103. for(int j=0;j<10-i;j++)  
  104. {  
  105. mrc=Box2DUtil.createBox  
  106. (  
  107. kd/2+bs+kd/2+(i-1)*(kd+5)/2+j*(kd+5),  
  108. SCREEN_HEIGHT-(kd-bw)/2-(i-1)*(bw+kd)/2,  
  109. kd/2,  
  110. bw/2,  
  111. false,  
  112. world,  
  113. ColorUtil.getColor(Math.abs(random.nextInt()))  
  114. );  
  115. bl.add(mrc);  
  116. }  
  117. }  
  118. }  
  119. mrc=Box2DUtil.createBox  
  120. (  
  121. 5*kd+bs+20,  
  122. SCREEN_HEIGHT-(kd+bw)*4-kd,  
  123. bw/2,  
  124. kd/2,  
  125. false,  
  126. world,  
  127. ColorUtil.getColor(Math.abs(random.nextInt()))  
  128. );  
  129. bl.add(mrc);  
  130. //创建球  
  131. MyCircleColor ball=Box2DUtil.createCircle(SCREEN_WIDTH/2-24, kd, kd/2, world,ColorUtil.getColor(Math.abs(random.nextInt())));  
  132. bl.add(ball);  
  133. ball.body.setLinearVelocity(new Vec2(0,50));  
  134. GameView gv= new GameView(this); 
  135. setContentView(gv); 

(8)显示界面类GameView

 

 
  1. package box2d.bheap; 
  2. import android.graphics.Canvas;  
  3. import android.graphics.Paint;  
  4. import android.view.SurfaceHolder;  
  5. import android.view.SurfaceHolder.Callback;  
  6. import android.view.SurfaceView;  
  7. public class GameView extends SurfaceView implements Callback{  
  8. MyBox2dActivity activity;  
  9. Paint paint;  
  10. DrawThread dt;  
  11. public GameView(MyBox2dActivity activity) {  
  12. super(activity);  
  13. this.activity=activity;  
  14. this.getHolder().addCallback(this);  
  15. paint =new Paint();  
  16. paint.setAntiAlias(true);  
  17. dt=new DrawThread(this);  
  18. dt.start();  
  19. }  
  20. public void onDraw(Canvas canvas) {  
  21. if(canvas==null) {  
  22. return ;  
  23. }  
  24. canvas.drawARGB(255, 255, 255, 255); //设置背景颜色白色  
  25. for (MyBody mb : activity.bl) {  
  26. mb.drawSelf(canvas, paint);  
  27. }  
  28. }  
  29. @Override 
  30. public void surfaceChanged(SurfaceHolder holder, int format, int width,  
  31. int height) {  
  32. }  
  33. @Override 
  34. public void surfaceCreated(SurfaceHolder holder) {  
  35. repaint();  
  36. }  
  37. @Override 
  38. public void surfaceDestroyed(SurfaceHolder holder) {  
  39. }  
  40. public void repaint() {  
  41. SurfaceHolder holder=this.getHolder();  
  42. Canvas canvas=holder.lockCanvas();  
  43. try {  
  44. synchronized(holder){  
  45. onDraw(canvas);  
  46. }  
  47. catch(Exception e){  
  48. e.printStackTrace();  
  49. finally {  
  50. if(canvas!=null) {  
  51. holder.unlockCanvasAndPost(canvas);  
  52. }  
  53. }  
  54. }  

(9)绘制线程类DrawThread

 

 
  1. package box2d.bheap;  
  2. import static box2d.bheap.Constant.*;  
  3. //绘制线程  
  4. public class DrawThread extends Thread  
  5. {  
  6. GameView gv;  
  7. public DrawThread(GameView gv)  
  8. {  
  9. this.gv=gv;  
  10. }  
  11. @Override 
  12. public void run()  
  13. {  
  14. while(DRAW_THREAD_FLAG)  
  15. {  
  16. gv.activity.world.step(TIME_STEP, ITERA);//开始模拟  
  17. gv.repaint();  
  18. try 
  19. {  
  20. Thread.sleep(20);  
  21. catch (InterruptedException e)  
  22. {  
  23. e.printStackTrace();  
  24. }  
  25. }  
  26. }  

希望本文所述对大家的jsp程序设计有所帮助。

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