- Mastering AndEngine Game Development
- Maya Posch
- 830字
- 2021-07-16 19:42:23
Integrating Box2D
Adding the Box2D physics engine to AndEngine is easy. Simply obtain a copy of the AndEnginePhysicsBox2DExtension
project (found at https://github.com/nicolasgramlich/AndEnginePhysicsBox2DExtension) and link it into your own project in the same way as you added the AndEngine project to your project before. Add the libandenginephysicsbox2dextension.so
library found in the /libs/armeabi/
folder of the extension project to the same folder of your own project if it's reported as missing during the running of your project. Normally, this copying is done automatically, but you may have to do it manually.
The first real challenge is making the Box2D physics engine work with the 3D models for which we integrated code in the previous chapter. To this end, we have to modify the following files:
MainActivity.java
Actor3D.java
MainActivity.java
Most of the changes have to be made in the MainActivity.java
file. To the global class variables, we add the following:
private static final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f); private PhysicsWorld mPhysicsWorld;
The FixtureDef
type defines the properties of a physics object. In this case, they are density, elasticity, and friction. These are set to reasonable values. We then modify the onCreateScene
callback function:
public void onCreateScene(OnCreateSceneCallback pOnCreateSceneCallback) throws IOException { mScene = new Scene(); mPhysicsWorld = new PhysicsWorld(new Vector2(0, (SensorManager.GRAVITY_EARTH * -1)), false); mScene.registerUpdateHandler(mPhysicsWorld); pOnCreateSceneCallback.onCreateSceneFinished(mScene); }
Here, we add the physics-world-related initialization. We create a new physics world with a gravity vector set to earth-level gravity (9.8g), though we have to invert it because of the Y-axis reversal of the branch of AndEngine we're using. Otherwise, we would have objects falling upwards, as the following diagram details:

Finally, we tell the new physics world that it's not allowed to sleep. This tells the simulation whether or not to simulate inactive bodies, which can improve performance but may lead to simulation inaccuracies. The resulting physics world is then registered with our scene so that the physics world can update the objects in the scene.
Next, we just have to create a physics body for our single model. This is done at the end of the onPopulateScene
function, before we add the Scene3D instance to Scene:
Body body; body = PhysicsFactory.createBoxBody(mPhysicsWorld, 0, 0, 10.0f, 10.0f, BodyType.DynamicBody, FIXTURE_DEF); mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(mActor3D, body, true, true));
This uses the factory class of the Box2D extension to create a new box body object, which is one of the standard rigid body types of Box2D. This object will be instantiated inside the physics world that we specify as the first parameter. We also set the location (center at the origin) and the body type and use the fixture we created earlier.
Finally, we create a new physics connector. What this does is establish a link between the physics object and the model (mActor3D
). The PhysicsConnector
class is configured by the last two boolean
parameters to send updates for position and rotation changes.
With that, we are done with the changes to the MainActivity
class. We just need to update the Actor3D
class now to make everything work.
Actor3D.java
The main change we have to make in the Actor3D
class is to make it implement the IEntity interface so that it can be used with the physics connector and receive updates. As it would be very messy to have this class directly implement the IEntity interface due to the many dozens of functions specified by this interface, we fortunately have an easier option:
public class Actor3D extends Entity {
By extending from AndEngine's own Entity
class, we indirectly implement the IEntity interface, and we only have to override two functions in it. These are used to set the position and rotation respectively:
@Override public void setPosition(final float pX, final float pY) { actorToWorldMatrix[12] = pX; actorToWorldMatrix[13] = pY; }
This function is pretty basic. The Box2D physics world sends position updates for each object that has this type of update enabled and for which a physics connector exists. AndEngine translates this position and calls this function in the relevant entity. Here, we directly update our actor's position in the world matrix using the new coordinates:
@Override public void setRotation(final float pRotation) { double rads = Math.toRadians(pRotation); actorToWorldMatrix[0] *= Math.cos(rads); actorToWorldMatrix[1] *= Math.sin(rads); actorToWorldMatrix[4] *= Math.sin(rads); actorToWorldMatrix[4] *= -1; actorToWorldMatrix[5] *= Math.cos(rads); }
The value given to this function is in degrees, which means that we have to convert it to radians for it to be useful for our matrix. The resulting value (in radians) is then used in a standard z-axis-oriented rotation without an intermediate transformation matrix. As the transformation is relatively straightforward, we can apply it directly.
With that, we have made all the changes required to enable our 3D models to make use of the Box2D extension provided with AndEngine. When we run the resulting application, we can see that our sample model object starts off in the center of the screen as usual, and then falls down, off the screen. This follows the parameters that we set for the physics world (the gravity vector) and the model (density).
- 軟件安全技術
- Learn Blockchain Programming with JavaScript
- Mastering Visual Studio 2017
- Mobile Web Performance Optimization
- Flask Blueprints
- Docker技術入門與實戰(第3版)
- SQL Server 2016從入門到精通(視頻教學超值版)
- Hands-On Data Structures and Algorithms with JavaScript
- PHP網絡編程學習筆記
- Visual Basic程序設計與應用實踐教程
- Access 2010數據庫應用技術(第2版)
- 編程菜鳥學Python數據分析
- Windows Embedded CE 6.0程序設計實戰
- Machine Learning for OpenCV
- Scrapy網絡爬蟲實戰