making dat 2d video games

Discussion in 'Science & Technology' started by beefrave, Dec 19, 2011.

Encyclopedia Dramatica Forums
A very friendly community
  1. beefrave

    beefrave
    Expand Collapse
    Intergalactic Internets Services LLC

    Joined:
    Jul 15, 2011
    Messages:
    2,908
    Occupation:
    www.blogtalkradio.com/magarhour
    Home Page:
    Introduction

    In this short game programming tutorial, you have seen how to create the main game window. Now, since we have a game scene, we need a game story, and game actors placed on that scene.
    The Story

    As we have agreed in the first part, we are going to create a simple 2D scrolling game (the space shooter game), learning that way the things that make up the game. So, the game story will be simple: you will pilot with the starship vessel through the asteroid field and fight against the enemy UFOs which will attack you during the game play. Now, let's see how to build these game elements.
    The Player

    I have decided to use some 3D modeling software in order to create the player starship and its animation. After some hard work, here is what came out (I am not a modeling expert as you can see):
    [​IMG]
    Since this is a scrolling shooter, the player will move to left, right, up, or down, or in some combination of these four movements. But, I have created animation just for going left and right. So, what does this image represent at all? It is called tile set image of the game character. In the game, it will be known as a "sprite". If differs from a static image because it has more images that make up an animation when played one by one on the screen. The more the number of images, the smoother the animation will be, but it will take more system memory to hold it.
    The Asteroid

    I have also modeled the asteroid and came up with the following tile sets:
    [​IMG] [​IMG]
    The asteroid has a "rotating" animation, and is free to fly to any direction, but in this case, I have decided to make it fall from the top of the screen to the bottom. If it hits the starship enough times, it will destroy it. Also, if the star ship fires a plasma towards the asteroid and hits it, it will be destroyed. So, we need the explosion animation for this.
    The Explosion

    I found the free "explosion.gif", an animated explosion GIF image, on the Internet, and took out the frames, and got the following:
    [​IMG]
    The explosion will occur in the case the starship hits the asteroid (and destroys it) or vice-versa.
    The UFO

    The UFO modeled tile set looks like this:
    [​IMG]
    Now, the movement of the UFO will depend on some other things, but we can say in this moment that it can move in any direction. It will attack the player, but can not be damaged by the asteroids nor will it damage them.
    The Plasma

    The plasma is a simple image, found on the Internet (also free), which looks like this:
    [​IMG] [​IMG]
    The plasma is fired by the player starship or UFOs. It can go just up or down, and that is why there are two versions of the same image. Since it travels very fast, I thought it would be very silly to animate something like this.
    The Star Field

    The game background star field is generated as a different intensity random placed white pixels, like below:
    [​IMG]
    Conclusion

    Now, we have modeled, prepared, and explained each game element of interest in our game. You may notice that here is missing the sound part, since I haven't put any sound in the game yet, but I'll write a separate article about that topic when I do. In the next part, we will see how to initialize and shutdown the DirectX sub-system.
    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
     
  2. Weezus Christ

    Weezus Christ
    Expand Collapse
    EDF Savior

    Joined:
    Jul 15, 2011
    Messages:
    8,926
    Occupation:
    breakfast mummy
    Home Page:
    have you seen my artwork? ive been dying to animate a 2d game forever using hi-res paintings of characters and backgrounds ...

    heres a good sample of what i would like to put in a video game. a combination of pencils, paints and digital effects.

    [​IMG]
     
  3. beefrave

    beefrave
    Expand Collapse
    Intergalactic Internets Services LLC

    Joined:
    Jul 15, 2011
    Messages:
    2,908
    Occupation:
    www.blogtalkradio.com/magarhour
    Home Page:
    we need to hang out more. i think .
     
  4. oddguy

    oddguy
    Expand Collapse
    The Prime Memeister

    Joined:
    Sep 17, 2011
    Messages:
    26,933
    Occupation:
    rare deepwater jew
    Home Page:
    i never understand anything you post...
     
  5. h0xnbl0w

    h0xnbl0w
    Expand Collapse
    EDF Hero

    Joined:
    Nov 21, 2011
    Messages:
    405
    Occupation:
    Dungeon Keeper
    Home Page:
    There was directx in the url so I just facepalmed and walked away.
     
  6. Weezus Christ

    Weezus Christ
    Expand Collapse
    EDF Savior

    Joined:
    Jul 15, 2011
    Messages:
    8,926
    Occupation:
    breakfast mummy
    Home Page:
    my leg is broken so i havent moved much from my computer all month.

    im weezus godborn on fecebook. thats a good way to get ahold of me.
     
  7. faggotmaximum

    faggotmaximum
    Expand Collapse
    EDF Hero

    Joined:
    Jul 20, 2011
    Messages:
    1,563
    Occupation:
    rape
    Before we're talking about quaternions, we'll review some basics regarding vectors, Euler angles, and matrices.

    Furthermore, for this document and working within Ogre, we will use a right-handed coordinate system. This means two things:

    First, we consider +X to point to the right of your monitor, +Y to point to the top of your monitor and +Z to point out of your monitor toward you.
    Next to find out which way +45 degrees rotates, point the thumb of your //right// hand down the axis of rotation (i.e. towards positiv infinity). The direction your fingers curl is the positive angle. (See also Right-hand Rule(external link))


    A quick video introduction to Euler angles, matrices, and quaternions can be found in the Google Tech Talk Sensor Fusion on Android Devices: A Revolution in Motion Processing(external link) starting at 35:30.
    Vectors

    A vector can be thought of as an arrow from a given initial point to another point in 3D space. It describes both the direction and the length of this arrow. The direction not only describes the bearing of the arrow but also where the arrowhead points to. This separates a vector from a line segment which only has a bearing but is "bi-directional". A vector is also different from a ray as rays have an infinite length.

    Describing two points would normally require six values for 3D space. In Ogre, vectors are stored in three values by assuming the first point is (0,0,0) and the second point is a relative offset. This is a common use of vectors. This given (0,0,0) can be the world origin, or it can be the origin of an object's local coordinate system. Be aware of which coordinate system you are working with when using transformations. Because vectors have only three values, they are also used to define 3D points.

    When a vector is normalized, the vector is scaled to a length of 1. We use normalized vectors (or unit vectors) when we wish to describe only a direction. This is necessary for expected results with many mathematical algorithms.

    In Ogre, vectors are commonly used to describe a single point, define a direction with a unit vector, or extract the distance between two points.

    Here are some common vector operations and what they are used for:

    Subtracting vector A from vector B generates a third vector that contains the direction and distance from A to B.
    Bv - Av = Av -> Bv
    Adding vector A and vector B gives vector C. You can visualize this as if you take vector B, and place its tail on vector A's head (like two arrows drawing out a path). Then vector C is the vector from the start of the path (A's tail) to the end of the path (B's head). Equivalently, you could get the same vector C by lining up the vectors in the opposite order: placing vector A's head at vector B's tail.
    Multiplying or dividing a vector by a scalar (read: a number) does not change the direction, but only changes the length of the vector. For instance the vector (1,1,1) describes a line that is angled 45 degrees off the XZ plane (horizontal), 45 degrees off the XY plane (vertical, faces towards you) and 45 degrees off the YZ plane (vertical, faces left/right). The length of the line is sqrt(x^2 + y^2 + z^2) - or, in this example, sqrt(3) which is about 1.73. Now if we multiply this vector by 2 we get (2,2,2). This describes a line with the exact same angles. However the length is now sqrt(12) or 3.46 (which is 1.73 times 2). See Vector3::length().
    A cross product of two vectors provides a third vector that is perpendicular to the initial two. This is a very useful computation. If you want to figure out which way is up/out from a polygon take the cross product of two edges and you have a vector pointing out. The cross product can be calculated for you by ogre. Vector3::crossProduct(Vector3).
    The dot product of two vectors allows us to find the angle between them. It is defined as
    DotPr(v1,v2) = Cos(Angle) * Len1 * Len2
    Where Len1 and Len2 are the length of the vectors. However typically you should normalize both vectors so the lengths are 1. This means the dot product is the cosine of the angle between the vectors. Stated another way:
    Angle = ArcCos(DotPr(v1,v2)) ; where Len1 = Len2 = 1
    This is also found in the API under Vector3::dotProduct(Vector3).

    Euler Rotations

    The method of rotation you may be more accustomed to is using yaw, roll and pitch.

    Yaw would be left/right rotation around the Y axis (vertical) on the XZ plane. Yaw is used when driving a car.
    Pitch is up/down rotation around the X axis (horizontal, pointing right) on the YZ plane. Pitch is used when flying a jet down or up, or when driving up hill or down.
    Roll is tilt rotation around the Z axis (pointing towards you) on the XY plane. Roll is literally what happens to your car when you take a curve too fast!


    Euler rotations can be useful and are supported in Ogre's API. There are problems however. One is that the order of operations is important. If you pitch an object 90 degrees, then yaw it 90 you get a different result than if yaw is done before pitch. Try it.

    Another big problem is known as gimbal lock(external link). A gimbal is an axis of rotation. This problem occurs when mathematically two axes of rotation become aligned and one gets canceled out.

    Finally, euler angles are limited in their practical application. What I mean by this is that to rotate an object arbitrarily it is not very practical to use yaw, roll and pitch operations. They are useful say if you want a yaw/pitch camera like many fps games. With a dual sceneNode trick you can get a camera that will use yaw and pitch operations without inducing roll. However, when you have an object facing one way and you want it to face another object in an arbitrary location, retrieving the current individual yaw, roll and pitch values then calculating the difference needed for a rotation to the new direction is not very efficient. Also, what if you want to do a smooth rotation from the current facing to the new direction? Not very practical. Enter matrices.
    Matrix Rotations

    Because working with arbitrary three dimensional euler rotations can produce a large amount of operations, matrices are usually used to store and transform them.

    One way of working with matrices is to use three, each specifying a certain angle offset from the X, Y and Z axes. This is our pitch (rotation on the X axis), yaw (Y axis) and roll (Z axis). We can store them in individual matrices, say matRotationX, matRotationY and matRotationZ. When we have decided on the angles we wish to rotate by and have stored them in our matrices, we can combine the operations into one transform matrix simply by multiplying them.

    matTransform = matRotationX * matRotationY * matRotationZ;

    Fortunately for us, Ogre implements a Matrix3 class to handle 3x3 matrices. The class also has the * operator overloaded so the above statement will work right in your code. To rotate an object in Ogre you first need to create a quaternion with this matrix by using the appropriate quaternion constructor or using FromRotationMatrix on a quaternion.

    Note that matrix multiplication is not commutative. A * B doesn't always equal B * A. The order in which you apply each matrix rotation is important, just as it is with straight euler angles. Also note that matrices as representations of euler angles are still subject to gimbal lock.

    Matrices can also be used to handle axis/angle rotations. The matrices above used concepts of yaw, roll and pitch. Think of these instead as rotation around Y, Z and X axes, respectively. It is possible to achieve any rotation by defining a single arbitrary axis and an angle of rotation. In doing this we avoid the problem of gimbal lock.

    There is a problem with both euler angle matrices and axis/angle matrices. It is called matrix drift, which I will describe in the quaternion section under the benefits list.
    Quaternion Rotations

    Quaternions are an interesting concept probably as new to you as they were to me when I first started this. As described above, when working with quaternions I find it easier to stop thinking about yaw, pitch and roll and instead think of rotation around axes. For instance, let's say we wanted to model a propeller on a jet. The jet faces down the Z axis. In euler terms the rotation would be called roll. In quaternions it is rotation around a vector pointing down the Z axis, or rotation around Vector3::UNIT_Z as we'd refer to it in Ogre.

    A quaternion is composed of four components: a vector with x, y, z coordinates and a w rotation. This is an axis/angle representation just as I touched on at the end of the matrix section. Quaternion math can get quite involved, even incorporating imaginary numbers. Fortunately we don't need to use all of that math, nor understand it to work with rotations.

    Try this exercise. Point your left index finger straight up. Next grab the tip of a pen with your right hand. Now by moving your wrist and hand around in a circle, try to spin the pen as flatly as possible, always perpendicular to your finger and parallel to the floor. It should look like you had just spun it on a table. Think of this as quaternion rotation around Vector3::UNIT_Y.

    Now let's say we have a vector from (0,0,0) to (1,1,-1). With our finger pointing straight right, point it up 45 degrees and away from you 45 degrees. Now rotate the pen around your finger, keeping it perpendicular at all times. Notice how the angle of the axis we choose creates a different rotation.

    Like matrices, we can combine quaternion rotations by multiplying them. However they are still not commutative. Q1 * Q2 != Q2 * Q1. Thus the order of application is still important. Also like matrices that represent axis/angle rotation, quaternions avoid gimbal lock.


    Benefits of Quaternions

    Quaternions do have advantages over matrices though. There are implementation pros and cons such as the number of multiplications, or additions during different operations, etc that have been discussed in the forum. Considering practical benefits though, here is a list :

    Axis/angle representation avoids gimbal lock.
    Modifying a rotation is easy. Say we have a rotation describing a -45 degree yaw (left turn). By creating a new quaternion describing a 10 degree yaw (right turn) and multiplying the two, we now have a rotation describing a -35 degree turn. You might use this when applying the same rotation to a number of different objects, or even multiple times to the same object (i.e. the player). The rotation factor increases or decreases depending on circumstances.
    Avoids costly alignment of matrix drift. This drift occurs when performing lots of operations on matrices using finite point precision, which is used in your computer. Rounding of real numbers graudally builds up and inevitably mucks up the matrix. Abnormalities in the rotation will start to appear due to this drift. The matrix must be normalized in order to reset this, however it is a costly operation. Quaternions on the other hand can still suffer from this drift, but it is much cheaper to normalize having only 4 values instead of 9 or more.
    Interpolation of rotations. When rotating an object, we might want the object to rotate smoothly over time. We'd like to say, "From your current orientation, rotate to face this point. But take about 300 frames to do it, so only move 1/300th of the rotation right now." Interpolation with matrices is possible, but then so is anything, isn't it? Quaternions provide two methods of interpolation: linear(slerp) and cubic(squad). Ogre provides three implementations: slerp, nlerp and squad. Linear interpolation allows one to specify the percentage of interpolation between the two quaternions. Linear means your "velocity" of movement is constant, which may feel jerky if used for a camera or object. Slerp and nlerp are both linear. Slerp is more accurate, but slower. Squad or cubic interpolation allows one to specify four quaternions a,p,q,b. P and Q are used to define a curve of interpolation "velocity" between points A and B. This allows us to slowly increase speed, stay constant, then decrease it during interpolation. See the External Resources section for links that will elaborate on this.
    Ogre uses quaternions! That's probably why you are reading this page. :) Often, you'll need to get the current orientation of an object, which is returned as a quaternion.