Game Development Community

Unable to find object: '' Attempting to call function 'spawntoken'

by Arden · in Torque Game Builder · 08/20/2010 (6:36 pm) · 14 replies

Hi all,

I'm experiencing some challenges in getting the following to work: every time a ghoul is hit by an arrow, I want a coin token to be spawned. I got the ghouls, player and arrow to work. When the ghoul being hit is at 0 HP, he calls the function to spawn a token before he is deleted. The problem is that when I run the game, it is unable to find the object. And when I hit a ghoul with an arrow, nothing happens.

I do this through the ghoul.cs file:

function Ghoul::hurt(%this, %damage)
{
%this.hitPoints -= %damage;
if ( %this.hitPoints <= 0 )
{
%token.spawntoken();
%this.safeDelete();
}
}

The spawntoken function is defined in Tokenspawner.cs:

// First create an array to store each token
$TokenSet = new SimSet();

function Token::onAddToScene(%this, %scenegraph)
{
//%this.hitPoints = 100;
$TokenSet.add(%this);
%this.setAnimation(coppercoinanimation);
// This is the name of the animation created in the editor (and present in managed/datablocks)
}


function Token::onLevelLoaded(%this, %scenegraph)
// The intent of this function is to create a first animated sprite without any zombie being hit for testing purposes
{
%this.schedule(1000, "spawntoken");
%this.spawnCount = 0;
}

function Token::spawntoken(%this)
// The intent of this function is to spawn a token when the function is called.
{
%token = new t2dAnimatedSprite("Token" @ %this.spawnCount)
{
scenegraph = %this.scenegraph;
config = "tokenDataBlock";
};
%token.setPosition(%this.getPositionX(), %this.getPositionY() + 10);
%this.spawnCount ++;
}

I've looked through the forum, but no matter what I try I can't get it to work. Any help to get me through this puzzle would be appreciated.

Thanks!

#1
08/20/2010 (6:43 pm)
At what point does it say object not found?
Where is your collision callback?
#2
08/20/2010 (6:47 pm)
Hi Kevin, thanks for the reply.
The collision callback is defined in Arrow.cs:

function Arrow::onCollision(%this, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contact)
{
if ( %dstObj.class $= "Ghoul" )
{
%dstObj.hurt(30);
%this.safeDelete();
}
}
#3
08/20/2010 (6:57 pm)
I would try changing %this to %srcObj only because that looks weird to me. If that doesn't help (it probably wont), insert a bunch of echo statements so you can see exactly which function loses the object. That will definitely help you nail it down. For example:

function Arrow::onCollision(%this, %dstObj, %srcRef, %dstRef, %time, %normal, %contactCount, %contact)
{
echo("Arrow::onCollision: hit");
   if ( %dstObj.class $= "Ghoul" )
   {
      echo("Arrow::onCollision: found ghoul");
      %dstObj.hurt(30);
      %this.safeDelete();
   }
}

put echos like that everywhere so you can trace the flow and see where it fails.
#4
08/20/2010 (7:07 pm)
function Ghoul::hurt(%this, %damage)
{
   %this.hitPoints -= %damage;
   if ( %this.hitPoints <= 0 )
   {
      %token.spawntoken();//what is %token?
      %this.safeDelete();
   }
}
#5
08/20/2010 (7:09 pm)
Added the echo commands like you suggested. The arrow hits and finds the ghouls. The ghouls dissapear when they get to 0 HP. Where are you suggesting I replace %this with %scrObj ? Sorry about this, I'm new to the language, and I'd like to get this assignment done with the help of the community so I can impress my partner next week :)
#6
08/20/2010 (7:11 pm)
%token does not exist in the code block, hence why it can't find the object to call the spawntoken() function on.
function Ghoul::hurt(%this, %damage)
{
%this.hitPoints -= %damage;
if ( %this.hitPoints <= 0 )
{
%token.spawntoken();
%this.safeDelete();
}
}
I'm a little short on time at the moment so I can't go through all the code, but perhaps, if you structure it like the following, it may work:
function spawntoken()
// The intent of this function is to spawn a token when the function is called.
{ 
%token = new t2dAnimatedSprite("Token" @ %this.spawnCount)
{
scenegraph = %this.scenegraph;
config = "tokenDataBlock";
};
%token.setPosition(%this.getPositionX(), %this.getPositionY() + 10);
%this.spawnCount ++;
}

