Add new christmas level

This commit is contained in:
Daddy32
2025-12-29 16:01:30 +01:00
parent 76ffee449d
commit 9243ac2df5
5 changed files with 300 additions and 2 deletions

View File

@@ -120,6 +120,7 @@
const createBallBodies = (x, y, color) => {
const scene = getCurrentScene();
const ballPhysics = scene?.config?.ballPhysics || {};
const debugSpawn = !!scene?.config?.debugSpawn;
const commonOpts = {
restitution: ballPhysics.restitution ?? 0.72,
friction: ballPhysics.friction ?? 0.01,
@@ -186,6 +187,71 @@
};
return { bodies: [body], constraints: [], blobId: null };
}
if (scene?.config?.ballShape === "gift") {
const size = config.ballRadius * 2;
const ribbonSize = Math.max(4, config.ballRadius * 0.35);
const ribbonColor = scene?.config?.giftRibbonColor || "#f8fafc";
if (debugSpawn) {
console.log("Spawn gift", {
sceneId: scene?.id,
x,
y,
color,
size,
});
}
const base = Bodies.rectangle(x, y, size, size, {
...commonOpts,
chamfer: { radius: Math.max(2, config.ballRadius * 0.18) },
});
const ribbonRender = {
fillStyle: ribbonColor,
strokeStyle: "#0b1222",
lineWidth: 2,
};
const verticalRibbon = Bodies.rectangle(x, y, ribbonSize, size * 1.02, {
render: ribbonRender,
});
const horizontalRibbon = Bodies.rectangle(
x,
y,
size * 1.02,
ribbonSize,
{
render: ribbonRender,
},
);
const bow = Bodies.rectangle(
x,
y - size * 0.34,
ribbonSize * 1.4,
ribbonSize * 0.8,
{
render: ribbonRender,
},
);
const body = Body.create({
parts: [base, verticalRibbon, horizontalRibbon, bow],
});
Body.setPosition(body, { x, y });
body.restitution = commonOpts.restitution;
body.friction = commonOpts.friction;
body.frictionAir = commonOpts.frictionAir;
body.frictionStatic = commonOpts.frictionStatic;
body.density = commonOpts.density;
body.render = {
...body.render,
...commonOpts.render,
visible: true,
};
body.plugin = {
color,
hasEntered: false,
entryCheckId: null,
shape: "gift",
};
return { bodies: [body], constraints: [], blobId: null };
}
if (scene?.config?.ballShape === "rect") {
const side = config.ballRadius * 2;
const body = Bodies.rectangle(x, y, side, side, {
@@ -214,6 +280,12 @@
if (isGameOver()) return;
const scene = getCurrentScene();
const sceneConfig = scene?.config || {};
if (sceneConfig.debugSpawn) {
console.log("Spawn tick", {
sceneId: scene?.id,
ballShape: sceneConfig.ballShape,
});
}
const { width, height } = getDimensions();
const spawnLimit = sceneConfig.spawnLimit;
if (Number.isFinite(spawnLimit) && spawnCount >= spawnLimit) {
@@ -393,6 +465,50 @@
const scene = getCurrentScene();
const initialCount = scene?.config?.initialSpawnCount || 0;
if (!initialCount || initialCount <= 0) return;
if (scene?.config?.debugSpawn) {
console.log("Initial burst", {
sceneId: scene?.id,
initialCount,
});
}
const areaSource = scene?.config?.initialSpawnArea;
let area = null;
if (typeof areaSource === "function") {
try {
area = areaSource({ ...getDimensions(), world });
} catch (err) {
console.error("initialSpawnArea function failed", err);
}
}
if (scene?.config?.debugSpawn) {
console.log("Initial spawn area", {
sceneId: scene?.id,
area,
});
}
if (area && Number.isFinite(area.xMin) && Number.isFinite(area.xMax)) {
const { width, height } = getDimensions();
const pad = config.ballRadius + 4;
const minX = Math.max(pad, Math.min(area.xMin, area.xMax));
const maxX = Math.min(width - pad, Math.max(area.xMin, area.xMax));
const minY = Math.max(pad, Math.min(area.yMin, area.yMax));
const maxY = Math.min(height - pad, Math.max(area.yMin, area.yMax));
if (scene?.config?.debugSpawn) {
console.log("Initial spawn bounds", {
sceneId: scene?.id,
minX,
maxX,
minY,
maxY,
});
}
for (let i = 0; i < initialCount; i += 1) {
const x = minX + Math.random() * Math.max(0, maxX - minX);
const y = minY + Math.random() * Math.max(0, maxY - minY);
spawnAtPosition({ x, y, markEntered: true });
}
return;
}
for (let i = 0; i < initialCount; i += 1) {
spawnBall();
}