This week's lab is an introduction to GameX. We'll learn how to use GameX, in the Visual Studio .NET environment, to make a basic game by compiling a sample program called ShipDemo, and then modify it in various ways.
You may work in groups of 2 or 3. This lab is not due during this lab period, but it is to your advantage to work through as much as you can now, while assistance is immediately available. If you run into problems finishing the lab project later, please free to contact any of the TAs for help.
Getting Started Using GameX with VS.NET
The GameX official homepage is http://www.rchoetzlein.com/gamex/ (but you should use the mirror at www.cs.cornell.edu/projects/game/GameX/). There you will find an overview of GameX and a description of its interface. It also has links to download GameX and the ShipDemo. Even if these are already on your machine, you should download and unzip "GameXR5Pack.zip" from the Downloads section of the Cornell mirror site, otherwise you may not have the correct versions. For this lab we will be using GameX version 5.05.
The first time you run Visual Studio .NET, it may prompt you with various questions about what kind of environment you want. I recommend you indicate you are a C++ developer.
We could just load the ShipDemo solution from the project file, but let's recreate the project for practice:
1) From the file menu, select a new project, and choose Win32 project under Visual C++ projects. Make sure you choose the location you want for the project (the default is fine as long as you know where it is). Name the project "MyShipDemo".
2) After hitting OK, in the next window go to the application settings tab, and make sure "Windows Application" and "Empty Project" are both checked. (NOTE: This step is very easy to forget, but your project will initially fail to compile if you don't do it.)
3) We need to specify the directories that VC++ will find the GameX files in. In the Tools menu, select Options. Under Projects->VC++ Directories, Select "Include files" in the pull-down menu, and the directories for GameX (wherever you put it on the machine, for instance "Z:\GameXR5Pack\GameXR5"). Then select "Library files" from the pull-down, and add the same GameX directory there too. Alternatively, if you want these changes to be saved within your project so you don't need to make them every time you switch to a new computer, you can set GameX as an include and library directory in your project properties: Right-click on the Project (not the solution) in the "Solution Explorer" pane and choose Properties, change Configuration to "All Configurations", then set the C/C++ -> General -> Additional Include Directories field and the Linker -> General -> Additional Library Directories field to the same GameX directory.
4) You'll now have an empty project. Now we need to add the source and header files. First, physically copy the .cpp and .hpp files into whatever directory your project is in (so we're using fresh copies of the code, rather than just the original code files). You'll also need to copy the Images folder and Sounds folder into that same directory. Then you can add the source files by either dragging them to the Source (or Header) files folder on the left side of the development environment, or by right-clicking on the Source (or Header) Files folder item and choosing "Add Existing Item" to browse for files to add. Add the three .cpp files to the Source Files, and the two .hpp files to the Header Files.
5) Make sure your display is set to 16-bit color so that your game will start up faster. Then compile and run the demo by hitting F5.
For future reference: Pressing Shift-F5 from VS.NET will immediately stop your game from running even if it has crashed or frozen, F9 adds/removes breakpoints, F10 steps (runs one line), F11 steps into a function call, Shift-F11 steps out of a function, and F5 continues (or starts) running normally (with debugging). Also, Ctrl-Shift-S can be used to save everything at once (all open code files, project settings, etc.).
Lab Project
To help get familiarized with how GameX works, we're going to be making a series of modifications to ShipDemo. Before doing so, it might be helpful to look through the code and see how it works. The GameX official page details a good chunk of similar code in its examples. After you understand the code to some degree, make the following changes (in the order given):
1) In shipdemox-main.cpp, add an extra parameter (an int of 60) to the call to GameX.Initialize, right after the parameter that starts as 400. If you run the game now, there should be no change. Now change the 60 to different values such as 100, 30, 600, and 5. Describe briefly what happens, i.e. the effect these have on the gameplay and/or graphics (in a file called readme.txt you will submit later). Leave the extra parameter at 60. If you wish to know more about what GameX is doing here, see the section "About Game Speed and Frame Rate" in the GameX documentation.
2) Modify the size of the game window, which starts as 800x400. Try several sizes, including 400x300, 100x1000, and 2000x2000, to see what happens. Try running the game in both windowed and full-screen mode for the various sizes, and fly the ship around and fire a little for each one. How do the ships and photons know to change where they bounce off of when you change the size of the screen? Does the game perform worse and/or look worse with some sizes than others? Is there a minimum or maximum size? Is there a "best" width to height ratio, and if so, in what way is it best? (Answer these questions either now or later, in your readme.txt.) Leave the game window set to 800x600 when done.
3) In shipdemox-ship.cpp, in the Ship::Draw method, change the size of the ships by changing each "1.25f" to a different value, and describe what the trend is for what different values do. Make sure to change the size of the ship's shadow by the same amount you change the size of the ship. Leave the size at 150% of normal, and also change the collision detection radius of the ships accordingly to be 150% of what it was before. The collision detection code is in the same file, in the Ship::CollideCheck method.
4) Implement "wrap-around" (this means when an object hits the edge of the playfield, it should keep going and reappear on the other side). To do this you may want to modify the lifespan of shots, and you may want to implement a "max speed" for the ships (perhaps by changing the "drag" to always affect them even when they are accelerating). Also, be aware that there are "clipping" issues: ideally you want a ship that's in the process of wrapping around to be drawn partially on one side, and partially on the other, which you can do by drawing the image twice (once on each side of the screen) for each screen edge that it is near. Don't worry if you can't get this working quite right yet, but try to get it working as well as possible.
5) In Photons::Draw, you will notice the constant DRAW_ADD is used. Look this constant up in the GameX documentation, and in the code, replace DRAW_ADD one-at-a-time with each of the other nine Image Drawing Mode constants such as DRAW_PLAIN and DRAW_BURN, and try them all out in separate runs of the game. Describe (in readme.txt) what visual effect each one causes as best as you can (including DRAW_ADD). Also, set the ships (but not their shadows) to draw with DRAW_ADD (in the Ship::Draw method of shipdemox-ship.cpp), and describe the effect. You do not need to test any of the constants starting with DRAWOP, although these are useful too. Return the ship to normal and the photon drawing constant to DRAW_ADD when you are done testing the drawing modes, or you can leave them as whatever you think makes the game look better.
6) Change the shots to fade out as they get older, so they don't seem to suddenly disappear when they are removed. Hint: Use "SetDrawShading". Also, make the shots look better by doing some or all of the following: Make them spin quickly using SetDrawAngle. Make certain color components fade out faster than others. Draw each shot an extra time with a larger size (try 4x) and lower or faster-fading opacity to make for a glowing light effect around each photon.
7) Implement collisions for shots. Make each connecting photon disappear, and also make it knock back the ship a little if you can. Make sure each ship is immune to its own photons (you might want to wait until part of question #10 below is done before doing this last part).
8) Change the blue ship (but not the red ship) to play its photon firing sound at a slightly lower frequency/pitch, such as 75% of normal. See the GameX documentation about playing sounds for information on how to do this. Also, make the photon sound "pan" (for both ships) depending on the x location of the ship that fired it (make sure it fades smoothly from left to middle to right).
9) Comment out the line of code that draws the background, run the game and describe what happens, then un-comment the background-drawing code to re-enable it. Change the appearance of the background (hopefully to something you think looks better or interesting) by running one or several of GameX's image filters on it when it is first loaded. See section 10 of the GameX documentation for details of how to do this. Also, remove the translation offsets given to DrawTiled and call GameX.SetDrawAngle beforehand with a changing angle value to make the background spin, but *please* make sure it spins very slowly, such as 1/100th of a degree every game loop. You can use GameX.GetGlobalCounter to get a value that increases continuously, which you can modify to be the changing rotation angle. A common problem you may encounter is that it spins jerkily or doesn't seem to spin continuously, in which case you probably forgot to cast to float or double before dividing (and so were unintentionally performing integer division). Finally, make the background drawn shaded with a high degree of transparency (i.e. low alpha such as 32 or 64) and describe what happens and why you think it's happening (it's related to the very first thing you did for this question #9). Leave the background this way, with all of these changes in effect at once. This will probably change the way your photons look, such as by obliterating most visible details inside them, in which case go back and change how photons are drawn so that they look more like they did before the background change. (Reducing their brightness may be enough.)
10) Change the red ship (but not the blue ship) to fire lasers instead of photons. Do this by giving the Photon struct an extra variable called "type", and changing AddPhoton to take in and assign the photon type. The red ship should then be made to add photons of a different "type" than the blue ship does. Once this is done, change the Photons::Draw function to draw the photons of the blue ship's type the same way as before, but to draw the photons of the red ship's type in a different way so they look like laser beams. To draw the "lasers", use the GameX.DrawLine function and any color or drawing mode you think looks best. Note that, since DrawLine takes two sets of (x,y) coordinates, you will need to decide on where the laser beam starts and where it ends. You could change the photons to keep track of some previous positions, but an easier way in this case is to subtract the photon's velocity from it's current position to come up with a second point's coordinates, and draw the line from that point to the current position. If the laser beam is too short, multiply the velocity when you subtract it by a higher number until the beam looks adequately long. If the laser beam is too thin, call GameX.SetDrawScale(width_in_pixels) before the call to DrawLine. If you want to try making the laser beams look prettier, you may use DrawLineImage (with the photon image) instead of DrawLine, but you must pass in "true" as the extra/optional parameter of DrawLineImage so that it still looks line-like.
11) Change a ship's controls so that moving the mouse leftward turns the ship counter-clockwise, moving the mouse right turns the ship clockwise, moving the mouse up accelerates forward, moving the mouse down accelerates backward, and left-click fires the photons. Make sure the ship does not respond hypersensitively to mouse movement, but moving the mouse quickly should cause more of a reaction than moving it slowly. Also make sure that you can hold down the mouse button for rapid-fire as it was before. As much as possible, make the mouse control "feel natural" to use, which can be achieved with some tweaking (changes elsewhere to turning speed etc. may be necessary). See the GameX documentation for information about getting mouse input with GameX.
This might seem like a lot of tasks, but hopefully you will find all of them reasonably simple and straightforward. To turn in the lab, hand in (using CMS) your code which completes all eleven tasks at once, along with a readme that answers questions and describes anything directly asked in the above tasks, and also describes how you handled each task and where in the code it was handled. You should submit the following files:
For this first lab, you may NOT add or change (or submit) any graphics files or sound files, however.
Please hand hand in one combined lab for your group. This will require you to make a group in CMS.
This lab project is due Friday, February 11th by 11:59pm (midnight).