Game Development Community

I want a whole Class to respawn.

by Maarten Visser · in Torque Game Builder · 11/20/2006 (4:39 am) · 15 replies

Is it possible to respawn a whole class after an action has been triggered. I now have an object which explodes on collision from a mine, and I want to respawn this whole mine class instead of only the particular mine that explodes on collision.

function Mine::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
   if(%dstObj.class $= "MySubmarine")
   {
      %srcObj.spawn();
   } 
}

This makes the source object (the mine) respawn, but I want the whole 'Mine' class to respawn. Could anyone provide me with a solution?

Thanks in advance,

MaarX

#1
11/20/2006 (5:22 am)
Off the top of my head you should put all your mines in a simgroup / simset and loop through it re-spawning them.

but it is 8am and i am kinda tired so there probably is a better way.
#2
11/20/2006 (10:36 am)
function Mine::onAdd(%this)
{
   if(!isObject(%this.scenegraph.mineSet))
      %this.scenegraph.mineSet = new SimSet();

   %this.scenegraph.mineSet.add(%this);
}

Now, whenever you create an object of the class "Mine" it will add it to the mineSet SimSet off of the scenegraph. To loop through the mineSet to perform an action on all of them you would do something like this.

function loopThroughMines()
{
   %mineSet = SceneWindow2D.getScenegraph().mineSet;
   %count = %mineSet.getCount();

   for(%i=0;%i<%count;%i++)
   {
      %mine = %mineSet.getObject(%i);

      // now do whatever you want with the mine object
   }
}
#3
11/21/2006 (3:10 am)
function loopThroughMines()
{
   %mineSet = SceneWindow2D.getScenegraph().mineSet;
   %count = %mineSet.getCount();

   for(%i=0;%i<%count;%i++)
   {
      %mine = %mineSet.getObject(%i);
      // now do whatever you want with the mine object
   }
}

function Mine::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
   if(%dstObj.class $= "MySubmarine")
   {
      %srcObj.spawn();
      %dstObj.modifyLife(-%srcObj.damageValue);
   } 
}

I added the 2 pieces of code as you said, I now have my mineSet. But I still don't know how to trigger the respawn now after the submarine explodes. Do I have to call the function onCollision from the "// now do whatever you want with the mine object" or what?

Also the start of my mine script is now:
function Mine::onLevelLoaded(%this, %scenegraph)
{
   %this.startingY = %this.getPositionY();

   %this.spawn();
}

function Mine::onAdd(%this)
{
   if(!isObject(%this.scenegraph.mineSet))
      %this.scenegraph.mineSet = new SimSet();

   %this.scenegraph.mineSet.add(%this);
}

I am wondering... Is onAdd the same as onLevelLoaded?
Sorry for I am a very bad scripter. But thanks already.
#4
11/21/2006 (3:28 am)
The difference is that onAdd is called once the object is added to a scenegraph, whereas onLevelLoaded is called when a level is loaded. What this means is that onLevelLoaded will not automatically be called on objects that you create via script, though you could always manually call it from onAdd - which would be called, assuming you added the object to a scenegraph when you created it.
#5
11/21/2006 (12:34 pm)
Thanks, that only leaves me to the question how (with which piece of code) I can respawn the whole mine class if one collides against the submarine.

function loopThroughMines()
{   %mineSet = SceneWindow2D.getScenegraph().mineSet;   
     %count = %mineSet.getCount();   
     for(%i=0;%i<%count;%i++)   
    {      
      %mine = %mineSet.getObject(%i); 
    
      //!!!
     %mineSet.spawn();
     //!!!

    }
}

I have tried a lot of combinations but they don't seem to work...
#6
11/21/2006 (12:48 pm)
You don't want to respawn the whole mineSet (well, you do, but not in that for loop ;)

Change the
%mineSet.spawn();
to
%mine.spawn();

I'd think that would work, assuming you're getting your %mineSet ID correctly. Throw some echoes in there to make sure the variables are what they should be at each step.

Hope that helps :)
#7
11/22/2006 (5:12 am)
Nope, it doesn't work for me yet... I think that theres something wrong with the simset code... When I type

%Mine = %mineSet.getObject(%i);


into the console it gives me an error:
'Unable to find object: ' ' Attempting to call function 'getObject'
#8
11/22/2006 (10:29 am)
You cannot type local variables into the console since there scope would only be within that single console call.

Post your scripts you're working with and I'll test it :)
#9
11/22/2006 (10:30 am)
Just in case you didn't know---

%mine

is a local variable, meaning it only exists within the function you use it in.

$mine

is a global variable, it exists within all of script (console) space.
#10
11/23/2006 (5:57 am)
Here is my mine script: (Mine.cs)

function Mine::onLevelLoaded(%this, %scenegraph)
{
   %this.startingY = %this.getPositionY();

   %this.spawn();
}

function Mine::onAdd(%this)
{
   if(!isObject(%this.scenegraph.mineSet))
      %this.scenegraph.MineSet = new SimSet();

   %this.scenegraph.MineSet.add(%this);
}

