Section 02 ยท Character packs

Character Pack Configuration

The char.json file identifies a character's visual and audio resources and defines how sprite-sheet cells are used for animation.

Preparation

A basic character requires an identifier, a display name, a sprite-sheet path, frame dimensions, and the required animation definitions. Portraits, poses, sounds, combat artwork, and VN sprites are optional. Their absence does not prevent the character from moving or communicating.

Resource paths are relative to the folder containing char.json. For example, "sheet": "overworld.png" refers to a file beside char.json, while "portraits/neutral.png" refers to a file in the portraits subdirectory.

Caution: Keep all required character resources within the character folder. A path such as ../shared_art/sheet.png may function on the development computer but will fail if the shared file is not distributed. File-name capitalization must also match exactly when the content is used on a Linux system.

Example character folder containing char.json and organized art folders
A self-contained character folder includes every resource referenced by its configuration.

Minimum Character Configuration

The following example contains the fields required for a basic character and includes one portrait for message display.

{
  "schema": 1,
  "id": "my_character",
  "name": "Display Name",
  "overworld": {
    "sheet": "overworld.png",
    "frame_width": 32,
    "frame_height": 48,
    "animations": {
      "idle_down": { "row": 0, "frames": [0, 1], "fps": 3 },
      "walk_down": { "row": 0, "frames": [2, 3, 4, 5], "fps": 8 }
    }
  },
  "portraits": { "default": "portraits/neutral.png" },
  "default_expression": "default",
  "texture_filter": "nearest",
  "chat_color": "#3d6134"
}
  • id is the stable internal identifier. Use letters, digits, and underscores.
  • name is the display name presented to users.
  • texture_filter controls image filtering. Use nearest for pixel art and linear for smooth, high-resolution artwork.
  • chat_color sets the background color of the in-character message panel. Use a sufficiently dark color to maintain contrast with white message text.
  • portraits.default identifies the fallback expression. Additional expression identifiers may be assigned as required.

Sprite-Sheet Definition

A sprite sheet is an image divided into equal animation cells. The frame_width and frame_height values define the dimensions of each cell. Row and column numbering begins at zero.

Small pixel-art overworld sprite sheet
The sprite-sheet arrangement may vary, provided that the configuration identifies the cells correctly.

The definition { "row": 0, "frames": [2, 3, 4, 5] } selects row 0 and plays columns 2, 3, 4, and 5 in the listed order.

Sprite-sheet cell reference
Row / Column Column0 Column1 Column2 Column3 Column4 Column5
Row 0 0 1 2 3 4 5
Row 1 0 1 2 3 4 5
Row 2 0 1 2 3 4 5
Row 3 0 1 2 3 4 5

The highlighted cells correspond to "row": 0 and "frames": [2, 3, 4, 5]. Row and column numbers begin at 0.

  • Blarp recognizes idle_down, idle_left, idle_right, idle_up, and the four corresponding walk_* names.
  • If a directional walk animation is unavailable, Blarp first uses the idle animation for that direction and then uses idle_down.
  • If the left-facing artwork is a horizontal reflection of the right-facing artwork, reference the same row and set "flip_h": true.
Reload the content after each configuration change and inspect the animation during operation.

Movement Speed and Partial Animation Loops

The overworld.speed value sets the base free-roam speed in pixels per second. Its default value is 160. The overworld.run_multiplier value multiplies that speed while Ctrl-run is active. Its default value is 1.5.

"overworld": {
  "speed": 150,
  "run_multiplier": 1.6,
  ...
}

The loop_from field permits an animation to play an introductory sequence once and then repeat only the remaining frames. Its value is a zero-based position within the frames list.

"idle_down": {
  "row": 4,
  "frames": [0, 1, 2, 3, 4, 5],
  "fps": 8,
  "loop_from": 2
}

In this example, all six positions play once. Positions 2 through 5 then repeat. This arrangement can be used for an action such as drawing a weapon before entering an idle stance or lifting off before entering a hover. The loop_from value refers to a position in the list, not to a sprite-sheet column number.

Alternate Walk Sets

The walk_sets object defines alternate movement modes, such as sneaking, skating, or running. Each named set may use a separate sprite sheet and separate frame dimensions.

"walk_sets": {
  "sneak": {
    "sheet": "sneak.png",
    "frame_width": 80,
    "frame_height": 80,
    "speed_multiplier": 0.55,
    "animation_speed_multiplier": 0.75,
    "animations": {
      "idle_down": { "row": 0, "frames": [0], "fps": 3 },
      "walk_down": { "row": 0, "frames": [0, 1, 2, 1], "fps": 6 }
    }
  }
}
  • speed_multiplier modifies ground speed while the set is selected.
  • Animation speed changes with ground speed unless animation_speed_multiplier specifies a separate value.
  • A set named run supplies the artwork used while Ctrl is held. The run_multiplier value continues to provide the speed increase.
  • The Walk selector is available when at least one alternate set is defined. The selected set is synchronized with other users.
