News May 12: "On-the-fly" resource updating for Cocos2d-x
Apr 22: New blog post: Inverted pendulum control
Apr 7: On-screen logging class for Cocos2d-x
Mar 22: Downhill Supreme 2 released for iOS and Android
Jan 2: YouTube video: Making soft-body wheels in RUBE
2013
Oct 6: Check out Supplyfront RTS, my 7dRTS entry continued.
Sep 26: R.U.B.E v1.5 released. Customizable item labels, snap-to-grid, export filtering, full-text help search.
Sep 18: Added RUBE sample loader for Cocos2d-X.
Sep 16: Updated RUBE sample loader for Cocos2d v2.
Aug 12: RUBE loader for Nape by Zeh Fernando
Aug 7: Added RUBE sample loader for SFML.
Jul 30: Try my MiniLD 7dRTS entry.
Jul 24: Added physics-driven particles tutorial.
Jul 20: New blog post: rendering solid ground (as in Downhill Supreme)
Jul 18: R.U.B.E v1.4 released. Command-line interface for batch jobs, hotkeys for scripts, better script management.
May 22: Downhill Supreme is out now! (iOS)
Apr 2: R.U.B.E v1.3 released. Collision bitplane editing, Cocos2d-iphone loader, usability improvements.
Mar 11: R.U.B.E v1.2 released. Now supports weld, friction, motor joints and automatic image reloading.
Mar 10: RUBE loader for libGDX by Tim Scott
Jan 28: New blog post: a functional combustion engine!
Jan 22: New blog post: wind tunnel
Jan 20: Added explosions tutorial.
Jan 16: Added buoyancy tutorial.
Jan 16: AndEngine sample project to load RUBE scene by Bart Hirst
Jan 14: R.U.B.E v1.1 released, now supports custom properties.
Jan 1: All basic tutorials are now available in Chinese at ohcoder.com Huge thankyou to @OhCoder!
2012
Dec 23: Discussion forums have been set up
Dec 4: R.U.B.E v1.0 is ready !
Dec 2: YouTube video: Box2D pendulum clock
Nov 26: New blog post: rocket platform thingy
Nov 25: Video of R.U.B.E scenes in Chipmunk.
Nov 23: A sample project to load R.U.B.E scenes into Chipmunk physics! Details here.
Nov 14: An XCode sample project to load R.U.B.E scenes on iOS is now available. Details here.
Nov 11: A Java version of b2dJson is now available, based on JBox2D.
Nov 6: A Javascript version of b2dJson based on box2dweb is now available. Demo here!
Nov 2: The full specification of the JSON format used by b2dJson can be found here: b2dJson file structure
Oct 28: YouTube video: 2-minute ragdoll in R.U.B.E Box2D editor
Sep 29: YouTube video: R.U.B.E Box2D editor usage example

Box2D C++ tutorials - Drawing your own objects

Last edited: July 14 2013

Chinese version -> 中文

Drawing your own objects


From the previous topic, it's obvious that using debug draw will not make for a very visually appealing game. Usually we would like to use our own method for drawing objects in the scene, and access the physics information from Box2D so that we know where to draw them. In this topic, we'll set up a class to use as a game entity, and then look at how to keep it in the right place. We will do this by storing a pointer to a Box2D body in the game entity.

For now all the entity class will do is render itself, but later we will expand it to demonstrate other topics. The focus of these tutorials is not on rendering, so we'll just draw a basic smiley face on a circle shape to confirm that it moves and rotates correctly.

For this topic let's set up an empty fenced area to start with.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    FooTest() {        
      //a static body
      b2BodyDef myBodyDef;
      myBodyDef.type = b2_staticBody;
      myBodyDef.position.Set(0, 0);
      b2Body* staticBody = m_world->CreateBody(&myBodyDef);
  
      //shape definition
      b2PolygonShape polygonShape;
    
      //fixture definition
      b2FixtureDef myFixtureDef;
      myFixtureDef.shape = &polygonShape;
      
      //add four walls to the static body
      polygonShape.SetAsBox( 20, 1, b2Vec2(0, 0), 0);//ground
      staticBody->CreateFixture(&myFixtureDef);
      polygonShape.SetAsBox( 20, 1, b2Vec2(0, 40), 0);//ceiling
      staticBody->CreateFixture(&myFixtureDef);
      polygonShape.SetAsBox( 1, 20, b2Vec2(-20, 20), 0);//left wall
      staticBody->CreateFixture(&myFixtureDef);
      polygonShape.SetAsBox( 1, 20, b2Vec2(20, 20), 0);//right wall
      staticBody->CreateFixture(&myFixtureDef);
    }
Drawing objects Let's call our game entity class Ball since it will be round and bouncing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  //outside and before the FooTest class
  class Ball {
  public:
    //class member variables
    b2Body* m_body;
    float m_radius;
  
  public:
    Ball(b2World* world, float radius) {
      m_body = NULL;
      m_radius = radius;
    }
    ~Ball() {}
  
  };
  
  //FooTest class member variable
  std::vector<Ball*> balls;
