EECE 478 – Computer
Transcription
EECE 478 – Computer
EECE 478 – Computer Graphics 3D Game Design – Final Report Futuristic Shooter Submitted: April-14-08 Rex Chang, 81535049 Martin Ma, 13778030 Derek Tam, 63491047 Sarah Wu, 62473046 Abstract This report details the nature, the design, and the implementation methods of our EECE 478 game project, which consists of a game world where two players can move around and shoot each other with projectile weapons. The game design is explained with the intention to allow the reader to know why and how the techniques are chosen and utilized in the final implementation. The game demonstrates the basic project requirements, while exploring various advanced features that can enhance the gameplay. 2 Table of Contents Abstract ......................................................................................................................................2 Table of Contents........................................................................................................................3 List of Figures.............................................................................................................................4 List of Abbreviations ..................................................................................................................5 1 Introduction .............................................................................................................................6 2 Game Description ....................................................................................................................8 3 Implementation Methods..........................................................................................................9 3.1 User Interface ....................................................................................................................9 3.1.1 Menu...........................................................................................................................9 3.1.2 Sound........................................................................................................................10 3.2 Collision Detection ..........................................................................................................12 3.2.1 Collision of Two Spherical Models ...........................................................................12 3.2.2 Collision of a Spherical Model and a Bounded Plane.................................................13 3.3 Game Mechanics .............................................................................................................15 3.3.1 Movement along the Board .......................................................................................15 3.3.2 Firing an Arrow.........................................................................................................16 3.3.3 Health Points and Magic Points Status.......................................................................17 3.4 Three-Dimensional Models..............................................................................................18 3.4.1 3DS Loaders .............................................................................................................19 3.4.2 Terrain Generation ....................................................................................................20 3.4.3 Frustum Culling ........................................................................................................21 3.5 Animation........................................................................................................................25 4 Possible Improvements ..........................................................................................................29 5 Flow Chart .............................................................................................................................30 3 List of Figures Figure 1 Right-Click Game Menu ...............................................................................................9 Figure 2 Collision of Two Spheres ............................................................................................12 Figure 3 Collision Between a Sphere and a Bounded Plane .......................................................14 Figure 4 Face Directions before Movement...............................................................................16 Figure 5 Face Directions after Movement..................................................................................16 Figure 8: Stick Figure - Front View...........................................................................................18 Figure 9: Stick Figure - Back View ..........................................................................................18 Figure 11 A Snowfield Terrain Using 3ds Max Studio ..............................................................20 Figure 12 Terrain with Bitmap 1 ...............................................................................................21 Figure 13 Terrain with Bitmap 2 ...............................................................................................21 Figure 14 Frustum Culling – Example Terrain ..........................................................................22 Figure 15 Before Frustum Culling.............................................................................................23 Figure 16 Area Inside the View Frustum...................................................................................23 4 List of Abbreviations GLUT OpenGL Utility Toolkit HP Health Point MP Magic points SDL_Mixer Simple DirectMedia Layer Mixer GLEW OpenGL Extension Wrangler (Library) 5 1 Introduction This report will show the nature of our game project, the design details, and the various features we implemented, along with the design decisions and less successful attempts when exploring more advanced features. The intention is to show the reader what our team had accomplished and how we accomplished them. Our game basically includes a 3D world with a game field, on which two players can shoot each other with projectile weapons (mainly a bow and arrows). The two players can move within the game field to dodge each other’s attacks. There is an HP (Health Point) bar and an MP (Magic Point) bar for each player. If the HP of one player drops to zero, the other player is considered to have won. The MP governs the arrow firing ability of the player. Our game had met the basic requirements in the project details, which include: (a) 3D viewing and objects with a moving camera; (b) lighting and material variations; and (c) texture mapping. There are advanced features we attempted implementing, including the following: (a) Sound effects (b) Collision detection (c) Physical simulation (d) Terrain (e) View frustum culling (f) Key frame animation These features are explained in more details in the corresponding sections. We believe there are many more elements and features we can add to the game to make the game more entertaining, but for the time frame given to complete the project, we are unable to include all of them. These possible improvements are briefly described in section 4 of this report. 6 7 2 Game Description As explained in the introduction, the game world contains a game field on which two character models can move around and shoot projectiles. The game allows two human players to take control of the in-game characters and fight against each other to see who may defeat the opponent first. The arrows can be fired at the expense of some MP, which regenerates over time. When MP drops to zero, no more arrows can be fired until it regenerates. If the arrow hits the opponent, the HP of the opponent will decrease based on the power of the fired arrow. When HP drops to zero, the character is considered dead, and the other player has won. Each of the characters can be controlled by keyboard keys or the joystick (mapped to these keys). The character can move (up, down, left, right), change heading (left or right), change projectile angle (up or down), or modify firing power (1 button). The game menu can be accessed with the right click of the mouse and it can start, pause, or quit the game. 8 3 Implementation Methods There are many different aspects of the implementation of this game that must be described to fully understand how this game was produced. This game involves creating a simple user interface, to numerous game mechanics algorithms, to various types of three-dimensional modelling, to several different animation techniques. The following sections with examine all the features of the game in further detail. 3.1 User Interface For the user interface of this game, a simple menu system was used. Also, while playing the game, specific sounds are associated with different actions. The following sections will describe how the menu was created and how sound was implemented for this project. 3.1.1 Menu The menu system is build using the OpenGL Utility Toolkit (GLUT) menu functions. GLUT provides a simple mechanism for creating pop-up menus. Each menu item is associated with a specified procedure. Our menu system contains three different selections, Start Game, Pause and Quit Game. The menu can be brought up when the right button of the mouse is clicked. Figure 1 Right-Click Game Menu 9 A menu is first created by calling int glutCreateMenu(void (*func)(int value)). This creates a simple menu in which you can add numerous entries for different tasks. Items are added into this menu by calling void glutAddMenuEntry(char* name, int value). In our project, as shown in Figure 1, three different choice selections had been added. To associate the right mouse button with the menu, the button must be assigned to this menu by calling void glutAttachMenu(int button). A menu event function is attached to the menu so that when a selection has been made, the correct action will be executed. 3.1.2 Sound The sound used for this project is implemented using the Simple DirectMedia Layer Mixer (SDL_MIXER) library. SDL_mixer is a simple multi-channel audio mixer that supports 8 channels of 16 bit stereo audio, plus a single channel of music, which includes the popular MikMod MOD, Timidity MIDI, Ogg Vorbis, and SMPEG MP3 libraries. This library divides sound into two categories: music and sound effect. Music constitutes as the sound played on the background and it is not event-driven. The music file needs to either be an mp3 or a MIDI extension. Sound effect is event-driven, thus working closely with mechanics of the game. For example, a sound is played when an arrow is released or when an arrow hits an object. The sound effect file must be a WAV extension. Here are the steps in using SDL_Mixer in our sound system: • Open up the audio device • Load sound effect files into memory • Play them when necessary • Clean up 10 The SDL_MIXER has several music player state functions to control the status of the music, such as int Mix_PlayingMusic() and int Mix_PausedMusic() to play and pause the music. Music player control functions were utilized to control the music playing during the game to play, pause, and resume the music. The SDL_MIXER has a feature on the sound effect which enables multiple sound effects played at the same time. Multiple sound effects are enabled through the utilization of numerous channels. Mix_PlayChannel(int channel, Mix_Chunk *chunk, int loops) is used to control which channel the sound is played on. -1 is passed to channel for the first free unreserved channel and 0 is passed to loops to play the sound sample only once. 11 3.2 Collision Detection Collision detection is required in many aspects of this game to make it perform as it should. A player cannot run through another player nor can it run through the walls of the obstacles. When an arrow hits a player or an obstacle, it must be detected so that the proper action can take place. Without collision detection, the entire game outlined in the game description section would not work. Two types of collision detection were used for this game, collision between two spheres and collision between a sphere and a plane. 3.2.1 Collision of Two Spherical Models The first type of collision detection implemented for this game was the collision of two spheres. This was used to simulate the collision of two players since each player has a cylindrical body and will only collide into another player at each other’s side. To detect a collision of two spherical bodies, the distance between the centres of the two bodies was calculated. If the distance, d, was greater than the sum of the radii of the bodies (r1 + r2), then they have not collided ( Figure 2). If the distance is equal to the sum of the two radii, then the two bodies are just touching; if the distance is less than the sum of the two radii, then the two bodies have begun to pass through each other. d r1 r2 Figure 2 Collision of Two Spheres 12 3.2.2 Collision of a Spherical Model and a Bounded Plane The second type of collision detection implement was the collision of a sphere and a plane. This simulates the collision of the body of a player and an obstacle. This second type involved more math than the first type. First the normal of the plane must be determined. This is accomplished by finding the cross product of two vectors on the plane. Vectors on the plane are simply vectors created by points are the plane, of which four are already known since they are the properties that define the plane. Secondly, since a point of the plane is known, a vector from a point on the plane to the center of the body is projected onto the normal of the plane. The length of this projection (Equation 1) is then equivalent to the distance between the center of the body and the plane itself. Equation 1 Length of Projection of Line cQ onto n Like the first collision type, if the distance calculated is greater than the radius of the body, then a collision has not occurred. If the distance is equal, then a collision might have occurred. To determine if a collision has indeed occurred, the collision point, P (Equation 2), must be within the boundary of the plane, which is set by the properties of the obstacle. Equation 2 Point of Collision Figure 3 helps to show how to determine if the collision point is within the boundary. To simplify the calculations for this game, the y values of all the points that define the plane must be equivalent (Qy = Ry = Sy = Ty) so that the height the plane is uniform throughout. This means 13 values Ty and Sy will be set to zero (the ground of the game) and Qy and Ry will be set to the same value, the height of the plane. Another predefined property of the plane is that it must be perpendicular to the ground. This means that values Qx and Tx, Rx and Sx, Qz and Tz, and Rz and Sz will be equivalent to each other. With these values set into place, it is easy to verify if the collision point is within the boundary. The collision point, P, is within the defined obstacle boundary if: • Qx ≤ Px ≤ Rx • and Qz ≤ Pz ≤ Rz • and 0 ≤ Py ≤ Ry Q(Qx, Qy, Qz) R P c r n T S Figure 3 Collision Between a Sphere and a Bounded Plane 14 3.3 Game Mechanics There are many components to the mechanics of this game. Different elements enhance different aspects of the game play. These game mechanic components include: • movement along the board • firing an arrow • hit point (HP) status • magic points (MP) status Since a number of the mechanics of this game have yet to be implemented, parts of this section will examine the methods of how an element will be implemented instead of how it was done. 3.3.1 Movement along the Board A player may move in four directions on the board, forward, backward, left, and right. This is achieved by pressing four different keyboard keys. If an obstacle or another player is its way, it will be unable to move in that direction. To accomplish this, four flags, one for each direction, are set for each player. If a collision has occurred, the flag will be set and the player will be unable to move in the direction in which the collision has taken place. When the player moves in such a way that it is no longer colliding with an object, the flag is unset. Originally, to increase the ease with which a player fires an arrow (next section), when either players move, both players will automatically rotate that they are always facing the other player (Figure 4 and Figure 5). This has been changed so that a player may rotate towards whichever direction it prefers to allow for greater manipulability of the player models. 15 Figure 4 Face Directions before Movement Figure 5 Face Directions after Movement 3.3.2 Firing an Arrow An arrow in this game contains numerous properties. There are two types of arrows that cause different reactions. The standard arrow just decreases a player’s HP, whereas the special arrow will produce a knock-back effect, which causes a player to lose HP and be forced to move back a few steps. Different types of arrows require different MP costs; this enhances the game play because every time an arrow is to be fired, the player will need to determine which arrow will produce the best affect. Besides the type of arrow affecting the cost of MP, the strength of the shot also has a different cost. A player can pull the arrow longer and, therefore, fire to a greater distance, but this will require a greater amount of MP. The strength of an arrow is displayed on a power bar and is determined by repeatedly pressing the “pull” key. At the desired strength, the player can press “fire” to fire the arrow. The firing of an arrow in this game is modelled using the projectile motion formulas. The x and z distance of the arrow is determined with Equations 3 and the y is determined with Equation 4. A player may rotate the angle of the arrow to the specific y direction it wants to aim at. dx = vxt and dz = vzt Equation 3 x and z Distance dy = vyt + ½at2 Equation 4 y Distance 3.3.3 Health Points and Magic Points Status Health points (HP) is used to keep track of the players’ health status. When a player is hit by an arrow, its HP will decrease. When a player’s HP reaches zero, it is dead and the other player has won. HP is stored in a variable that is updated every time a player is hit by an arrow. A player’s magic points (MP) is what it costs a player to fire an arrow. Magic points decreases every time an arrow is fired and regenerates as time passes. A player cannot attack if it does not have sufficient MP saved up to fire an arrow, in this case, a player must wait for MP to regenerate enough to afford the cost of an arrow. MP is also stored in a variable that is updated every time an arrow is fired or after a specific regeneration interval has passed. HP and MP status bars are displayed above each player’s head. They are drawn as rectangles in red and blue colours for HP and MP, respectively. These bars are placed above the players’ head because with the camera of the game moving around, it would be difficult to draw static bars in the frame. Furthermore, placing the hp/mp bars above the models’ heads is more convenient for players because they will not be distracted from the gameplay by looking away from the board to view various statuses. 17 3.4 Three-Dimensional Models We wanted to make our 3D game look more exciting, so we created our own 3D models with programs such as 3DS max studio to use in our game. However, loading the 3D models that we created in 3DSmax to our OpenGL game is a lot more difficult than we imagined. It requires a thorough understanding of the 3DS chunk structure and writing a 3DS loader to load the models into our game. Figures 8 and 9 show two different views of the static bowmen model that we made in 3DSmax studio. Figure 6: Stick Figure - Front View Figure 7: Stick Figure - Back View Since we were short on time, we tried to locate 3ds loaders that were readily available on the net for use in our project. We made many attempts to find 3ds loaders for loading our models into the game most of which gave us quite a lot of problems such as missing or outdated header files (glaux.h, glew.h…) or incompatible with our compiler software. We tried quite a few 3ds loaders, most of which did not work entirely the way we expected them to behave. The only two 3ds loaders that successfully loaded our code were: “SpaceSimulator” and “Anim8or”, both of which have their strengths and shortcomings. 18 3.4.1 3DS Loaders “Lib3ds” is one of the most commonly used open source 3ds loaders on the web which is geared for those who are Lib3ds unfamiliar with the 3ds chunk structure. However, our compiler setup seemed to be missing some components that were required to run the source code for this loader. Thus, we were unable to use this loader. “SpaceSimulator” is a 3d game made with the use of a selfwritten 3ds loader. But it does not contain some of the 3ds SpaceSimulator chunks that we needed in our game such as lighting, materials and animation. However, it does provide texture mapping on the object itself. “Anim8or” is a 3D program which allows importing of 3ds models from 3ds max and has an internal converter to C which extracts all the vertices, normals, information within the 3ds file. This allows us to load the static model for the game. However, similar to SpaceSimulator, Anim8or’s exported C format did not contain information on the Anim8or animation keyframes, lighting and material inside the 3ds file. We did, however, located, an anim8or viewer which provided decent lighting and visibility for our model. If we are not able to find a loader which includes the animation and lighting details within the 3ds file, we will be using a static model exported from Anim8or in our game. Anim8or is by far the best static model loader that we found on the web. MD2 is one of the 3d modelling formats that support MD2 animation keyframes, lighting and materials. We will be using MD2 for our animated model. Please refer to section 3.5 Animation for more information. 19 3.4.2 Terrain Generation We wanted to give a more realistic feel to our game so we created a terrain for our models to walk on. One of the terrain model creation methods that we looked at was using 3DSmax to create a 3DS model and load the terrain into our game as a static model using “Anim8or” or other 3DS model loaders. However, this method poses a problem as the height information which is needed to define the player boundary is not shown in the 3ds format. Thus, we cannot use this method to define our terrain. Figure 11 shows a snowfield terrain that we made in 3DS Max studio. Figure 8 A Snowfield Terrain Using 3ds Max Studio In the end, we decided to extract the height information from a grayscale bitmap that we created. The bitmap is displayed in a 24 bit 128x128 grayscale format. The terrain loader is written in a way that the program extracts height information from the bitmap based on the color intensity of the bitmap. White represents the maximum height and black represents the minimum height. If 20 our bitmap consists of regions with colors that are gray, then terrains with heights that are between the maximum and minimum heights will be shown. The two figures below show two example terrains generated by two different bitmaps. Figure 9 Terrain with Bitmap 1 Figure 10 Terrain with Bitmap 2 3.4.3 Frustum Culling 21 The terrain can easily be the largest model in the game and rendering it without optimization will drastically slow down the overall loading time of the game. Thus, a technique known as “frustum culling” is used to hide certain parts of the terrain that is not visible by the viewer. This technique enables our games to have faster loading times. Our frustum culling is still in its early development and we hope to have it made ready by the time of our demo. The figure below shows an explanation of the fundamentals of frustum culling. The following is an explanation of the fundamentals of frustum culling. Total number of faces that need to be rendered without frustum culling is 1458 (Figure 11). Figure 11 Frustum Culling – Example Terrain Source: http://accad.osu.edu/~aprice/courses/BVE/frustum/frustum.html When modeling the terrain, we can cut the model down to multiple parts that match together. The above image shows the terrain cut into nine sections (Figure 12). 22 Figure 12 Before Frustum Culling In Figure 13, the highlighted portion of the terrain model is the only part that’s detected by the terrain engine as it is the only area that is inside the view frustum. Thus, the highlighted portion is the only area that is rendered. Figure 13 Area Inside the View Frustum 23 This optimization technique allows the terrain engine to render 648 faces as opposed to 1458 faces on the whole terrain. 24 3.5 Animation Originally we decided to work with 3ds (3ds Max) models for animation. Though there are many online guides on the chunk structure of the 3ds model, most of the loaders available on the internet do not support key frame animation. Therefore, we can only easily use them to load static 3ds models into our game. Although it is possible to load a series of static models and animate them inside our program, this approach is quite inefficient and requires a lot of bookkeeping by our game engine. After some research and experimenting with different model files, we have decided to use the md2 (Quake 2) model files for character animation because it supports the necessary features we need. There are also many available resources online about the model structure and loaders that can be integrated with our code. In addition, the game Quake 2 is open-source, so we can study how the original game utilizes the md2 models. We primarily used the tutorial available on the website “The Quake II’s MD2 file format” (http://tfc.duke.free.fr/old/models/md2.htm) by David Henry. The loader available on the same website is also incorporated into our code. Most of the following diagrams and codes depicting the data structure and the algorithms are also from the website. The key frame animation structure is embedded in the MD2 model, as shown in figure 17 below: 25 Figure 17 Animation Data Structure in the MD2 model (from “The Quake II’s MD2 file format”) As shown in the figure, each animation sequence contains a number of frames, and each frame contains the vertices required to display. We can identify these animation sequences by their starting and ending frames. The following code segment demonstrates how we identify the different sequences common in most MD2 models: anim_t CMD2Model::animlist[ 21 ] = { // first, last, fps { { { { { { { { { { { { { { { { { { { { { 0, 40, 46, 54, 58, 62, 66, 72, 84, 95, 112, 123, 135, 154, 160, 196, 173, 178, 184, 190, 198, 39, 45, 53, 57, 61, 65, 71, 83, 94, 111, 122, 134, 153, 159, 168, 172, 177, 183, 189, 197, 198, 9 10 10 7 7 7 7 7 7 10 7 6 10 7 10 7 5 7 7 7 5 }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, }, // // // // // // // // // // // // // // // // // // // // // STAND RUN ATTACK PAIN_A PAIN_B PAIN_C JUMP FLIP SALUTE FALLBACK WAVE POINT CROUCH_STAND CROUCH_WALK CROUCH_ATTACK CROUCH_PAIN CROUCH_DEATH DEATH_FALLBACK DEATH_FALLFORWARD DEATH_FALLBACKSLOW BOOM }; To make these sequences easier to call, enumerated types are introduced so the main program can easily access them, as shown in the following code segment: typedef enum { STAND, RUN, ATTACK, PAIN_A, PAIN_B, PAIN_C, JUMP, FLIP, SALUTE, FALLBACK, WAVE, POINT, 26 CROUCH_STAND, CROUCH_WALK, CROUCH_ATTACK, CROUCH_PAIN, CROUCH_DEATH, DEATH_FALLBACK, DEATH_FALLFORWARD, DEATH_FALLBACKSLOW, BOOM, MAX_ANIMATIONS } animType_t; In addition to draw the frames stored in each sequence, we need to also interpolate between frames to make the animation smooth. The linear interpolation model in the MD2 loader is described in a simple formula: Xinterpolated = Xinital + InterpolationPercent * (Xfinal - X inital) We will be able to create any arbitrary number of intermediate frames necessary for our program to smoothly render the animation. The following figure shows the MD2 model loader rendering a Gunner model in Quake 2: 27 Figure 18 The Gunner model in Quake 2 The following 2 figures show 2 frames in the “Attack” animation sequence: Figure 19 Attack animation: Loading Figure 20 Attack animation: Ready to Fire 28 4 Possible Improvements There are many improvements that can make our game more entertaining. The following list includes some major ones: (a ) Network play: This allows the two human players to play remotely against each other rather than having to be both physically present at one place to play the game. (b) AI: This allows the human player to fight against a computer character, or even allow computer vs. computer gameplay for viewing. This is also potentially useful in team matches. (c) Team Play: This allows more than 2 human players to join the game and form 2 teams to compete with each other. (d) Shadow: The shadow generation of the models will also give the game a more realistic feel of the characters. (e) Skybox: This simulates a more realistic environment for the game field. 29 5 Flow Chart The following figures are the flow charts of the various components of our game engine: Game Graphic Initialization Initialize the camera Load Terrain Load Static models (obstacles/a rrows) Compute texture mapping and lighting properties Load animated MD2 models (Player models) 30 MP Bar Arro No w Shot? Yes Create Arrow MP- - Other MP++ Game Engine No Game Over? Yes Game End 31 HP Bar Shot No by arrow? Yes HP- - Other Game Engine No Is HP = 0? Yes Game End 32