Game Development Community

trigger moving towards

by Anthony Ratcliffe · in Torque Game Builder · 04/28/2009 (2:45 pm) · 24 replies

hi there, i'll set the scene I have a a player named playerclass and class named player. I have an enemy.class name enemy with a trigger mounted to it with the class name enemytigger. what im trying to do is move toward the player when the player moves within the trigger, i tried dissembling the move towards behavior and came up with this

function enemytrigger::onEnter(%this, %object)
{
%this.enemy.moveTo(%playerclass.object.position, 10);
echo("im in the trigger");
}

i think im along the right lines the trigger fire however i get no move towards

i have an error in the log
game/gameScripts/enemy.cs (7): Unable to find object: '' attempting to call function 'moveTo'

doesn't seem to be able to find my playerclass.

its been a good year since i used tgb and never used trigger before so would anyone mind explain correcting my work

regards ant
Page «Previous 1 2
#1
04/28/2009 (6:28 pm)
Hi there, I think I see what's wrong with your code.

In your code example, %this is a reference to the trigger object, not your enemy. %object would be a reference to your your playerClass (or whatever collided with your trigger).


If you define an enemy global variable $enemy, earlier in your code, regarding this current enemy, it will be easy to access it.

$enemy.moveTo(%object.position());

Without seeing the rest of your code, it's hard to tell exactly what will work. Whatever you do, just be sure you realize what %this, and %object are.

Another option may be to create a SimSet, of all your enemies, and loop through each of them each time your player moves. Something like this:

