Articles Archive
Articles Search
Director Wiki
 

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!

Will Turnage is a multimedia programmer based in New York City. In addition to his weekly role as Director Online's Multimedia Handyman, he is also the Technology Director for Sony Music's Client Side Technologies Group. You can read more about his work at http://will.turnage.com/.

Copyright 1997-2017, Director Online. Article content copyright by respective authors.