The Camera2D Class

Let's put all this together into a single class. We want it to store the camera's position, the standard frustum width and height, and the zoom factor. We also want a convenience method that sets the viewport (always use the whole screen) and projection matrix correctly. Additionally we want a method that can translate touch coordinates to world coordinates. Listing 8-15 shows our new Camera2D class.

Listing 8-15. Camera2D.java, Our Shiny New Camera Class for 2D Rendering package com.badlogic.androidgames.framework.gl;

import javax.microedition.khronos.opengles.GLl0;

import com.badlogic.androidgames.framework.impl.GLGraphics; import com.badlogic.androidgames.framework.math.Vector2;

public class Camera2D {

public final Vector2 position; public float zoom; public final float frustumWidth; public final float frustumHeight; final GLGraphics glGraphics;

As discussed, we store the camera's position, frustum width and height, and zoom factor as members. The position and zoom factor are public, so we can easily manipulate them. We also need a reference to GLGraphics so we can get the up-to-date width and height of the screen in pixels for transforming touch coordinates to world coordinates.

public Camera2D(GLGraphics glGraphics, float frustumWidth, float frustumHeight) { this.glGraphics = glGraphics; this.frustumWidth = frustumWidth; this.frustumHeight = frustumHeight;

this.position = new Vector2(frustumWidth / 2, frustumHeight / 2); this.zoom = l.0f;

In the constructor we take a GLGraphics instance and the frustum's width and height at the zoom factor 1 as parameters. We store them and initialize the position of the camera to look at the center of the box bounded by (0,0,1) and (frustumWidth, frustumHeight,-1), as in Figure 8-19. The initial zoom factor is set to 1.

public void setViewportAndMatrices() { GLl0 gl = glGraphics.getGL();

gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());

gl.glMatrixMode(GLl0.GL_PROJECTION);

gl.glLoadIdentity();

gl.glOrthof(position.x - frustumWidth * zoom / 2, position.x + frustumWidth * zoom/ 2, position.y - frustumHeight * zoom / 2, position.y + frustumHeight * zoom/ 2, l, -l);

gl.glMatrixMode(GLl0.GL_MODEL VIEW); gl.glLoadIdentity();

public void setViewportAndMatrices() { GLl0 gl = glGraphics.getGL();

gl.glViewport(0, 0, glGraphics.getWidth(), glGraphics.getHeight());

gl.glMatrixMode(GLl0.GL_PROJECTION);

gl.glLoadIdentity();

gl.glOrthof(position.x - frustumWidth * zoom / 2, position.x + frustumWidth * zoom/ 2, position.y - frustumHeight * zoom / 2, position.y + frustumHeight * zoom/ 2, l, -l);

gl.glMatrixMode(GLl0.GL_MODEL VIEW); gl.glLoadIdentity();

The setViewportAndMatrices() method sets the viewport to span the whole screen, and sets the projection matrix in accordance with our camera's parameters, as discussed previously. At the end of the method we tell OpenGL ES that all further matrix operations are targeting the model view matrix and load an identity matrix. We will call this method each frame so we can start from a clean slate. No more direct OpenGL ES calls to set up our viewport and projection matrix.

public void touchToWorld(Vector2 touch) {

touch.x = (touch.x / (float) glGraphics.getWidth()) * frustumWidth * zoom; touch.y = (l - touch.y / (float) glGraphics.getHeight()) * frustumHeight * zoom; touch.add(position).sub(frustumWidth * zoom / 2, frustumHeight * zoom / 2);

The touchToWorld() method takes a Vector2 instance containing touch coordinates and transforms the vector to world space. This is the same thing we just discussed; the only difference is that we use our fancy Vector2 class.

0 0

Post a comment