An alternate walk set may replace both movement and idle animations.

Pose Definitions

A pose is a user-activated animation, such as a wave, seated position, or cheer. Define poses within the overworld object.

"poses": {
  "wave": {
    "row": 0, "frames": [2, 3, 4, 5], "fps": 6,
    "loop": false, "sound": "sfx/wave.wav"
  },
  "ready": {
    "row": 2, "frames": [0, 1], "fps": 4,
    "loop": true
  }
}
  • loop: false plays the pose once and then returns the character to its idle animation.
  • loop: true repeats the pose until movement or selection of another pose cancels it.
  • A pose may override sheet, the frame dimensions, and offset: [x, y]. A negative Y offset moves tall artwork upward so that the character's feet remain aligned with the ground position.
The Pose selector uses the first frame of each pose as its preview image.

Footsteps and Text Blips

Footsteps

"footsteps": {
  "frames": [0, 2],
  "sounds": [
    { "sound": "sfx/step1.wav", "weight": 1 },
    { "sound": "sfx/step2.wav", "weight": 1 }
  ]
}

Footstep frame numbers are local positions within the active walk_* list. If the list is [2,3,4,5], local positions 0 and 2 correspond to sprite-sheet columns 2 and 4.

Assign short footstep sounds to animation positions at which a foot contacts the ground.

Text blips

A text blip is a short sound played while an in-character message is being revealed. The configuration accepts one sound path, an array of paths, or weighted sound choices.

"blips": [
  { "sound": "blips/low.wav", "weight": 3 },
  { "sound": "blips/high.wav", "weight": 1 }
],
"blip_pitch": [0.9, 1.1]

Use a short audio sample because the sound may be triggered in rapid succession. Blarp plays blips for visible characters and does not play them for spaces.

Pitch variation reduces audible repetition when one sample is triggered repeatedly.

Typing Indicator Adjustment

While a user is typing, Blarp displays the upper half of the idle_down frame at the lower-left of the viewport. Use typing_indicator to correct the scale or position when the default extraction does not align with the artwork.

"typing_indicator": {
  "scale": 1.25,
  "offset": [8, -12]
}

VN Sprite Definitions

VN sprites are large character images used by the visual-novel display. By default, they share expression identifiers with portraits. The expression selected for a message therefore selects the corresponding VN sprite.

"vn_sprites": {
  "default": "vn/default.png",
  "angry": "vn/angry.png",
  "happy": "vn/happy.png"
}

If the portrait and VN sprite identifiers do not match, define the relationship explicitly.

"vn_sprites": {
  "grin": {
    "image": "vn/grin.png",
    "portraits": ["smug", "smirk", "sly"]
  },
  "weep": {
    "image": "vn/weep.png",
    "portraits": ["sad"]
  }
}

The first portrait in the portraits list is the primary expression when the VN sprite is selected. If no explicit relationship is available, Blarp first attempts to match identifiers and then falls back to portrait artwork.

Blarp VN sprite and portrait-linking interface
Multiple portrait expressions may be associated with one VN sprite.

Shout Definitions

A shout applies a room-wide presentation effect to the next message. The effect may display an image, play a sound, suspend room movement briefly, and direct the camera toward the speaker.

"shouts": {
  "objection": {
    "sound": "shouts/objection.wav",
    "image": "shouts/objection.png"
  },
  "hold_it": { "sound": "shouts/holdit.wav" }
}

Each configured identifier becomes a Shout button. Selecting the button assigns the effect to the next message; the selection is cleared after the message is sent.

Note: A shout affects all users in the room. Use it only when a room-wide interruption is appropriate.

A shout may use audio alone or combine audio with a centered banner image.

Combat Clip Definitions

The combat system supports three optional character animations: attack, hit, and defeat.

"combat": {
  "attack": {
    "row": 4, "frames": [0, 1, 2], "fps": 12,
    "sound": "sfx/swing.wav"
  },
  "hit": {
    "row": 5, "frames": [0, 1], "fps": 10
  },
  "defeat": {
    "row": 6, "frames": [0, 1, 2], "fps": 6
  }
}
  • attack plays when an action targets another combatant. Blarp turns the attacker toward the target before playback.
  • hit plays when the character loses HP. It does not play for healing, missed actions, or status improvements.
  • defeat plays when the character's HP reaches zero.
  • Each entry accepts pose options, including a separate sheet, frame dimensions, offset, horizontal reflection, sound, and a one-time introductory sequence.