Game Development Community

Handling multiple instances of an object

by Jake Vinson · in Torque Game Builder · 08/11/2005 (8:37 am) · 7 replies

When I declare an object as local (using %), it seems as though I should be able to change individual instances of the object while they're still on screen. For example, my code creates a %ball, sets its image map, physics properties, etc., then every second creates a new one.

Because they're local variables and I couldn't find anything in the documentation to tell me otherwise, it looks like once they're created I can't reference them and change their settings.

For situations like this, would I have to dynamically create an array or a linked list of some sort, and rather than killing them at their world limit, pop them from the array?

If any of that's unclear, imagine that I have 3 balls on the screen at once. If you get a powerup, those three balls double in size, then when two new balls was added, they'd appear with the default settings (at the normal size). Then another powerup would make all of the balls red, so I'd have 3 big red balls and two normal sized red balls. So in the course of getting all kinds of powerups, theoretically each ball could be different.

#1
08/11/2005 (8:46 am)
Unless you are keeping global variables to them, you will lose your handle to those sprites when they go out of scope of your function. However, all is not lost. You can enumerate the scenegraph's object collections to get back handles to objects that are in the scene. I've seen how in another thread here, but a quick Google did not turn it up this morning.

That said, creating arrays are braindead easy, just keep a counter and do the following:

//initialize the counter somewhere
$spriteCounter = 0;
 
//add a new object
$spriteList[$spriteCounter++] = new fxStaticSprite2D() {...

Now you've got a global, growing list of sprites to keep track of yourself.
#2
08/11/2005 (8:51 am)
When you create an object its gets a unqiue ID... like 1548. So when you do

%ball = new fxStaticSprite2D() {scenegraph = t2dSceneGraph; };

it really is storing the reference to the object inside of %ball...

Now when the function ends that %ball variable is destroyed, though the object is still in existence, you just don't have a reference to it anymore.

In my Physics Demo(Heres a tutorial about creating it) I dynamically named the objects as well as adding them to an array...

$blocks::names[$blocks::ammount] = "block" @ $blocks::ammount;
   // Create Bouncy Ball.
   %ball = new fxStaticSprite2D($blocks::names[$blocks::ammount]) { scenegraph = t2dSceneGraph; };

that way it would name the object "block0", "block1", "block2", etc... as well as add them to

$blocks::names[0] = "block0";
$blocks::names[0] = "block1";
$blocks::names[0] = "block2";

Now you can store just the reference in an array too, so i could've done it like this

$blocks::names[$blocks::ammount] = new fxStaticSprite2D() { scenegraph = t2dSceneGraph; };

So instead of just dynamically generating the name and then storing that name in a list, I simply store the object reference in the array.
#3
08/11/2005 (8:52 am)
If you want to reference any of the balls after creation you could give each instance a unique name on creation.

%ball = new fxStaticSprite2D(ball1){...};
...
%ball = new fxStaticSprite2D(ball2){...};
...
then later reference them using ball1.function, ball2.function etc

Or if you have a lot of objects created you could add them all to a simset as and when you create them

new SimSet(gameBalls);

... stuff

%ball = new fxStaticSprite2D(){...};
... set this balls params
gameBalls.add( %ball );

%ball = new fxStaticSprite2D(){...};
... set this balls params
gameBalls.add( %ball );

So long as you made gameBalls global or gave it a name, you can then itterate through all the balls added to it whenever you need to.

for ( %n = 0; %n < gameballs.getCount(); %n++ )
{
  %ball = gameballs.getObject(%n);
  %ball.dostuff();
}

When an item is deleted, in this case a ball, it will automatically be removed from all simsets its a member of as well as the simgroup.

EDIT: Wow lots of replies in the time it took me to type this, take your pick :)
#4
08/11/2005 (6:08 pm)
Thanks a lot for all the responses! One question though - how could I have found out about the SimSet without asking? I can'f find it in any of my documentation... and for that matter, where can I get more info on functions used with SimSets?
#5
08/11/2005 (6:37 pm)
Do this in the console

