`

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帧。

相关推荐

    Android下2d物理引擎Box2d用法简单实例

    Box2D是一个强大的2D物理引擎,被广泛应用于游戏开发和模拟系统中,尤其是在Android平台上。这个引擎允许开发者创建复杂的物理交互,如重力、碰撞检测、摩擦力和弹力等,无需从头编写底层物理代码。在Android上使用...

    ChromeOS镜像文件.zip

    目录: ChromeOS-PC-20130222-oscome.com ChromeOS-Vanilla-4028.0.2013_04_20_1810-r706c4144 ChromeOS-Vanilla-4028.0.2013_04_20_1810-r706c4144-VirtualBox ChromeOS-Vanilla-4028.0.2013_04_20_1810-r706c4144-VMWare ChromeOS-virtualbox-20130222-OSCOME.COM ChromeOS-vmware-20130222-OSCOME.COM 网盘文件永久链接

    ieee33节点matlab模型

    IEEE33节点模型搭建,matlab

    3GPP R15 38.331 5G NR无线资源控制(RRC)协议规范解析

    3GPP R15 38.331 5G NR无线资源控制(RRC)协议规范解析

    基于ssm+mysql实现的零食商城系统(电商购物).zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用,资源为网络商品(电子资料类)基于网络商品和电子资料商品的性质和特征不支持退款

    19考试真题最近的t44.txt

    19考试真题最近的t44.txt

    JSP基于SSH2新闻发布系统.zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用,资源为网络商品(电子资料类)基于网络商品和电子资料商品的性质和特征不支持退款,质量优质,放心下载使用

    19考试真题最近的t49.txt

    19考试真题最近的t49.txt

    19考试真题最近的t61.txt

    19考试真题最近的t61.txt

    电动汽车充电站选址定容优化:基于MATLAB建模求解与成本最小化策略,电动汽车充电站选址定容优化:基于MATLAB的最优规划模型及初学者指南,电动汽车充电站的最优选址定容MATLAB程序 以规划期内充

    电动汽车充电站选址定容优化:基于MATLAB建模求解与成本最小化策略,电动汽车充电站选址定容优化:基于MATLAB的最优规划模型及初学者指南,电动汽车充电站的最优选址定容MATLAB程序 以规划期内充电站的总成本 (包括投资、运行和维护成本)和网损费用之和最小为目标,考虑了相关的约束条件,构造了电动汽车充电站最优规划的数学模型。 从34个位置中,选取7个充电站地址,进行选址优化 关键词:电动汽车;充电站;选址和定容 程序注释清晰,适合初学者学习 ,电动汽车; 充电站选址定容; MATLAB程序; 规划模型; 成本优化; 网损费用; 初学者学习; 程序注释清晰,基于MATLAB的电动汽车充电站选址定容优化程序:成本最小化与约束条件下的选址策略

    威纶通触摸屏图库模板程序:多尺寸适用,PS原文件可自由修改,便捷电气助手应用,威纶通触摸屏图库模板程序:多尺寸适用,PS原文件可自由修改,便捷电气助手应用,威纶通触摸屏图库模板程序(电气助手) 可直接

    威纶通触摸屏图库模板程序:多尺寸适用,PS原文件可自由修改,便捷电气助手应用,威纶通触摸屏图库模板程序:多尺寸适用,PS原文件可自由修改,便捷电气助手应用,威纶通触摸屏图库模板程序(电气助手) 可直接使用。 内附原图、PS原文件可自行修改 不同触摸屏,不同寸尺都可以使用 ,威纶通触摸屏; 图库模板程序; 电气助手; 直接使用; 原图; 修改; 兼容不同寸尺,威纶通触摸屏图库模板程序:电气助手,便捷编辑通用模板

    群辉引导7.2.2 最新 vmware workstation 已经帮忙转换好为vmdk文件 直接使用就可以

    修复 "保存'/opt/rr'的修改" 后 主菜单锁死问题. 修复 trivial 插件的语法错误. 修复 open-vm-tools 套件 缺失的 SOCKETS 驱动. 添加 vmtools 插件, 包含 qemu-ga & open-vm-tools. 4.1. 该插件会自动判断环境并启用对应的功能, 物理机也不用刻意删除该插件. 4.2. 新安装用户会默认选中, 升级用户如需要请手动添加该插件. 4.3. 如启用该插件, 请不要再在系统中安装套件. 修复 wireless 插件. 5.1. 修复 RR 下无线网络 IP 显示和刷新问题. 5.2. 修复 RR 下设置 SSID&PSK 后 DSM 下不驱动的问题. 5.3. 同步 RR 下的 SSID&PSK 到 DSM 下. 5.4. 修复 junior 模式下无线网络的支持, 已支持 无线网卡的 DSM 系统安装. (暂时不支持 intel 无线网卡) 5.5. wpa_supplicant.conf 文件位于引导盘第一个分区根目录, 纯无线环境可手动放置该文件后其启动引导.

    19考试真题最近的t66.txt

    19考试真题最近的t66.txt

    19考试真题最近的t37.txt

    19考试真题最近的t37.txt

    Arduino-Mega2560开发板-毕业设计

    Arduino_Mega2560开发板工程文件 包含 原理图 PCB图

    智能养猪系统的高精度称重算法及其Python实现(含详细可运行代码及解释)

    内容概要:本文详述了一种用于智能养猪的高精度称重系统设计及其实现方法,主要涵盖了卡尔曼滤波、数据采集与预处理、重量估算与存储等功能。文中提供了完整的Python代码示例和详细的代码解释,旨在减少噪声干扰并提高数据准确性。具体而言,通过对采集的数据进行卡尔曼滤波,去除异常值,并使用一定时间段内数据的平均值作为最终的体重估计。此外,还实现了一个简单的图形用户界面,能够实时显示称重数据和估计的重量。 适合人群:农业自动化领域的开发者和技术爱好者,尤其关注智能畜牧业的技术应用。 使用场景及目标:适用于智能养猪场的精准称重,提高养猪效率和管理水平,确保获取高精度、可靠的牲畜体重数据,帮助养殖场更好地管理饲养过程。同时,提供完整的源代码有助于相关人员理解和优化现有系统。 阅读建议:对于想要深入了解智能畜牧业相关技术的读者来说,可以通过本教程掌握从硬件接入、软件设计再到数据处理全流程的具体细节。重点关注各个关键算法的实现原理及其应用场景,从而为自己的项目带来启示与借鉴。

    基于SSM框架构建积分系统和基本商品检索系统(Spring+SpringMVC+MyBatis+Lucene+Redis+MAVEN).zip(毕设&课设&实训&大作业&竞赛&项目)

    项目工程资源经过严格测试运行并且功能上ok,可实现复现复刻,拿到资料包后可实现复现出一样的项目,本人系统开发经验充足(全栈全领域),有任何使用问题欢迎随时与我联系,我会抽时间努力为您解惑,提供帮助 【资源内容】:包含源码+工程文件+说明等。答辩评审平均分达到96分,放心下载使用!可实现复现;设计报告也可借鉴此项目;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 下载后请首先打开说明文件(如有);整理时不同项目所包含资源内容不同;项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用,资源为网络商品(电子资料类)基于网络商品和电子资料商品的性质和特征不支持退款

    最新更新!!!地级市-产业链韧性数据(2006-2021年)

    ## 01、数据简介 产业链韧性是指在产业链部分环节出现问题或遭受内外部冲击时,产业链仍能保持其稳定性和动态平衡,迅速做出反应并恢复正常运转的能力。这种能力体现了产业链的复杂适应性,是其能够应对各种不确定性因素和破坏性事件的重要保障。 产业链韧性是保障产业链安全稳定运行的重要基础,对于提升产业竞争力、推动经济高质量发展具有重要意义。 数据名称:地级市-产业链韧性数据 数据年份:2006-2021年 ## 02、相关数据 代码 年度 城市 产业结构HHI 获得专利数 第一产业增加值占GDP比 第二产业增加值占GDP比 第三产业增加值占GDP比 产业链韧性

    PNP发射极接地开关仿真原理图

    PNP发射极接地开关仿真原理图

Global site tag (gtag.js) - Google Analytics