home    forums    games    source    mods    projects    store    contact
CUBEFIELD

     In Cubefield you must dodge oncoming cubes at increasing speeds. I made this game in Flash, and while I cannot release the full source code because I am required to ensure that all versions online bear the yoarcade.net logo, I wanted to at least give the core classes I used and an explanation of how they work.

     Play online | Download (Windows) | Download (Mac)

SCREENS


SOURCE
     I cannot make the full source available, but I am releasing the 3D code, which is in truth the only interesting part. Here's a very basic primer in 3D projection and how my code works:

     Rendering 3D objects can be done by projecting them onto the monitor. We use a pyramidal frustum to represent the camera's view of the scene: you can think of the small rectangle, or front clipping plane, as the computer monitor. Since the three dimensional objects in the scene are made out of polygons, which are in turn defined by points (vertices) in space, by finding the projection of those vertices onto the front clipping plane we can draw a 2D image representing our perspective of the 3D scene.

     Projection is a linear transformation. You can multiply a matrix by a vector representing a point in 3D space to find where it lies on the monitor - if you're interested, I suggest Wikipedia's article on 3D projection. Video cards are excellent at doing this, they have highly specialized mulitipliers and pipelines that can perform the calculations very quickly. When working with a platform like Flash that is not so great at crunching numbers, though, it is not very realistic to do full 3D. For Cubefield, I instead chose to use a far simpler projection that does not have all the capabilities of the normal method.

     My method was to essentially abandon rotation and scaling to make things quicker. In my projection, the view frustum is locked in place at the origin, unable to rotate or move. This grants us some special properties. In particular, the projected x coordinate on the monitor is a function only of the x and z coordinates in 3D space. Similarly, projected y is a function of 3D y and z. Imagine a point in 3D space moving horizontally and its projection: the y-coordinate in the projection will not change. This means that the coordinates can be computed separately, rather than through a matrix multiplication.


     To define the view frustum, I use four values: the width and height of the screen, the angle of the left/right sides, and the angle of the top/bottom sides. To the left is a diagram of a cross-section of the frustum, taken from above looking down: it shows the width of the front clipping plane and the angle of the sides. These are all that is necessary to compute projected x from 3D x and z. A cross-section from the side would similarly show height of the front clipping plane and angle of the top and bottom sides.


     The image on the right shows how projected x is calculated. First, notice that it is possible to compute the width across the frustum at a given z: all we have to do is add 2*z*tan(u) to the width of the front clipping plane. Second, see that the ratio of the 3D point's x value to that width is the same as the projected point's x value to the front clipping plane width. Let width(z) be the width of the frustum at z (so width(0) is the width of the front clipping plane), (x,y,z) be a point 3D space, and (x',y') be its projection. This gives the equation x/width(z)=x'/width(0), or x'=width(0)*x/(width(0)+2*z*tan(u). The equation for y is symmetrical: if v is the angle, then y'=height(0)*y/(height(0)+2*z*tan(v)). That's all there is to it, we now have the projected point.

     The rest is easy. If a set of points form a polygon in 3D space, then we can represent it in 2D by filling in the projected points. Since I used solid fills rather than textures, this was simple: I just used the flash vector drawing function to draw fills on a movie clip. It is important that the polygons are drawn in order by their distance from the frustum, so that if polygon A is in front of polygon B, A obscures B rather than the other way around. I actually didn't do this completely; I just ordered the cubes by their z-coordinates, so occasionally when two cubes are right next to each other the one that's farther away is drawn in front. It was a small enough glitch that I decided it was worth it to save the time of doing a true depth sort.

     Besides the 3D rendering, the game's code is very simple, no particularly neat tricks. If you have any questions about any of it, though, please feel free to contact me.