directory structureD3DDrv.dll GBSPLib.dll Genesis.dll GlideDrv.dll SoftDrv.dll softdrv2.dll Zapp.h ZCamera.h ZPlayer.h InitGenesis.cpp MainLoop.cpp ProjectZ.cpp ZApp.cpp ZCamera.cpp Zplayer.cpp all genesis actor files all genesis include files all genesis level files all genesis library files /////////////////////////////////// // program flow ////////////////////////////////// WinMain App = new ZApp App->InitApp create window show window InitGenesis() create genesis engine load genesis driver set gamma create Camera LoadLevel Create the player character SetTimer GetMessage Loop WinProc WM_CREATE - hide cursor WM_TIMER - MainLoop() WM_MOUSEMOVE - App->SetMouse(x,y) WM_DESTROY - WM_KEYDOWN VK_ESCAPE Cleanup Cleanup delete(App) App->Cleanup Camera World Engine MainLoop move the player character set the camera to the player eye height render the world ** version 2.01 - It Starts basically the ZApp class handles all of the window initialization and the GENESIS specific initialization, then the program just waits for the user to press the escape key and it exits. nothing pretty, but you should see the GENESIS logo. it is an example of how to initialize GENESIS. Items to experiment with in the ZApp constructor change the values of the window size variables to see the window size change, also change from windowed mode to fullscreen mode, however if you do go fullscreen make sure your width and height is 640x480 or 800x600 or it'll crash. ** version 2.02 - we add the world moved InitGenesis code to it's own file. it is still part of the ZApp class but moving it makes it easier to find and it unclutters the ZApp .cpp file. added levels directory to the project directory. it contains the GENESIS level files in .bsp format added the world variable to the ZApp class. the world is the main GENESIS structure. it contains everything related to the 3d view you can render, it contains the map, the lights, the actors, everything. added the camera to the ZApp class. the camera is a definition of how we want to view the world when we render it. for example, do we want it to take up the entire screen or just a portion of it. keep in mind that we dont support movement in this example, just loading a level and displaying it. Items to experiment with try loading a different map by changing the filename in the ZApp::InitApp() function. make sure to include the entire path to the map file and the .bsp extension. for example "\\levels\\mymap.bsp" enter an invalid map name to see how the error handling can detect and help you understand what failed by showing messageboxes all the way from the loadlevel function back to the winmain function. you should see messages saying loadlevel failed, then initapp failed, and then winmain failed. it is very easy to debug this way. try different FOV values for the camera to make it zoom in and out by changing the value of fov in the Camera->Create() function ** version 2.03 we can move! In order to add movement to our little demo, we first have to determine WHAT we are moving? Are we moving the world? Are we moving the camera? Are we moving a player? of course we eventually move the camera, but it makes things easier if we pretend we have a player in the game and that we are moving HIM around the world. We do this by adding another class to our demo, this one is called ZPlayer. ZPlayer represents an invisible character in our game that can walk, run and jump. in a later demo we will add a visual actor for our player, but for now just think of him as invisible. added class ZPlayer. limited functionality for this demo. movement restricted to movehead() only interface is sloppy in that creation requires knowledge of screen size. added ZPlayer variable to ZApp class. instantiated in ZApp::InitApp Destroyed in ZApp::Cleanup Utilized in MainLoop Items to experiment with try changing the MouseSensitivity value in ZApp to see what effect it has on the Player head movement. try changing the value of the camera FOV as in the previous demo, now it will make the change more noticable. ** version 2.04 gravity takes hold ok so we can move our player's head around, now it's time to move the body. first we'll start with a description of the movement technique and then write our code. movement inside a genesis world consists of many parts, these parts are as listed.... remember where you started attempt to move check for collision with world stuff between where you started and where you are trying to go react to the collision if you hit something stop, step up, or slide the thing to remember is that it doesnt matter which way you are moving, forward, backward, left, right, up, down.. it's all done the same way. this demo will provide basic movement in all directions. added movement code to ZPlayer class MoveForward() MoveBackward() MoveStrafeLeft() MoveStrafeRight() ApplyGravity() added code to move player to a good starting position added code to raise camera to player eye level in order to use the keyboard to move our plpayer around , we need a function the will detect keypresses. we will call this function iskeydown() and it will be used in the MainLoop added BOOL IsKeyDown(int VK_CODE) function in ZApp class Items to experiment with change the speed of the ZPlayer object. change the gravityspeed of the ZPlayer object. reprogram the VK_?? keys to different values to use different keys for movement ** version 2.05 A better movement mousetrap you may have noticed that our movement code isnt perfect. for example, when we hit a wall we just stop. this isnt good enough, when we hit a wall we should slide along that wall if needed. Genesis provides us with the needed information in the m_Collision structure. Also, we can currently walk DOWN ramps, but we cant walk Up them. the reason is that the ramp is detected as a collision by genesis, in reality it IS a collision, however, we dont want to treat it as a collision. We trick genesis into doing this by moving Up slightly and then moving forward. then if we hit a wall we let gravity bring us back down, and it will allow us to walk up the ramps. you might have also noticed that we can walk through the corners of some walls, we take care of that by one more collision detection. rearranged ZPlayer movement code to make it more modular added code in ZPlayer class movement code to allow sliding during movement Items to experiment with change the speed of the ZPlayer object. change the gravityspeed of the ZPlayer object. reprogram the VK_?? keys to different values to use different keys for movement ** version 2.06 Adding the Actor this time around we add an actor. we'll use the dema.act file as our test actor. since the actor is really just a visual in the demo and GENESIS can take care of most of the work, it will be fairly easy to implement. all of our changes take place in the ZPlayer code and basically goes like this. during the creation of the player, load an animation file (dema.act) and setup the bounding box (still hard coded values). then simply keep track of what animation we need and animate every loop of the mainloop. added actors directory to main program directory added code for actor loading in ZPlayer class added State variable for tracking actor movement style added code for actor animation in ZPlayer class Items to experiment with changing the file used for the animation can be done, however, whatever file you choose must have the walk animation defined or the program will crash. for example, you cannot use Armor.act as the player actor because it doesnt have any animations in it. version 2.07 ** Adding the Doors adding the doors requires a little explanation about the map files and how doors are stored in them. genesis allows us to add any item we wish into the map files. literally anything we wish! we simply define the item we want in a manner that the genesis map editor can understand, and then it will store the information in the map itself, and we can retrieve the information anytime we desire. A door is simply another object to genesis and it is defined like this in the genvs.h file // Door #pragma GE_Type("Model.ico") typedef struct Door { #pragma GE_Published geWorld_Model *Model; geVec3d Origin; #pragma GE_Origin(Origin) } Door; we add the code to decode this structure and we call the door manipulation routine every loop before we render the world. added entities.h file to project added entities.cpp file to project added ZDoor structure version 2.08 ** Adding more Entities adding entities to the world is exactly the same as adding doors. Just define them so the map editor can use them, add them to the world via the map editor, and then decode them at runtime. for this example we'll add a few items to a default map that I made. it is just one room, but it contains many entities. changed default map to mytest.bsp added entity defines to entities.h file added code to decode the entities in ZApp version 2.09 ** Collision Detection! the next order of business for us has to be collision detection of the new objects that we just added, and in order to do this, we need to create bounding boxes for all of our items. remember that a bounding box is the smallest box that can contain our actor. genesis has provided a nice little utility for showing us the bounding box. it is a function called DrawBoundBox and is located in the file drawbbox.c. i renamed the file drawbbox.cpp :) and added it to the project. now i predeclare the function in the entities.h file so we can call it, then i added bounding box code to each Init(whatever) function and then call the drawbbox during the rotate(whatever) function. WHEW! version 2.10 ** Easier Entities lets make adding entities a little easier by creating a base class called ZObject from which all entities will be derived. by doing this we can put all of the creation, movement, rendering etc.. into the base object class and then all of our objects will automatically have all these functions avaialable. we also need to create a quick and dirty array class to hold all of our objects, we'll call it ZObjectsArray and put one instance in the ZApp class to hold all of our entities in one place. first things first we delete all of the Init functions in the ZEntities file because we can do it better in the ZObject class contructor. version 2.11 ** A Better Player ok, since we created an object class, this time we rewrite the ZPlayer class to be derived from the ZObject class. we do this so that all of the actions that can be done on an object can automatically be done to the player also.