Question

There are a lot of examples concerning projectile motions in 2D games.

  • But, what are the equations for implementing a projectile motion on a 2D top down view game? For example, we want to kick a ball and increase its height (just like sensible soccer).

I read that there could be two sprites, one for the ball and one for its shadow that can create an illusion of ball getting higher.

  • However, how can we implement collision detection and response when the ball hits a post? Do we have to use the z coordinate as well?
Was it helpful?

Solution

The problem you're facing illustrates the important difference between graphics and logic - that is, the difference between What the user sees happening and the underlying virtual world that that image reflects.

The dimensionality of a 2D and 3D world need not always match. In fact, fundamentally, all graphics are 2D, in everything from Pong to Skyrim. The only decisions that the game developer must make regarding dimensionality are:

  • is the game logic 3D?
  • if so, how is the 3D world projected to the 2D screen, and from what angle?

The answer to the first question, in your case, seems to be a yes, considering the ball can be kicked up in the air. This means that you are now working in the realm of full-fledged "3D" graphics, to the extent that such graphics could ever exist. By "2D top down" game, you now probably mean "depthless 3D top-down game." This is accomplished using either orthogonal or isometric projection, which you can google if you're curious.

The shadow effect is a fine choice to accomplish such a projection, as very simple cues can go a long way in a player's visual perception of a space. Remember, it's not an illusion any more than the 3D graphics in halo are an illusion. The screen is flat, our retinas are flat, and the graphics should be flat too. That doesn't make the world, virtual or physical, any less 3D.

For the second question, you're probably not going to be projecting completely top-down. If you were, the shadow would always be obscured by the ball, and you'd only ever see the top of the soccer players' heads. I'm guessing you're probably talking about a 45 degree angle down projection, which looks much more natural and has been used in games since the beginning of time. Pokemon is a prime example. Here all that in action:

class SoccerBall extends GameObject3D {
    voic draw() {
        translate(x, y / 2); // the camera is at an angle, so we foreshorten in the y direction
        drawShadow();
        translate(0, z / 2);
        drawBall();
        // cleanup the changes we made to the graphics state
        translate(-x, -y / 2 - z / 2);
    }
}

Now, back to your original question, which was mostly about the game logic. By introducing height to the ball's location, you have without a doubt introduced a z-dimension. For your case, this z-dimension may be rarely used. You might want to split your objects up into GameObjects and GameObject3Ds, with the former haviing an x and y and the latter having an additional z (or maybe a height, which might be a little more informative).

The projectile motion is really simple. Just increment and decrement the height as needed

class SoccerBall extends GameObject3D {
    float vel_x;
    float vel_y;
    float vel_z;

    // most of the soccer ball class...

    void kick(angle direction, angle inclination, float force) {
        // calculate based on direction
        vel_x = force * cos(direction);
        vel_y = force * sin(direction);
        // take into account inclination
        vel_z = force * sin(inclination);
        vel_x *= cos(inclination);
        vel_y *= cos(inclination);
    }

    void movement_update(float delta_time) {
        // this function assumes our location
        // units are in meters
        // and our velocity units
        // are in meters/second

        // apply gravity
        vel_z -= 9.8 * delta_time; // EDIT: switched from += to -=.  += could be useful if you're playing soccer with a balloon for a ball!

        // move
        x += vel_x * delta_time;
        y += vel_y * delta_time;
        z += vel_z * delta_time;
    }
}

For collision detection, if you only care about collision with the ground them your can do a simple if (z < 0) {z = 0; vel_z = 0} check. For anything more complicated, grid-based systems are always a good bet for collision detection, because calculating an objects's grid square is cheap (floor(x), floor(y)), and then you only need to check against other object in your square. This is just as easy in 3D as in 2D, and there plenty of good explanations of it elsewhere on the Internet.

Have fun with your game :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top