function Mine::spawn(%this)
{
   %this.state = "fallingDown";
   %this.speed = getRandom(%this.minSpeed, %this.maxSpeed);

   %this.originX = getRandom(%this.minX, %this.maxX);
   %this.originY = getRandom(%this.minY, %this.maxY);

   %this.setPosition(%this.originX, %this.startingY);

   %this.moveTo(%this.originX, %this.originY, %this.speed, true, true);

   if(isEventPending(%this.respawnSchedule))
      cancel(%this.respawnSchedule);
   
   %respawnTime = getRandom(%this.minRespawnTime, %this.maxRespawnTime);

   %this.respawnSchedule = %this.schedule(%respawnTime, "spawn");
}

function Mine::onPositionTarget(%this)
{
   %this.floatRange = getRandom(%this.minFloatRange, %this.maxFloatRange);

   switch$(%this.state)
   {
      case "fallingDown":
         %this.floatDown();

      case "floatingDown":
         %this.floatUp();
     
      case "floatingUp":
         %this.floatDown();
   }
}

function Mine::floatDown(%this)
{
   %this.state = "floatingDown";

   %targetY = %this.originY + %this.floatRange;

   %this.moveTo(%this.originX, %targetY, %this.speed, true, true);
}

function loopThroughMines()
{
   %MineSet = SceneWindow2D.getScenegraph().mineSet;
   %count = %MineSet.getCount();

   for(%i=0;%i<%count;%i++)
   {
      %Mine = %mineSet.getObject(%i);

   //!!!
      $Mine.spawn();
      %i.spawn();
   //!!!

   }
}

function Mine::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, 

%normal, %contactCount, %contacts)
{
   if(%dstObj.class $= "PlayerFish")
   {

      %dstObj.modifyLife(-%srcObj.damageValue);

      %srcObj.schedule(1, "spawn");

   } 
}

function Mine::onWorldLimit(%this, %mode, %limit)
{
   switch$ (%limit)
   {
      case "bottom":
         %this.spawn();
   }
}

Thanks already:)

Do I need you to provide with anything more?

(My game.cs links to 2 scripts, one of the mine and one of the submarine movement.)
#11
11/29/2006 (1:27 pm)
Hmmm... I did make a LITTLE progress... But not much... Now I have the last mine that is added to the scene marked with $mine... So that (last) mine can respawn... But the class respawn is not working. Please help me out on this one. Thanks.

I think that the Mine is not added into the Simset... as there is no place where Mine gets called...I only see "!isObject". (That is probably the part where the simset is created... With no mines in it yet).

In the second function you gave me... it loads the Simset... Then it will count the number of mines...

%count = %mineSet.getCount();
for(%i=0;%i<%count;%i++)


But how can the code %count get the correct number of mines... There is no place where a value (of the mines ) has been stored... And if it were to count any object(s) ... It must be counting the background/ submarine/ and mines... But it doesnt as nothing is declared (I think...)

Please help me out, Thanks
#12
12/06/2006 (8:12 pm)
Try doing this.

function Mine::onAdd(%this)
{
   if(!isObject(mineSet))
      new SimSet(mineSet);

   mineSet.add(%this);

   //Test it out
   mineSet.listObjects();
}

and just use "mineSet" whenever you need to access it. Making the SimSet a member/part of the scengraph seemed to be causing some problem with it, what I do not know.
#13
12/07/2006 (7:59 am)
Thank you very much... I think the group is now saved as $mines (when I type $mines.listObjects(); into the console, it lists the mines that are on the scene. I assigned $mines to the simset)

But now... I assume that I only have to trigger the respawn of the $mines objects... So I have a function which is "spawn". (Which works with single mines) But now I can't respawn the $mines ...

The code which I use for this is:

function Mine::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
   if(%dstObj.class $= "MySubmarine")
   {

      %dstObj.modifyLife(-%srcObj.damageValue);
      $mines.schedule(0, "spawn");    <--- this one doesn't work:S
      %srcObj.schedule(0, "spawn"); <---this one works

   } 
}

Thanks for the piece of code you gave me:) That works:D
#14
12/07/2006 (3:24 pm)
I think you have to call spawn on each object by the loopThroughMines function you have. The $mines simset doesn't have a spawn function I assume and I dont think it calls the function in every object in it (would be kinda neat feature if it did though).

function Mine::onCollision(%srcObj, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contacts)
{
   if(%dstObj.class $= "MySubmarine")
   {
      %dstObj.modifyLife(-%srcObj.damageValue);
      
      //This function should loop through all the mines and call the spawn function
      loopThroughMines();
   } 
}

/* what I imagine the function to look like.

   %count = $mines.getCount();

   for(%i=0;%i<%count;%i++)
   {
      %Mine = $mines.getObject(%i);

      %Mine.spawn();
   }

*/
#15
12/08/2006 (3:19 am)
Thank you very much for all the help (everyone:) ) ... It's working now... It's weird how all these things work... But I'm starting to understand it a bit:P