mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-10-17 22:31:26 +02:00
feat(tavern): a real cat (Pet Cats Pack, CC-0)
The old 'cat' used a char-goblin sprite (green monster). Replaced with actual pixel cats from the Pet Cats Pack (CC-0, commercial-ok): - html/assets/cats/cat1..6-idle.png — 6 cats, 10-frame 50x50 idle strips. - catSprites.js: loads + animates a cat sprite (RK.drawCatCanvas), flips to face left. - tileRenderer: draws entities with kind 'cat' via the cat sprite path (shadow + frame). - tavernLife: spawns a RANDOM cat that wanders the customer floor (not behind the bar), injected as kind 'cat' with its catSprite id. Degrades to a villager if catSprites.js isn't loaded. - tavern.html loads catSprites.js. Client-only (no server change). Suite 57 suites / 413 tests green.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 968 B |
Binary file not shown.
|
After Width: | Height: | Size: 847 B |
Binary file not shown.
|
After Width: | Height: | Size: 963 B |
Binary file not shown.
|
After Width: | Height: | Size: 976 B |
Binary file not shown.
|
After Width: | Height: | Size: 1022 B |
Binary file not shown.
|
After Width: | Height: | Size: 1001 B |
@@ -0,0 +1,44 @@
|
||||
(function (root) {
|
||||
'use strict';
|
||||
var RK = root.RK = root.RK || {};
|
||||
|
||||
// Pet Cats Pack (CC-0). Each idle strip is 10 frames of 50x50 laid out horizontally.
|
||||
var FRAMES = 10, FW = 50, FH = 50, FRAME_MS = 150;
|
||||
var CATS = ['cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6'];
|
||||
var images = {};
|
||||
|
||||
function imgFor(id) {
|
||||
if (!CATS.includes(id)) id = 'cat3';
|
||||
if (!images[id]) {
|
||||
var im = new Image();
|
||||
im.src = 'assets/cats/' + id + '-idle.png';
|
||||
images[id] = im;
|
||||
}
|
||||
return images[id];
|
||||
}
|
||||
|
||||
RK.catIds = function () { return CATS.slice(); };
|
||||
RK.randomCatId = function () { return CATS[Math.floor(Math.random() * CATS.length)]; };
|
||||
RK.isCat = function (id) { return CATS.indexOf(id) !== -1; };
|
||||
|
||||
// Draw an animated cat centered in its cell, feet near the bottom of the tile. Flips to face left.
|
||||
RK.drawCatCanvas = function (ctx, e, cell, now) {
|
||||
var im = imgFor(e.catSprite || 'cat3');
|
||||
if (!im.complete || !im.naturalWidth) return false;
|
||||
var frame = Math.floor((now || 0) / FRAME_MS) % FRAMES;
|
||||
var sx = frame * FW;
|
||||
var size = cell * 1.25; // a touch bigger than a tile
|
||||
var dx = e.x * cell + (cell - size) / 2;
|
||||
var dy = e.y * cell + cell - size + cell * 0.12;
|
||||
ctx.save();
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
if (e.facing === 'left') {
|
||||
ctx.translate(dx + size, dy); ctx.scale(-1, 1);
|
||||
ctx.drawImage(im, sx, 0, FW, FH, 0, 0, size, size);
|
||||
} else {
|
||||
ctx.drawImage(im, sx, 0, FW, FH, dx, dy, size, size);
|
||||
}
|
||||
ctx.restore();
|
||||
return true;
|
||||
};
|
||||
})(window);
|
||||
@@ -78,7 +78,8 @@
|
||||
return { minY: 3, maxY: rows - 2, minX: 1, maxX: cols - 2 };
|
||||
}
|
||||
function catArea(cols, rows) {
|
||||
return { minY: 1, maxY: rows - 1, minX: 1, maxX: cols - 2 };
|
||||
// The customer floor (in front of the bar) — not behind the counter, not the walls.
|
||||
return { minY: 4, maxY: rows - 2, minX: 1, maxX: cols - 2 };
|
||||
}
|
||||
|
||||
// ---- Speech bubbles ---------------------------------------------------------
|
||||
@@ -220,8 +221,13 @@
|
||||
}));
|
||||
}
|
||||
|
||||
// (No "cat": it used the char-goblin sprite, which read as a green monster stuck in the
|
||||
// wall. Left out until there's an actual pet/critter sprite.)
|
||||
// A tavern cat — a random pixel cat from the Pet Cats Pack that wanders the floor.
|
||||
var catSpot = findFloor(4, rows - 4);
|
||||
var cat = makeNPC('cat', 'cat', null, catSpot.x, catSpot.y, {
|
||||
label: null, color: '#e8a060', role: 'cat', roamArea: catArea(cols, rows)
|
||||
});
|
||||
cat.catSprite = (RK.randomCatId ? RK.randomCatId() : 'cat3');
|
||||
this.npcs.push(cat);
|
||||
};
|
||||
|
||||
TavernLife.prototype._pickTarget = function (npc, scene) {
|
||||
@@ -303,9 +309,10 @@
|
||||
scene.entities.push({
|
||||
id: npc.id,
|
||||
x: npc.x, y: npc.y,
|
||||
kind: 'avatar',
|
||||
kind: npc.role === 'cat' ? 'cat' : 'avatar',
|
||||
avatar: npc.avatar,
|
||||
appearance: npc.appearance,
|
||||
catSprite: npc.catSprite || null,
|
||||
color: npc.color,
|
||||
char: npc.role === 'cat' ? 'c' : '@',
|
||||
facing: npc.facing,
|
||||
|
||||
@@ -188,6 +188,11 @@
|
||||
ctx.stroke();
|
||||
continue;
|
||||
}
|
||||
// Tavern cat — a standalone animated sprite (Pet Cats Pack), not a char-atlas avatar.
|
||||
if (e.kind === 'cat') {
|
||||
drawEntityShadow(ctx, e.x * cell + cell / 2, e.y * cell + cell * 0.9, cell * 0.28, cell * 0.11);
|
||||
if (window.RK && RK.drawCatCanvas && RK.drawCatCanvas(ctx, e, cell, now)) continue;
|
||||
}
|
||||
// Character-like entity: soft ground shadow, then the sprite (or fallback circle).
|
||||
drawEntityShadow(ctx, e.x * cell + cell / 2, e.y * cell + cell * 0.92, cell * 0.34, cell * 0.14);
|
||||
// Roguelike character sprite, or premium animated skin; else the fallback circle.
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<script src="js/render/charCustomize.js"></script>
|
||||
<script src="js/render/atlas.js"></script>
|
||||
<script src="js/render/charSprites.js"></script>
|
||||
<script src="js/render/catSprites.js"></script>
|
||||
<script src="js/render/assetPacks.js"></script>
|
||||
<script src="js/render/avatarVisuals.js"></script>
|
||||
<script src="js/render/designedRoom.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user