Bumping into things
I keep track of which sprites overlap which, every tick, so you don’t have to check every pair yourself. When two start to touch, I tell each one, and when they come apart, I tell them that too.
Walls
A boundary is a rectangle that’s part of the level: a floor, a wall, the edge
of the screen. BOUNDARY ADD gives it a name and two corners with -> between them. A solid
sprite can’t go through a solid boundary; with enclosure, it can’t get out
of one.
SCREEN 320, 240
MEMORYBUFFER "ball", 12, 12
CIRCLE (6, 6), 5, 14, 14
END MEMORYBUFFER
BOUNDARY ADD "box", (20, 20) -> (300, 220) !! solid enclosure
LINE (20, 20) -> (299, 219), 8 !! box
BEHAVIOR "fly"
IMPULSE 3, 2
BOUNCE 1, 1
END BEHAVIOR
ENABLE SPRITE 0
SET SPRITE 0 !! image("ball") x(100) y(60) solid behavior("fly")
SHOW SPRITE 0
PAUSE
IMPULSE 3, 2 is a push, once, when the behavior starts, and the ball keeps
the speed it was given. BOUNCE 1, 1 turns it around when it runs into
something solid, and keeps all of its speed: BOUNCE 0.8, 0.8 would lose a
fifth of it at every bounce.
Crash-tan’s Tip:
VELOCITYsets the speed again every tick, so a sprite withVELOCITYcan’t be turned around by a bounce. For things that bounce, push them withIMPULSE.
Finding out
ONCOLLISION, inside a behavior, runs when a sprite with that behavior
touches something. It’s given who it is (me), what it touched (other, a
sprite’s number, or -1 for a boundary), the other thing’s tag (other_tag),
and for a boundary, which edge of it was hit. It runs on my tick, beside
your program, so here it only counts, and the loop does the drawing.
SCREEN 320, 240
MEMORYBUFFER "ball", 12, 12
CIRCLE (6, 6), 5, 15, 15
END MEMORYBUFFER
BOUNDARY ADD "box", (0, 0) -> (320, 240) !! solid enclosure
hits = 0
last = ""
BEHAVIOR "fly"
IMPULSE 4, 3
BOUNCE 1, 1
ONCOLLISION
hits = hits + 1
last = edge
END ONCOLLISION
END BEHAVIOR
ENABLE SPRITE 0
SET SPRITE 0 !! image("ball") x(160) y(120) solid behavior("fly")
SHOW SPRITE 0
DO
IF COOLDOWN(1)
FRAME
CLS
LOCATE 1, 1
PRINT "hits:", hits, " last edge:", last
END FRAME
END IF
LOOP
Sprites touching sprites
Two sprites don’t have to be solid to touch. I tell them whenever they
overlap. AFTERCOLLISION runs when they come apart again.
SCREEN 320, 240
MEMORYBUFFER "blue", 16, 16
LINE (0, 0) -> (15, 15), 9 !! box fill
END MEMORYBUFFER
MEMORYBUFFER "red", 16, 16
LINE (0, 0) -> (15, 15), 12 !! box fill
END MEMORYBUFFER
TOSPRITESHEET "block", ["blue", "red"]
BEHAVIOR "slide"
VELOCITY PARAM("vx", 1), 0
ONCOLLISION
IF other >= 0 THEN SET SPRITE me !! frame(1)
END ONCOLLISION
AFTERCOLLISION
IF other >= 0 THEN SET SPRITE me !! frame(0)
END AFTERCOLLISION
END BEHAVIOR
ENABLE SPRITE 0
SET SPRITE 0 !! image("block") frame(0) x(20) y(112)
!! behavior("slide") behavior_params({vx: 1})
SHOW SPRITE 0
ENABLE SPRITE 1
SET SPRITE 1 !! image("block") frame(0) x(284) y(112)
!! behavior("slide") behavior_params({vx: -1})
SHOW SPRITE 1
PAUSE
The blocks are blue, turn red while they overlap, and go blue again once they’ve passed through each other.
Crash-tan’s Tip: Being shown and being solid have nothing to do with touching. A hidden sprite still touches things, and a sprite that isn’t solid still hears about every overlap. Solid only means it can’t go through.
Asking instead
Sometimes you just want to know, right now, from your own loop.
spritetouching(0, "TOP") says whether sprite 0 is up against the top of a
boundary (standing on a floor, say), and gives the boundary’s tag, or "".
point_in_box(x, y, left, top, width, height) asks whether a point is inside
a box, which is handy for clicking on things.
SCREEN 320, 240
DO
IF COOLDOWN(1)
over = point_in_box(mousex, mousey, 110, 90, 100, 60)
shade = 9
IF over THEN shade = 12
MEMORYBUFFER "button"
LINE (110, 90) -> (210, 150), shade !! box fill
END MEMORYBUFFER
FRAME
CLS
PUTIMAGE (0, 0), "button"
END FRAME
END IF
LOOP