Defining the Game World

The classic chicken-and-egg problem haunts us again. You learned in the last chapter that we have a correspondence between world units (e.g., meters) and pixels. Our objects are defined physically in world space. Bounding shapes and positions are given in meters, velocities are given in meters per second. The graphical representations of our objects are defined in pixels, though, so we have to have some sort of mapping. We overcome this problem by first defining a target resolution for our graphical assets. As with Mr. Nom we will use a target resolution of 320x480 pixels (aspect ratio of 1.5). The next thing we have to do is establish a correspondence between pixels and meters in our world. The mock-up in Figure 9-1 gives us a sense of how much screen space different objects use, as well as their proportions relative to each other. I usually choose a mapping of 32 pixels to 1 meter for 2D games. So let's overlay our mock-up, which is 320x380 pixels in size with a grid where each cell is 32x32 pixels. In our world space this would map to 1 x1 meter cells. Figure 9-3 shows our mock-up and the grid.




Figure 9-3. The mock-up overlaid with a grid. Each cell is 32x32 pixels and corresponds to a 1x1-meter area in the game world.

Figure 9-3 is of course a little bit cheated. I arranged the graphics in a way so that they line up nicely with the grid cells. In the real game we'll place the objects at noninteger positions.

So what can we make of Figure 9-3? First of all we can directly estimate the width and height of each object in our world in meters. Here are the values we'll use for the bounding rectangles of our objects:

Bob is 0.8x0.8 meters; he does not entirely span a complete cell.

A platform is 2x0.5 meters, taking up two cells horizontally and half a cell vertically.

A coin is 0.8x0.5 meters. It nearly spans a cell vertically and takes up roughly half a cell horizontally.

■ A spring is 0.5x0.5 meters, talking up half a cell in each direction. The spring is actually a little bit taller than it is wide. We make its bounding shape square so that the collision testing is a little bit more forgiving.

With those sizes we also have the sizes of the bounding rectangles of our objects for collision detection. We can adjust them if they turn out to be a little too big or small depending on how the game plays out with those values.

Another thing we can derive from Figure 9-3 is the size of our view frustum. It will show us 10x15 meters of our world.

The only thing left to define are the velocities and accelerations we have in the game. This is highly dependent on how we want our game to feel. Usually you'd have to do some experimentation to get those values right. Here's what I came up with after a few iterations of tuning:

■ The gravity acceleration vector is (0,-13) m/s2, slightly more than what we have here on earth and what we used in our cannon example.

■ Bob's initial jump velocity vector is (0,11) m/s. Note that the jump velocity only affects the movement on the y-axis. The horizontal movement will be defined by the current accelerometer readings.

■ Bob's jump velocity vector will be 1.5 times his normal jump velocity when he hits a spring. That's equivalent to (0,16.5) m/s. Again, this value is purely derived from experimentation.

■ Bob's horizontal movement speed is 20 m/s. Note that that's a directionless speed, not a vector. I'll explain in a minute how that works together with the accelerometer.

■ The squirrels will patrol from the left to the right and back continuously. They'll have a constant movement speed of 3 m/s. Expressed as a vector that's either (-3,0) m/s if the squirrel moves to the left or (3,0) m/s if the squirrel moves to the right.

So how will Bob's horizontal movement work? The movement speed we defined before is actually Bob's maximum horizontal speed. Depending on how much the player tilts her phone, Bob's horizontal movement speed will be between 0 (no tilt) and 20 m/s (fully tilted to one side).

We'll use the value of the accelerometer's x-axis since our game will run in portrait mode. When the phone is not tilted, the axis will report an acceleration of 0 m/s2. When fully tilted to the left so that the phone is in landscape orientation, the axis will report roughly -10 m/s2. When fully tilted to the right the axis will report an acceleration of roughly 10 m/s2. All we need to do is normalize the accelerometer reading by dividing it by the maximum absolute value (10) and then multiply Bob's maximum horizontal speed by that. Bob will thus travel 20 m/s to the left or right when the phone is fully tilted to one side and less if the phone is tilted less. Bob can move around the screen twice per second when the phone is fully tilted.

We'll update this horizontal movement velocity each frame based on the current accelerometer value on the x-axis, and combine it with Bob's vertical velocity, which is derived from the gravity acceleration and his current vertical velocity, as we did for the cannonball in the earlier examples.

One essential aspect of the world is the portion we see of it. Since Bob will die when he leaves the screen on the bottom edge, our camera also plays a role in the game mechanics. While we'll use a camera for rendering and move it upward when Bob jumps, we won't use it in our world simulation classes. Instead we record Bob's highest y-coordinate so far. If he's below that value minus half the view frustum height, we know he has left the screen. We thus don't have a completely clean separation between the model (our world simulation classes) and the view, since we need to know the view frustum's height to determine whether Bob is dead or not. We can live with this, I'd say.

Let's have a look at the assets we need.

0 0

Post a comment