function Ghoul::hurt(%this, %damage)
{
%this.hitPoints -= %damage;
if ( %this.hitPoints <= 0 )
{
spawntoken();
%this.safeDelete();
}
}
#7
08/20/2010 (7:26 pm)
Patrick is correct. You need to rewrite it so that you can call spawnToken before the token exists. Patrick put this in a global function. But now %this references nothing. My preference would be to make %this into your level class. The level class would store dynamic data relating to the level contents and stuff like that.

function myLevel::spawntoken(%this,%ghoul)
// The intent of this function is to spawn a token when the function is called.
{
   %token = new t2dAnimatedSprite("Token" @ %this.spawnCount)
   {
      scenegraph = %ghoul.scenegraph;
      config = "tokenDataBlock";
   };

   %token.setPosition(%ghoul.getPositionX(), %ghoul.getPositionY() + 10);

   %this.spawnCount ++;
}

function Ghoul::hurt(%this, %damage)
{
   %this.hitPoints -= %damage;
   if ( %this.hitPoints <= 0 )
   {
      $myLevel.spawntoken(%this);//pass in the ghoul
      %this.safeDelete();
   }
}

With this approach you have to change parameters such as spawnCount to belong to the $myLevel object (which makes sense when you think about it).
#8
08/20/2010 (7:27 pm)
Great Patrick! This fixed the first part of the problem :)) Now the game is finding the function, and I'm getting no error messages. However, the object is still not dispalyed on screen and the "coppercoinanimation" is not playing.

For the sake of simplicity, I've changed the setposition coordonates in Spawntoken() to:

token.setPosition(0.062, -11.563);

#9
08/20/2010 (7:50 pm)
Hey Kevin, creating a level class makes perfect sense, as it will make sorting of dynamic data easier. However, after making this re-write, I'm back to square one. The game cannot find the object when attempting to call the funtion 'spawntoken'....

Since the Spawntoken function has two new parameters, and I'm only passing %this as the ghoul, could it be part of the problem?
#10
08/20/2010 (8:03 pm)
function myLevel::spawntoken(%this,%ghoul)
%this = myLevel object

function Ghoul::hurt(%this, %damage)
%this = Ghoul object

Its complicated to explain and difficult to understand if this is your first time working with classes and instantiated objects. I believe your problem now (based on your description) is that you have not defined $myLevel. Try this with your main scenegraph and see what happens:

function myLevel::onLevelLoaded(%this)
{
   $myLevel = %this;
}

You have to go into the level editor and set your scenegraph class to "myLevel".
#11
08/20/2010 (8:21 pm)
This is just GREAT. Really. Now I have a nice token spawning on screen :)))))

I can't tell you how much I apprecitate your help. I'm fired up about making a game, but I'm frustrated about all the baby steps I have to take before I get there.

I think you guys absolutely ROCK!!!!! I think a great part of what makes Torque so powerful is the community. Kevin, Patrick, Achievement unlocked in getting an absolute beginner see the light.

Cheers!!!!!!!! :)))))))))))))))))))))))
#12
08/20/2010 (8:58 pm)
Actually, I still have an error that occurs in this piece of code:

echo ("spawntoken create new sprite intiated.");
%token = new t2dAnimatedSprite("Token" @ %this.spawnCount)
{
scenegraph = %ghoul.scenegraph;
config = "tokenDataBlock";
};
echo ("spawntoken create new sprite done.");

The error I am getting is: "Cannot create namespace parent linkage of Token from t2danimatedsprite to Token"

Any idea what that is?
#13
08/20/2010 (9:24 pm)
%token = new t2dAnimatedSprite("Token" @ %this.spawnCount)
I don't think you are using this part of that line:
"Token" @ %this.spawnCount
It should work fine without it:
%token = new t2dAnimatedSprite()

btw, I'm happy to see you using echo statements to track the flow of your logic!
#14
08/20/2010 (9:35 pm)
Works fantastically. Thanks Kevin. And yes, now I'm finding echo being somewhat the most powerful function in Torque script :)