Behaviors and Patterns Guide
This guide introduces behaviors and patterns in Crash BASIC - a declarative system for animating and controlling hardware sprites without writing frame-by-frame logic.
What Are Behaviors?
Behaviors are named, reusable sprite animation and movement definitions. Instead of manually updating sprite positions and frames each tick, you define behaviors once and apply them to sprites. The engine handles the rest.
' Define a behavior
BEHAVIOR "wobble"
BOSCILLATE AMPLITUDE 5, 3
END BEHAVIOR
' Apply it to a sprite
SET SPRITE 0 BEHAVIOR "wobble"Defining Behaviors
Single Behavior Block
BEHAVIOR "name"
' commands go here
END BEHAVIORMultiple Behaviors in One Block
Use labels to define multiple behaviors together:
BEHAVIOR "left":
BMOVE -10, 0
"right":
BMOVE 10, 0
END BEHAVIORBranching at Declaration Time
IF and SELECT CASE can appear inside a BEHAVIOR (or PATTERN) block. These run once, when the block is declared — they choose which commands the behavior is built from, they do not run per tick:
BEHAVIOR "enemyMove"
SELECT CASE difficulty
CASE 0
BVELOCITY -1, 0
CASE 1
BVELOCITY -2, 0
CASE ELSE
BVELOCITY -3, 0
END SELECT
END BEHAVIORUse it to build difficulty tiers, platform variants, or debug builds from one definition. For logic that must run every tick, use a WHEN condition on a pattern step instead.
Movement Commands
BMOVE - Constant Movement
Moves the sprite by a fixed amount each tick.
BEHAVIOR "moveRight"
BMOVE 2, 0 ' Move right 2 pixels per tick
END BEHAVIOR
BEHAVIOR "diagonal"
BMOVE -1, 1 ' Move down-left
END BEHAVIORBVELOCITY - Continuous Velocity
Contributes a standing movement intent, not a one-shot kick. The engine zeroes the BVELOCITY contribution at the start of every tick and each active BVELOCITY command adds its value back — so several behaviors carrying BVELOCITY are additive rather than last-one-wins.
BEHAVIOR "walkLeft"
BVELOCITY -2, 0 ' keeps moving left while active
END BEHAVIOR
BEHAVIOR "conveyor"
BVELOCITY 1, 0 ' stacks with the above: net -1
END BEHAVIORBecause the contribution is rebuilt every tick, it has no inertia, and three consequences follow that surprise people:
BFRICTIONdoes not decay it — there is nothing accumulated to decay.- A solid collision does not zero it. The sprite keeps pushing against whatever blocked it for as long as the behavior is active.
BBOUNCEcannot rebound it. The reflection is applied and then overwritten by the constant on the next tick, so a BVELOCITY-driven sprite presses against a wall instead of bouncing off it.
For a discrete kick — a jump, dash, recoil or knockback — use BIMPULSE. It seeds the accumulated velocity once, and unlike BVELOCITY it decays under friction and can be zeroed by a collision.
The optional third component sets vertical (elevation) velocity — see BGRAVITY.
BACCELERATION - Physics
Applies continuous acceleration each tick, accumulating into the sprite's velocity. This is the momentum BFRICTION decays and BBOUNCE reflects.
BEHAVIOR "falling"
BACCELERATION 0, 0.5 ' Gravity
END BEHAVIOR
BEHAVIOR "cannonball"
BIMPULSE 5, -3 ' Initial launch (one-shot)
BACCELERATION 0, 0.2 ' Gravity arc
END BEHAVIORBIMPULSE - One-Shot Velocity Kick
Adds (ix, iy) to the sprite's accumulated accel_velocity exactly once per behavior activation, then becomes a no-op for the rest of that activation. The seeded velocity persists in accel_velocity and decays through BFRICTION (if any) the same way BACCELERATION contributions decay.
| Argument | Description |
|---|---|
ix |
Horizontal impulse in pixels per tick. Added to accel_velocity_x once on activation. |
iy |
Vertical impulse in pixels per tick. Same semantics on the Y axis (positive = down). |
BIMPULSE is the right primitive for discrete kicks of momentum — jumps, dashes, recoil, knockback. To re-fire, the behavior must be deactivated and re-activated (typically driven from a pattern step or a WHEN trigger). On reactivation a fresh internal state is built and the impulse fires again.
' Classic jump — impulse fires once, gravity pulls back
BEHAVIOR "jump"
BIMPULSE 0, -8
BACCELERATION 0, 0.5
END BEHAVIOR
' Dash with friction settle — impulse, then ice-style decay
BEHAVIOR "dashRight"
BIMPULSE 6, 0
BFRICTION 0.1, 0
END BEHAVIOR
' Pattern-driven recoil — re-fires on every pattern reactivation
PATTERN "shoot"
BEHAVIOR "recoil" DURATION 8
BEHAVIOR "idle" DURATION 12
END PATTERN
BEHAVIOR "recoil"
BIMPULSE -2, 0
BFRICTION 0.2, 0
END BEHAVIORHow BIMPULSE fits with the other velocity primitives:
| Command | Cadence | Where it lands | Decays via BFRICTION? |
|---|---|---|---|
BMOVE |
every tick | direct position translation | n/a — no velocity |
BVELOCITY |
every tick | overwrites bvelocity |
no — bvelocity is reset each tick |
BIMPULSE |
once per activation | adds to accel_velocity |
yes |
BACCELERATION |
every tick | adds to accel_velocity |
yes |
Both axes accept VARIANCE for per-instance jitter and support @paramName=default parameter references for pattern-driven values.
BFRICTION - Universal Velocity Decay
Universally decays the sprite's accumulated accel_velocity every tick, regardless of collisions. Per-axis: 0 = frictionless, 1 = instant stop, in between = exponential decay (e.g. 0.1 = lose 10% per tick). Combines with BACCELERATION for terminal velocity behaviour — equilibrium ≈ acceleration / friction.
| Argument | Description |
|---|---|
x_friction |
Decay coefficient on X axis. 0 = no decay, 1 = instant stop. |
y_friction |
Decay coefficient on Y axis. Same scale. |
' Air-resistance falling object — converges to terminal velocity ≈ 10
BEHAVIOR "airDrop"
BACCELERATION 0, 1.0
BFRICTION 0, 0.1
END BEHAVIOR
' Ice puck — slows naturally on both axes after a hit
BEHAVIOR "icePuck"
BFRICTION 0.04, 0.04
END BEHAVIORBFRICTION does not affect BVELOCITY (which is reset and re-derived each tick) or BMOVE (constant-motion intent). It only decays the persistent accel_velocity accumulator. VARIANCE on each axis gives per-instance jitter — useful for swarms that need slightly different settle behaviour.
BBOUNCE - Collision Reflection
Makes the sprite bounce off solid boundaries on collision instead of being stopped flat. Each axis has its own restitution coefficient — 0 absorbs all energy (sprite stops dead), 1 is perfect elastic (no energy loss), in between loses a fraction per hit. Both BVELOCITY contributions and accumulated BACCELERATION are reflected together.
| Argument | Description |
|---|---|
x_restitution |
Bounce coefficient on X axis (LEFT/RIGHT walls). 0 = absorb, 1 = perfect. |
y_restitution |
Bounce coefficient on Y axis (TOP/BOTTOM walls). Same scale. |
For SLOPE boundaries, the velocity is reflected along the slope's normal vector and scaled by the average of x_restitution and y_restitution — so a ball hitting a 45° SE slope from above bounces cleanly up and to the right.
BEHAVIOR "rubberBall"
BBOUNCE 0.9, 0.9
BVELOCITY 5, 0
BACCELERATION 0, 0.4 ' Gravity
END BEHAVIOR
BEHAVIOR "basketball"
BBOUNCE 0.7, 0 ' Rolls along floor, no Y bounce
BVELOCITY 4, 0
END BEHAVIORVARIANCE on each restitution gives natural-feeling jitter, useful for swarms of bouncing particles:
BEHAVIOR "sparkBounce"
BBOUNCE 0.85 VARIANCE(-0.1, 0.05), 0.85 VARIANCE(-0.1, 0.05)
BVELOCITY 4 VARIANCE(-3, 3), -6 VARIANCE(-2, 2)
BACCELERATION 0, 0.3
END BEHAVIORWhen BBOUNCE is not in any active behavior, sprites use the default zero-on-block behavior (accel_velocity in the blocked direction is zeroed; BVELOCITY persists). Activating BBOUNCE swaps that for the reflection above; deactivating the behavior clears the bounce profile.
BGRAVITY - Vertical Pull
Sprites have a third axis: ELEVATION, their height above the layer. BGRAVITY strength accelerates a sprite back toward the floor every tick — sugar for the vertical part of BACCELERATION 0, 0, -strength. Use a positive strength.
BEHAVIOR "hop"
BIMPULSE 0, 0, 16 ' kick upward (third component is z)
BGRAVITY 1 ' pull back to the ground
BBOUNCE 0, 0, 0.4 ' keep 40% on landing
END BEHAVIORElevation is only rendered on an AFFINE or PERSPECTIVE plane layer, where the sprite rides toward the camera eye-height and foreshortens with distance. On a flat layer the physics still runs but you will not see it, which is why 2D platformers do their jumping on screen Y instead.
BFRICTION's optional third coefficient decays vertical speed — air resistance, or a terminal fall speed of roughly gravity / z_friction. Read the live height with SPRITEELEVATION(id), which is what a WHEN condition uses for landing detection.
BELEVATE - Height Animation
Tweens elevation from one height to another, mirroring BALPHA/BSCALE/BROTATE. This is a scripted lift rather than physics — no gravity involved.
BEHAVIOR "rise"
BELEVATE 0 TO 32 DURATION 30
END BEHAVIOR
BEHAVIOR "fall"
BELEVATE 32 TO 0 DURATION 30
END BEHAVIOR
' Sequence them in a looping PATTERN for a continuous hover
PATTERN "hover" LOOP
"rise"
"fall"
END PATTERNPATH - Waypoint Movement
Moves the sprite along a series of waypoints.
| Modifier | Description |
|---|---|
ABSOLUTE |
Use screen coordinates (default is relative to starting position) |
SPEED n |
Pixels per tick (default: 1) |
LOOP |
Repeat indefinitely |
PINGPONG |
Reverse at endpoints instead of jumping back |
BEHAVIOR "bounce"
PATH (0,0), (0,-20), (0,0) SPEED 3 LOOP
END BEHAVIOR
BEHAVIOR "patrol"
PATH ABSOLUTE (100,100), (200,100) SPEED 2 LOOP PINGPONG
END BEHAVIOR
BEHAVIOR "square"
PATH (0,0), (50,0), (50,50), (0,50) LOOP
END BEHAVIORBFOLLOW - Follow Another Sprite
Makes the sprite follow a target sprite, maintaining minimum distance.
BEHAVIOR "followPlayer"
BFOLLOW 0 DISTANCE 40 SPEED 2
END BEHAVIOR
BEHAVIOR "companion"
BFOLLOW 0 DISTANCE 24 SPEED 1.5
ANIMATE "pet", 0, 1, 2, 3 FRAMERATE 10
END BEHAVIORBORBIT - Orbital Movement
Makes the sprite orbit around a fixed point or another sprite.
' Orbit around a coordinate
BEHAVIOR "orbitCenter"
BORBIT (160, 120) DISTANCE 50
END BEHAVIOR
' Orbit around sprite 0
BEHAVIOR "satellite"
BORBIT SPRITE 0 DISTANCE 30 SPEED 2
END BEHAVIOR
' Counterclockwise orbit
BEHAVIOR "shield"
BORBIT SPRITE 0 DISTANCE 32 SPEED 8 COUNTERCLOCKWISE
END BEHAVIOR
' Spiral inward
BEHAVIOR "spiral"
BORBIT (160, 120) DISTANCE 80 DECAY 0.5
END BEHAVIORBOSCILLATE - Smooth Oscillation
Creates smooth back-and-forth movement around the starting position using a sine wave.
| Modifier | Description |
|---|---|
AMPLITUDE x, y |
Maximum displacement in pixels |
SPEED n |
Degrees per tick (default: 6, full cycle ~60 ticks) |
DECAY n |
Reduce amplitude each tick (settles to start) |
PHASE n |
Initial sine angle in radians (default 0; supports VARIANCE for per-instance scatter) |
PERSISTENT |
Keep final position when behavior ends |
BEHAVIOR "hover"
BOSCILLATE AMPLITUDE 0, 8 ' Vertical bob
END BEHAVIOR
BEHAVIOR "sway"
BOSCILLATE AMPLITUDE 15, 0 SPEED 3
END BEHAVIOR
BEHAVIOR "landing"
BOSCILLATE AMPLITUDE 0, 15 SPEED 10 DECAY 0.4
END BEHAVIORInitial phase. The default starting phase is 0 — every instance assigned this behavior begins synchronized at the wave origin. To scatter starting phases across many sprites or mutation points (so a swarm of bobbers doesn't move in lockstep), use PHASE with VARIANCE:
BEHAVIOR "swarmBob"
BOSCILLATE AMPLITUDE 0, 8 SPEED 4 PHASE 0 VARIANCE(0, 6.28)
END BEHAVIORVARIANCE(0, 6.28) covers a full 2π cycle, so each instance gets a uniformly random offset.
Phase carryover between behaviors. When a sprite transitions from one BOSCILLATE behavior directly into another, the new behavior automatically inherits the previous behavior's current phase — the wave continues smoothly across the join with no visual jerk. The carryover applies for one transition only: if you switch through a non-oscillating behavior in between, the chain breaks and the next BOSCILLATE starts fresh at phase 0 (or its explicit PHASE override). An explicit PHASE on the new behavior always wins over an inherited value.
' These two idles share momentum across the swap — no twitch.
BEHAVIOR "idleSlow"
BOSCILLATE AMPLITUDE 0, 6 SPEED 3
END BEHAVIOR
BEHAVIOR "idleFast"
BOSCILLATE AMPLITUDE 0, 6 SPEED 8
END BEHAVIORBSHAKE - Random Shake
Creates random jittering for damage feedback or tremor effects.
BEHAVIOR "damaged"
BSHAKE AMPLITUDE 4
BBLINK 5
END BEHAVIOR
BEHAVIOR "unstable"
BSHAKE AMPLITUDE 2
END BEHAVIORVisual Commands
ANIMATE - Frame Animation
Cycles through sprite sheet frames.
' Use all frames from sprite sheet
BEHAVIOR "idle"
ANIMATE "player" FRAMERATE 10
END BEHAVIOR
' Specific frames
BEHAVIOR "walk"
ANIMATE "player", 0, 1, 2, 3 FRAMERATE 10
END BEHAVIOR
' Frame range (0 TO 18 expands to 0, 1, 2, ..., 18)
BEHAVIOR "run"
ANIMATE "player", 0 TO 18 FRAMERATE 15
END BEHAVIORAseprite Timing and Hitboxes
An .ase/.aseprite file carries per-frame durations and per-frame slice geometry, and two clauses put them to work:
' Play at the per-frame timings authored on the Aseprite timeline
BEHAVIOR "run"
ANIMATE "heroRun", 0 TO 7 FRAMERATE OFSPRITE
END BEHAVIOR
' AUTOBBOX drives the hitbox from the file's slice, per frame
BEHAVIOR "attack"
ANIMATE "heroAttack", 0 TO 5 AUTOBBOX FRAMERATE OFSPRITE
END BEHAVIORFRAMERATE OFSPRITE means re-timing an animation is a save in Aseprite, not a code change. AUTOBBOX means a sword swing whose hitbox only extends on the frames where the blade is out becomes an animator decision instead of a table of magic numbers.
EVENTSON - Frame Events
Trigger events when specific frames are displayed:
BEHAVIOR "walk"
ANIMATE "player", 0, 1, 2, 3 EVENTSON(1, 3) FRAMERATE 10
END BEHAVIOR
SUB OnWalkFrame(sprite_id, frame)
IF frame = 1 THEN PLAYWAV "step1"
IF frame = 3 THEN PLAYWAV "step2"
END SUB
CALL EVENT OnWalkFrame() AS "PLAYER_FRAME"Event names are derived from the image name: ANIMATE "player" fires events named PLAYER_FRAME.
BALPHA - Transparency Animation
BEHAVIOR "fadeIn"
BALPHA 0 TO 1 DURATION 30
END BEHAVIOR
BEHAVIOR "pulse"
BALPHA 1 TO 0.3 DURATION 15 LOOP
END BEHAVIORBSCALE - Scale Animation
BEHAVIOR "grow"
BSCALE 1, 1 TO 2, 2 DURATION 30
END BEHAVIOR
BEHAVIOR "breathe"
BSCALE 1, 1 TO 1.2, 1.2 DURATION 10 LOOP
END BEHAVIORBROTATE - Rotation Animation
Two modes: absolute (FROM TO) and relative (single value from current angle).
' Absolute: spin from 0 to 360
BEHAVIOR "spin"
BROTATE 0 TO 360 DURATION 60 LOOP
END BEHAVIOR
' Relative: rotate 360 degrees from current
BEHAVIOR "spinRelative"
BROTATE 360 DURATION 60 LOOP
END BEHAVIOR
' With custom origin (center)
BEHAVIOR "spinCenter"
BORIGIN 0.5, 0.5
BROTATE 0 TO 360 DURATION 60 LOOP
END BEHAVIORBORIGIN - Anchor Point
Sets the sprite's anchor/pivot point using normalized coordinates (0-1).
| Value | Position |
|---|---|
0, 0 |
Top-left (default) |
0.5, 0.5 |
Center |
1, 1 |
Bottom-right |
BEHAVIOR "centerSpin"
BORIGIN 0.5, 0.5
BROTATE 0 TO 360 DURATION 60 LOOP
END BEHAVIORBBLINK - Visibility Toggle
BEHAVIOR "invincible"
BBLINK 4 ' Toggle every 4 ticks
END BEHAVIORBIMAGE - Change Sprite Texture
BEHAVIOR "powered"
BIMAGE "playerPowered"
BSCALE 1, 1 TO 1.2, 1.2 DURATION 30 LOOP
END BEHAVIORBSHADER - Animated Shader Effects
Animates a shader parameter over time. Auto-attaches the shader when behavior activates.
BEHAVIOR "dissolve"
BSHADER "Dissolve" @progress=0 TO 1 DURATION 60
END BEHAVIOR
BEHAVIOR "glow"
BSHADER "Glow" @intensity=0.5 TO 1.0 DURATION 30 LOOP
END BEHAVIORCollision Handlers
A behavior can react to being hit, with inline BASIC that runs when a contact happens. Both blocks are edge-triggered — once per contact, not once per tick.
DIM dx AS INTEGER
dx = -1
BEHAVIOR "patrol"
BVELOCITY @vx = 0, @vy = 0
ONCOLLISION
' Before resolution: impact_vx / impact_vy still hold the speed we hit at
IF tag_b$ = "spikes" THEN CALL Damage(index_a)
END ONCOLLISION
AFTERCOLLISION
' After resolution: the engine has already stopped us. Turn around.
dx = dx * -1
SET SPRITE index_a BEHAVIOR "patrol", @vx = dx, @vy = 0
END AFTERCOLLISION
END BEHAVIORWhen each one runs. A tick goes contact -> resolution -> next tick. ONCOLLISION runs on contact, before resolution, so it sees the velocity you struck at — the value resolution is about to zero or reflect. AFTERCOLLISION runs between resolution and the next tick, once the engine has stopped or bounced you, which makes it the place to decide what to do about the hit.
A solid contact always resolves, so both land on the tick of the hit and AFTERCOLLISION does not wait for you to move away. That matters because BVELOCITY never stops pressing — a sprite held against a wall would otherwise never separate. A ghost contact has no resolution to follow, so its AFTERCOLLISION waits for the overlap to end.
The scoped values, describing the contact as it began:
| Value | Meaning |
|---|---|
index_a |
the sprite whose behavior this is |
index_b |
the other sprite, or -1 for a boundary |
tag_a$ / tag_b$ |
the two tags (tag_b$ is the boundary tag when index_b = -1) |
edge$ |
which face was contacted |
impact_vx / impact_vy |
velocity at impact, pre-resolution |
Rules:
- Declare persistent variables outside the block. A handler body scopes like a
SUB, so assigning an undeclared name creates a local that vanishes on return — hencedxabove. - No blocking statements.
PAUSE,DELAY,DELAY UNTILandYIELDare rejected at definition time; a handler runs on the behavior tick loop and would freeze every sprite in the game. - Changes take effect next tick — swapping behavior,
GHOST,SOLID. - Boundary contacts key on the tag, not the segment, so a wall of ten
"wall"pieces is one surface and sliding across seams does not re-fire. - Both sprites fire in a sprite-to-sprite hit, each seeing itself as
index_a— including a stationary sprite that something ran into.
Re-issuing a behavior with different @params rebuilds it, which is how the turn-around above works. Re-issuing with the same params is deliberately a no-op, so a DO loop can re-assert a behavior every frame without restarting BMOVE timing or re-rolling VARIANCE.
Applying Behaviors to Sprites
Adding Behaviors
SET SPRITE 0 BEHAVIOR "walkRight"
SET SPRITE 0 BEHAVIOR "fadeIn" ' Multiple behaviors stackRemoving Behaviors
SET SPRITE 0 BEHAVIOR DELETE "fadeIn" ' Remove specific
SET SPRITE 0 BEHAVIOR NONE ' Clear allChecking Behaviors
IF HASBEHAVIOR(0, "walkRight") THEN PRINT "Walking"
' Get all active behaviors
behaviors$ = SPRITEBEHAVIORS$(0) ' Returns "WALKRIGHT,FADEIN"Combining Multiple Behaviors
Multiple behaviors can be active simultaneously and their effects combine:
BEHAVIOR "walkRight"
ANIMATE "player", 0, 1, 2, 3 FRAMERATE 10
BMOVE 2, 0
END BEHAVIOR
BEHAVIOR "bobbing"
BOSCILLATE AMPLITUDE 0, 3
END BEHAVIOR
' Apply both - sprite walks right while bobbing
SET SPRITE 0 BEHAVIOR "walkRight"
SET SPRITE 0 BEHAVIOR "bobbing"INCLUDES - Composing at Definition Time
Rather than applying several behaviors to every sprite, compose them once into one:
BEHAVIOR "bobbing"
BOSCILLATE AMPLITUDE 0, 3
END BEHAVIOR
BEHAVIOR "walkRight" INCLUDES("bobbing")
ANIMATE "player", 0, 1, 2, 3 FRAMERATE 10
BMOVE 2, 0
END BEHAVIOR
SET SPRITE 0 BEHAVIOR "walkRight" ' bobs tooThe included behavior's commands are folded in, and collision handlers stack: every inherited ONCOLLISION runs, in composition order.
Parameterized Behaviors
Use @paramName=default syntax to create reusable behaviors with variable values:
BEHAVIOR "moveToPoint"
BMOVE @targetX=0, @targetY=0
END BEHAVIOR
' Use with overrides (evaluated at assignment time)
SET SPRITE 0 BEHAVIOR "moveToPoint", @targetX=100, @targetY=playerY
' Use with defaults
SET SPRITE 1 BEHAVIOR "moveToPoint"Variance - Randomized Values
Add randomness to behavior values using VARIANCE or VARIANCEINT:
BEHAVIOR "randomVelocity"
BVELOCITY 5 VARIANCE(-2, 2), 0 ' X velocity: 3 to 7
END BEHAVIOR
BEHAVIOR "randomDirection"
BMOVE 0 VARIANCEINT(-1, 1, NONZERO), 0 VARIANCEINT(-1, 1, NONZERO)
END BEHAVIOR
BEHAVIOR "variedAnimation"
ANIMATE "sprite", 1, 2 FRAMERATE 10 VARIANCE(2, 3)
END BEHAVIORPatterns - Sequencing Behaviors
Patterns orchestrate behaviors over time, creating complex animation sequences.
Basic Pattern
PATTERN "walkCycle" LOOP
"walkRight" DURATION 120
"idle" DURATION 60
END PATTERN
SET SPRITE 0 PATTERN "walkCycle"Step Modes
| Mode | Description |
|---|---|
DURATION ticks |
Run behavior for fixed time |
| (no modifier) | Completion mode - wait for behavior to finish |
WHEN condition |
Active while condition is true |
' Completion mode - waits for fadeOut to finish
PATTERN "fadeAndDie"
"fadeOut"
DISABLE
END PATTERN
' Conditional - responds to input
PATTERN "playerControl" LOOP
"idle"
"walkRight" WHEN KEYDOWN("RIGHT")
"walkLeft" WHEN KEYDOWN("LEFT")
END PATTERNPattern Commands
Commands that affect the sprite directly:
| Command | Description |
|---|---|
SHOW |
Make sprite visible |
HIDE |
Make sprite invisible |
DISABLE |
Remove/destroy the sprite |
SOLID |
Enable collision |
GHOST |
Disable collision |
FADE [SPEED n] |
Fade alpha to 0 |
RETAG "tag" |
Change sprite tag |
GOTOPATTERN "name" |
Switch to another pattern |
BEVENT "name" |
Fire a custom event |
PATTERN "death"
GHOST ' Stop collisions
"hit" DURATION 10
"fall" ' Completion mode
FADE SPEED 2
DISABLE ' Remove sprite
END PATTERN
PATTERN "transform"
RETAG "powered"
GOTOPATTERN "powerMode"
END PATTERNCommands with WHEN
Commands can have conditions too:
PATTERN "enemy" LOOP
"patrol"
DISABLE WHEN health <= 0
END PATTERNTechniques and Recipes
Walking Character
BEHAVIOR "walkRight"
ANIMATE "player", 0, 1, 2, 3 FRAMERATE 10
BMOVE 2, 0
END BEHAVIOR
BEHAVIOR "walkLeft"
ANIMATE "player", 0, 1, 2, 3 FRAMERATE 10
BMOVE -2, 0
BFLIPX ON
END BEHAVIOR
BEHAVIOR "idle"
ANIMATE "player", 0, 1 FRAMERATE 5
END BEHAVIOR
PATTERN "playerMovement" LOOP
"idle"
"walkRight" WHEN KEYDOWN("RIGHT")
"walkLeft" WHEN KEYDOWN("LEFT")
END PATTERNJumping with Gravity
BEHAVIOR "jump"
BIMPULSE 0, -8 ' one-shot kick; BVELOCITY would push up forever
BACCELERATION 0, 0.5
END BEHAVIOR
BEHAVIOR "falling"
BACCELERATION 0, 0.5
END BEHAVIOROn a plane layer, where sprites have real height, this is BIMPULSE 0, 0, 16 plus BGRAVITY 1 instead — the jump happens on the elevation axis rather than on screen Y.
Floating Collectible
BEHAVIOR "float"
ANIMATE "coin", 0, 1, 2, 3 FRAMERATE 8
BOSCILLATE AMPLITUDE 0, 8
END BEHAVIOR
BEHAVIOR "collected"
BSCALE 1, 1 TO 1.5, 1.5 DURATION 15
BALPHA 1 TO 0 DURATION 15
END BEHAVIOR
PATTERN "coin"
"float"
"collected" WHEN collected
DISABLE
END PATTERNEnemy Patrol
BEHAVIOR "patrolRight"
ANIMATE "enemy", 0, 1, 2, 3 FRAMERATE 8
BMOVE 1, 0
END BEHAVIOR
BEHAVIOR "patrolLeft"
ANIMATE "enemy", 0, 1, 2, 3 FRAMERATE 8
BMOVE -1, 0
BFLIPX ON
END BEHAVIOR
PATTERN "patrol" LOOP
"patrolRight" DURATION 120
"patrolLeft" DURATION 120
END PATTERNTimed patrol is fine for open ground. If the enemy should turn around when it actually hits something rather than on a stopwatch, drive it from the collision instead:
DIM edx AS INTEGER
edx = -1
BEHAVIOR "patrolBounce"
ANIMATE "enemy", 0, 1, 2, 3 FRAMERATE 8
BVELOCITY @vx = 0, @vy = 0
AFTERCOLLISION
edx = edx * -1
SET SPRITE index_a BEHAVIOR "patrolBounce", @vx = edx, @vy = 0
END AFTERCOLLISION
END BEHAVIOROrbiting Shields
BEHAVIOR "orbitShield"
BORBIT SPRITE 0 DISTANCE 32 SPEED 5
BROTATE 360 DURATION 60 LOOP
END BEHAVIOR
' Create 3 shields at different starting angles
FOR i = 0 TO 2
SET SPRITE 10 + i, SPRITEX(0), SPRITEY(0), "shield"
SET SPRITE 10 + i BEHAVIOR "orbitShield"
NEXT iDeath Animation
BEHAVIOR "deathSpin"
BORIGIN 0.5, 0.5
BROTATE 0 TO 720 DURATION 60
BSCALE 1, 1 TO 0, 0 DURATION 60
BALPHA 1 TO 0 DURATION 60
END BEHAVIOR
PATTERN "die"
GHOST
"deathSpin"
DISABLE
END PATTERNDamage Feedback
BEHAVIOR "hit"
BSHAKE AMPLITUDE 4
BBLINK 5
END BEHAVIOR
' Apply temporarily
SET SPRITE 0 BEHAVIOR "hit"
' Remove after delay (in your game loop)
IF hitTimer > 30 THEN SET SPRITE 0 BEHAVIOR DELETE "hit"Screen Shake (Using Camera Sprite)
BEHAVIOR "screenShake"
BSHAKE AMPLITUDE 8
END BEHAVIOR
' Apply to a "camera" sprite that offsets all rendering
SET SPRITE 255 BEHAVIOR "screenShake"Saving and Loading Behaviors
Behaviors and patterns can be serialized to JSON and loaded back, so you can author them once and reuse them across projects:
SAVE BEHAVIOR "walkCycle" TO "walk.json"
LOAD BEHAVIOR "walk.json"
SAVE PATTERN "patrol" TO "patrol.json"
LOAD PATTERN "patrol.json"A saved behavior is written in its resolved form — declaration-time IF/SELECT already flattened away — while @param defaults and VARIANCE are preserved. A saved pattern keeps its steps, runtime WHEN conditions, durations and LOOP flag.
Loading registers everything in the file under its saved name; re-loading a name that already exists overwrites it, exactly as re-declaring the block would. Saving an undefined name, or loading a missing or malformed file, is a loud runtime error rather than a silent partial load.
For a whole parented sprite tree plus the behaviors it uses, see SAVE RIG / LOAD RIG.
Attribute Persistence
When behaviors are deactivated, some attributes revert while others persist:
| Reverts | Persists |
|---|---|
| Visibility (BBLINK restores visible) | Position (BMOVE, PATH, etc.) |
| Velocity (BVELOCITY zeros out) | Alpha (BALPHA final value) |
| Shaders (BSHADER removes shader) | Scale (BSCALE final value) |
| Rotation (BROTATE final angle) | |
| Flip state (BFLIPX/BFLIPY) | |
| Image/Frame (ANIMATE, BIMAGE) | |
| Origin (BORIGIN) |
Special case: BACCELERATION velocity persists when a single behavior is deactivated but clears when ALL behaviors are cleared with BEHAVIOR NONE.
Summary
- Behaviors define reusable animation and movement logic
- Multiple behaviors can be active simultaneously and combine
- Parameters make behaviors flexible and reusable
- Variance adds controlled randomness
- Patterns sequence behaviors over time with transitions and conditions
- Use DURATION for timed steps, WHEN for conditional steps, or omit modifiers for completion mode
- INCLUDES composes behaviors at definition time; declaration-time
IF/SELECT CASEpicks which commands a behavior is built from - ONCOLLISION / AFTERCOLLISION let a behavior react to being hit — before and after the engine resolves the contact
- BVELOCITY is continuous, BIMPULSE is a one-shot kick — reach for BIMPULSE for jumps, dashes and knockback
- SAVE / LOAD BEHAVIOR (and PATTERN, and RIG) move authored motion between projects