diff --git a/web/src/components/Placeholder/pieces/DESIGN.md b/web/src/components/Placeholder/pieces/DESIGN.md index 42b49f774..273c3cf58 100644 --- a/web/src/components/Placeholder/pieces/DESIGN.md +++ b/web/src/components/Placeholder/pieces/DESIGN.md @@ -46,3 +46,4 @@ Avoid padding an animation with duplicate frames just to hit a standard count. A - `OwlBlink.svg`: five-frame blink/idle strip with breathing wings, blink, and ear-feather settle. - `FalconIdle.svg`: four-frame idle strip with breathing, blink, alert head shift, and tail flick. +- `WoodpeckerPeck.svg`: six-frame tree-trunk peck strip with red crest, chisel beak, barred wing, impact chips, recoil, and settle. diff --git a/web/src/components/Placeholder/pieces/OwlBlink.svg b/web/src/components/Placeholder/pieces/OwlBlink.svg index 9633f07ad..db2142846 100644 --- a/web/src/components/Placeholder/pieces/OwlBlink.svg +++ b/web/src/components/Placeholder/pieces/OwlBlink.svg @@ -3,9 +3,9 @@ A five-frame 32 by 32 pixel owl idle and blink animation strip. @@ -32,17 +33,17 @@ - - + + - + - + @@ -68,8 +69,8 @@ - - + + diff --git a/web/src/components/Placeholder/pieces/WoodpeckerPeck.svg b/web/src/components/Placeholder/pieces/WoodpeckerPeck.svg new file mode 100644 index 000000000..05e2a0ef5 --- /dev/null +++ b/web/src/components/Placeholder/pieces/WoodpeckerPeck.svg @@ -0,0 +1,162 @@ + + Woodpecker peck pixel tileset + A six-frame 32 by 32 pixel woodpecker pecking a tree trunk. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/src/components/Placeholder/tileSprites.ts b/web/src/components/Placeholder/tileSprites.ts index 8cce29fec..b7326b595 100644 --- a/web/src/components/Placeholder/tileSprites.ts +++ b/web/src/components/Placeholder/tileSprites.ts @@ -1,5 +1,6 @@ import FalconIdle from "./pieces/FalconIdle.svg?url"; import OwlBlink from "./pieces/OwlBlink.svg?url"; +import WoodpeckerPeck from "./pieces/WoodpeckerPeck.svg?url"; export interface TileSprite { name: string; @@ -27,6 +28,14 @@ export const TILE_SPRITES: TileSprite[] = [ frames: 4, duration: 960, }, + { + name: "WoodpeckerPeck", + src: WoodpeckerPeck, + frameWidth: 32, + frameHeight: 32, + frames: 6, + duration: 1080, + }, ]; export function pickTileSprite(): TileSprite { diff --git a/web/tests/placeholder-pool.test.ts b/web/tests/placeholder-pool.test.ts index 9944ce985..98503c65c 100644 --- a/web/tests/placeholder-pool.test.ts +++ b/web/tests/placeholder-pool.test.ts @@ -4,14 +4,15 @@ import { DEFAULT_MESSAGES, type PlaceholderVariant } from "@/components/Placehol describe("TILE_SPRITES integrity", () => { it("registers 32px by 32px sprite strips with animation-specific frame counts", () => { - expect(TILE_SPRITES.map((sprite) => sprite.name)).toEqual(["OwlBlink", "FalconIdle"]); + expect(TILE_SPRITES.map((sprite) => sprite.name)).toEqual(["OwlBlink", "FalconIdle", "WoodpeckerPeck"]); expect(TILE_SPRITES.map((sprite) => [sprite.name, sprite.frames])).toEqual([ ["OwlBlink", 5], ["FalconIdle", 4], + ["WoodpeckerPeck", 6], ]); for (const sprite of TILE_SPRITES) { - expect(sprite.name).toMatch(/^[A-Z][A-Za-z]+(Idle|Hop|Blink|Drift|Flutter|Hover)$/); + expect(sprite.name).toMatch(/^[A-Z][A-Za-z]+(Idle|Hop|Blink|Drift|Flutter|Hover|Peck)$/); expect(sprite.frameWidth).toBe(32); expect(sprite.frameHeight).toBe(32); expect(sprite.frames).toBeGreaterThanOrEqual(2);