3D Game Programming All In One (2004)
.pdf158 |
Chapter 5 |
■ Game Play |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The new folder tree is |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
the one we will be |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sticking with for the |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rest of the book. We |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
will be adding a cou- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ple more folder nodes |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for specialized fea- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tures in later chap- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ters, but otherwise, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this is the final form. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Modules |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
You will not need to |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type in the root main |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
module again, because |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it won't be any differ- |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ent this time around. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||||||
|
Figure 5.1 |
The Emaga5 folder tree. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In the control branch, |
|||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
the first major differ- |
ence is that the initialize.cs module has been split in two, with a client version and a server version. Each of the new modules is now located in its respective branches—control/serv- er/ and control/client/. They still perform the same tasks as before, but splitting the initialize functions and putting them in their permanent homes prepares us for all our later organizational needs.
There were also the two modules: control/server.cs and control/client.cs. We will now expand these and relocate them as control/server/server.cs and control/client/client.cs, respectively.
The final module from Chapter 4 is player.cs. We will be expanding it greatly and relocating it to control/server/players/player.cs.
Furthermore, we will add several new modules to handle various functional features of the game. We'll address each file as we encounter it in the chapter.
Make sure you have run the EmagaCh5KitInstall program before proceeding, because it creates our folder tree for us.
Control Modules
As before, the control modules are where we focus our game-specific energies. In the root control folder is the control main module. The rest of the code modules are divided
Team LRN
Control Modules |
159 |
between the client and server branches. The data branch is where our art and other data definition resources reside.
control/main.cs
Type in the following code and save it as the control main module at C:\Emaga5\control\main.cs. In order to save on space, there are fewer source code comments than in the last chapter.
//------------------------------------------------------------------------
// control/main.cs
// Copyright (c) 2003 by Kenneth C. Finney. //------------------------------------------------------------------------
Exec("./client/presets.cs");
Exec("./server/presets.cs");
package control { function OnStart()
{
Parent::OnStart();
Echo("\n++++++++++++ Initializing control module ++++++++++++");
Exec("./client/initialize.cs");
Exec("./server/initialize.cs");
InitializeServer(); // Prepare the server-specific aspects
InitializeClient(); // Prepare the client-specific aspects
}
function OnExit()
{
Parent::onExit();
}
}; // Client package
ActivatePackage(control); // Tell TGE to make the client package active
Right off the bat, we can see some new additions. The two Exec statements at the beginning load two files that contain presets. These are script variable assignment statements. We make these assignments here to specify standard or default settings. Some of the variables in those files pertain to graphics settings, others specify input modes, and things like that.
Next we have the control package, which has a few minor changes in its OnStart() function. This is where we load the two new initialization modules and then call the initialization functions for the server and then the client.
Team LRN
160 Chapter 5 ■ Game Play
Client Control Modules
Modules that affect only the client side of the game are contained in the control/client folder tree. The client-specific activities deal with functions like the interface screens and displays, user input, and coordinating game start-up with the server side of the game.
control/client/client.cs
Many features that were in client.cs in the last chapter are now found in other modules. The key mapping and interface screen code that were located in this module, client.cs, have been given homes of their own, as you'll see later. Type in the following code and save it as C:\Emaga5\control\client\client.cs.
//============================================================================
//control/client/client.cs
//Copyright (c) 2003 by Kenneth C. Finney. //============================================================================ function LaunchGame()
{
createServer("SinglePlayer", "control/data/maps/book_ch5.mis"); %conn = new GameConnection(ServerConnection); %conn.setConnectArgs("Reader");
%conn.connectLocal();
}
function ShowMenuScreen()
{
//Start up the client with the menu...
Canvas.setContent( MenuScreen );
Canvas.setCursor("DefaultCursor");
}
function SplashScreenInputCtrl::onInputEvent(%this, %dev, %evt, %make)
{
if(%make)
{
ShowMenuScreen();
}
}
//============================================================================ // stubs //============================================================================ function onServerMessage()
{
}
Team LRN
Client Control Modules |
161 |
function onMissionDownloadPhase1()
{
}
function onPhase1Progress()
{
}
function onPhase1Complete()
{
}
function onMissionDownloadPhase2()
{
}
function onPhase2Progress()
{
}
function onPhase2Complete()
{
}
function onPhase3Complete()
{
}
function onMissionDownloadComplete()
{
}
We've added three new functions, the first of which is LaunchGame(). The code contained should be familiar from Emaga4. This function is executed when the user clicks on the Start Game button on the front menu screen of the game—the other options available on the front screen are Setup and Quit.
Next is ShowMenuScreen(), which is invoked when the user clicks the mouse or hits a key when sitting viewing the splash screen. The code it invokes is also familiar from Emaga4.
The third function, SplashScreenInputCtrl::onInputEvent(), is a callback method used by a GuiInputControl, in this case the SplashScreenInputCtrl, which is attached to the splash screen for the narrow purpose of simply waiting for user input, and when it happens, closing the splash screen. We get the user input value in the %make parameter. Figure 5.2 shows what the splash screen looks like.
The rest of the functions are the by-now-famous stub routines. These are mostly client/server mission (map) loading and coordination functions. These will get more attention in later chapters. You are free to leave out the stub routines, but if you do, you will end up with a ton of warning messages in the log file.
Team LRN
162 Chapter 5 ■ Game Play
Figure 5.2 The Emaga5 splash screen.
new GuiChunkedBitmapCtrl(MenuScreen) { profile = "GuiContentProfile"; horizSizing = "width";
vertSizing = "height"; position = "0 0"; extent = "640 480"; minExtent = "8 8"; visible = "1"; helpTag = "0";
bitmap = "./interfaces/emaga_background"; useVariable = "0";
tile = "0";
new GuiButtonCtrl() {
profile = "GuiButtonProfile"; horizSizing = "right"; vertSizing = "top";
position = "29 300"; extent = "110 20"; minExtent = "8 8"; visible = "1";
command = "LaunchGame();"; helpTag = "0";
text = "Start Game"; groupNum = "-1"; buttonType = "PushButton";
control/client/interfaces- /menuscreen.gui
All of the user interface and display screens now have modules of their own, and they reside in the interfaces branch of the client tree. Note that the extension of these modules is .gui. Functionally, a .gui is the same as a .cs source module. They both can contain any kind of valid script code, and both compile to the .dso binary format. Type in the following code and save it as C:\Emaga5\control\client\interfaces\menuscreen.gui.
Team LRN
Client Control Modules |
163 |
};
new GuiButtonCtrl() {
profile = "GuiButtonProfile"; horizSizing = "right"; vertSizing = "top";
position = "29 350"; extent = "110 20"; minExtent = "8 8"; visible = "1";
command = "Canvas.pushDialog(SetupScreen);"; helpTag = "0";
text = "Setup"; groupNum = "-1";
buttonType = "PushButton";
};
new GuiButtonCtrl() {
profile = "GuiButtonProfile"; horizSizing = "right"; vertSizing = "top";
position = "29 400"; extent = "110 20"; minExtent = "8 8"; visible = "1"; command = "Quit();"; helpTag = "0";
text = "Quit"; groupNum = "-1";
buttonType = "PushButton";
};
};
What we have here is a hierarchical definition of nested objects. The outer object that contains the others is the MenuScreen itself, defined as a GuiChunkedBitmapCtrl. Many video cards have texture size limits; for some nothing over 512 pixels by 512 pixels can be used. The ChunkedBitmap splits large textures into sections to avoid these limitations. This is usually used for large 640 by 480 or 800 by 600 background artwork.
MenuScreen has a profile property of GuiContentProfile, which is a standard Torque profile for large controls that will contain other controls. Profiles are collections of properties that can be applied in bulk to interface (or gui) objects. Profiles are much like style sheets (which you will be familiar with if you do any HTML programming), but using Torque Script syntax.
Team LRN
164Chapter 5 ■ Game Play
The definition of GuiContentProfile is pretty simple:
if(!IsObject(GuiContentProfile)) new GuiControlProfile (GuiContentProfile)
{
opaque = true;
fillColor = "255 255 255";
};
Basically, the object is opaque (no transparency allowed, even if an alpha channel exists in the object's source bitmap image). If the object doesn't fill the screen, then the unused screen space is filled with black (RGB = 255 255 255).
After the profile, the sizing and position information properties are set. See the sidebar titled "Profile Sizing Settings: horizSizing and vertSizing" for more information.
The extent property defines the horizontal and vertical dimensions of MenuScreen. The minExtent property specifies the smallest size that the object can have.
The visible property indicates whether the object can be scene on the screen. Using a "1" will make the object visible; a "0" will make it invisible.
The last significant property is the bitmap property—this specifies what bitmap image will be used for the background image of the object.
There are three GuiButtonCtrl objects contained in the MenuScreen. Most of the properties are the same as found in the GuiChunkedBitmapCtrl. But there are a few that are different
and important.
|
The first is the command proper- |
|
ty. When the user clicks this |
|
button control, the function |
|
specified in the command proper- |
|
ty is executed. |
|
Next, the text property is where |
|
you can enter the text label that |
|
will appear on the button. |
|
Finally, the buttonType property |
|
is how you specify the particular |
|
visual style of the button. |
|
Figure 5.3 shows the MenuScreen |
Figure 5.3 The Emaga5 MenuScreen. |
in all its glory. |
Team LRN
Client Control Modules |
165 |
Profile Sizing Settings: horizSizing and vertSizing
These settings are used to define how to resize or reposition an object when the object's container is resized. The outermost container is the Canvas; it will have a starting size of 640 pixels by 480 pixels. The Canvas and all of the objects within it will be resized or repositioned from this initial size.
When you resize a container, all of its child objects are resized and repositioned according to their horizSizing and vertSizing properties. The resizing action will be applied in a cascading manner to all subobjects in the object hierarchy.
The following property values are available:
Center |
The object is positioned in the center of its container. |
Relative |
The object is resized and repositioned to maintain the same size and position relative |
|
to its container. If the parent size doubles, the object's size doubles as well. |
Left |
When the container is resized or moved, the change is applied to the distance between |
|
the object and the left edge of the screen. |
Right |
When the container is resized or moved, the change is applied to the distance between |
|
the object and the right edge of the screen. |
Top |
When the container is resized or moved, the change is applied to the distance between |
|
the object and the top edge of the screen. |
Bottom |
When the container is resized or moved, the change is applied to the distance between |
|
the object and the bottom edge of the screen. |
Width |
When the container is resized or moved, the change is applied to the extents of the |
|
object. |
Height |
When the container is resized or moved, the change is applied to the extents of the |
|
object itself. |
control/client/interfaces/playerinterface.gui
The PlayerInterface control is the interface that is used during the game to display information in real time. The Canvas is the container for PlayerInterface. Type in the following code and save it as C:\Emaga5\control\client\interfaces\playerinterface.gui.
new GameTSCtrl(PlayerInterface) { profile = "GuiContentProfile"; horizSizing = "right"; vertSizing = "bottom"; position = "0 0";
extent = "640 480";
Team LRN
166 Chapter 5 ■ Game Play
minExtent = "8 8"; visible = "1"; helpTag = "0";
noCursor = "1";
new GuiCrossHairHud() {
profile = "GuiDefaultProfile"; horizSizing = "center"; vertSizing = "center"; position = "304 224";
extent = "32 32"; minExtent = "8 8"; visible = "1"; helpTag = "0";
bitmap = "./interfaces/emaga_gunsight"; wrap = "0";
damageFillColor = "0.000000 1.000000 0.000000 1.000000"; damageFrameColor = "1.000000 0.600000 0.000000 1.000000"; damageRect = "50 4";
damageOffset = "0 10";
};
new GuiHealthBarHud() {
profile = "GuiDefaultProfile"; horizSizing = "right"; vertSizing = "top";
position = "14 315"; extent = "26 138"; minExtent = "8 8"; visible = "1"; helpTag = "0"; showFill = "1"; displayEnergy = "0"; showFrame = "1";
fillColor = "0.000000 0.000000 0.000000 0.500000"; frameColor = "0.000000 1.000000 0.000000 0.000000"; damageFillColor = "0.800000 0.000000 0.000000 1.000000"; pulseRate = "1000";
pulseThreshold = "0.5"; value = "1";
};
new GuiBitmapCtrl() {
profile = "GuiDefaultProfile"; horizSizing = "right";
Team LRN
Client Control Modules |
167 |
vertSizing = "top"; position = "11 299"; extent = "32 172"; minExtent = "8 8"; visible = "1"; helpTag = "0";
bitmap = "./interfaces/emaga_healthwidget"; wrap = "0";
};
new GuiHealthBarHud() {
profile = "GuiDefaultProfile"; horizSizing = "right"; vertSizing = "top";
position = "53 315"; extent = "26 138"; minExtent = "8 8"; visible = "1"; helpTag = "0"; showFill = "1"; displayEnergy = "1"; showFrame = "1";
fillColor = "0.000000 0.000000 0.000000 0.500000"; frameColor = "0.000000 1.000000 0.000000 0.000000"; damageFillColor = "0.000000 0.000000 0.800000 1.000000"; pulseRate = "1000";
pulseThreshold = "0.5"; value = "1";
};
new GuiBitmapCtrl() {
profile = "GuiDefaultProfile"; horizSizing = "right"; vertSizing = "top";
position = "50 299"; extent = "32 172"; minExtent = "8 8"; visible = "1"; helpTag = "0";
bitmap = "./interfaces/emaga_healthwidget"; wrap = "0";
};
new GuiTextCtrl(scorelabel) { profile = "ScoreTextProfile"; horizSizing = "right";
Team LRN