%distance = t2dVectorDistance(%playerClass.position(), %enemy.position();

if (%distance <= %enemyRange)
{
%enemy.moveTo(%player.position());
)


Hope that's helpful!

#2
04/28/2009 (6:34 pm)
thats all my code atm, im not a fan of vector and i really not sure it would work in this game.

so i could do somthing like this

name enemy
class name enemyclass

//code//

enemyclass = $enemy

function enemytrigger::onEnter(%this, %object)
{
$enemy.moveTo(%playerclass.position,10());
echo("im in the trigger");
}
#3
04/29/2009 (10:19 am)
Hi Anthony,

Earlier in your your code, you will need to assign an object pointer to the current enemy to $enemy...
$enemy = %enemyObject;

function enemyTrigger::onEnter(%this, %object)
  {
    $enemy.moveTo(%object.position());
  }

You don't have to specify %playerclass explicitly. If a playerClass object enters your trigger, a reference to it will be passed to the trigger via %object. This way you can make calls directly to it from within the trigger. Does that make sense?

To make better sense of it, it might help to know ow to check what %object is. If you only want it to move toward your player, not other objects, you may want to check that it's a player first:

$enemy = %enemyObject;

function enemyTrigger::onEnter(%this, %object)
  {
    if(%object.class $= "playerClass")
      {
        $enemy.moveTo(%object.position());
      {
  }
#4
04/29/2009 (11:28 am)
i've just tried your code and it came up with errors.

$enemy = %enemyObject;

function enemytrigger::onEnter(%this, %object)
{
if(%object.class $= "playerClass")
{
$enemy.moveTo(%object.position());
{
}



function enemytrigger::onLeave(%this, %object)
{
}



///////ERRORS/////////


>>> Some error context, with ## on sides of error halt:
enemy = %enemyObject;



function enemytrigger::onEnter(%this, %object)

{

if(%object.class $= "playerClass")

{

$enemy.moveTo(%object.position());

{

## ## }







function enemytrigger::onLeave(%this, %object)

{

}
>>> Error report complete.
#5
04/29/2009 (1:16 pm)
Sorry about that.

I didn't include the velocity. this should be the correct syntax now.

$enemy.moveTo(%object.position(), 10);
#6
05/03/2009 (9:18 am)
still errors from that code u included

$enemy = %enemyObject;

function enemytrigger::onEnter(%this, %object)
{
if(%object.class $= "playerClass")
{
$enemy.moveTo(%object.position(), 10);
{
}



function enemytrigger::onLeave(%this, %object)
{
}




////error////////////

>>> Some error context, with ## on sides of error halt:
enemy = %enemyObject;



function enemytrigger::onEnter(%this, %object)

{

if(%object.class $= "playerClass")

{

$enemy.moveTo(%object.position(), 10);

{

## ## }







function enemytrigger::onLeave(%this, %object)

{

}


>>> Error report complete.

Activating DirectInput...
DirectInput joystick failed to enable!
Loading compiled script C:/Documents and Settings/Administrator/Desktop/game/MyGames23/MyGame/game/data/levels/untitled.t2d.
Error: cannot change namespace parent linkage of bullet from t2dStaticSprite to bullet.
#7
05/03/2009 (9:34 am)
another way i was think of doing it is to call a behaviour insted

if player is in the trigger
play this behaviour
and this one
untill dead
is somthing like thta possible
#8
05/03/2009 (9:39 am)
example using the face towards behaviour


function FaceObjectBehavior::onUpdate(%this)
{

IF PLAYER IN ENEMY TRIGGER RUN THIS TURN TOWARDS CODE
{
if (!isObject(%this.object))
return;

%vector = t2dVectorSub(%this.object.position, %this.owner.position);
%targetRotation = mRadToDeg(mAtan(%vector.y, %vector.x)) + 90 + %this.rotationOffset;

if (%this.turnSpeed == 0)
%this.owner.setRotation(%targetRotation);
else
%this.owner.rotateTo(%targetRotation, %this.turnSpeed, true, false, true, 0.1);
}
}
#9
05/04/2009 (5:46 pm)
anyone? i cant find any examples of just simply using a trigger to move enemys this is getting silly
#10
05/08/2009 (10:50 pm)
bump
#11
05/09/2009 (4:08 pm)
Hi Anthony,

Maybe if you post a bit more of your code, it would be easier to troubleshoot. The logic is simple, really. When an object of a given class enters the trigger, call a moveto on it.
#12
05/09/2009 (4:36 pm)
thats all the code ive written so far just want to get this trigger working first. im just moving the enemy class name enemyclass with a trigger classname enemytrigger when the play classname playerclass walks in he moves to him
#13
05/09/2009 (5:25 pm)
Hi Anthony,

Apologies for not doing this sooner, but I've been baffled by your issue, so I spent a little time building this for you as an example. I think I've commented it quite thoroughly, but let me know if you have any questions :

function enemyClass::onLevelLoaded(%this, %sceneGraph)
{
  
   // There is a sprite already loaded in the level builder
   // class was set to enemyClass, which is why this method will be called
     
     
   // Create a global variable, and assign it a
   // pointer to this enemy (the one that's loaded in the level bulder) 
   $enemy = %this;
     
   // Turn on debug, so we can see the trigger
   %sceneGraph.setDebugOn(5);
  
  
  // Create a trigger, notice the variable name we are assigning it to
  // "%this" is the enemy set up in the level builder, so 
  // we are assigning this enemy it's own trigger.  
  // This will allow us to move this enemy's trigger more easily.
  
  
     %this.triggerObject = new t2dTrigger() {
      canSaveDynamicFields = "1";
      sceneGraph = %sceneGraph;
      class = "enemyTrigger";
      Position = %this.position;
      size = "20 20";
      CollisionActiveSend = "1";
      CollisionActiveReceive = "1";
      CollisionCallback = "1";
        
   };
   
   // Ok, this is a bit goofy, but can be handy later
   // in english this is saying:
   // this enemy's trigger object has a field called parentObject, 
   // the value of which is a reference to this enemy. 
   %this.triggerObject.parentObject = %this;   
   
   
   // Let's make good use of our enemy object, and store it's speed
   // this is nice to do if you will have different enemies of varying speed
   // And we are making the enemy move via different functions, so this will
   // ensure it moves at a consistant velocity.
   %this.speed = 10;
   
   // Enable Update Callback on this enemy, 
   // so we can make the trigger move with the enemy 
   %this.enableUpdateCallback();
   
   // Bonus feature, we can make the enemy move back to it's original spot
   // after the player leaves it's range.  This is mainly to demonstrate
   // an example use of the trigger onLeave method.
   %this.originalPosition = %this.position;
}

function playerClass::onLevelLoaded(%this, %sceneGraph)
{
   // A player sprite was already configured in the level editor,
   // class was set to playerClass, which is why this method will be called   
   
   // a global reference to this player   
   $player = %this;
   
   // send collisions, and receive. 
   // send to your trigger, receive from the enemy. 
   // receiving is assumed because the enemy will probably be
   // able to collide with your player to damage it.
   %this.setCollisionActive(true, true); 
   %this.setCollisionCallback(true);
   
}


function enemyClass::onUpdate(%this)
{
 
   // Make the trigger move with the enemy, if necessary.
   // %this is referring to the enemy, not the trigger, but we can access 
   // the triggerObject stored within %this...
   %this.triggerObject.setPosition(%this.position);
 
}

function enemyTrigger::onEnter(%this, %object)
{
   // IMPORTANT!
   // %this = this trigger!
   // %object = the object which collided with the trigger
      
   // comment just for debugging purposes   
   echo("Something entered the trigger!");
   
   if (%object.class $="playerClass")
   {
      // comment just for debugging purposes       
      echo(" A PlayerClass object entered the trigger!");  
      
      // We don't have a reference to the enemy, Good thing
      // we made a global reference!   
      $enemy.moveTo(%object.getPosition(), $enemy.speed);
      
      // Here's an example of using a reference, if we did make one.
      // un Comment the line above to test this way.
      // %this.parentObject.moveTo(%object.getPosition(), %this.parentObject.speed);
      
      
   }
}


function enemyTrigger::onLeave(%this, %object)
{
   
   // comment just for debugging purposes       
   echo("Something just left the trigger!");    
   
   // IMPORTANT!!   
   // %this = this trigger, not this enemy
   // %object = the object that just left this trigger 
   // We don't have a reference to the enemy, Good thing
   // we made a global reference!
   $enemy.moveTo($enemy.originalPosition, $enemy.speed);  
   
   // or an example using the reference back to the parent object
   // uncomment the line above to test this way...
   //%this.parentObject.moveTo(%this.parentObject.originalPosition, %this.parentObject.speed);
}

function enemyClass::KillMe(%this) 
{
   // Kill this enemy's trigger first...
   %this.triggerObject.safeDelete();
   
   // Then kill this enemy!
   %this.safeDelete();
}

Let me know how this works out for you.

Johnny
#14
05/09/2009 (5:42 pm)
FYI,

In the above example, carefully read all the comments in the trigger onLeave and onEnter area.

I demonstrated two ways of doing almost the same thing. Accessing the global variable will probably be fine for your player, because you probably will only ever have one. It will work just fine for one enemy, but in the case that you have several enemies (which is most likely) I've included, in the trigger, a reference back to the parent.

This may be strange, but it works just fine. I think there is a method getParent(), or something like that, but I haven't looked it up. This works, so I just use it that way.

I hope this helps, I know you've been struggling with it for a bit now.

Johnny
#15
05/09/2009 (7:40 pm)
thats a great example and i thank you so much however a weird issue has arised, my key commands work fine, when i add the enemy.cs they stop, and the only way to test was to use the shooter behaviour to move my player
#16
05/09/2009 (7:48 pm)
another weird thing is if i place 3 enemyclass objects in the scene only 1 will move?

edit 4 am here didnt read it properly sorry!
another edit after looking at it i dont really understand how to move more than one? is it simple declaring another varible? however im not sure how
#17
05/09/2009 (10:13 pm)
Hi Anthony, without seeing your code, it's hard to tell why your key commands stopped working.

To get all the enemies working, you can't call them by using the $enemy variable. You will need to call them individually. Like the other example of adding the reference to the trigger, and a reference back to the parent. You'll have to add triggers to each of the enemies, via script, so they get stored in the enemy object. I would create the enemy via script, and add the triggers as part of the spawn method. Look at the shooter demo to get an idea of how to spawn your sprites.
#18
05/10/2009 (9:28 am)
sorry im not to sure what you mean by "Like the other example of adding the reference to the trigger, and a reference back to the parent" I planned on having the sprites sit in the level not loading them on the fly

edit - sorted the problem by having various scripts for various enemys, another problem it seems as well as the control one is i cannot add the turret behavior to them otherwise they don't seem to think im in the trigger


this is my player controls that dont seem to work once i add this script

///code///
function playerclass::onLevelLoaded(%this, %scenegraph)
{
$player = %this;

moveMap.bindCmd(keyboard, "left", "playerLeft();", "playerLeftStop();");
moveMap.bindCmd(keyboard, "right", "playerRight();", "playerRightStop();");
moveMap.bindCmd(keyboard, "up", "playerup();", "playerupStop();");
moveMap.bindCmd(keyboard, "down", "playerdown();", "playerdownStop();");

%this.enableUpdateCallback();
}
function playerLeft()
{
$player.moveLeft = true;
}

function playerLeftStop()
{
$player.moveLeft = false;
}

function playerRight()
{
$player.moveRight = true;
}

function playerRightStop()
{
$player.moveRight = false;
}

function playerup()
{
$player.moveup = true;
}

function playerupStop()
{
$player.moveup = false;
}


function playerdown()
{
$player.movedown = true;
}

function playerdownStop()
{
$player.movedown = false;
}



function playerclass::update(%this)
{
if (%this.moveLeft && %this.moveRight)
{
%this.setLinearVelocityX(0);
return;
}

if (%this.moveLeft)
{
if (!%this.againstLeftWall)
{
%this.againstRightWall = false;
%this.setLinearVelocityX(-30);
}
return;
}

if (%this.moveRight)
{
if (!%this.againstRightWall)
{
%this.againstLeftWall = false;
%this.setLinearVelocityX(30);
}
return;
}

if (!%this.moveLeft && !%this.moveRight)
{
%this.setLinearVelocityX(0);
}




if (%this.moveup && %this.movedown)
{
%this.setLinearVelocityy(0);
return;
}

if (%this.moveup)
{
if (!%this.againstupWall)
{
%this.againstdownWall = false;
%this.setLinearVelocityy(-30);
}
return;
}

if (%this.movedown)
{
if (!%this.againstdownWall)
{
%this.againstupWall = false;
%this.setLinearVelocityy(30);
}
return;
}

if (!%this.moveup && !%this.movedown)
{
%this.setLinearVelocityy(0);
}


}


function playerclass::onUpdate(%this)
{
%this.update();



%this.setCurrentAnimation();
}

function playerClass::setCurrentAnimation(%this)
{

if ($player.moveLeft == true || $player.moveRight == true || $player.moveup == true || $player.movedown == true)
{
if (%this.getAnimationName() $= "playerRunAnimation")
{
if(%this.getIsAnimationFinished())
{
%this.playAnimation(PlayerRunAnimation);
return;
}
}else
{
%this.playAnimation(PlayerRunAnimation);
}
}else
{
%this.playAnimation(PlayerStandAnimation);
}
}
#19
05/10/2009 (3:23 pm)
just a note adding the deals damage behaviour also makes the enemy disappear :S
#20
05/11/2009 (9:37 am)
Hi Anthony.

The code I made for you contains two example ways to access your objects from a method originating in another class. Read the comments in my code, so you can see what I'm doing (using $enemy, or %this.parentObject).


OK, you are running playerClass::onLevelLoaded twice. Once in my code, once in your code. You need to combine these, and run it one time. More importantly, you need to combine the playerClass::onUpdate methods, too.

I think this thread has exhausted beyond the scope of getting an object to move toward another object. I don't mean to be rude, but you are going to have to look at example code as just that, an example. You can't just cut and paste it into your project and expect it to work. You have to analyze how it works, then you will be able to figure out how to merge it with your existing project.

I can't anticipate all the things you've already accounted for.

FYI, I think it's great to use the level builder to get started, but it's VERY important to look at the code it generates, to understand how it works. It's important to ween yourself away from relying on it too heavily.

Read the behavior tutorial/documentation, get used to what behaviors are doing. Do you have 10 different things running updates and callbacks? Each of those happen every 32 milliseconds. Are they all on the same object? Can they all be combined into a single method? It's important to read about what callbacks are and what happens with onUpdate. How/why does onLevelLoaded run, or not run? Knowing this stuff is fundamental to you being successful with Torque.



Page «Previous 1 2