Question

I'm implementing a simple tile-based game which incorporates time based movement.

My code that is responsible for movement and collision detection is

private function onEnterFrame(event:Event):void
{
    if (waiting && game.movingBreakers <= 0)
        endLevel();

    var interval:int = getTimer() - oldTime;
    oldTime += interval;
    var totalBreakers:uint = breakers.length;

    if (totalBreakers)
    {
        for each (var breaker:Breaker in breakers)
        {
            if (!breaker.moving)
                continue;

            switch (breaker.direction)
            {
                case TOP:
                    breaker.y -= SPEED * interval;
                break;

                case BOTTOM:
                    breaker.y += SPEED * interval;
                break;

                case LEFT:
                    breaker.x -= SPEED * interval;
                break;

                case RIGHT:
                    breaker.x += SPEED * interval;
                break;
            }

            checkCollisions(breaker);
        }
    }
}

The issue I faced recently is that for some irrelevant reason with the game, there was a heavy cpu load on my computer. As a result, the frames of the game were updated on a later time, but the sprites (breakers) were at the right position as their movement based on time. However, some collisions were failed due to the fact that the sprites moved at a further position because of the greater time difference between the last two frames. Hence, my question is how can someone solve this collision detection issue in time based movement?

Was it helpful?

Solution

There are a few good ways of solving this scenario when doing movement on delta time.

1) One of the most common ways is to do "fixed time steps". This is essentially an implementation that forces your update() (or a movement() in this case) on the affected object to only run once the "time step" has elapsed. Let's say you have a variable constant for FIXED_STEP:int = 10, this value of 10 represents 10ms. If your delta time (interval) has elapsed 10ms or more you issue the update() however many times your (elapsed time / FIXED_STEP) and any remaining time gets added to the next elapsed time value.

An example would be saying your delta time is 45ms, so you would run update() 4 times and add 5 to your next delta time.

This will allow your collisions to still be detected. Here is a C# explanation that I think explains it pretty well also: Fixed Time Step C# XNA

2) Another way you can do it is to calculate your distance to move your object between frames and then subdivide the distance to create movement steps. i.e. - Your object (a 40x40 rectangle) at point A will move to point B, the distance is 200px on the X axis, you move your object by 200 / object.width (which is 40) = 5, so you will call your movement() 5 times, and move by the objects width of 40px. This will cover the area of movement and your collision can be detected at any one of those movement updates.

There are other ways of doing this but probably not as good for performance reasons. Ray casting and finding the point of intersection on the given path of the object is very accurate but very performance intensive, and would require a bit of digging to learn and implement.

I've also read that some create a new object from the origin before the update() to the position after and use that to do the detection. i.e. - object A at point( 0, 0 ) moves to ( 200, 0 ) after the next frame, you create an area from (0, 0) to (200 + object.width, 0 + object.height) and run the collision test against that object instead.

Anyway I hope this helps, good luck!

OTHER TIPS

You should use the CollisionTestKit library for AS3.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top