Scheduling issues
by Christo Irving · in Torque Game Builder · 03/16/2007 (6:15 pm) · 7 replies
I am using schedule in a puzzle game to handle the falling pieces. What I'm working on now is a rapid falling command for the down key which doubles the falling speed, all is going alright but it's feeling sluggish because the function has to wait for the last drop (from y to y-1) to be completed. I would like to know if there is a way to speed up or slow down a scheduled event.
The first of the two options I can think of would be to somehow change the wait time after the schedule has been activated, so that a schedule(1000,... acts like a schedule(500,... but I doubt this is really an option.
The second option would be to cancel the schedule, record the time remaining, and double or halve the remainder and use that for a new schedule. So for example if the cancel comes after a schedule(2000,.. has waited 1000ms, a new schedule(500,... would be set up.
...or am I just going at this all wrong?
The first of the two options I can think of would be to somehow change the wait time after the schedule has been activated, so that a schedule(1000,... acts like a schedule(500,... but I doubt this is really an option.
The second option would be to cancel the schedule, record the time remaining, and double or halve the remainder and use that for a new schedule. So for example if the cancel comes after a schedule(2000,.. has waited 1000ms, a new schedule(500,... would be set up.
...or am I just going at this all wrong?
About the author
#2
03/17/2007 (2:05 pm)
Why don't you just make a static tick every x milliseconds which moves the pieces a bit down and if the accelerator key is pressed, the move amount is a big higher than normal. Does that help?
#3
What I have is that the piece ticks down one spot in the grid at a time until it hits the bottom. the important line is:
03/18/2007 (10:19 pm)
That's kinda what I'm doing. Here's the pertinent code (bare in mind that I only had a intro level of C++ so my code might be sloppy. I honestly wouldn't know)...function Matrix::Falling(%this)
{
//check for and stop scheduled falls, otherwise pressing down causes multiple scheduled Falling events
cancel($Dropped);
cancel($CallingFalling);
//check the landscape below
if($y < $HeightOfY[$x])
{
//tick the location counter, animate the fall, and tell the piece to keep Falling
$y++;
$FallingTile.moveTo(%this.getTilePosition($x, $y, 2), 50);
$CallingFalling = %this.schedule(%this.FallSpeed, "Falling");
}else{
//distroy the original and change the tilemap to show where the piece landed, then make a new piece Fall
%this.DisplayTile($FallingTile);
%this.Fall();
}
return;
}What I have is that the piece ticks down one spot in the grid at a time until it hits the bottom. the important line is:
%this.schedule(%this.FallSpeed, "Falling");FallSpeed is how much time there is between ticks, what happens now is that if the player has pushed the down button and not let go when the piece is... ticking, then the next schedule will be faster, and it will remain faster, not until the player lets go, but until the player has let go and the piece has fallen another spot. I want to be able to speed up or slow down the piece while a schedule is running, because it always is running.
#4
You can call back to any object from the scenegraph every tick:
Note that this code assumes that there will be only one "MyThing" object at a time. If you have a series of objects, you might consider storing a SimSet on the scenegraph and iterating over it to update a series of objects.
03/19/2007 (3:57 pm)
Instead of changing the rate at which you reschedule the falling function, you should be updating the object every tick and changing the rate at which it falls.You can call back to any object from the scenegraph every tick:
function MyThing::onLevelLoaded(%this, %scenegraph)
{
// store a reference to this object on the scenegraph
%scenegraph.thing = %this;
}
// this will be called from the scenegraph's onUpdateScene method
function MyThing::update(%this)
{
[...game logic here...]
}
// this assumes your scenegraph is named "MyScene"
function MyScene::onUpdateScene(%this)
{
%this.thing.update();
}Note that this code assumes that there will be only one "MyThing" object at a time. If you have a series of objects, you might consider storing a SimSet on the scenegraph and iterating over it to update a series of objects.
#5
03/20/2007 (10:15 am)
Maybe I'm not understanding what you're suggesting (or maybe your not understanding what I am doing), I think what you have here is a way to have the movement updated every frame but there are two problems with this. The first is the warning in the reference section of the doc...Quote:This is called every frame, and thus is dependent on the frame rate of the engine. Therefore, you should not do any movement of objects here, because the speed at which they move will not be constant.The second problem (and arguably one I may just have to get over) is that my game simply falls one grid cell at a time with an animation of movement instead of smoothly crawling down the screen, with your code I would have to change the way the code works so that events happen when a piece passes a certain point, so the check for whether or not the next spot down is open would happen every 10 clicks down the y axis... right? Or is there a way to use this code simply to handle the speed of the fall and use my current cell based code to handle the logistical end? The problem seems the same, how do you handle a timed event so that the timing can be changed on the fly.
#6
For example:
This is a crude example but should give you the general idea. It remains time-constant regardless of frame rate/update call rate, and you can simply change $timeBetweenMoves to speed up and slow down the rate of fall.
edit: Just wanted to point out that you'd want to initialize %object.lastMoveTime to getRealTime(); when the object first spawns on the board, and there are other common sense things I left out, but hopefully it demonstrates the options available
03/20/2007 (4:03 pm)
Both of your points can be adressed by using the update callback not as a "update the position incrementally every frame" but update the cumulative time that has passed since the last move and check that against a variable that equals the time between actual movement (then you just change that variable as needed to adjust how quick your object moves).For example:
function MyThing::onLevelLoaded(%this, %scenegraph)
{
// store a reference to this object on the scenegraph
%scenegraph.thing = %this;
}
// this will be called from the scenegraph's onUpdateScene method
function MyThing::update(%this)
{
%currentTime = getRealTime();
%timeDifference = %this.lastMoveTime - %currentTime;
if (%timeDifference > $timeBetweenMoves)
{
%moves = mFloor(%timeDifference / $timeBetweenMoves);
%this.moveDownSomeSpaces(%moves);
%this.lastMoveTime = %currentTime - (%timeDifference % $timeBetweenMoves);
}
}
// this assumes your scenegraph is named "MyScene"
function MyScene::onUpdateScene(%this)
{
%this.thing.update();
}This is a crude example but should give you the general idea. It remains time-constant regardless of frame rate/update call rate, and you can simply change $timeBetweenMoves to speed up and slow down the rate of fall.
edit: Just wanted to point out that you'd want to initialize %object.lastMoveTime to getRealTime(); when the object first spawns on the board, and there are other common sense things I left out, but hopefully it demonstrates the options available
#7
03/20/2007 (4:10 pm)
That looks like what I've been looking for. Thanks everyone.
Associate Tom Eastman (Eastbeast314)
I'm not sure if I understand what you're trying to do.