Swarming the mouse
June 22, 1998
by Pat McClellan
Dear Multimedia Handyman,
I've seen a lot of demos that when you move the cursor, a sprite follows in a delayed smooth movement and then moves accordingly by its own. The best sample is the Director 6's "About Director " in the Apple menu when the Director Application is open, how can I do this?
Daniel
Daniel,
Director 6's "About Director" movie is a work of art. Be sure to let it play long enough to hear the song. Blockbuster Video has stolen this singing smiley face for a recent series of ads... but they just don't do it as well as About Director.
Regarding the movement of the other sprites in this movie... I don't know that I can duplicate the behavior. There are many things interacting to generate the motion and I don't know how these things were prioritized. But, we can take a shot at it and then you can tweak the code until you're happy with it.
Getting a sprite to follow the cursor is easy. Simply set the locH and locV to the mouseH and mouseV. The tricky part is getting the motion to be fluid and delayed. To accomplish this, we'll need to set the location to be a point between where the sprite currently is and the cursor's location.
This behavior will make several sprites on the stage "swarm" toward the cursor at varying speeds. The math involved is easy. First we'll calculate the difference in the current loc and the cursor. Then we'll divide that by a property I call pSpeed. I've set this randomly in the beginSprite handler, though you might want to make this a property to be set in the getPropertyDescriptionList handler.
-- Swarm Behavior (simple) property pSpeed, pMySprite on beginSprite me set pMySprite = the spriteNum of me set pSpeed = random(10) + 5 end on exitFrame me set deltaLoc = (point(the mouseH, the mouseV)¬ - the loc of sprite pMySprite)/pSpeed set newLoc = the loc of sprite pMySprite + deltaLoc set the loc of sprite pMySprite to newLoc end
Now let's expand on this. In addition to responding to the location of the mouse, the motion of the sprites need to be restricted to the stage. We can do this with a simple if statement about the newLoc. If the newLoc is within the stage's rect, then we'll move the sprite to the newLoc. Otherwise, it just stops. We'll set a property called pStageRect in our beginSprite handler. This value is the rect of the stage, less 1/2 the width and 1/2 the height of the sprite. This adjustment is necessary because the loc of sprite refers to the registration point (regPoint) which I have set to the center of these sprites.
-- Swarm Behavior with stage limit property pSpeed, pMySprite, pStageRect on beginSprite me set pMySprite = the spriteNum of me set pSpeed = random(30) + 10 set hMargin = the width of sprite pMySprite/2 set vMargin = the height of sprite pMySprite/2 set pStageRect = rect(0 + hMargin, 0 + vMargin, ¬ the stageRight - the stageLeft - hMargin, the ¬ stageBottom - the stageTop - vMargin) end on exitFrame me set mouseLoc = point(the mouseH, the mouseV) set deltaLoc = (mouseLoc - the loc of sprite ¬ pMySprite)/pSpeed set newLoc = the loc of sprite pMySprite + deltaLoc if inside (newLoc, pStageRect) then set the loc of sprite pMySprite to newLoc end if endFinally, the difficult part is making the sprites pay attention to each other. Let's say we want the sprites to avoid each other. They don't have to repel each other, just no overlaps. This behavior reminds me of Soccer for six-year-olds. They all just swarm around the ball, bouncing off each other.
For this, we'll need to create a global list of all the sprites which are "in the swarm". Start with an on startMovie script that initializes the variable.
on startMovie global gSpriteList set gSpriteList = [] endIn the beginSprite handler of the behavior, add the last line which adds the pMySprite value to the gRectList. Now, after checking to make sure that the new location will be on the stage, we'll also check to see if the new location will intersect any of the other sprites. If so, then we don't move the sprite.
The checkIntersect handler is where we look through the gSpriteList, checking the intersect value of the new rect of our sprite with the rect of the other sprites. As soon as any intersection is found (greater than our "slop" amount), then we jump out of that handler and return a value of 1 for overlap. The sprite is moved only if overlap = 0.
-- Swarm Behavior with stage limit and avoidance property pSpeed, pMySprite, pStageRect global gSpriteList on beginSprite me set pMySprite = the spriteNum of me set pSpeed = random(30) + 10 set hMargin = the width of sprite pMySprite/2 set vMargin = the height of sprite pMySprite/2 set pStageRect = rect(0 + hMargin, + vMargin, ¬ the stageRight - the stageLeft - hMargin, the ¬ stageBottom - the stageTop - vMargin) add gRectList, pMySprite end on exitFrame me set mouseLoc = point(the mouseH, the mouseV) set deltaLoc = (mouseLoc - the loc of sprite ¬ pMySprite)/pSpeed set newLoc = the loc of sprite pMySprite + deltaLoc set newRect = offset(the rect of sprite pMySprite, ¬ the locH of deltaLoc, the locV of deltaLoc) if inside (newLoc, pStageRect) then -- test overlap set overlap = checkIntersect (me, newRect) if NOT overlap then set the loc of sprite pMySprite to newLoc end if end if end on checkIntersect me, newRect set spritesToCheck = count(gSpriteList) repeat with i = 1 to spritesToCheck set whichSprite = getAt(gSpriteList, i) if whichSprite = pMySprite then next repeat else set checkRect = the rect of sprite whichSprite set slopRect = rect(0,0,20,20) if intersect(newRect, checkRect) > slopRect then return 1 end if end if end repeat return 0 endThis is just a start. There are infinite ways you can manipulate the sprites... setting up priorities of motion, dependencies, gravity, etc. Each sprite can also have its own sub-pattern of motion; spinning on a small radius around it's own center of gravity for example. For some great examples of this type of interaction and interdependence, be sure to take some time examining Mark Peden's Amoebic Lifeforms [http://www.mousedown.demon.co.uk/amoebic.lifeforms/start.htm]. (You can also read an interview with Mark in the Developer Profile archives in the Features section.)
Have fun experimenting with the behaviors and good luck with your program.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.