Game Development Community

Need Help Understanding Variables, Functions, and Methods

by Leo Gura · in Torque Game Builder · 09/19/2006 (5:28 am) · 6 replies

I have yet another problem I can't get my head around; it involves passing variables from instance to instance and one class to another. As I understand it, when I declare a variable with "$" (like $objectID) it will exist forever and be accessible by all classes and instances. Now, when I declare a variable with "%" (like %objectID) then this variable will exist only during the execution of a function. Once the function is complete, the variable %objectID will be lost forever. I need a way to create variables that are specific to a particular instance, but that aren't just limited to a single function. Otherwise I don't really understand how anything robust can be programmed.

Here's a typical example for you: I'm trying to create a comet tail particle effect on each instance of a bullet whose class is "playerBall". When a bullet is created I start up the particle effect, storing the effect's handle in a local variable called "%effTrail". Then, when the bullet flys outside the world limits, I need to destroy the particle effect I created for the bullet, but to do so, I need the local variable %effTrail, which has already been deleted!!! And I can't use a global variable because I have several bullets existing at any give moment. How do you deal with this problem?

function playerBall::fire(%this)
{
%effTrail = new t2dParticleEffect() {scenegraph = %this.scenegraph;};
%effTrail.loadEffect("~/data/particles/testpart1.eff");
%effTrail.mount(%this,0,0,0,false,true,false,false);
%effTrail.playEffect();
}

function playerBall::onWorldLimit(%this,%limitMode,%limit)
{
%BallIDLocal = %this;
%effTrail.stopEffect(true,true);
}


I'm also confused about how methods and functions are declared and called. If I declare a method, does that mean I can only call it from the class I declared on? So, for example, "function playerBall::onWorldLimit()" can only be called by instances of playerBall? On the other hand, if I declare a fuction like "function explode()" then it can be called by any object? And that would mean that I cannot have two different classes declare a function called "function explode()"? Is there a way to call a method that was declared on one class, from another class?

Additionally, I don't understand all the circumstances in which I must use "%this". Suppose I'm trying to set a schedule for an instance. Should I write:

%this.schedule(16,BallDistance);
or
schedule(16,BallDistance);

What would be the difference here? And how would I go about setting a schedule for not just a single instance, but for all instances of the same class? Like if I wanted to destroy all instances of a bullet 4 seconds after some event occurs.

That's a lot of questions, but I've been trying to sort through these issues by trial-and-error and still can't figure out what I consider to be the bread and butter of object oriented programming. Thanks for helping me out.

#1
09/19/2006 (6:17 am)
You don't need to worry about your effect. If the effect is mounted, and owned, it will be deleted when the object it's mounted to is deleted. No need to track it and delete it yourself.
%effTrail.mount(%this,0,0,0,false,true,true,false);
I'm sure someone will come along and correct any mistakes I make on the next part, but basically, yes, playerBall::onWorldLimit will be called just by playerBall objects. If you make a function called explode(%this), then you can call it from anywhere, and providing it makes sense in your code, you could pass in any object.

The other option would be playerBall::explode, enemy1::explode and so-on to give each thing its own exploding function.

Your first use of schedule obviously sets the schedule on the object. If you use the second option, you will want:
schedule(16, %this, "BallDistance");
Ofcourse %this needs to be valid in the place that you set the schedule. It's also useful if you want to assign the schedule to a variable so you can check later on if the schedule is still pending.

Not sure about looping through all of the objects of a particular type, but you could create a simset and add each bullet to it. As the bullets are naturally deleted, they are removed from the set. When your event fires, you can either loop through the simset, and set the lifetime of the bullets to 4 seconds, or set a schedule to activate in 4 seconds that loops through the set and deletes the bullets.
#2
09/19/2006 (1:44 pm)
I understand your problem I also thought that myself when I started coding in TGB, here are 3 answers I can provide.

1.You have to realize, torque script is not a robust compiler language like C++ or even C# is a script language (like quake script) therefore it doesnt work the same way a regular program does. and Thats why you either keep a variable forever or just when is needed.

2.Heres the magic word, "Simsets" they are the equivalent of arrays in flash and dictionaries in PHP is a dynamic Array which objects can be destroyed or created at any time. Learn to use those and your problems will be over.

3. since you are using a robust API sometimes the functions will sent you the data you need without you looking for it. In this case you have two options. 1.Mounting as already explained. 2.Use the onWorldLimit callback to safedelete the object when it exits the world, simple as that!
#3
09/19/2006 (2:47 pm)
Yes, there is a quick work-around for many of my problems, such as the Mounting technique detailed by Philip, however, this technique does not fully appreciate the nuance of the problem. Firstly, I was already using mounting to stick the particle effect to the bullet. Secondly, the reason I need to manually kill the effect is because I need to set the parameters inside the "stopEffect(true,true)" function to true and true. Otherwise, when the ball exists the camara view, it is destroyed, and the comet tail doesn't naturally die-off, but rather is destroyed immediately. Thus, I still see a need to manually kill the effect with "stopEffect(true,true)", and in order to do this, I need the handle of the originally created effect, which has already been deleted.

How did the creators of this language intend for me to use the stopEffect() function? Obviously they could not be under the assumption that I would be creating and stopping a particle effect in the same function, could they? And obviously there needs to be the possibility that I can have multiple effects at the same time, so a simple global variable doesn't work either. This is the conundrum I don't understand.

I find myself surrounded by dilemmas of this sort on all sides. My goal here is not to find a particular work-around-- which may or may not exist for the bullet-comet-tail problem-- but to find a general technique that will allow me to tackle all such issues as they arise. Of course, a solution to the specific bullet-comet-tail problem would be nice too :)
#4
09/19/2006 (2:58 pm)
The answer is dynamic variables. In your PlayerBall::fire function, add
%this.particleEff = %effTrail;
Now you just call
%this.particleEff.StopEffect(true, true);
in your onWorldLimit. =3
#5
09/19/2006 (3:45 pm)
Ah! So there's a third type of variable afterall?! Is this "dynamic" particleEff variable going to exist outside of the particular function? If so, that would solve all my problems.
#6
09/19/2006 (4:51 pm)
That's not really a variable at all. It is a field of an object. It lasts until the object itself is deleted.