Using Timers - Callback Function? [Solved]
by Jesse Allen · in Torque 2D Beginner · 01/01/2014 (5:41 am) · 5 replies
Happy New Year guys!
I've been trying to get some timers working within a couple Behavior.cs files and not having much luck. I was hoping someone may be able to light the way and tell me what I'm doing wrong here.
PlayerControlsBehavior
In one case, I am dealing with player controls. In my PlayerControlsBehavior.cs I have a function called updateMovementX(). This just updates the LinearVelocityX of the character. Now, the problem I was trying to solve was that every time the character moved right, bumped a wall, and then jumped he wouldn't continue going right and clear the wall. So what I did was I just set a timer in another function, updateMovementY(), like so:
This is basically firing off the updateMovementX() function 4 times within a second after the character jumps, granted that the character is moving. This actually worked, and my character is now able to clear jumps even if he bumps the wall first while holding a direction key. But there is one small problem. My console keeps yelling at me:
SimObject::startTimer() - The callback function of 'updateMovementX' does not exist.
I'm not sure what I am or am not doing correctly since I am getting the results I wanted and the timer seems to be working.
WanderBehavior
The other case deals with an NPC's movement behavior. In my WanderBehavior.cs I have 2 functions called moveLeft() and moveRight(). Then I have a 3rd function called randomMovement() that just randomly decides if the character should start up moveLeft() or moveRight(). Alright, so what's the problem? Well I am trying to have the NPC start a timer when it collides with the terrain that will call the function randomMovement() every so often. So my onCollision looks like this:
In this case, it's even worse because I get the error about the callback function not existing and it doesn't work. If I change the timer to:
Any advice or direction here would be welcomed, I've exhausted all the options to solve this I've come up with. I've looked into behavior outputs and inputs, and vaguely understand that concept although I am not sure if that would apply here or not. Anyhow I hope someone might be able to clear this all up for me! Cheers and Happy New Year forum-goers!
I've been trying to get some timers working within a couple Behavior.cs files and not having much luck. I was hoping someone may be able to light the way and tell me what I'm doing wrong here.
PlayerControlsBehavior
In one case, I am dealing with player controls. In my PlayerControlsBehavior.cs I have a function called updateMovementX(). This just updates the LinearVelocityX of the character. Now, the problem I was trying to solve was that every time the character moved right, bumped a wall, and then jumped he wouldn't continue going right and clear the wall. So what I did was I just set a timer in another function, updateMovementY(), like so:
function PlayerControlsBehavior::updateMovementY(%this)
{
%this.owner.setLinearVelocityY((%this.jump) * %this.jumpSpeed);
$PlayerGrounded = false;
if($PlayerGrounded == false)
{
if(World.PlayerMoving == true)
{
%this.owner.startTimer("updateMovementX", 250, 4);
}
}
}This is basically firing off the updateMovementX() function 4 times within a second after the character jumps, granted that the character is moving. This actually worked, and my character is now able to clear jumps even if he bumps the wall first while holding a direction key. But there is one small problem. My console keeps yelling at me:
SimObject::startTimer() - The callback function of 'updateMovementX' does not exist.
I'm not sure what I am or am not doing correctly since I am getting the results I wanted and the timer seems to be working.
- Why is the console yelling at me?
- Is there a difference between a 'regular' function and a 'callback' function?
- If so, how do I ensure that the function I am trying to call on with my Timer will be recognized as a 'callback' function?
WanderBehavior
The other case deals with an NPC's movement behavior. In my WanderBehavior.cs I have 2 functions called moveLeft() and moveRight(). Then I have a 3rd function called randomMovement() that just randomly decides if the character should start up moveLeft() or moveRight(). Alright, so what's the problem? Well I am trying to have the NPC start a timer when it collides with the terrain that will call the function randomMovement() every so often. So my onCollision looks like this:
function WanderBehavior::onCollision(%this, %object, %collisionDetails)
{
if(%object.class $= "BiomeClass")
{
%this.owner.npcGrounded = true;
//echo("Wanderer on ground.");
%this.owner.startTimer(%this.randomMovement(), 5000);
}
}In this case, it's even worse because I get the error about the callback function not existing and it doesn't work. If I change the timer to:
%this.owner.call(%this.randomMovement());it will work but of course the NPC will never call randomMovement again. So basically he'll take off in one direction randomly and that's it; I want him to take off in one direction, and then (using a timer) know to stop and consider what direction he's going and act accordingly from time to time. It also should be noted here that if the NPC is starting this timer onCollision with the terrain, a timer might not be the best option here since he'll be colliding with the terrain pretty much constantly. Suggestions?
Any advice or direction here would be welcomed, I've exhausted all the options to solve this I've come up with. I've looked into behavior outputs and inputs, and vaguely understand that concept although I am not sure if that would apply here or not. Anyhow I hope someone might be able to clear this all up for me! Cheers and Happy New Year forum-goers!
About the author
Skilled Artist and Musician. Intermediate Torque Developer.
#2
You are, as usual, correct that there is no reason to be doing this on collision. Perhaps the first time collision occurs as you've illustrated above, but just on collision will lead to all sorts of a mess. I was initially doing this because I hadn't figured out other ways to trigger things happening. With a better understanding of the %this and %this.owner difference I believe I am equipped to make some of this stuff work with timers! Thanks a ton Simon, helpful as always!
01/01/2014 (11:36 am)
Wow Simon. Perfectly clear explanation of what's going on here, thanks. I haven't had a chance to plug it in yet, but I know it will work just by reading over this here. I've just been calling on something that quite literally doesn't exist, just as the console log has been telling me. You are, as usual, correct that there is no reason to be doing this on collision. Perhaps the first time collision occurs as you've illustrated above, but just on collision will lead to all sorts of a mess. I was initially doing this because I hadn't figured out other ways to trigger things happening. With a better understanding of the %this and %this.owner difference I believe I am equipped to make some of this stuff work with timers! Thanks a ton Simon, helpful as always!
#3
For the PlayerControlsBehavior I just changed:
For the WanderBehavior I just had to put the timer in the onBehaviorAdd() function to get it rolling.
Glad to have a simple solution for once, cheers!
01/01/2014 (3:20 pm)
Update:I was able to get both cases working rather easily with your advice Simon, thanks again. For anyone who may be reading, here's what I changed:For the PlayerControlsBehavior I just changed:
%this.owner.startTimer("updateMovementX", 250, 4);to:%this.startTimer("updateMovementX", 250, 4);For the WanderBehavior I just had to put the timer in the onBehaviorAdd() function to get it rolling.
Glad to have a simple solution for once, cheers!
#4
Your questions are pretty well formulated, thus easy to answer with concrete examples; I really think these posts will help others starting out with T2D!
Keep it up, Jesse.
01/01/2014 (4:20 pm)
Congrats!Your questions are pretty well formulated, thus easy to answer with concrete examples; I really think these posts will help others starting out with T2D!
Keep it up, Jesse.
#5
Simon, I followed your updates to the source here:
Cursor Bitmap Forum Post
Using this I was able to get the custom cursor working, thanks a ton Simon! I've been using a sprite with a script to make it stick to the mouse onTouchDragged. This is okay, but leads to strange rendering in some cases. I believe the change here to make the platform cursor 'go away' will end up being much better. Thanks again my friend!
Update: Actually, sooner than later I suppose. Ran into a snag with the cursor. Custom Cursor
01/03/2014 (3:32 am)
Well I was just about to post about custom cursors not showing up, but then I decided to try and recompile the solution myself.Simon, I followed your updates to the source here:
Cursor Bitmap Forum Post
Using this I was able to get the custom cursor working, thanks a ton Simon! I've been using a sprite with a script to make it stick to the mouse onTouchDragged. This is okay, but leads to strange rendering in some cases. I believe the change here to make the platform cursor 'go away' will end up being much better. Thanks again my friend!
Quote:Keep it up, Jesse.You bet. Many postings just like this one have helped me tremendously in learning about T2D. I'll be sure to ask if I need help; I have been fortunate to have had the support of the community up to this point. Many of the forum-goers here are very good at problem-solving, and as such are starting to (oh no!) rub off on me! Giving solid attempts, I'm finding that I am starting to solve many problems without needing to ask questions. This doesn't change the fact that I am very new to the engine and coding in general, so surely I'll need help again soon!
Update: Actually, sooner than later I suppose. Ran into a snag with the cursor. Custom Cursor
Associate Simon Love
Owners and behaviors aren't the same object!
%this.owner.startTimer("updateMovementX", 250, 4);This tells the owner of the Behavior to call its own version of updateMovementX, but the function exists in the Behavior's namespace and not its owner's!
%this = the Behavior object.
%this.owner = The player object on which the Behavior exists.
One way around this would be to define an updateMovement function on your owner object, which then calls on its behavior's updateMovementX.
new Sprite(MyPlayerObject) { //...create the behaviors... playercontrolsbehavior = /*your behavior instance*/ } function MyPlayerObject::updateMovementX(%this) {... %this.playercontrolsbehavior.updateMovementX(); }I initially thought that Behavior connections would be a solution, but while you can delay a raised output, you cannot tell it to delay the input after this; Connections are meant to fire off in immediate sequence
I think that this is also the error in the WanderBehavior, remember that
will always look for the callback function on the object calling startTimer.
As for the wandering collision issue, I just don't understand why you feel obligated to start it onCollision. Maybe something like a variable which determines if this is the first time collision occurs?
in onCollision,
if(%this.firsttime) { %this.owner.startTimer(%this.owner.randomMovement(), 5000); %this.firsttime = false; }Remember there are a many ways to solve these problems; be creative and you'll figure it out.
Don't worry, it's just like playing guitar, once you get comfortable with it, what at first seemed insurmountable becomes routine.
Happy New Year!