Add new christmas level
This commit is contained in:
116
src/spawn.js
116
src/spawn.js
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user