Game Development Community

GPGT Chapter 10 - Issues and Questions

by Edward F. Maurina III · in Torque Game Engine · 05/16/2006 (10:45 pm) · 11 replies

Hello All. This thread is dedicated to any questions or issues that you may find in this chapter.

If you have issues and questions for other chapters, please post them in the appropriate thread:
Chapters 1 & 2
Chapter 3
Chapter 4
Chapter 5
Chapter 6
Chapter 7
Chapter 8
Chapter 9
Chapter 10
Chapter 11
Chapter 12
Chapter 13
Chapter 14

GPGT Support Page
Appendix E. Maze Runner Lessons (Steps Only) - Covers Mac and Windows
OSX Executable - Use for GPGT Lesson Kit and MazeRunner

#1
06/22/2006 (4:07 pm)
Hi Edward -

just a potential small improvement -

on page 392 you demonstrate how to have an event shedule over and over:
function repeatForever() {
   // do something
   schedule(1000, 0, repeatForever);
}

and provide the warning that it's generally safer to have object-bound schedule-events because the events will get cancelled if the object is deleted, and otherwise you run the risk of runaway schedules.

which is very sound advice !

but one technique i use with global (non-object-bound) repeat-forever events is this:

$gTimerRepeatForever = 0;   // this line is actually optional.

function repeatForever() {
   cancel($gTimerRepeatForever);
   // do something
   $gTimerRepeatForever = schedule(1000, 0, repeatForever);
}

.. this way, if you should inadverdently (or advertently) call the function twice you'll avoid introducing two parallel schedule-events running.


edit: is this the sort of stuff you're looking for in these threads ? would you prefer email for stuff like this ?
#2
06/23/2006 (2:32 pm)
This is exactly the kind of thing I'm looking for in these threads. I want people to feel free to dicuss ideas and to ask questions someplace where they can be easily found by other book owners.

Thanks,
www.hallofworlds.com/how.ico Hall Of Worlds - For Gamers
EdM|GPGT
#3
10/10/2006 (9:37 am)
I also added a similar loop but just gave it a termination condition within this function itself.
like
function repeat(%var)
{ // ....
//.....
var++;
if(var != 100)
{
schedule(1000,0,repeat);
}
//...
//...
}
So that we do not require a global variable.
Is this a recursion .
#4
10/10/2006 (9:43 am)
Saurabh -

yes that's a recursion; any function which calls itself is recursive.

you might consider re-working the function to something more like this:

function repeat(%numTimesLeft)
{
   // do stuff
   %numTimesLeft--;
   if (%numTimesLeft > 0)
      schedule (1000, 0, repeat, %numTimesLeft);
}


.. the advantage here is that it doesn't hard-code the limit of 100 into the function.
so you could call repeat(100) to have it repeat 100 times, or repeat(2) to have it repeat twice.
#5
10/10/2006 (10:00 am)
Moved to other thread.
#6
10/27/2006 (12:40 pm)
@All Readers - I'm starting to answer ALL of my oustanding GPGT questions. It will take me a few days, so please bear with me over the weekend.

- Thanks


@Saurabh and Orion E. - I'm going to agree and disagree with the information given thus far. I'm responding because I want to be sure that TorqueScript users understand the different ways you can 'recurse'.

1. Saurabh's code:
function repeat(%var)
{ // ....
//.....
var++; 
if(var != 100)
{
schedule(1000,0,repeat);
}
//...
//...
}

is not strictly recursive. Why? Well, because a schedule is being used to call repeat, instead of a direct call.

2. The above code is not passing the %var variable in the schedule call which will cause the function to get "" for %var. Thus, based on the code I see, this function will run forever scheduling new calls to happen every 1000 milliseconds. To fix this, simply change the schecule call to this: schedule(1000,0,repeat,%var);

3. To make this function truly recursive do this:
function repeat(%var)
{ // ....
//.....
var++; 
if(var != 100)
{
repeat(%var);
}
//...
//...
}

The above code is truly recursive and matches the definition given by Orion E.

4. There are benefits and drawbacks to either method (scheduling or direct calling), but keep in mind that direct recursion has a limit. Eventually, if the function recurses too deeply you will crash the engine, where as the schedule method will NOT crash the engine.

