Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 30 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
30
Dung lượng
437,66 KB
Nội dung
if (%scale < 5.0) // and hasn't gotten too big
%scale += 0.3; // make it bigger
else
$grow = false; // if it's too big, don't let it grow more
}
else // if it's shrinking
{
if (%scale > 3.0) // and isn't too small
%scale -= 0.3; // then make it smaller
else
$grow = true; // if it's too small, don't let it grow smaller
}
%shape.setScale(%scale SPC %scale SPC %scale);
%shape.setTransform(%lx SPC %ly SPC %lz SPC %rx SPC %ry SPC %rz SPC %rd);
schedule(200,0,AnimShape, %shape, %dist, %angle, %scale);
}
function DoAnimTest()
//
// a function to tie together the instantiation
// and the movement in one easy to type function
// call.
//
{
%as = InsertTestShape();
$grow = true;
AnimShape(%as,0.2, Ϫ1, Ϫ2);
}
This module is almost identical to the
MoveShape()
module we worked with earlier.
The function
AnimShape
accepts a shape handle in
%shape
, a distance step as
%dist
, an angle
value as
%angle
, and a scaling value as
%scale
and uses these to transform the shape indi-
cated by the
%shape
handle.
First, it obtains the current position of the shape using the
%shape.getTransform()
method
of the Item class.
As with the earlier
MoveShape()
function, the
AnimShape()
function fetches the transform of
the shape and updates one of the axis values.
Then it updates the rotation value stored
%rd
.
3D Programming 117
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Then it adjusts the scale value by determining if the shape is growing or shrinking.
Depending on which way the size is changing, the scale is incremented, unless the scale
exceeds the too large or too small limits. When a limit is exceeded, the change direction is
reversed.
Next, the scale of the shape is changed to the new values using the
%shape.setScale()
method for the shape.
Finally, the function sets the item's transform to be the new transform values within the
%shape.setTransform()
statement.
The
DoAnimTest()
function first inserts the new instance of the shape object using the
InsertTestShape()
function and saves the handle to the new object in the variable
%as
.It
then calls the
AnimShape()
function, specifying which shape to animate by passing in the
handle to the shape as the first argument and also indicating the discrete movement step
distance, the discrete rotation angle, and the discrete size change value with the second,
third, and fourth arguments.
To use the program, follow these steps:
1. Make sure you've saved the file as 3DGPAi1\CH3\animshape.cs.
2. Run the Chapter 3 demo using the shortcut in the 3DGPAi1 folder.
3. Press the Start button when the demo screen comes up.
4. Make sure you don't move your player-character after it spawns into the game
world.
5. Bring up the console window.
6. Type in the following, and press Enter after the semicolon:
exec("CH3/animshape.cs");
You should get a response in the console window similar to this:
Compiling CH3/animshape.cs
Loading compiled script CH3/animshape.cs.
This means that the Torque Engine has compiled your program and then loaded it
into memory. The datablock definition and the three functions are in memory,
waiting to be used.
7. Now, type the following into the console, and close the console quickly afterward:
DoAnimTest();
What you should see now is the heart dropping from the air to the ground; it then
begins moving away from you toward the right. Go chase after it if you like, to get
a sense of how fast it is moving.
Chapter 3
■
3D Programming Concepts118
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Go ahead and experiment with the program. Try moving the item through several axes at
once, or try changing the distance.
3D Audio
Environmental sounds with a 3D component contribute greatly to the immersive aspect
of a game by providing positional cues that mimic the way sounds happen in real life.
We can control 3D audio in the scene in much the same way we do 3D visual objects.
Type the following program and save it as 3DGPAi1\CH3\animaudio.cs.
// ========================================================================
// animaudio.cs
//
// This module contains the definition of an audio emitter, which uses
// a synthetic water drop sound. It also contains functions for placing
// the test emitter in the game world and moving the emitter.
// ========================================================================
datablock AudioProfile(TestSound)
//
// Definition of the audio profile
//
{
filename = "~/data/sound/testing.wav"; // wave file to use for the sound
description = "AudioDefaultLooping3d"; // monophonic sound that repeats
preload = false; // Engine will only load sound if it encounters it
// in the mission
};
function InsertTestEmitter()
//
// Instantiates the test sound, then inserts it
// into the game world to the right and offset somewhat
// from the player's default spawn location.
//
{
// An example function which creates a new TestSound object
%emtr = new AudioEmitter() {
position = "0 0 0";
rotation = "1 0 0 0";
scale = "1 1 1";
profile = "TestSound"; // Use the profile in the datablock above
3D Programming 119
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
useProfileDescription = "1";
type = "2";
volume = "1";
outsideAmbient = "1";
referenceDistance = "1";
maxDistance = "100";
isLooping = "1";
is3D = "1";
loopCount = "-1";
minLoopGap = "0";
maxLoopGap = "0";
coneInsideAngle = "360";
coneOutsideAngle = "360";
coneOutsideVolume = "1";
coneVector = "0 0 1";
minDistance = "20.0";
};
MissionCleanup.add(%emtr);
// Player setup-
%emtr.setTransform("-200 -30 12 0 0 1 0"); // starting location
echo("Inserting Audio Emitter " @ %emtr);
return %emtr;
}
function AnimSound(%snd, %dist)
//
// moves the %snd by %dist amount each time
//
{
%xfrm = %snd.getTransform();
%lx = getword(%xfrm,0); // first, get the current transform values
%ly = getword(%xfrm,1);
%lz = getword(%xfrm,2);
%rx = getword(%xfrm,3);
%ry = getword(%xfrm,4);
%rz = getword(%xfrm,5);
%lx += %dist; // set the new x position
%snd.setTransform(%lx SPC %ly SPC %lz SPC %rx SPC %ry SPC %rz SPC %rd);
schedule(200,0,AnimSound, %snd, %dist);
}
Chapter 3
■
3D Programming Concepts120
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
function DoMoveTest()
//
// a function to tie together the instantiation
// and the movement in one easy to type function
// call.
//
{
%ms = InsertTestEmitter();
AnimSound(%ms,1);
}
DoMoveTest(); // by putting this here, we cause the test to start
// as soon as this module has been loaded into memory
In this program, we also have a datablock, but you'll notice that it is different this time.
This datablock defines an audio profile. It contains the name of the wave file that contains
the sound to be played, a descriptor that tells Torque how to treat the sound, and a flag to
indicate whether the engine should automatically load the sound or wait until it encoun-
ters a need for the sound. In this case, the engine will wait until it knows it needs the file.
The
InsertTestEmitter
function is structured the same as the earlier
InsertTestShape
func-
tion, but this time it creates the object with a call to
new AudioEmitter
, and there are quite
a few properties to be set. These properties will be explained in much greater detail in
Chapters 19 and 20.
Another difference to note is the last line, which is a call to
DoMoveTest
. This allows us to
load and run the program in one go, using the exec call. After the Torque Engine compiles
the program, it loads it into memory and runs through the code. In our earlier program,
like the
AnimShape
module, Torque would encounter the datablock and function defini-
tions. Because they are definitions, they aren't executed, just loaded into memory. The last
line, however, is not a definition. It is a statement that calls a function. So when Torque
encounters it, Torque looks to see if it has the function resident in memory, and if so, it
executes the function according to the syntax of the statement.
To use the program, follow these steps:
1. Make sure you've saved the file as 3DGPAi1\CH3\ animaudio.cs.
2. Run the Chapter 3 demo using the shortcut in the 3DGPAi1 folder.
3. Press the Start button when the demo screen comes up.
4. Make sure you don't move your player-character after it spawns into the game world.
5. Bring up the console window.
6. Type in the following, and press Enter after the semicolon:
exec("CH3/animaudio.cs");
3D Programming 121
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
You should get a response in the console window similar to this:
Compiling CH3/animaudio.cs
Loading compiled script CH3/animaudio.cs.
You should also begin to hear the dripping sound off to the right-hand side. If you
wait without moving your player in any way, not even using the mouse to turn his
head, you will notice the sound slowly approach you from the left, pass over to the
right in front of you, and then pass off into the distance to the left. Pretty neat, huh?
Moving Right Along
So, we've now seen how 3D objects are constructed from vertices and faces, or polygons.
We explored how they fit into that virtual game world using transformations and that the
transformations are applied in particular order—scaling, rotation, and then finally trans-
lation. We also saw how different rendering techniques can be used to enhance the appear-
ance of 3D models.
Then we learned practical ways to apply those concepts using program code written using
Torque Script and tested with the Torque Game Engine.
In the next chapter, we will dive deeper into learning how to use Torque Script.
Chapter 3
■
3D Programming Concepts122
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
123
Game Programming
chapter 4
I
n the preceding two chapters you were introduced to a few new concepts: program-
ming, 3D graphics, manipulating 3D objects, and stuff like that. Most of it was fairly
broad, in order to give you a good grasp of what you can do to make your game.
The next bunch of chapters get down and dirty, so to speak. We're going to muck around
with our own hands examining things, creating things, and making things happen.
In this chapter we're going to hammer at the Torque Script for a while, writing actual code
that will be used to develop our game. We'll examine in detail how the code works in order
to gain a thorough understanding of how Torque works. The game we are going to create
has the rather unoriginal name of Emaga, which is just agame spelled backward. The
Chapter 4 version will be called Emaga4. Of course, you may—and probably should—
substitute whatever name you wish!
Torque Script
As I've said before, Torque Script is much like C/C++, but there are a few differences.
Torque Script is typeless—with a specific exception regarding the difference between
numbers and strings—and you don't need to pre-allocate storage space with variable dec-
larations.
All aspects of a game can be controlled through the use of Torque Script, from game rules
and nonplayer character behavior to player scoring and vehicle simulation. A script com-
prises statements, function declarations, and package declarations.
Most of the syntax in Torque Game Engine (TGE) Script language is similar to C/C++ lan-
guage, with a high correlation of keywords (see Table A.3 in Appendix A) between the two.
Although, as is often the case in scripting languages, there is no type enforcement on the
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
variables, and you don't declare variables before using them. If you read a variable before
writing it, it will be an empty string or zero, depending on whether you are using it in a
string context or a numeric context.
The engine has rules for how it converts between the script representation of values and
its own internal representation. Most of the time the correct script format for a value is
obvious; numbers are numbers (also called numerics), strings are strings, the tokens
true
and
false
can be used for ease-of-code-reading to represent 1 and 0, respectively. More
complicated data types will be contained within strings; the functions that use the strings
need to be aware of how to interpret the data in the strings.
Strings
String constants are enclosed in single quotes or double quotes. A single-quoted string
specifies a tagged string—a special kind of string used for any string constant that needs
to be transmitted across a connection. The full string is sent once, the first time. And then
whenever the string needs to be sent again, only the short tag identifying that string is
sent. This dramatically reduces bandwidth consumption by the game.
A double-quoted (or standard) string is not tagged; therefore, whenever the string is used,
storage space for all of the characters contained in the string must be allocated for what-
ever operation the string is being used for. In the case of sending a standard string across
connections, all of the characters in the string are transmitted, every single time the string
is sent. Chat messages are sent as standard strings, and because they change each time they
are sent, creating tag ID numbers for chat messages would be pretty useless.
Strings can contain formatting codes, as described in Table 4.1.
Chapter 4
■
Game Programming124
Table 4.1 Torque Script String Formatting Codes
Code Description
\r Embeds a carriage return character.
\n Embeds a new line character.
\t Embeds a tab character.
\xhh Embeds an ASCII character specified by the hex number (
hh
) that follows the x.
\c Embeds a color code for strings that will be displayed on-screen.
\cr Resets the display color to the default.
\cp Pushes the current display color onto a stack.
\co Pops the current display color off the stack.
\cn Uses
n
as an index into the color table defined by
GUIControlProfile.fontColors.
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Objects
Objects are instances of object classes, which are a collection of properties and methods
that together define a specific set of behaviors and characteristics. A Torque object is an
instantiation of an object class. After creation, a Torque object has a unique numeric iden-
tifier called its handle. When two handle variables have the same numeric value, they refer
to the same object. An instance of an object can be thought of as being somewhat like a
copy of an object.
When an object exists in a multiplayer game with a server and multiple clients, the server
and each client allocate their own handle for the object's storage in memory. Note that
datablocks (a special kind of object) are treated differently—more about this a little later.
note
Methods
are functions that are accessible through objects. Different object classes may have some
methods that are common between them, and they may have some methods that are unique to
themselves. In fact, methods may have the same name, but work differently, when you move from
one object class to another.
Properties
are variables that belong to specific objects and, like methods, are accessed through
objects.
Creating an Object
When creating a new instance of an object, you can initialize the object's fields in the
new
statement code block, as shown here:
%handle = new InteriorInstance()
{
position = "0 0 0";
rotation = "0 0 0";
interiorFile = %name;
};
The handle of the newly created
InteriorInstance
object is inserted into the variable
%handle
when the object is created. Of course, you could use any valid and unused
variable you want, like
%obj
,
%disTing
, or whatever. Note in the preceding example that
%handle
is a local variable, so it is only in scope—or valid—within the function where it is
used. Once the memory is allocated for the new object instance, the engine then initial-
izes the object's properties as directed by the program statements embedded inside the
new
code block. Once you have the object's unique handle—as assigned to
%handle
, in this
case—you can use the object.
Torque Script 125
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
Using Objects
To use or control an object, you can use the object's handle to access its properties and
functions. If you have an object handle contained in the local variable
%handle
, you can
access a property of that object this way:
%handle.aproperty = 42;
Handles are not the only way to access objects. You can assign objects a name that can be
used to access the object, if you don't have a handle at hand. Objects are named using
strings, identifiers, or variables containing strings or identifiers. For example, if the object
in question is named
MyObject
, all of the following code fragments (A, B, C, D) are the same.
A
MyObject.aproperty = 42;
B
"MyObject".aproperty = 42;
C
%objname = MyObject;
%objname.aproperty = 42;
D
%objname = "MyObject";
%objname.aproperty = 42;
These examples demonstrate accessing a property field of an object; you invoke object
methods (functions) in the same way. Note that the object name—
MyObject
— is a string
literal, not a variable. There is no
%
or
$
prefixed to the identifier.
Object Functions
You can call a function referenced through an object this way:
%handle.afunction(42, "arg1", "arg2");
Note that the function
afunction
can also be referred to as a method of the object con-
tained in
%handle
. In the preceding example, the function named
afunction
will be execut-
ed. There can be multiple instances of functions named
afunction
in a script, but each
must be part of different namespaces. The particular instance of
afunction
to be executed
will be selected according to the object's namespace and the namespace hierarchy. For
more about namespaces, see the sidebar.
Chapter 4
■
Game Programming126
Team LRN
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
[...]... existing games, customizing the games to look or play differently The term is often used in the independent game development scene The word Mod is often capitalized What we are doing when we create the Emaga game is in many ways similar to creating a Mod— much like a certain kind of Mod that is often called a Total Conversion Torque, however, is not a game, it is an engine So we are in reality not modifying... flesh out the game Root Main Once it has found the root main module, Torque compiles it into a special binary version containing byte code, a machine-readable format The game engine then begins executing the instructions in the module The root package can be used to do anything you like, but the convention established with the GarageGames code is that the root package performs the following functions:... anything to do Then the initialize.cs module is loaded, after which the two initialization functions are called Finally, there is the OnExit() function, which does nothing more than pass the buck to the function in the root main module OnExit() All in all, control/main.cs is a fairly lazy, though important, little module Team LRN Initialization Debugging Scripts Using the trace() Function The engine... 138 Chapter 4 ■ GameProgramming The stub routine OnExit() is next A stub routine is a function that is defined but actually does nothing The common code modules have a call to this routine, but we have nothing for it to do We could just leave it out, but a good policy is to provide an empty stub to avoid warning messages from appearing in our log file—when the Torque Engine tries to call a nonexistent... a call to OnStart() This will call all versions of OnStart() that appear in the add-on packages in order of their appearance in $addonList, with common being first, control next, and finally this root main module If there is an OnStart() defined in common, then it gets called Then the one in control, and so on When we get to the end of the module, the various threads initiated by the OnStart() calls... generic initialization Performs the command line parameter parsing and dispatch Defines the command line help package Invokes packages and add-ons (Mods) Here is the root main.cs module Type it in and save it as Emaga4\main.cs You can skip the comments if you like, in order to minimize your typing // -// /main.cs // // root main module for 3DGPAI1 emaga4 tutorial game. .. Help features and content files User interface definitions, widget definitions, profiles, and images We will not be using all of these features in the code we'll be looking at in this chapter, but by the end of the book, we will be using all of it! Preparation In this chapter we will be concentrating on the control scripts found in the control subtree, as outlined in Figure 4.2 To prepare for this, you... are ticking over, doing their own things So now what? Well, our next point of interest is the control/main.cs module, which we called with the Exec() function just before we started loading the add-ons Control Main The main.cs module for the control code is next on our tour Its primary purposes in Emaga4 are to define the control package and to call the control code initialization functions (In later... modules into memory, initialize the common functions, and basically get the ball rolling over there We will talk about the common code modules in a later chapter Team LRN Control Main After that we do the same thing for the control code modules, the details of which we will cover later in this chapter Then we actually start loading the add-ons using the previously defined LoadAddOns() function Finally,... will be using a simplified version of this tree In the distribution of TGE you receive with the CD, the executable is called tge.exe The particular main.cs file Figure 4.1 General game folder tree located in the game root folder can be thought of as the root main module This expression is useful for distinguishing that particular main.cs module from others with the same name that aren't in the game root . hands examining things, creating things, and making things happen.
In this chapter we're going to hammer at the Torque Script for a while, writing actual. will be contained within strings; the functions that use the strings
need to be aware of how to interpret the data in the strings.
Strings
String constants