Racing in a Figure Eight
December 3, 2000
by Will Turnage
Dear Multimedia Handyman
I'm working on a racing game view from above, and the track is shaped like a figure eight. How can I make it so that the car doesn't run off the course? I've seen examples of how to do this with straight borders, like in a maze, but not round ones.
Arno
Dear Arno,
I was working on exactly this problem a few weeks ago, and after being up to my neck in complex mathematical algorithms it hit me that the best way to do this type of collision detection involves no math at all. Essentially, all you have to use is the Lingo terms sprite within and sprite intersects.
Normally, the Lingo terms sprite within and sprite intersects determine their results based on the bounding rectangles of each sprite. In the case of a figure eight, this really doesn't help us out.
However, if both sprites have a Matte ink applied, then Lingo checks the actual outline of each sprite instead of checking the bounding rectangles.
In this example, we'll start off with two sprites, one for the race track itself and another for the race car. On every frame, we'll check to see if the car is within the race track. If so, then we'll move the car forward. Otherwise, we can assume that the car hit the edge of the track, and we'll move it backwards.
property pLoc
property pMySprite
property pSpeed
on beginSprite me
pMySprite = sprite(me.spriteNum)
pLoc = pMySprite.loc
pSpeed = 5
end
on prepareFrame me
calculateLocation(me)
end
on calculateLocation me
--the sin and cos functions work using
--radians instead of degrees so first we
--have to convert the angle to radians
angleInRadians = pMySprite.rotation * pi() / 180.0
--next we calculate the amount of locH
--and locV that we travel
tempH = -(pSpeed * sin(angleInRadians))
tempV = pSpeed * cos(angleInRadians)
-- set the sprite equal to it's new location
pMySprite.loc = pLoc + point(tempH, tempV)
-- if the sprite is within the race track then
if pMySprite.within(sprite(1)) then
-- check to see if the sprite intersects
-- the loops in the middle
if pMySprite.intersects(sprite(3)) or pMySprite.intersects(sprite(4)) then
-- move the sprite backward
pLoc = pLoc - point(tempH, tempV)
else
-- move the sprite forward
pLoc = pLoc + point(tempH, tempV)
end if
else
-- otherwise, move the sprite backwards
pLoc = pLoc - point(tempH, tempV)
end if
pMySprite.loc = pLoc
end
This solution works really well until you realize that the car can still run over the inside of the figure eight. To fix this, you need to create separate Cast members for the insides of the figure eight. Place the new bitmaps in the Score, and be sure to apply the Matte ink.
Now, all we have to do is add one more check to the script. This script will first look to see if the car is inside the track. If so, then it will check to see if you're colliding with one of the center pieces.
-- if the sprite is within the race track then
if pMySprite.within(sprite(1)) then
--check to see if the sprite intersects
--the loops in the middle
if pMySprite.intersects(sprite(3)) or
pMySprite.intersects(sprite(4)) then
-- move the sprite backward
pLoc = pLoc - point(tempH, tempV)
else
-- move the sprite forward
pLoc = pLoc + point(tempH, tempV)
end if
else
-- otherwise, move the sprite backwards
pLoc = pLoc - point(tempH, tempV)
end if
A sample Director 7 movie is available for download in Mac or Windows format.
Good luck racing!
Copyright 1997-2024, Director Online. Article content copyright by respective authors.