(To get the last part to compile, you may have to #include <vector> at the top of the file.) Notice that now instead of storing references to Box2D bodies directly, we let each game entity look after that and we store a reference to the game entities instead. Add a render function to the Ball class to draw a nice smiley face. The important thing to note here is that we are drawing the face so that it is centered on the point (0,0) and it will not be rotated. The radius is taken to be 1 for the default rendering.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  //Ball::render
    void render() {
      glColor3f(1,1,1);//white
  
      //nose and eyes
      glPointSize(4);
      glBegin(GL_POINTS);
      glVertex2f( 0, 0 );
      glVertex2f(-0.5, 0.5 );
      glVertex2f( 0.5, 0.5 );
      glEnd();
      
      //mouth
      glBegin(GL_LINES);
      glVertex2f(-0.5,  -0.5 );
      glVertex2f(-0.16, -0.6 );
      glVertex2f( 0.16, -0.6 );
      glVertex2f( 0.5,  -0.5 );
      glEnd();
  
      //circle outline
      glBegin(GL_LINE_LOOP);
      for (float a = 0; a < 360 * DEGTORAD; a += 30 * DEGTORAD) 
        glVertex2f( sinf(a), cosf(a) );
      glEnd();
    }
Just a couple more things to do. In the FooTest constructor, after the fenced area is set up, add a Ball entity into the scene (this should really be deleted in the class destructor if you wish to add that too).
1
2
3
  //add ball entity to scene in constructor
  Ball* ball = new Ball(m_world, 1);
  balls.push_back( ball );
And finally, to actually draw the ball entities we'll need to add to the Step() function. If you put this after the call to Test::Step(), the ball will be drawn on top of the existing debug draw data.
1
2
3
  //in Step() function, after Test::Step()
  for (int i = 0; i < balls.size(); i++)
    balls[i]->render();
Drawing objects Now we have one ball entity, but it's being drawn at the default location of (0,0) and we didn't need a physics engine to do that huh? Let's add to the constructor of the Ball class to set up a circle shape body for the ball. Now it becomes apparent why the Ball constructor requires the b2World pointer:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    // Ball class constructor
    Ball(b2World* world, float radius) {
      m_body = NULL;
      m_radius = radius;
  
      //set up dynamic body, store in class variable
      b2BodyDef myBodyDef;
      myBodyDef.type = b2_dynamicBody;
      myBodyDef.position.Set(0, 20);    
      m_body = world->CreateBody(&myBodyDef);
  
      //add circle fixture
      b2CircleShape circleShape;
      circleShape.m_p.Set(0, 0); 
      circleShape.m_radius = m_radius; //use class variable
      b2FixtureDef myFixtureDef;
      myFixtureDef.shape = &circleShape;
      myFixtureDef.density = 1; 
      m_body->CreateFixture(&myFixtureDef); 
    }
Drawing objects Ok, there is a physics body in the scene but our face is not being drawn at the body's position. To do this, let's add another function to the Ball class to set up the OpenGL transform before rendering. Depending on what rendering API you use, there may be better methods for doing this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    //in Ball class
    void renderAtBodyPosition() {
          
      //get current position from Box2D
      b2Vec2 pos = m_body->GetPosition();
      float angle = m_body->GetAngle();
  
      //call normal render at different position/rotation
      glPushMatrix();
      glTranslatef( pos.x, pos.y, 0 );
      glRotatef( angle * RADTODEG, 0, 0, 1 );//OpenGL uses degrees here
      render();//normal render at (0,0)
      glPopMatrix();
    }
Don't forget to change the rendering call in the Step() function to use the new renderAtBodyPosition. Now even if you turn the debug draw display off (uncheck the 'Shapes' checkbox on in the control panel) your own rendering code still draws the ball at the correct position and rotation. Drawing objects Just for fun we could use some more feedback from the physics engine to change the color of the ball at different speeds. For example, set the color like this:
1
2
3
4
5
  //in Ball::render
  b2Vec2 vel = m_body->GetLinearVelocity();
  float red = vel.Length() / 20.0;
  red = min( 1, red );
  glColor3f(red,0.5,0.5);
How about adding a whole bunch of balls to the scene - just change the FooTest constructor to loop a few times:
1
2
3
4
5
  //in FooTest constructor
  for (int i = 0; i < 20; i++) {
    Ball* ball = new Ball(m_world, 1);
    balls.push_back( ball );
  }
Drawing objects We could make the balls random sizes too, since variable sizes were considered when we set up the Ball class:
1
2
3
4
5
  for (int i = 0; i < 20; i++) {
    float radius = 1 + 2 * (rand()/(float)RAND_MAX); //random between 1 - 3
    Ball* ball = new Ball(m_world, radius);
    balls.push_back( ball );
  }
Drawing objects Uh-oh... somethings not right here, the balls don't collide properly anymore. Or at least that's what you could be thinking if this was a more complex scene, and you had confidently thrown away the debug draw code in favour of your eye-popping fancy graphics. Since we have the debug draw ready to hand, it only takes a second to see what's really going on in the physics engine: Drawing objects Okay so that was a bit contrived, but I just wanted to illustrate the usefulness of having a debug draw implementation available throughout your development progress. Finally, to fix the size problem we just need to scale the rendering code:
1
2
3
4
5
6
7
  //inside Ball::renderAtBodyPosition
  glPushMatrix();
  glTranslatef( pos.x, pos.y, 0 );
  glRotatef( angle * RADTODEG, 0, 0, 1 );
  glScalef( m_radius, m_radius, 1 ); //add this to correct size
  render();
  glPopMatrix();
Drawing objects


Next: User data