The reason the engine can be crashed by recursion is that when you call a function from itself, the engine must temporaryly place the currently executing code on hold (stack it up) and start the new call. Eventually this stack tracking method will use up the engine's resources and/or all of memory and whamo! Crash.

5. There is an alternative to the 'timed' schedule used above. I like to think of it as the 'wait until I'm done' schedule. In this instance, you call schedule and pass it a 0 for the delay. This tells the engine to do it as soon as it can (i.e. as soon as other events scheduled for now have executed. So, why do this? Well, it is a safe way to do deletes where you are deleting the object that the current method is operating on. This may be a little deep or perhaps just unclear, so just remember that 0 is a valid schedule time.

6. The purpose of recursion is generally to solve a problem by partitioning it. That is, a function is called. This function then splits the problem it is designed to solve into smaller parts and recurses (calls itself to solve the smaller problem set). Eventually, the splitting gets to a point where only one 'problem element' is left. At this point, the recursed function may return a results which is then used by the last call to the function, which then returns a value ..., until you have completely unwound the recurssion.


I hope that this discussion was helpful (and accurate). Any CS majors or instructors seeing a mistake in my statements should feel free to rebutt them and to correct me.

www.hallofworlds.com/how.ico Hall Of Worlds - For Gamers
EdM|GPGT
#7
04/08/2007 (8:11 am)
Hello All,
I got a question about callbacks, especially about onAdd() and onRemove(). When i try to attach this callbacks for projectile, why this 2 callbacks aren't called ?

i'm using the crossbow.cs from the starter.fps

function CrossbowProjectile::onAdd(%DB, %obj)
{
error("\nOBJ : "@%obj.getName()@" DB : "@%DB.getName()@" client : "@%obj.client@" created !");
}

function CrossbowProjectile::onRemove(%DB, %obj)
{
error("\nOBJ : "@%obj.getName()@" DB : "@%DB.getName()@" client : "@%obj.client@" removed !");
}

Are this callbacks cannot work with projectiledatablock ?

thank you in advance
#8
04/08/2007 (11:38 am)
@Suryadiputra

Hi. Yes, neither the onAdd(), not the onRemove() callback is called when you create a projectile.

However, you can still get what you need done.

For work you would do in onAdd(), simply modify the code that creates the projectile. Add the code you need after the projectile is created.
Search for "new Projectile()", which is usually in a callback named "onFire()".

For the work you would do in onRemove(), simply modify the onExplode() method for your projectile. Of course, this won't work for projectiles that are fired into the air and just fade out before hitting something, but I think you can see where I'm going with this.


Last, you can always modify the engine to call onAdd() and onRemove() for projectiles. Try searching for "scriptOnAdd()" and "scriptOnRemove()" in the source.



www.hallofworlds.com/how.ico Hall Of Worlds - For Gamers
EdM|GPGT
#9
12/25/2007 (1:03 am)
Chapter 10 Page 416 defines a client function of

PlayGUI::DoSomething( %ID, %x, %y) {
//do something
}

then the clientCmd* is

clientCmdTellPlayGUIDoSomething( %x, %y) {
PlayGUI.DoSomething( %x, %y);
}

See what I'm getting at?

Neurosys.Post( %errata);
return;
#10
12/26/2007 (1:18 pm)
Neurosys,

I'm afraid I don't see what you're getting at.

With this code, you can cause PlayGui::DoSomething() to be called on every client via the client command:

clientCmdTellPlayGUIDoSomething()

as follows:

for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) 
{
   %cl = ClientGroup.getObject( %clientIndex );

   clientCommand( %cl , 'TellPlayGuiDoSomething' , 10 , 20 );      
   }

On every client, the client command would be called as follows:

clientCmdTellPlayGUIDoSomething( 10 , 20 );

In turn, it would call PlayGUI::DoSomething as follows:

PlayGUI.DoSomething( 10 , 20 );

This automatically passes in the ID of PlayGUI as the first argument. So, if the ID of PlayGUI is 1500 on a particular client, then when the function is called, the arguments to PlayGUI::DoSomething() are set as follows:

%ID == 1500
%x == 10
%y == 20


.....

So, if I missed your point, or this has been confusing, feel free to post back. I don't guarantee to answer right away, but I'm curious if I did miss the point.

www.hallofworlds.com/how.ico Hall Of Worlds - For Gamers
EdM|GPGT
#11
12/26/2007 (11:11 pm)
Im an idiot. Sorry.