The Matrix, the README: "No one can tell you what the Matrix is...you have to see it for yourself." Don Hoffman, Billy Hewlett Built with Visual C++ 6.0 for Windows 95/98 Requires include of: Winmm.lib Opengl32.lib Glu32.lib Glaux.lib Note that the Matrix and MoveEditor are separate C projects for building. Running The Matrix: The Matrix runs under Windows 95/98 All wav, bmp, and txt data files must be in the same directory as the executables. To play the Matrix, double click on "Matrix.exe" To run the move editor double click on "MoveEdit.exe" The moves are stored in "movefile.exe" The move structure is stored in "fafile.txt" Game play for The Matrix The basic idea of the Matrix is to kill all of the other enemies while not being shot. The basic commands are "W" walk "A" turn left "D" turn right "S" back up "Z" cartwheel left "C" cartwheel right "X" backflip In addition, pressing walk and turn left (right) together performs a turning walk and pressing back and turn left (right) performs a spin move. In addition, the mouse controls where the arms point for shooting. The arms are relative to Neo (obviously) so if Neo facing the screen, moving the mouse left will make his arms appear to move right. If you let go of the mouse, the arms will eventually reset themselves to the animation of the current move. To shoot, press the left mouse button. If you hold the left mouse button down Neo will continue to shoot until you release it. To activate slow-mo, press and hold the right mouse button. This causes Neo to move at 1/2 the speed and enemies to move at 1/10 speed. Since Neo already moves almost twice as fast as the enemies, this is very noticeable. To turn invisible, press and hold the space bar. Being invisible means that the enemies can't see you, but one of the enemies most common tactics is to shoot where they last saw you, so staying in one spot and turning invisible is not recommended. Both invisibility and slow-mo are limited. If you use them too much they will not work. Over time the ability to cause slow-mo and to become invisible comes back. Pressing "Enter" re-spawns Neo to full health, but it also revives all enemies. "Escape" quits. Hints on Game Play: Hide behind the columns. Use back-flip and cartwheels and the spin moves a lot. Turn invisible and move away when the enemy knows where you are. Use slow-mo and cartwheel around the enemy while shooting. Move Editor (for advanced users): To edit moves, open the move editor. The purple figure that you see represents Neo. To change the camera angle, use the arrow keys. To change the zoom, use the "page up" and "page down" keys. The following are the keys for the move editor: "Q" Put Neo in animation mode. You can tell when Neo is in animation mode because his body changes color While not in animation mode: "T","R","F","G","V","B" Rotate Neo "Y","U","H","J","N","M" Translate Neo 1...9 Select limb. "W","A", "S","D" Rotate selected limb "E" Save current position as waypoint While in animation mode or not in animation mode: "L" Write current animation to movefile "I" Clear animations "K" Reset Neo "O" Toggle absolute mode "X" speed up animations "C" original speed for animations Escape quits While in animation mode, the same keys that control Neo in the game all apply. (i.e. "W" is walk, ect.) For example, try selecting Neo's upper arm by clicking "1." Move it around with the "WASD" keys. Press "E" to remember the position. Move it around some more with the "WASD" keys. Click "E" again. Now hit "Q." Neo should move his arms between the positions you have selected. If you press "L" Neo's new arm-waving move will be written to the move file and the fafile. The Move File While the move editor is extremely useful in creating Neo's moves, sometimes it is necessary to manually change Neo's moves in the movefile or fafile. Before you do it is highly recommended that you make a copy of both files (as there is no error checking). Open movefile.txt. The format of the move file is Move_Name Number_of_Waypoints Speed_of_Waypoint_1 Speed_of_Waypoint_2 ... Limb 1 angle 1, Limb1 angle 2, Limb 2 angle 1... Limb 8 angle 8, Neo X, Neo Y, Neo Z, Neo X Angle, Neo Y angle, Neo Z angle. Neo X, Neo Y and Neo Y angle are always relative, while all other values are absolute, so 0,0,0,0...4,0,0,0,0,0 moves Neo 4 units forward every time this way point is reached. Look at the other moves for examples. The FA File The fa file stores the finite autonoma that describes how Neo's moves are linked together. The format is " move_name1 -> move_name2 key flag" If you press key and Neo is in position move_name1, Neo will go to move_name2 The flag commands: 1 or 2 if key is pressed go to this move 3 or 4 whenever key is not pressed go to this move 1 and 3 go to the beginning of the next move, while 2 and 4 maintain the current waypoint number, which is useful, for example, when you want to go from walking to walking while turning but you don't start the walking animation over. Do not use flags 2 or 4 unless both the starting and ending moves have the same number of waypoints. In addition, if the number zero is used as a key, the first move will go to the second after completing (regardless of flag) It is recommended that you study how the current moves work in the movefile and fafile before adding your own. Every move in the fafile must appear in the movefile and every move in the move file must appear in the fafile. Advanced Requirements: --------------------------------------- 1) Move Editor (see above). 2) AI The basic idea of the AI is that the enemies try to find you and then they try to shoot you. When an enemy learns of your location, every enemy knows where you are. If no enemy sees you, they remember the last place you were seen. (For example if Neo turns invisible or hides behind columns) There are basically three states, with different enemy behaviors for each state: State 1: The enemy can see you The enemy turns towards you and shoots at you. State 2: The enemy can't see you and has reached your last known location The enemy randomly turns left, turns right, or walks forward. State 3: The enemy can't see you but has not reached your last known location The enemy randomly chooses between turning and walking, turning towards your last location and shooting, or walking toward your last known location It turns out that shooting where Neo last was is a pretty effective strategy, typically pinning Neo behind a column. In addition, if the enemy notices that another enemy is in its line of fire it won't fire. This cuts down on friendly fire a lot, but does not eliminate it, for example if one enemy fires and then another enemy moves into the bullet's path. There are several reasons that the enemies AI is designed as described. First of all, the random state changes assure that an enemy can eventually work itself out from corners or from behind columns. (In CS224 I learned that random movement is actually one of the most effective ways for a robot to escape from constrained positions). Secondly, the AI does not dodge or take cover. In the Matrix, Neo can move much more quickly then enemies can, and because of this dodging is pretty ineffective for them. (Check out the move speeds in the fafile) In addition, with the large number of enemies (5) and the small number of Neos (1), it is usually most effective to shoot Neo rather then try to dodge. The enemy uses the same move generation and fafile that Neo does, but uses dude_walk, dude_turn_left, and other "dude" moves. 3) Sound Bullets firing and impacting with different objects cause related sounds to be played. Enemies sighting Neo also cause a sound to be played. 4) Collision Detection All objects collision detect with walls & columns by determining if the current motion will make them cross the plane defined by a given object's side bullets also collision detect with characters in the same way, with the character 'space' defined by a basic bounding box around the character. The camera collision detects with walls and columns when it is near Neo, as it is at all times except during a respawn. Other Special Features ---------------------------------- While the assignment handout suggests the special features described above, we feel the following features are least as difficult and should also be considered "special features" as well (for extra credit, since we have the requisite 2 * N features) 1) "Smart" Camera The camera is a slow-camera style, which tries to float above and behind Neo's head. It lags behind his motion, however, so that he moves slightly faster than it does, making it look like a floating camera, rather than a camera mounted on his shoulder. It also swings around in front of him rather than colliding with walls and columns. This was designed to look cool should he be shot at while hiding behind a column once we get particle clouds working for when bullets hit walls & columns. 2) Full Skeletal Animation (including some hierarchical scene mapping) The Neo pipeline: First, we started with a Neo model from Quake2 in .mdb format. Then we converted it to a display list using "3D Exploration," from http://www.xdsoft.com/explorer/. Next we try to choose which vertices are part of the torso, upper left arm, lower left arm, ect. As there are over 500 vertices in the Neo model, this required a significant amount of work. Next we figured out where each joint should be. Then we rotated the limbs so that they matched the "start" position in the move creator. Each triangle that fit within a limb was stored in a display list, while triangles whose vertices were in more then one limb were stored in a giant array. To draw Neo, we translate to Neo's location and rotation, and then draw the torso display list. Then we translate to where Neo's upper left arm should be and then rotate. Then we translate to where Neo's lower left arm should be and draw that. This assures that rotations of the lower arm are relative to rotations of the rotations of the upper arm. (A limited form of Hierarchical Scene Mapping) As we do this, we keep track of each of the rotation/position matrices for each limb. Finally, we connect joint triangles by multiplying each vertex by its respective rotation/position matrix. This assures that we have no holes in joints, and that they move somewhat realistically. (That is, the triangles on the top of Neo's knee will stretch as Neo bends his lower leg backwards, while the triangles on the underside will scrunch.) When The Matrix starts up, we store each of the moves in a hash table (the hash table is from cs140, but heavily modified). Then we load the fafile and store it as a mapped linked list, with links between moves that follow each other. The current position of each limb of each character is known, as well as delta movement and target position in each joint, angle, and direction. A "move" is a series of waypoints, such as "leg backwards" and "leg forward". Once all limbs have reached their current target position, the next waypoint is loaded as the next target position. Then the next delta move is calculated and the animation resumes. When the user presses a key, we look at what state Neo is in and what the key should do. If the fafile (now stored in memory) says to change to a new state, we change the current set of waypoints to that new state, and animate towards the first waypoint of the new state. External code sources: ---------------------- We based our windows interaction code around that written by Jeff Molofee for his www.demonews.com/hosted/nehe tutorials. We decided not to use GLUT at all. Content: -------- The 3D character model: the Shotgun Messiah Quake2 model by Mike McMillen The Neo skin: Quake2 skin for above model by Rinoa Heartilly Background textures: Wall texture from basic Quake2 texture list, by Id software floor texture made by combining and editing various marble textures found at free texture sites online Sound effects were sampled directly from The Matrix DVD.