new SimSet(testSet);
testSet.dump();

all objects have that built into them
#6
08/11/2005 (6:46 pm)
There are also SimGroups... which are pretty much the same except for two factors
- When deleted it deletes everything within it (can imagine some very usefull aspects for this)
- Can only be in one SimGroup at a time


there are also ScriptObjects, like

new ScriptObject(testObject);

then you can define parameters on it

testObject.data[0] = "blah0";
testObject.data[1] = "blah1";
testObject.data[2] = "blah2";
testObject.value = 100;

etc...

then you can store these in SimSets/SimGroups since they can only store objects...

all objects have a built in save function as well, so if you create the testObject like I did and then created a simset like this

new SimSet(gameData);

then added the ScriptObject to it

gameData.add( testObject );

you then could type this

gameData.save("T2D/client/saves/save.cs");

... open up that file with a text editor and you get this

//--- OBJECT WRITE BEGIN ---
new SimSet(gameData) {

   new ScriptObject(testObject) {
         value = "100";
         data1 = "blah1";
         data2 = "blah2";
         data0 = "blah0";
   };
};
//--- OBJECT WRITE END ---

Now ScriptObject can be copied... you can do this

new ScriptObject(test1:testObject);
new ScriptObject(test2:testObject);
new ScriptObject(test3:testObject);

now if we add them too

gameData.add(test1);
gameData.add(test2);
gameData.add(test3);

and re-save it out, we get this

//--- OBJECT WRITE BEGIN ---
new SimSet(gameData) {

   new ScriptObject(testObject) {
         value = "100";
         data1 = "blah1";
         data2 = "blah2";
         data0 = "blah0";
   };
   new ScriptObject(test1) {
         value = "100";
         data1 = "blah1";
         data2 = "blah2";
         data0 = "blah0";
   };
   new ScriptObject(test2) {
         value = "100";
         data1 = "blah1";
         data2 = "blah2";
         data0 = "blah0";
   };
   new ScriptObject(test3) {
         value = "100";
         data1 = "blah1";
         data2 = "blah2";
         data0 = "blah0";
   };
};
//--- OBJECT WRITE END ---

Now this data can be reloaded when the game loads again with this command
exec("T2D/client/saves/save.cs");

edit: reformatted board code blocks :)
#7
08/11/2005 (7:21 pm)
Script objects also have three levels of inheritence... say we created a base class like this
and add some starting values to it

function createEntityClass()
{
   new ScriptObject(Entity){
      health = 100;
      mana = 250;
      strength = 10;
   };
}


now lets make our own onAdd function attached to this "Entity" object which will get called everytime an entity is created...

function Entity::onAdd(%this)
{
   echo("New Entity added -" SPC %this.getName());
}

then we can create a child class of it, like this

function createOrcClass()
{
   new ScriptObject(Orc) {
      class = Entity;   
   };
   Orc.health = Orc.class.health + 50;
   Orc.strength = Orc.class.strength + 5;
}

(I did the health and strength that way so it would build off of its class)

run the createEntityClass(); function in the console and you should see this
Quote:
New Entity added - Entity

then you should see this in the console when createOrc(); function is run

Quote:
New Entity added - Orc

now you can create a function like this

function createOrc(%name)
{
   new ScriptObject(%name){
      class = Orc;
      superClass = Entity;
   };
}

then just call it like this

createOrc(Bob);
and if you want to overide the entity onAdd you can do so by adding one to Orc

function Orc::onAdd(%this)
{
   echo("New Orc of added -" SPC %this.getName());
}

and it will fire when you create an orc

now to test this add

function Entity::yell(%this)
{
   echo("This yelled -" SPC %this.getName());
}

then whatever orcs you created with "createOrc" call ".yell();" on them and you should see the console react properly