DDirectorWikiDirector & Lingo Encyclopedia

Sprites

Sprite properties, geometry, puppeting, naming, sprite channels, and runtime sprite state semantics.

What a sprite is

A sprite is an instance of a cast member occupying a Score channel for a span of frames. Its properties (position, size, ink, blend, visibility, behaviors) are independent of the member: two sprites can show the same member differently.

lingo
sprite(5).member = member("ball")
sprite(5).loc = point(200, 150)
sprite(5).ink = 36                   -- Background Transparent
sprite(5).blend = 50                 -- 50% opacity
sprite(5).visible = TRUE

Geometry properties

PropertyMeaning
locpoint(locH, locV): stage position of the member's regPoint.
locH / locVComponents of loc.
locZDepth override; defaults to the channel number. Higher draws in front.
rectOn-stage bounding rect. Reading gives current geometry; writing stretches the sprite.
width / heightRect dimensions; writing stretches.
quadFour corner points (D8.5+): arbitrary quadrilateral distortion for bitmaps.
rotationDegrees clockwise (bitmap/text/flash/vector members).
skewDegrees of horizontal skew.
flipH / flipVMirroring flags.
regPoint (member)Anchor; see Cast members.
constraintSprite number whose rect constrains this sprite's loc (used for sliders).

Geometry pipeline order (must be reproduced exactly): member pixels -> regPoint anchor -> stretch to sprite rect (if resized) -> flip -> rotation/skew about the regPoint -> quad (if set, replaces rot/skew path) -> stage placement at loc.

the stretch of sprite (legacy) flags whether the sprite uses authored size vs member natural size; assigning width/height/rect sets it. Resetting a stretched sprite to natural size: assign member rect dimensions or toggle puppeting off and let score state reassert.

Appearance properties

PropertyMeaning
inkCompositing mode 0-41; see Ink modes.
blend0-100 opacity percentage (works with most inks).
foreColor / backColorColor pair used by 1-bit members, fields, and some inks (background key for Background Transparent).
visibleChannel visibility. Affects the CHANNEL, persists across spans; classic gotcha.
trailsLeaves previous frames' pixels on stage (no erase).
directToStage (member)Media draws over everything, ignores ink/compositing.
mask (member, digital video) / maskImage (imaging)Masking inputs.

Identity and structure

lingo
sprite(5).spriteNum          -- 5
sprite(5).name               -- MX 2004 sprite names
sprite("hudPanel").loc       -- lookup by name
sprite(5).memberNum          -- member number (assign to swap image fast)
sprite(5).castLibNum
sprite(5).scriptInstanceList -- attached behavior instances
sprite(5).scriptNum          -- first behavior's script member number
the currentSpriteNum         -- sprite whose handler is executing
the spriteNum of me          -- behavior's own channel

Sprite names (MX 2004) let code survive channel reordering; name assignment requires score recording. Preservation-era content (D8.5 and earlier) is entirely channel-number based.

Puppeting and runtime authority

lingo
puppetSprite 5, TRUE     -- Lingo owns channel 5 (score updates stop)
sprite(5).puppet = TRUE  -- same, property form

Authority rules (see also The object model):

  • Non-puppeted sprites: score data re-syncs channel state at each frame boundary; Lingo writes persist only until then (but are visible during the current frame's render and hit testing).
  • Puppeted sprites: Lingo state persists until puppetSprite n, FALSE, which also snaps the channel back to authored score state on the next sync.
  • Behavior property writes to their own sprite auto-persist for the span (MX 2004 auto-puppet).
  • A channel with no authored sprite can be puppeted and populated entirely from Lingo (sprite(5).member = ...), the standard dynamic-object technique before makeScriptedSprite (MX 2004) formalized it.
  • endSprite fires when a puppeted channel's span logically ends only if there was an authored span; fully dynamic channels never generate span events, and their behaviors (attached via scriptInstanceList) must be managed manually.

Interaction properties

PropertyMeaning
moveableSpriteUser can drag the sprite directly.
editableEditable text sprite (fields/text): receives focus and typing.
cursorCursor ID or [castMember, maskMember] pair while over the sprite.
hilite (member)Button member checked/highlight state.
mouseOverButtonRollover state for button members.

Hit testing (the clickOn, rollover(), mouse events) uses sprite geometry, ink, and member type; Matte ink hits only the visible (non-white-matte) area, other inks hit the bounding box. Full rules and open questions: Input and hit testing.

Sprite relationship operators

lingo
sprite 3 intersects 5      -- bounding/quad areas overlap (TRUE/FALSE)
sprite 3 within 5          -- sprite 3's area entirely inside sprite 5's

These are documented as operating on the sprites' bounding areas (quads when rotated); with Matte ink the comparison uses matte outlines. Collision code in old games is built on these plus manual rect math.

Reading decompiled sprite code

Common patterns worth recognizing:

lingo
-- channel pool allocation (dynamic UIs)
repeat with ch = 900 to 950
  if sprite(ch).memberNum < 2 then exit repeat
end repeat
puppetSprite ch, TRUE

-- member-swap animation
sprite(ch).memberNum = baseNum + (the frame mod 4)

-- offscreen parking instead of hiding
sprite(ch).locH = -2000

The parking idiom means emulators must keep offscreen sprites fully alive (events, stepFrame, memory) rather than culling them.