`

android 2d物理引擎-APEngine

 
阅读更多

转载http://crackren.iteye.com/blog/812663

APE(Actionscript Physics Engine) 是一个 ActionScript3 写成的物理引擎,用于模拟现实中物体发生的运动和碰撞。它是免费、开源的,遵循 MIT 协议。很适合做简单的物理游戏.

现提供了 Alpha, Java Port, C++ SDL Ports 三个版本 .

 

 

这里我把官网上的一个Demo移植到了Android上,模拟器上的帧率是5帧左右,真机在HTC Magic G2 上测试也只是6,7帧的样子.我把代码上传上来大家看看能不能优化,还有如果有真机的话希望把在你机子上运行的速度和真机的配置说一下,比较一下各类机器的差异.

 

 

Java代码 复制代码 收藏代码
  1. package Test.APEngineTest;   
  2.   
  3. import android.graphics.Canvas;   
  4. import android.graphics.Paint;   
  5. import android.util.Log;   
  6. import android.view.KeyEvent;   
  7. import android.view.SurfaceView;   
  8. import android.view.SurfaceHolder;   
  9. import android.content.Context;   
  10. import android.graphics.Color;   
  11. import android.graphics.Paint.Style;   
  12.   
  13. import java.lang.Runnable;   
  14.   
  15. import java.util.ArrayList;   
  16.   
  17. import ape.*;   
  18.   
  19. public class ApeTest extends SurfaceView implements Runnable, SurfaceHolder.Callback{   
  20.     // APEngine 世界   
  21.     private APEngine APEngine = new APEngine();   
  22.     // 两个轮子   
  23.     private SpringConstraint wheelConnector;   
  24.     private WheelParticle wheelParticleA;   
  25.     private WheelParticle wheelParticleB;   
  26.     // 车身   
  27.     private RectangleParticle rotatingRect;   
  28.     // 世界中需要刷新的所有物理列表   
  29.     private ArrayList paintQueue;   
  30.        
  31.     private Canvas mCanvas = null;   
  32.     private Paint mPaint = null;   
  33.     SurfaceHolder mSurfaceHolder = null;     
  34.        
  35.     public static final int SCREEN_WIDTH = 320;   
  36.     public static final int SCREEN_HEIGHT= 480;   
  37.     public static final int PLAY_HEIGHT  = 400;    
  38.     public static final int SPEED        = 15;   
  39.     public static final double keySpeed = 0.2;   
  40.        
  41.     //计算帧率   
  42. //  private long mFPSLockTime = 0;   
  43.     private long mFPSShowTime = 0;              //   
  44.     private long mNowTime = 0;                  //现在的时间   
  45.     private int mLoopCount = 0;                 //循环次数   
  46.     private float mFPS = 0.0f;                  //帧速   
  47. //  private float mFPSTime = (1000.0f/30);      //每帧最大执行时间(默认30帧)   
  48.     private Paint mFPSPaint = new Paint();   
  49.        
  50.     public ApeTest(Context context)   
  51.     {   
  52.         super(context);   
  53.         setFocusable(true);   
  54.         setFocusableInTouchMode(true);   
  55.            
  56.         mSurfaceHolder = this.getHolder();   
  57.         mSurfaceHolder.addCallback(this);   
  58.          
  59.         mPaint = new Paint();   
  60.         mPaint.setAntiAlias(true);   
  61.         mPaint.setColor(Color.BLACK);   
  62.         mPaint.setStyle(Style.STROKE);   
  63.         APEngine.setDefaultPaint(mPaint);   
  64.            
  65.         InitWorld();          
  66.               
  67.     }//end of func   
  68.        
  69.     public void InitWorld()    
  70.     {   
  71.            
  72.         // set up the events, main loop handler, and the engine. you don't have to use   
  73.         // enterframe. you just need to call the ApeEngine.step() method wherever   
  74.         // and however your handling your program cycle.   
  75.            
  76.         // the argument here is the deltaTime value. Higher values result in faster simulations.   
  77.         APEngine.init((double)1/4);   
  78.            
  79.         // SELECTIVE is better for dealing with lots of little particles colliding,    
  80.         // as in the little rects and circles in this example   
  81.         APEngine.setCollisionResponseMode(APEngine.SELECTIVE);   
  82.            
  83.         // gravity -- particles of varying masses are affected the same   
  84.         APEngine.addMasslessForce(new Vector(0,3));   
  85.                            
  86.         // surfaces   
  87.         RectangleParticle floor = new RectangleParticle(325,324,649,50,0,true,1,0.3,0);   
  88.         APEngine.addParticle(floor);   
  89.   
  90.         RectangleParticle floorBumpA = new RectangleParticle(400,295,90,300.4,true,1,0.3,0);   
  91.         APEngine.addParticle(floorBumpA);   
  92.            
  93.         RectangleParticle floorBumpB = new RectangleParticle(330,295,90,30,-0.4,true,1,0.3,0);   
  94.         //APEngine.addParticle(floorBumpB);   
  95.            
  96.         RectangleParticle floorLeftAngle = new RectangleParticle(80,290,120,20,0.5,true,1,0.3,0);   
  97.         APEngine.addParticle(floorLeftAngle);   
  98.            
  99.         RectangleParticle leftWall = new RectangleParticle(15,99,30,500,0,true,1,0.3,0);   
  100.         APEngine.addParticle(leftWall);   
  101.                
  102.         RectangleParticle rightWall = new RectangleParticle(634,99,30,500,0,true,1,0.3,0);   
  103.         APEngine.addParticle(rightWall);   
  104.            
  105.         // 桥 开始点   
  106.         RectangleParticle bridgeStart = new RectangleParticle(80,70,150,25,0,true,1,0.3,0);   
  107.         APEngine.addParticle(bridgeStart);   
  108.            
  109.         // 桥结束点   
  110.         RectangleParticle bridgeEnd = new RectangleParticle(380,70,100,25,0,true,1,0.3,0);   
  111.         APEngine.addParticle(bridgeEnd);   
  112.            
  113.         RectangleParticle bridgeEndAngle = new RectangleParticle(455,102,100,25,0.8,true,1,0.3,0);   
  114.         APEngine.addParticle(bridgeEndAngle);   
  115.            
  116.         RectangleParticle rightWallAngle = new RectangleParticle(595,102,100,25,-0.8,true,1,0.3,0);   
  117.         APEngine.addParticle(rightWallAngle);   
  118.            
  119.         // 旋转矩形rotator   
  120.         rotatingRect = new RectangleParticle(525,180,70,14,0,true,1,0.3,0);   
  121.         APEngine.addParticle(rotatingRect);   
  122.            
  123.         // 小矩形   
  124.         RectangleParticle littleRect = new RectangleParticle(525,180,10,10,0,false,1,0.3,0);   
  125.         APEngine.addParticle(littleRect);   
  126.            
  127.         // 把旋转矩形和小矩形用皮筋连接到一起   
  128.         SpringConstraint rotConnector = new SpringConstraint((AbstractParticle)rotatingRect.getCornerParticles().get(1), (AbstractParticle)littleRect, 0.2);           
  129.         APEngine.addConstraint(rotConnector);   
  130.            
  131.         // bridge   
  132.         CircleParticle bridgePA = new CircleParticle(200,70,4,false,1,0.3,0);   
  133.         APEngine.addParticle(bridgePA);   
  134.            
  135.         CircleParticle bridgePB = new CircleParticle(240,70,4,false,1,0.3,0);   
  136.         APEngine.addParticle(bridgePB);   
  137.            
  138.         CircleParticle bridgePC = new CircleParticle(280,70,4,false,1,0.3,0);   
  139.         APEngine.addParticle(bridgePC);   
  140.            
  141.         SpringConstraint bridgeConnA = new SpringConstraint((AbstractParticle)bridgeStart.getCornerParticles().get(1), bridgePA, 0.9);   
  142.         bridgeConnA.setCollidable(true);   
  143.         bridgeConnA.setCollisionRectWidth(10);   
  144.         bridgeConnA.setCollisionRectScale(0.6);   
  145.         APEngine.addConstraint(bridgeConnA);   
  146.   
  147.         SpringConstraint bridgeConnB = new SpringConstraint(bridgePA, bridgePB, 0.9);   
  148.         bridgeConnB.setCollidable(true);   
  149.         bridgeConnB.setCollisionRectWidth(10);   
  150.         bridgeConnB.setCollisionRectScale(0.6);   
  151.         APEngine.addConstraint(bridgeConnB);   
  152.            
  153.         SpringConstraint bridgeConnC = new SpringConstraint(bridgePB, bridgePC, 0.9);   
  154.         bridgeConnC.setCollidable(true);   
  155.         bridgeConnC.setCollisionRectWidth(10);   
  156.         bridgeConnC.setCollisionRectScale(0.6);   
  157.         APEngine.addConstraint(bridgeConnC);   
  158.            
  159.         SpringConstraint bridgeConnD = new SpringConstraint(bridgePC, (AbstractParticle)bridgeEnd.getCornerParticles().get(0), 0.9);   
  160.         bridgeConnD.setCollidable(true);   
  161.         bridgeConnD.setCollisionRectWidth(10);   
  162.         bridgeConnD.setCollisionRectScale(0.6);   
  163.            
  164.         APEngine.addConstraint(bridgeConnD);   
  165.            
  166.         // 汽车    
  167.         wheelParticleA = new WheelParticle(60,10,20,false,1,0.3,0,1);   
  168.         wheelParticleA.setMass(2);   
  169.         APEngine.addParticle(wheelParticleA);   
  170.            
  171.         wheelParticleB = new WheelParticle(140,10,20,false,1,0.3,0,1);   
  172.         wheelParticleB.setMass(2);   
  173.         APEngine.addParticle(wheelParticleB);   
  174.                    
  175.         wheelConnector = new SpringConstraint(wheelParticleA, wheelParticleB,0.5);   
  176.         wheelConnector.setCollidable(true);   
  177.         wheelConnector.setCollisionRectWidth((double)10);   
  178.         wheelConnector.setCollisionRectScale((double)0.9);   
  179.         APEngine.addConstraint(wheelConnector);   
  180.            
  181.         // little boxes   
  182.         for (int i = 0; i < 10; i++) {   
  183.             double px = (7 * i) + 120;   
  184.             APEngine.addParticle(new RectangleParticle(px,200,10,5,Math.random() * Math.PI,false,1.8,0.1,0.0));   
  185.             APEngine.addParticle(new CircleParticle(px+40,210,3.5,false,1.8,0.1,0.0));   
  186.         }   
  187.            
  188.         /*  
  189.         After adding all the particles and constraints, you can retrieve them using the   
  190.         getXXX methods from the APEngine class. Then you can go through them and paint them  
  191.         when necessary. Alternatively you can keep track of them yourself by manually adding  
  192.         them to your own lists.  
  193.         */  
  194.         paintQueue = APEngine.getAll();   
  195.     }//end of func   
  196.        
  197.     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)   
  198.     {   
  199.            
  200.     }   
  201.   
  202.     public void surfaceCreated(SurfaceHolder holder)   
  203.     {   
  204.         Log.v("surfaceCreated()""线程启动前");   
  205.         new Thread(this).start();   
  206.     }   
  207.   
  208.     public void surfaceDestroyed(SurfaceHolder holder)   
  209.     {   
  210.         //alive = false;   
  211.     }   
  212.   
  213.     //触摸屏事件   
  214.     @Override     
  215.     public boolean onTouchEvent(android.view.MotionEvent event){     
  216.         //XTouch.OnTouch(event.getAction(), event.getX(), event.getY());   
  217.         if (wheelParticleA==null || wheelParticleB==null) {   
  218.             return false;   
  219.         }   
  220.         if (event.getAction() == android.view.MotionEvent.ACTION_DOWN) {   
  221.             if (event.getX() < 240) {   
  222.                 wheelParticleA.setAngularVelocity(-keySpeed);   
  223.                 wheelParticleB.setAngularVelocity(-keySpeed);   
  224.             }else {   
  225.                 wheelParticleA.setAngularVelocity(keySpeed);   
  226.                 wheelParticleB.setAngularVelocity(keySpeed);   
  227.             }   
  228.         }   
  229.         else if (event.getAction() == android.view.MotionEvent.ACTION_UP) {   
  230.             wheelParticleA.setAngularVelocity(0);   
  231.             wheelParticleB.setAngularVelocity(0);   
  232.         }   
  233.         return super.onTouchEvent(event);     
  234.     }     
  235.        
  236.     @Override  
  237.     public boolean onKeyDown(int keyCode, KeyEvent event)   
  238.     {   
  239.         switch (keyCode)   
  240.         {   
  241.         case KeyEvent.KEYCODE_BACK:    
  242.             android.os.Process.killProcess(android.os.Process.myPid());   
  243.             break;   
  244.   
  245.         case KeyEvent.KEYCODE_DPAD_UP:   
  246.             //moveFlag = 1;   
  247.             break;   
  248.   
  249.         case KeyEvent.KEYCODE_DPAD_DOWN:    
  250.             //moveFlag = 2;   
  251.             break;   
  252.   
  253.         case KeyEvent.KEYCODE_DPAD_LEFT:    
  254.             //moveFlag = 3;   
  255.             wheelParticleA.setAngularVelocity(-keySpeed);   
  256.             wheelParticleB.setAngularVelocity(-keySpeed);   
  257.             break;   
  258.   
  259.         case KeyEvent.KEYCODE_DPAD_RIGHT:   
  260.             //moveFlag = 4;   
  261.             wheelParticleA.setAngularVelocity(keySpeed);   
  262.             wheelParticleB.setAngularVelocity(keySpeed);   
  263.             break;   
  264.         }   
  265.   
  266.         return super.onKeyDown(keyCode, event);   
  267.     }   
  268.   
  269.     @Override  
  270.     public boolean onKeyUp(int keyCode, KeyEvent event)   
  271.     {   
  272.         //moveFlag = 0;   
  273.         wheelParticleA.setAngularVelocity(0);   
  274.         wheelParticleB.setAngularVelocity(0);   
  275.         return super.onKeyUp(keyCode, event);   
  276.     }   
  277.        
  278.     protected void onDraw(Canvas canvas) {   
  279.         super.onDraw(canvas);   
  280.   
  281.     }   
  282.        
  283.      public void run() {     
  284.     
  285.         boolean bStop = false;   
  286.         Log.v("Thread1)""is Running");   
  287.         while(!bStop)   
  288.         {   
  289.                
  290.             // 获取画布     
  291.             mCanvas = mSurfaceHolder.lockCanvas();   
  292.             // 缩小到2/3大小,J2SE移植过来时太大没有改变,直接缩放Canvas   
  293.             mCanvas.scale(2f/3, 2f/3);   
  294.             // 清屏   
  295.             ClearScreen(mCanvas);   
  296.             // 更新计算物理世界的数据   
  297.             UpdateWorld(mCanvas);   
  298.             PaintWorld(mCanvas);      
  299.             PaintFps(mCanvas);   
  300.                
  301.             // 锁帧   
  302. //          try {    
  303. //              Thread.sleep(SPEED);   
  304. //          }    
  305. //          catch (InterruptedException e)    
  306. //          {   
  307. //          }   
  308.   
  309.             //解锁画布,提交画好的图像   
  310.             mSurfaceHolder.unlockCanvasAndPost(mCanvas);   
  311.                
  312.         }   
  313.      }     
  314.        
  315.        
  316.     public void PaintWorld(Canvas canvas)    
  317.     {   
  318.         APEngine.setDefaultContatiner(canvas);   
  319.            
  320.         for (int i = 0; i < paintQueue.size(); i++) {   
  321.                 //TG TODO need to write code that determined the type of objects and sets their method.    
  322.             if (paintQueue.get(i) instanceof RectangleParticle)     
  323.                 ((RectangleParticle)paintQueue.get(i)).paint();   
  324.             else if (paintQueue.get(i) instanceof CircleParticle)    
  325.                     ((CircleParticle)paintQueue.get(i)).paint();   
  326.             else if (paintQueue.get(i) instanceof SpringConstraint)    
  327.                 ((SpringConstraint)paintQueue.get(i)).paint();                 
  328.         }   
  329.   
  330.     }//end of func   
  331.            
  332.     public void UpdateWorld(Canvas canvas)    
  333.     {   
  334.         APEngine.step();   
  335.         rotatingRect.setRotation(rotatingRect.getRotation() + 0.03);           
  336.     }//end of func    
  337.        
  338.     public void ClearScreen(Canvas canvas)   
  339.     {   
  340.         //清屏   
  341.         canvas.drawColor(Color.WHITE);   
  342.     }   
  343.        
  344.     /**  
  345.      * 计算显示帧速  
  346.      * @param canvas  
  347.      */  
  348.     public void PaintFps(Canvas canvas)    
  349.     {   
  350.         mLoopCount += 1;   
  351.         mNowTime = System.currentTimeMillis();   
  352.         if ((mNowTime - mFPSShowTime)>=1000) {   
  353.             mFPS = (float)(mLoopCount*10000/(mNowTime-mFPSShowTime))/10;   
  354.             mLoopCount = 0;   
  355.             mFPSShowTime = mNowTime;   
  356.         }   
  357.                                    
  358.         //XDebug.Print("XGameView", "PaintFPS");   
  359.         canvas.drawText(String.valueOf(mFPS)+" FPS"10020, mFPSPaint);   
  360.            
  361.     }//end of func   
  362.          
  363. }//end of class  
package Test.APEngineTest;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint.Style;

import java.lang.Runnable;

import java.util.ArrayList;

import ape.*;

public class ApeTest extends SurfaceView implements Runnable, SurfaceHolder.Callback{
	// APEngine 世界
	private APEngine APEngine = new APEngine();
	// 两个轮子
	private SpringConstraint wheelConnector;
	private WheelParticle wheelParticleA;
	private WheelParticle wheelParticleB;
	// 车身
	private RectangleParticle rotatingRect;
	// 世界中需要刷新的所有物理列表
	private ArrayList paintQueue;
	
	private Canvas mCanvas = null;
	private Paint mPaint = null;
	SurfaceHolder mSurfaceHolder = null;  
	
	public static final int SCREEN_WIDTH = 320;
	public static final int SCREEN_HEIGHT= 480;
	public static final int PLAY_HEIGHT  = 400; 
	public static final int SPEED        = 15;
	public static final double keySpeed = 0.2;
	
	//计算帧率
//	private long mFPSLockTime = 0;
	private long mFPSShowTime = 0;				//
	private long mNowTime = 0;					//现在的时间
	private int mLoopCount = 0;					//循环次数
	private float mFPS = 0.0f;					//帧速
//	private float mFPSTime = (1000.0f/30);		//每帧最大执行时间(默认30帧)
	private Paint mFPSPaint = new Paint();
	
	public ApeTest(Context context)
	{
		super(context);
		setFocusable(true);
		setFocusableInTouchMode(true);
		
		mSurfaceHolder = this.getHolder();
		mSurfaceHolder.addCallback(this);
      
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
		mPaint.setColor(Color.BLACK);
		mPaint.setStyle(Style.STROKE);
		APEngine.setDefaultPaint(mPaint);
		
 		InitWorld();       
 		   
	}//end of func
	
   	public void InitWorld() 
   	{
        
		// set up the events, main loop handler, and the engine. you don't have to use
		// enterframe. you just need to call the ApeEngine.step() method wherever
		// and however your handling your program cycle.
		
		// the argument here is the deltaTime value. Higher values result in faster simulations.
		APEngine.init((double)1/4);
		
		// SELECTIVE is better for dealing with lots of little particles colliding, 
		// as in the little rects and circles in this example
		APEngine.setCollisionResponseMode(APEngine.SELECTIVE);
		
		// gravity -- particles of varying masses are affected the same
		APEngine.addMasslessForce(new Vector(0,3));
						
		// surfaces
		RectangleParticle floor = new RectangleParticle(325,324,649,50,0,true,1,0.3,0);
		APEngine.addParticle(floor);

		RectangleParticle floorBumpA = new RectangleParticle(400,295,90,30, 0.4,true,1,0.3,0);
		APEngine.addParticle(floorBumpA);
		
		RectangleParticle floorBumpB = new RectangleParticle(330,295,90,30,-0.4,true,1,0.3,0);
		//APEngine.addParticle(floorBumpB);
		
		RectangleParticle floorLeftAngle = new RectangleParticle(80,290,120,20,0.5,true,1,0.3,0);
		APEngine.addParticle(floorLeftAngle);
		
		RectangleParticle leftWall = new RectangleParticle(15,99,30,500,0,true,1,0.3,0);
		APEngine.addParticle(leftWall);
			
		RectangleParticle rightWall = new RectangleParticle(634,99,30,500,0,true,1,0.3,0);
		APEngine.addParticle(rightWall);
		
		// 桥 开始点
		RectangleParticle bridgeStart = new RectangleParticle(80,70,150,25,0,true,1,0.3,0);
		APEngine.addParticle(bridgeStart);
		
		// 桥结束点
		RectangleParticle bridgeEnd = new RectangleParticle(380,70,100,25,0,true,1,0.3,0);
		APEngine.addParticle(bridgeEnd);
		
		RectangleParticle bridgeEndAngle = new RectangleParticle(455,102,100,25,0.8,true,1,0.3,0);
		APEngine.addParticle(bridgeEndAngle);
		
		RectangleParticle rightWallAngle = new RectangleParticle(595,102,100,25,-0.8,true,1,0.3,0);
		APEngine.addParticle(rightWallAngle);
		
		// 旋转矩形rotator
		rotatingRect = new RectangleParticle(525,180,70,14,0,true,1,0.3,0);
		APEngine.addParticle(rotatingRect);
		
		// 小矩形
		RectangleParticle littleRect = new RectangleParticle(525,180,10,10,0,false,1,0.3,0);
		APEngine.addParticle(littleRect);
		
		// 把旋转矩形和小矩形用皮筋连接到一起
		SpringConstraint rotConnector = new SpringConstraint((AbstractParticle)rotatingRect.getCornerParticles().get(1), (AbstractParticle)littleRect, 0.2);		
		APEngine.addConstraint(rotConnector);
		
		// bridge
		CircleParticle bridgePA = new CircleParticle(200,70,4,false,1,0.3,0);
		APEngine.addParticle(bridgePA);
		
		CircleParticle bridgePB = new CircleParticle(240,70,4,false,1,0.3,0);
		APEngine.addParticle(bridgePB);
		
		CircleParticle bridgePC = new CircleParticle(280,70,4,false,1,0.3,0);
		APEngine.addParticle(bridgePC);
		
		SpringConstraint bridgeConnA = new SpringConstraint((AbstractParticle)bridgeStart.getCornerParticles().get(1), bridgePA, 0.9);
		bridgeConnA.setCollidable(true);
		bridgeConnA.setCollisionRectWidth(10);
		bridgeConnA.setCollisionRectScale(0.6);
		APEngine.addConstraint(bridgeConnA);

		SpringConstraint bridgeConnB = new SpringConstraint(bridgePA, bridgePB, 0.9);
		bridgeConnB.setCollidable(true);
		bridgeConnB.setCollisionRectWidth(10);
		bridgeConnB.setCollisionRectScale(0.6);
		APEngine.addConstraint(bridgeConnB);
		
		SpringConstraint bridgeConnC = new SpringConstraint(bridgePB, bridgePC, 0.9);
		bridgeConnC.setCollidable(true);
		bridgeConnC.setCollisionRectWidth(10);
		bridgeConnC.setCollisionRectScale(0.6);
		APEngine.addConstraint(bridgeConnC);
		
		SpringConstraint bridgeConnD = new SpringConstraint(bridgePC, (AbstractParticle)bridgeEnd.getCornerParticles().get(0), 0.9);
		bridgeConnD.setCollidable(true);
		bridgeConnD.setCollisionRectWidth(10);
		bridgeConnD.setCollisionRectScale(0.6);
		
		APEngine.addConstraint(bridgeConnD);
		
		// 汽车 
		wheelParticleA = new WheelParticle(60,10,20,false,1,0.3,0,1);
		wheelParticleA.setMass(2);
		APEngine.addParticle(wheelParticleA);
		
		wheelParticleB = new WheelParticle(140,10,20,false,1,0.3,0,1);
		wheelParticleB.setMass(2);
		APEngine.addParticle(wheelParticleB);
				
		wheelConnector = new SpringConstraint(wheelParticleA, wheelParticleB,0.5);
		wheelConnector.setCollidable(true);
		wheelConnector.setCollisionRectWidth((double)10);
		wheelConnector.setCollisionRectScale((double)0.9);
		APEngine.addConstraint(wheelConnector);
		
		// little boxes
		for (int i = 0; i < 10; i++) {
			double px = (7 * i) + 120;
			APEngine.addParticle(new RectangleParticle(px,200,10,5,Math.random() * Math.PI,false,1.8,0.1,0.0));
			APEngine.addParticle(new CircleParticle(px+40,210,3.5,false,1.8,0.1,0.0));
		}
		
		/*
		After adding all the particles and constraints, you can retrieve them using the 
		getXXX methods from the APEngine class. Then you can go through them and paint them
		when necessary. Alternatively you can keep track of them yourself by manually adding
		them to your own lists.
		*/
		paintQueue = APEngine.getAll();
	}//end of func
	
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
	{
		
	}

	public void surfaceCreated(SurfaceHolder holder)
	{
		Log.v("surfaceCreated()", "线程启动前");
		new Thread(this).start();
	}

	public void surfaceDestroyed(SurfaceHolder holder)
	{
		//alive = false;
	}

	//触摸屏事件
	@Override  
    public boolean onTouchEvent(android.view.MotionEvent event){  
        //XTouch.OnTouch(event.getAction(), event.getX(), event.getY());
		if (wheelParticleA==null || wheelParticleB==null) {
			return false;
		}
		if (event.getAction() == android.view.MotionEvent.ACTION_DOWN) {
			if (event.getX() < 240) {
				wheelParticleA.setAngularVelocity(-keySpeed);
				wheelParticleB.setAngularVelocity(-keySpeed);
			}else {
				wheelParticleA.setAngularVelocity(keySpeed);
				wheelParticleB.setAngularVelocity(keySpeed);
			}
		}
		else if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
			wheelParticleA.setAngularVelocity(0);
			wheelParticleB.setAngularVelocity(0);
		}
        return super.onTouchEvent(event);  
    }  
	
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		switch (keyCode)
		{
		case KeyEvent.KEYCODE_BACK: 
			android.os.Process.killProcess(android.os.Process.myPid());
			break;

		case KeyEvent.KEYCODE_DPAD_UP:
			//moveFlag = 1;
			break;

		case KeyEvent.KEYCODE_DPAD_DOWN: 
			//moveFlag = 2;
			break;

		case KeyEvent.KEYCODE_DPAD_LEFT: 
			//moveFlag = 3;
			wheelParticleA.setAngularVelocity(-keySpeed);
			wheelParticleB.setAngularVelocity(-keySpeed);
			break;

		case KeyEvent.KEYCODE_DPAD_RIGHT:
			//moveFlag = 4;
			wheelParticleA.setAngularVelocity(keySpeed);
			wheelParticleB.setAngularVelocity(keySpeed);
			break;
		}

		return super.onKeyDown(keyCode, event);
	}

	@Override
	public boolean onKeyUp(int keyCode, KeyEvent event)
	{
		//moveFlag = 0;
		wheelParticleA.setAngularVelocity(0);
		wheelParticleB.setAngularVelocity(0);
		return super.onKeyUp(keyCode, event);
	}
   	
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

	}
	
     public void run() {  
 
        boolean bStop = false;
        Log.v("Thread1)", "is Running");
		while(!bStop)
		{
			
		   	// 获取画布  
	        mCanvas = mSurfaceHolder.lockCanvas();
	        // 缩小到2/3大小,J2SE移植过来时太大没有改变,直接缩放Canvas
	        mCanvas.scale(2f/3, 2f/3);
	        // 清屏
	    	ClearScreen(mCanvas);
	    	// 更新计算物理世界的数据
        	UpdateWorld(mCanvas);
        	PaintWorld(mCanvas);   
        	PaintFps(mCanvas);
            
        	// 锁帧
//        	try { 
//        		Thread.sleep(SPEED);
//        	} 
//        	catch (InterruptedException e) 
//        	{
//        	}

			//解锁画布,提交画好的图像
			mSurfaceHolder.unlockCanvasAndPost(mCanvas);
			
		}
     }  
   	
   	
	public void PaintWorld(Canvas canvas) 
	{
		APEngine.setDefaultContatiner(canvas);
		
		for (int i = 0; i < paintQueue.size(); i++) {
				//TG TODO need to write code that determined the type of objects and sets their method. 
			if (paintQueue.get(i) instanceof RectangleParticle)  
				((RectangleParticle)paintQueue.get(i)).paint();
			else if (paintQueue.get(i) instanceof CircleParticle) 
					((CircleParticle)paintQueue.get(i)).paint();
			else if (paintQueue.get(i) instanceof SpringConstraint) 
				((SpringConstraint)paintQueue.get(i)).paint();				
		}

	}//end of func
		
	public void UpdateWorld(Canvas canvas) 
	{
		APEngine.step();
		rotatingRect.setRotation(rotatingRect.getRotation() + 0.03);		
	}//end of func 
   	
	public void ClearScreen(Canvas canvas)
	{
		//清屏
    	canvas.drawColor(Color.WHITE);
	}
	
	/**
	 * 计算显示帧速
	 * @param canvas
	 */
	public void PaintFps(Canvas canvas) 
	{
		mLoopCount += 1;
		mNowTime = System.currentTimeMillis();
		if ((mNowTime - mFPSShowTime)>=1000) {
			mFPS = (float)(mLoopCount*10000/(mNowTime-mFPSShowTime))/10;
			mLoopCount = 0;
			mFPSShowTime = mNowTime;
		}
								
		//XDebug.Print("XGameView", "PaintFPS");
		canvas.drawText(String.valueOf(mFPS)+" FPS", 100, 20, mFPSPaint);
		
	}//end of func
	  
}//end of class

 

 

参考:

官方网站: http://www.cove.org/ape/  

官方API: http://www.cove.org/ape/docs/api/

官方SVN: http://ape.googlecode.com/svn/

中文API参考: http://wenku.baidu.com/view/193e97cfa1c7aa00b52acb47.html 这个是APEngine的介绍才12个类,在我附件里也有

官方提供了两个Demo

Demo1: http://www.cove.org/ape/demo1.htm


Demo2: http://www.cove.org/ape/demo2.htm


APEngine

优点: 简单易用,文件很少很适合学习阅读

缺点: 是不支持多边形

分享到:
评论
2 楼 xieyu1232001 2011-10-18  
我的G10可以跑40帧每秒
1 楼 lifegame2008 2011-09-16  
我在公司的机器上,三星的V210,1GH主频,2.3.3的系统,能跑43帧。

相关推荐

    瘸腿蛤蟆笔记38-cocos2d-x-3.2 Box2d物理引擎Ray-cast代码

    《瘸腿蛤蟆笔记38-cocos2d-x-3.2 Box2d物理引擎Ray-cast代码》 本文将深入探讨Cocos2d-x 3.2版本中Box2D物理引擎的Ray-cast(射线检测)功能。Box2D是一款广泛应用于2D游戏开发的开源物理引擎,它提供了强大的物理...

    cocos引擎老版本集合(cocos2d-x-2.2.1 - 3.5).zip

    cocos引擎老版本下载集合(cocos2d-x-2.2.1 - 3.5),分别有cocos2d-x-3.5、cocos2d-x-3.4、cocos2d-x-3.2、cocos2d-x-2.2.6、cocos2d-x-2.2.2和cocos2d-x-2.2.1。

    经典版本 方便下载 源码 旧版本 3.8 官网找不到了 cocos2d-x-3.8.zip

    《cocos2d-x 3.8:经典游戏引擎源码解析》 cocos2d-x 是一个跨平台的游戏开发框架,它基于C++,同时提供了Lua和JavaScript的绑定,让开发者可以方便地在多种操作系统上创建2D游戏、演示程序和其他图形交互应用。这...

    android cocos2d-2.0-x-2.0.4 jar包

    开发cocos2d-20.0-x-2.0.4用的jar包,这个是最新的。懒人必备!!

    jbox2d-2.0.1-library-only.jar

    jbox2d-2.0.1-library-only JAVA版本的BOX2D物理引擎;

    cocos2d-x-3.4旧版引擎下载

    cocos2d-x-3.4下载,不多说。或者可以下载另一个资源 cocos引擎老版本集合(cocos2d-x-2.2.1 - 3.5) http://download.csdn.net/download/crazymagicdc/9982656

    cocos引擎老版本集合(cocos2d-x-2.2.1 - 3.5)

    cocos引擎老版本下载集合(cocos2d-x-2.2.1 - 3.5),分别有cocos2d-x-3.5、cocos2d-x-3.4、cocos2d-x-3.2、cocos2d-x-2.2.6、cocos2d-x-2.2.2和cocos2d-x-2.2.1。

    cocos2d-x-3.1.zip

    1. **跨平台支持**:Cocos2d-x 3.1支持多种操作系统和设备,包括iOS、Android、Windows、Mac、Linux等,使得开发者可以编写一次代码,到处运行。 2. **C++基础**:Cocos2d-x主要采用C++作为编程语言,同时也支持Lua...

    瘸腿蛤蟆笔记42-cocos2d-x-3.2 Box2d物理引擎Motor Joint代码

    【瘸腿蛤蟆笔记42-cocos2d-x-3.2 Box2d物理引擎Motor Joint代码】 在游戏开发中,物理引擎是一个重要的组成部分,它能够帮助开发者模拟真实世界中的物理现象,使得游戏中的物体运动更加逼真。Cocos2d-x是一个广泛...

    cocos2d-x-2.1.5

    cocos2d-x-2.1.5

    ios应用源码之物理引擎-grenadegame 2018128

    在这个项目中,开发者可能利用了诸如Box2D或Chipmunk这样的知名物理引擎库,来实现游戏对象的碰撞检测、重力模拟和其他物理现象。 一、物理引擎基础知识 物理引擎是游戏开发中的核心组件,它负责模拟现实世界的物理...

    box2d物理引擎cocos2d

    Box2D是一个开源的2D物理引擎,广泛用于游戏开发,尤其在Cocos2d这样的2D游戏引擎中。Cocos2d是一个流行的跨平台的游戏开发框架,它提供了丰富的功能和工具,使得开发者能够轻松创建各种2D游戏。在本案例中,我们...

    cocos2d-x-3.2旧版引擎下载

    cocos2d-x-3.2下载,不多说。或者可以下载另一个资源 cocos引擎老版本集合(cocos2d-x-2.2.1 - 3.5) http://download.csdn.net/download/crazymagicdc/9982656

    Android应用源码之Angle v1.0_2D游戏引擎-IT计算机-毕业设计.zip

    7. **物理引擎**:虽然这是一个2D游戏引擎,但可能包含简单的物理模拟,如重力、碰撞响应等,帮助游戏对象的行为更真实。 8. **事件处理**:Android系统的触摸事件、按键事件等需要被适配和处理,以便响应玩家的...

    cocos2d-android-1资源:API文档

    在Android平台上,cocos2d-x是其主要实现,而“cocos2d-android-1”可能是该框架的一个特定版本。这个压缩包中的“cocos2d-android-1-doc”文件很可能是该版本的API文档,对于开发者来说是一份非常重要的参考资料。 ...

    jbox2d-2.0.1-library-only 不要积分

    提示 由于本案例开发时使用了第三方的物理引擎JBox2D,因此需要在项目中添加相应的支持jar包"jbox2d-2.0.1-library-only.jar"。如果读者不清楚如何在Eclipse中为项目添加jar包,可以查阅相关资料,本书篇幅所限不再...

    Cocos2d-Android-1游戏开发

    在Android游戏开发中,Cocos2d-Android-1提供了一系列核心组件,包括场景管理、精灵动画、物理引擎、粒子系统、定时器和事件处理等。这些组件使得开发者能够轻松构建复杂的交互式游戏。例如,场景管理允许开发者组织...

    cocos2d-x box2d 物理引擎

    《cocos2d-x与Box2D:构建基础物理引擎》 在游戏开发领域,物理引擎扮演着至关重要的角色,它赋予游戏中的对象以真实世界中的运动规律,从而增加游戏的真实感和趣味性。cocos2d-x是一个流行的开源2D游戏开发框架,...

    瘸腿蛤蟆笔记39-cocos2d-x-3.2 Box2d物理引擎自由落体代码

    在本篇中,我们将深入探讨使用Cocos2d-x 3.2框架集成Box2D物理引擎实现自由落体效果的编程技术。Cocos2d-x是一个广泛使用的开源游戏开发框架,它支持多种平台,包括iOS、Android以及桌面系统。Box2D是一个强大的2D...

Global site tag (gtag.js) - Google Analytics