I will summarize the recently learned box2D, but it does not involve joints for the moment. Let's wait for a while and try again! This time I will summarize it through an instance I wrote myself!
First, I have to explain the purpose of this programming: to draw several objects on the screen, including dynamic objects and static objects. box2D is used to simulate the physical world, the dynamic object is subjected to gravity, and the static object cannot be subjected to gravity, but it can collide with the dynamic object to change its state. In addition, to facilitate observation of more results, objects on the screen, both dynamic and static, can be moved by touching them with your fingers.
Since the world of box2D is measured in meters and our programming is measured in pixels, this involves the problem of unit conversion and requires many steps to generate a Body object, there are a lot of functions that need to be converted, which will inevitably bring some trouble to our programming. So I thought of re-encapsulating the Body object in box2d, which was originally intended to inherit the Body object, however, since Box2d uses the factory mode to generate objects, rather than simply creating new objects, even the inherited Body cannot be used, I want to construct a BodyFactory object, it generates the Body object,
BodyFactory. java:
Package com. example. box2dtest; 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 BodyFactory {private World world; public BodyFactory (World w) {// The constructor must submit the World object of the Body generated in it. world = w ;} public Body outBox (float x, float y, float w, float h, boolean isStatic) {// generate a rectangular object Body. Most of the functions construct a Box using methods circulating on the Internet, but one thing to note is the body. m_userData is a self-written class. The PolygonDef pd = new PolygonDef (); if (isStatic) {pd. density = 0;} else {pd. density = 1;} pd. friction = 0.8f; pd. restitution = 0.3f; pd. setAsBox (w/2/BodyConstant. RATE, h/2/BodyConstant. RATE); BodyDef bd = new BodyDef (); bd. position. set (x + w/2)/BodyConstant. RATE, (y + h/2)/BodyConstant. RATE); Body body = world. createBody (bd); body. createShape (pd); BodyDetail bodyDetail = new BodyDetail (); bodyDetail. shape = BodyDetail. BOX; bodyDetail. width = w; bodyDetail. height = h; bodyDetail. isStatic = isStatic; bodyDetail. body = body; bodyDetail. sd = pd; body. m_userData = bodyDetail; body. setMassFromShapes (); return body;} public Body outCircle (float x, float y, float r, boolean isStatic) {// generate a circular object Body CircleDef pd = new CircleDef (); if (isStatic) {pd. density = 0;} else {pd. density = 1;} pd. friction = 0.8f; pd. restitution = 0.3f; pd. radius = r/BodyConstant. RATE; BodyDef bd = new BodyDef (); bd. position. set (x/BodyConstant. RATE, y/BodyConstant. RATE); Body body = world. createBody (bd); body. createShape (pd); BodyDetail bodyDetail = new BodyDetail (); bodyDetail. shape = BodyDetail. CIRCLE; bodyDetail. width = r; bodyDetail. height = r; bodyDetail. isStatic = isStatic; bodyDetail. body = body; bodyDetail. sd = pd; body. m_userData = bodyDetail; body. setMassFromShapes (); return body;} public void setBoundary (float x, float y, float w, float h) {// you can set the border outBox (x, y, w, 1, true); outBox (x, y + h, w, 1, true); outBox (x, y, 1, h, true ); outBox (x + w, y, 1, h, true );}}
We can see that there is a BodyDetail object in the Code. Why is there this object? In the end, we will use traversing all the Body objects in the world to draw the screen, which brings about a problem. That is, when traversing, we get the Body object, is the Body a circle, a rectangle, or other shapes? What is its size, width, and height? These things may be obtained by the self-contained methods and attributes of the Body object, but there is too little information on the Internet. I did not find them, but even if I can get them, there is still information that I cannot get, for example, the color, so we can construct the information of the class containing the Body, oh, right, body. m_userData is an Object, so it allows us to carry any information:
Package com. example. box2dtest; import org. jbox2d. collision. shapeDef; import org. jbox2d. dynamics. body; import android. graphics. canvas; import android. graphics. paint; import android. graphics. paint. style; public class BodyDetail {public static final int BOX = 1, CIRCLE = 2; public int shape; public float width, height; public boolean isStatic = false; public Body body; public ShapeDef sd; private float den Sity_bnk = 0; private Paint paint; private float angle, centerX, centerY, X, Y; public BodyDetail () {paint = new Paint (); paint. setAntiAlias (true); paint. setStyle (Style. STROKE);} public void setStatic (boolean B) {if (density_bnk = 0) {density_bnk = sd. density;} sd. density = 0f;} else sd. density = density_bnk; body. destroyShape (body. m_shapeList); // note that this is the method to change the shape of the body, that is, delete the previous shap E, and then create a new shape. After finding it online for a long time, I did not find any method. It was discovered only by observing the function name! Body. createShape (sd); body. setMassFromShapes ();} public boolean getStatic () {if (sd. density = 0f) {return true;} return false;} public void draw (Canvas canvas) {angle = (float) (body. getAngle () * 180/Math. PI); centerX = body. getPosition (). x * BodyConstant. RATE; centerY = body. getPosition (). y * BodyConstant. RATE; X = centerX-width/2; Y = centerY-height/2; canvas. save (); canvas. rotate (angle, centerX, centerY); switch (shape) {case BOX: canvas. drawRect (X, Y, X + width, Y + height, paint); break; case CIRCLE: canvas. drawCircle (centerX, centerY, width, paint); break; default: break;} canvas. restore ();} public boolean contain (float x, float y) {switch (shape) {case BOX: if (x-X <width & x-X> 0 & y-Y> 0 & y-Y
It can be found that these types contain many attributes and methods. These methods are useful in the future and can be used. I want to know through their names, the appeal Code uses the BodyConstant class, which is very simple and used to save some constants. Although this program only has one, it is worthwhile to make the program hierarchical.
public class BodyConstant { public static final float RATE = 30f;}
This RATE constant is the Conversion Relationship Between the set pixels and meters. In this case, 30 pixels are equivalent to 1 meter in the physical world.
In this way, all the preparations are completed. Next let's take a look at MySurfaceView:
Package com. example. box2dtest; import org. jbox2d. collision. AABB; import org. jbox2d. common. vec2; import org. jbox2d. dynamics. body; import org. jbox2d. dynamics. world; import android. content. context; import android. graphics. canvas; import android. graphics. color; import android. graphics. paint; import android. graphics. paint. style; import android. util. log; import android. view. motionEvent; import android. view. surfaceHo Lder; import android. view. surfaceView; import android. view. surfaceHolder. callback; public class MySurfaceView extends SurfaceView implements Callback, Runnable {private Thread th; private SurfaceHolder sfh; private Canvas canvas; private Paint paint; private boolean flag; private boolean touch = false; private Body touchBody; private BodyDetail touchBodyDetail; World world; AABB aabb; Vec2 gravity; Float timeStep = 1f/60f; final int iterations = 10; @ Override public boolean onTouchEvent (MotionEvent event) {// override onTouchEvent to implement screen touch listening // TODO Auto-generated method stub super. onTouchEvent (event); if (event. getAction () = MotionEvent. ACTION_DOWN) {touchBody = world. getBodyList (); touchBodyDetail = (BodyDetail) touchBody. m_userData; for (int I = 1; I <world. getBodyCount (); I ++) {// traverses the body and uses con Determine whether to select an object. If selected, set it to static to avoid dynamic objects from simulating the physical world movement touchBodyDetail = (BodyDetail) touchBody when selected. m_userData; if (touchBodyDetail. contain (event. getX (), event. getY () {touchBodyDetail. setStatic (true); touch = true; break;} touchBody = touchBody. m_next;} else if (event. getAction () = MotionEvent. ACTION_MOVE & touch = true) {touchBody. setXForm (new Vec2 (event. getX ()/BodyConstant. RATE, event. GetY ()/BodyConstant. RATE), touchBody. getAngle (); // set the new coordinates of the selected object based on the coordinates of the finger movement, and keep the previous angle} else if (event. getAction () = MotionEvent. ACTION_UP & touch = true) {touchBodyDetail. setStatic (false); touch = false;} return true;} public MySurfaceView (Context context) {super (context); this. setKeepScreenOn (true); sfh = this. getHolder (); sfh. addCallback (this); paint = new Paint (); paint. setAntiAlias (true); Paint. setStyle (Style. STROKE); setFocusable (true);} public World createWorld (float x1, float y1, float x2, float y2) {aabb = new AABB (); gravity = new Vec2 (0f, 10f); aabb. lowerBound. set (x1/BodyConstant. RATE, y1/BodyConstant. RATE); aabb. upperBound. set (x2/BodyConstant. RATE, y2/BodyConstant. RATE); return new World (aabb, gravity, false);} public void surfaceCreated (SurfaceHolder holder ){ World = createWorld (-20,-20, getWidth () + 20, getHeight () + 20); BodyFactory bodyFactory = new BodyFactory (world); bodyFactory. outBox (0, getHeight ()-100,110, 10, true); // Several bodyFactory objects are generated using bodyFactory. outBox (100, 10, 40, 20, false); bodyFactory. outBox (getWidth ()-200, getHeight ()-50, 90, 10, true); bodyFactory. setBoundary (0, 0, getWidth (), getHeight (); bodyFactory. outCircle (150,200, 50, True); flag = true; th = new Thread (this); th. start ();} public void myDraw () {try {canvas = sfh. lockCanvas (); if (canvas! = Null) {canvas. drawColor (Color. WHITE); Body body Body = world. getBodyList (); for (int I = 1; I <world. getBodyCount (); I ++) {// traverses the body in the World. Note: I starts from 1, that is, even if there is no body in the world, getBodyCount () 1 BodyDetail bodyDetail = (BodyDetail) body is returned. m_userData; // bodyDetail. draw (canvas); // call the draw method of bodyDetail to draw the image body = body on the canvas. m_next ;}} catch (Exception e) {Log. e ("Error", "Error! ");} Finally {if (canvas! = Null) sfh. unlockCanvasAndPost (canvas) ;}} public void Logic () {world. step (timeStep, iterations); // call step} public void run () {while (flag) {myDraw (); Logic (); try {Thread. sleep (long) timeStep * 1000);} catch (Exception ex) {Log. e ("Error", "Error! ") ;}} Public void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {} public void surfaceDestroyed (SurfaceHolder holder) {flag = false ;}}
This class inherits surfaceView, which is displayed as a control on the screen. There are comments on the details, so it won't be too long. Finally:
import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(new MySurfaceView(this)); }}
Set the view for the main class and run it. Ah, it's finished. It's hard to get tired. Due to the limited level, there may be many errors. I hope you don't have to correct it. Thank you!
Attached:
650) this. width = 650; "src =" http://www.bkjia.com/uploads/allimg/131229/121K96012-0.jpg "style =" float: none; "title =" 360-9128507.jpg "alt =" 112238934.jpg"/>
650) this. width = 650; "src =" http://www.bkjia.com/uploads/allimg/131229/121K92509-1.jpg "style =" float: none; "title =" 360-9181423.jpg "alt =" 127240505.jpg"/>
650) this. width = 650; "src =" http://www.bkjia.com/uploads/allimg/131229/121K9A38-2.jpg "style =" float: none; "title =" 360-9203138.jpg "alt =" 1272488.jpg"/>
This article is from the "Essays in wenjian minor" blog. For more information, contact the author!