Take as much time as you would like to create an image of the car. Make it so that it faces right. Then, once it's in the stack, we'll start adding the required functions to its script. A size of about 40 pixels across should be about right. Our sample car is also available on www.PacktPub.com. The following is a close-up image of what we're talking about, as seen in Photoshop:
Yours can be even better than that, if you like! Save it as a 24-bit PNG that has transparency. Ok, start your engines…:
ImageDataTests
stack. Name it car1
.car2
, car3
, and so on.global gBackdropMaskData,gMaskWidth,gSpeeds,gMovingCars,gMaskWidth
on startStopCars if gMovingCars is true then put false into gMovingCars else put the maskData of image "backdrop" into gBackdropMaskData put the width of image "backdrop" into gMaskWidth setSpeeds put true into gMovingCars send moveCars to this card in 2 ticks end if end startStopCars
setSpeeds
handler, which is called by startStopCars
, will initialize the gSpeeds
variable with a random speed for each of the car images. It will also set the initial direction to zero as well as position the car at a known location in the white area (200, 200
in this case). Add the setSpeeds
handler to the stack script below the startStopCars
handler:on setSpeeds put empty into gSpeeds repeat with a = 1 to 100 put "car" & a into carname if there is a image carname then put (random(10)+10)/10 into item 1 of line a of gSpeeds put 0 into item 2 of line a of gSpeeds set the loc of image carname to 200,200 else exit repeat end if end repeat end setSpeeds
moveCars
handler, shown in step 8, we're going to look at the gBackdropMaskData
variable to check whether the car is going to run into something solid. Add this hitBarrier
function:function hitBarrier pX,pY put (pY-1)*gMaskWidth + pX into tStartChar put charToNum(char tStartChar of gBackdropMaskData) into tMaskValue if tMaskValue = 255 then return true else return false end hitBarrier
moveCars
handler is initially called by the startStopCars
handler, and then, it calls itself after every two ticks until the gMovingCars
variable is set to false
. Type in the long moveCars
handler into the stack script:on moveCars put the long time lock screen repeat with a = 1 to 100 put "car" & a into carname put .1 into anglechange if there is a image carname then put 0 into counter repeat while counter < 20 add 1 to counter put item 1 of line a of gSpeeds into tCarSpeed put item 2 of line a of gSpeeds into tCarDirection put item 1 of the loc of image carname into tCarX put item 2 of the loc of image carname into tCarY put the round of ((cos(tCarDirection)*tCarSpeed)*20 + tCarX) into tLookAheadX put the round of ((sin(tCarDirection)*tCarSpeed)*20 + tCarY) into tLookAheadY if hitBarrier(tLookAheadX,tLookAheadY) then put tCarDirection + anglechange into item 2 of line a of gSpeeds put anglechange * -1 * ((20 - random(10))/10) into anglechange put max(1,tCarSpeed - .1) into item 1 of line a of gSpeeds else put min(3,tCarSpeed + .05) into item 1 of line a of gSpeeds exit repeat end if end repeat set the loc of image carname to item 1 of the loc of image carname + (tLookAheadX-item 1 of the loc of image carname)/10,item 2 of the loc of image carname + (tLookAheadY-item 2 of the loc of image carname)/10 set the angle of image carname to 360 - item 2 of line a of gSpeeds / PI * 180 else exit repeat end if end repeat unlock screen if gMovingCars is true then send moveCars to this card in 2 ticks end moveCars
Collision avoidance
Take a moment to look at the moveCars
handler; what is it doing? You will no doubt have heard about collision detection; this is where you have code that recognizes when one object has collided with another object or a wall perhaps. You might as well trigger an explosion or a collision sound when that happens. For our example though, we actually don't want things to collide, as we want the cars to turn before they collide. For each car, up to 100 of them, we will look ahead of the car to check whether it collides with the edges of the course. If it's going to do so, we will change the direction that the car is heading toward, repeatedly, until a safe forward direction is found.
on mouseUp startStopCars end mouseUp
state
field you created changes.Having already used imageData to implement a color picker and to act as multiple button areas, we went on to use the maskData of the image as a collision map. There is quite a bit of arithmetic behind making the cars move in intelligent ways, and you could go on to change some of the numbers to get different behavior from the cars or you could take a break and get ready to make a jigsaw puzzle!
For the U.S. map, we only needed to simulate 50 buttons. If you make use of the red, green, and blue values, how many buttons could you simulate?
Answer: 3
As with the discussion about bits and bytes (hey, I'm sure we weren't going to see these words for the rest of this chapter!), the red, green, and blue values combine to give us 2 to the power of 24 possible values. If you only used two of the colors, then the answer would have been 65,536.
The things we have tried so far in this chapter use techniques that would be useful in any LiveCode application and are not specific to mobile applications. You can try the stack you have constructed; it will work well on a mobile device with 20 cars driving around the screen! The color picker and states map work on a mobile when its screen is touched. However, these tests don't really make use of the mobile features.