JackyJacky

Jacky can wear hats that dynamically track his head position, tilt, and scale across every animation frame. You can cycle through available hats, adjust their placement in real time, and — if you are a skin creator — embed precise frame-by-frame head coordinates directly in your skin manifest so hats sit perfectly on your custom character.

Open the Manifest Builder


How Hats Work

A hat is a transparent overlay window that renders a PNG (or GIF) image directly above Jacky. On every animation tick, Jacky calculates the head position using tracking data and moves, rotates, and scales the hat to match.

Tracking Data Priority

Jacky resolves hat position in this order:

  1. Skin-defined tracking — If your skin's manifest.json includes a hat block with per-frame coordinates, those are used first.
  2. Fallback database — If the skin has no hat config, Jacky uses the included database, which contains pre-computed head coordinates for the default companion (calibrated at 256×256).
  3. Default placement — If no data is available for a state, the hat defaults to the sprite's top-center.
Info

The fallback database works well for the default companion, but custom skins with different proportions or head shapes should always include their own hat tracking data in the manifest.

Tracking During Missing Frames

If a frame has no defined tracking data (intentionally left out), Jacky hides the hat for that frame. If a frame is simply missing but the animation state is defined, Jacky reuses the last valid pose to avoid flicker.


Including Hat Tracking in Your Skin Manifest

To provide custom hat placement for your skin, add a hat object inside your manifest.json. Reference the Skins & Animations guide for the full manifest structure.

Hat Block Structure

The hat object maps animation folder names to arrays of per-frame tracking entries:

{
  "type": "skin",
  "name": "MyCustomSkin",
  "version": "1.0.0",
  "author": "YourName",
  "description": "A custom companion with hat support",
  "skin": {
    "sprite_size": 128,
    "fps": 12,
    "sprite_facing": "right",
    "card": {
      "title": "My Companion",
      "description": "A custom friend for your desktop",
      "author": "YourName",
      "link": "https://yoursite.com"
    }
  },
  "hat": {
    "Idle": [
      { "frame": 0, "x": 64, "y": 28, "angulo": 0.0, "distancia": 100.0 },
      { "frame": 1, "x": 64, "y": 29, "angulo": 1.5, "distancia": 101.0 },
      { "frame": 2, "x": 63, "y": 27, "angulo": -0.8, "distancia": 99.0 }
    ],
    "Walking": [
      { "frame": 0, "x": 62, "y": 26, "angulo": -3.0, "distancia": 95.0 },
      { "frame": 1, "x": 65, "y": 30, "angulo": 2.5, "distancia": 102.0 }
    ],
    "Dance": [
      { "frame": 0, "x": 70, "y": 25, "angulo": 0.0, "distancia": 105.0 }
    ],
    "Sleep": [
      { "x": 50, "y": 80, "angulo": 45.0, "distancia": 80.0 }
    ]
  }
}
Warning

Folder names in the hat object must match the folder names on disk (e.g., Idle, Walking, Dance), not the internal PetState enum names. See the Animation States Reference for the full folder name list.

Per-Frame Entry Fields

FieldTypeRequiredDescription
frameintNoFrame index to apply these coordinates to. If omitted, entries are assigned sequentially (entry 0 → frame 0, entry 1 → frame 1, etc.)
xfloatYesHorizontal head position (pixels), relative to your sprite_size.
yfloatYesVertical head position (pixels), relative to your sprite_size.
angulofloatNoHead tilt angle in degrees. Use angle as an alias. Defaults to 0.
distanciafloatNoTracking distance factor (affects dynamic scaling). Use distance as an alias. Defaults to 1.0. Higher values = head moves more between frames.

Coordinate System

  • All x and y values are relative to the sprite's top-left corner, in pixels at the skin's native sprite_size.
  • Jacky automatically scales these coordinates to the current display size.
  • If you specify explicit frame numbers, only those frames will show the hat. Frames without entries will hide the hat.

Horizontal Mirroring

When Jacky faces left, the hat is automatically mirrored horizontally — the x coordinate is flipped relative to the sprite center, and the rotation angle is inverted. You do not need to provide separate coordinates for left-facing sprites.


Changing and Adjusting Hats

Hat Sources

Jacky looks for hat images in two locations:

  1. Bundled hats — Default hats shipped with Jacky in assets/hats/.
  2. User hats — Custom hats placed in the ~/.jacky/hats/ directory.

If a user hat has the same filename as a bundled hat, the user version takes priority.

Supported formats: .png (static) and .gif (animated).

Context Menu

Right-click Jacky to open the context menu, then find the Hats submenu:

OptionDescription
Enable HatsToggle the hat overlay on/off.
Next HatSwitch to the next available hat.
Previous HatSwitch to the previous available hat.
Adjust Hat...Open the floating Hat Adjuster panel.

Hat Adjuster Panel

The Hat Adjuster is a frameless floating panel that lets you fine-tune hat placement in real time:

ControlRangeDefaultDescription
Enable HatsOn/OffOffToggle the hat overlay.
Fixed PositionOn/OffOffLock the hat to a fixed position on the sprite (ignores tracking data).
Size10% – 300%100%Scale the hat relative to its original size.
Offset X-100 – 100 px0Shift the hat horizontally.
Offset Y-200 – 200 px-40Shift the hat vertically (negative = up).
Angle-180° – 180°Rotate the hat by a fixed offset.

All sliders update the hat position live. Click Reset to revert to defaults, or close the panel to save your adjustments.


Persistence

All hat settings are saved to Jacky's config.json and persist across restarts:

  • hat_enabled — Whether hats are active.
  • hat_current — The currently selected hat filename.
  • hat_scale — Custom scale percentage.
  • hat_offset_x / hat_offset_y — Custom position offsets.
  • hat_angle — Custom rotation offset.
  • hat_fixed_position — Whether to use a fixed position instead of tracking data.

Tips for Skin Creators

  • Capture tracking data externally — Use an optical flow or point-tracking tool (e.g., Lucas-Kanade) to record head coordinates frame by frame, then export them into your manifest.json.
  • Provide data for common states — At minimum, include Idle and Walking entries. Other states will fall back to the bundled database or defaults.
  • Test with the Adjuster — Load your skin, enable hats, and use the Hat Adjuster to verify placement. If hats sit correctly without adjustments, your tracking data is accurate.
  • Omit intentional gaps — If the head is not visible in certain frames (e.g., a spin animation where the head is hidden), omit those frame entries to hide the hat naturally.