Box 2D 2.1a Tutorial – Part 8 (Camera zooming)
In the last tutorial we started work on our BasicCamera for Box2D, where we added functions such as lookAt and panning so we could translate our camera position, as well as helper functions to convert from world to raster coordinates and vice versa.
We will again be revisiting this class. This time, so that we can add zooming capabilities.
Adding the zooming is not too hard at all. Basically, wherever we have been using PIXELS_TO_METRE in the BasicCamera class, it is now necessary to multiply it by a zoom value.
So let’s open up the BasicCamera class from the last tutorial. You can grab the project files from here.
Start by adding a zoom parameter to our class’s constructor and create a class member variable that zoom will be assigned to. While we are at it, we will also create a class member variable called _adjustedPixelsToMeters which we will come back to later.
private var _zoom:Number;
private var _adjustedPixelsToMetre:Number;
public function BasicCamera(parent:Sprite,rasterWidth:Number,rasterHeight:Number,worldWidth:Number,worldHeight:Number,zoom:Number=1)
{
_container = parent;
_rasterWidth = rasterWidth;
_rasterHeight = rasterHeight;
_worldWidth = worldWidth;
_worldHeight = worldHeight;
this.zoom = zoom;
}
Next, let’s create a getter and setter for the zoom.
public function get zoom():Number
{
return _zoom;
}
public function set zoom(zoom:Number):void
{
_zoom = zoom;
}
In the setter we want to scale the container by the zoom. One minor problem is that when we scale the container, the X and Y position stays the same but the width and height of the container changes. This means that as we zoom, the centre point of the world changes. To solve this, we can record the point in world coordinates that is currently in the center of the screen, apply the zoom, and then call our lookAt function to re-centre the display.
You might also notice that we have extensively used the PIXELS_TO_METRE constant throughout this class. Well, with zooming we need to multiply this value by the zoom value. So to make things tidier we are going to assign this value to the class member variable _adjustedPixelsToMetre that we created earlier.
public function set zoom(zoom:Number):void
{
if(zoom<=0)
return;
var wc:b2Vec2 = getWorldPoint(_rasterWidth / 2, _rasterHeight/2);
_zoom = zoom;
_container.scaleX = _zoom;
_container.scaleY = _zoom;
_adjustedPixelsToMetre = _zoom * PIXELS_TO_METRE;
lookAt(new b2Vec2(wc.x, wc.y));
}
Now that is done, we will change all the PIXELS_TO_METRE references in the BasicCamera class to the _adjustedPixelsToMetre. I will omit showing all the changes.
External classes such as the Bubble class, will still reference the PIXELS_TO_METRE as I find it handy to think in pixels when designing a world, but is not means necessary.
Finally, let’s update our onKeyPress function in the CameraDemo class so that we can test the zoom.
private function onKeyPress(event:KeyboardEvent):void
{
var camera:BasicCamera = ServiceLocator.resolve(BasicCamera);
switch(event.keyCode)
{
case Keyboard.LEFT:
camera.pan(new b2Vec2(2, 0));
break;
case Keyboard.RIGHT:
camera.pan(new b2Vec2(-2, 0));
break;
case Keyboard.UP:
camera.pan(new b2Vec2(0, 2));
break;
case Keyboard.DOWN:
camera.pan(new b2Vec2(0, -2));
break;
case Keyboard.C:
camera.lookAt(new b2Vec2(800/BasicCamera.PIXELS_TO_METRE,600/BasicCamera.PIXELS_TO_METRE));
break;
//Plus key
case 187:
camera.zoom+=0.01;
break;
//Minus key
case 189:
camera.zoom-=0.01;
}
}
So there we are, another camera tutorial done. Once again here is the completed project file for this tutorial. The next tutorial we will look at adding some logic to make our camera a bit smarter and more useful to us.

