"Doesn't connect" marks on transport ends that would join one block off (t67 phase 4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,6 +53,28 @@ function drawFlowArrows() {
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
// "Doesn't connect": a red ring with a slash at a transport end that would join one block up or
|
||||
// down (nearMiss), on built pieces, ghosts and the drag preview alike.
|
||||
function drawJoinMark(bx, by, end, code, v) {
|
||||
const e = pieceEnds(code, v)[end], ctx = R.ctx, r = Math.max(3, BS * R.zp * 0.24);
|
||||
const c = worldToScreenPx(bx * BS + BS / 2 + e.dx * BS / 2, by * BS + BS / 2 + e.dy * BS / 2);
|
||||
ctx.save();
|
||||
ctx.fillStyle = 'rgba(14,12,11,0.7)'; ctx.beginPath(); ctx.arc(c.x, c.y, r * 1.2, 0, Math.PI * 2); ctx.fill();
|
||||
ctx.strokeStyle = '#ef6a55'; ctx.lineWidth = Math.max(1.2, r * 0.3);
|
||||
ctx.beginPath(); ctx.arc(c.x, c.y, r * 0.75, 0, Math.PI * 2); ctx.stroke();
|
||||
ctx.beginPath(); ctx.moveTo(c.x - r * 0.53, c.y + r * 0.53); ctx.lineTo(c.x + r * 0.53, c.y - r * 0.53); ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
function drawJoinMarks() {
|
||||
const v = viewCells();
|
||||
const bx0 = Math.max(0, Math.floor(R.camX / BS)), bx1 = Math.min(BW - 1, Math.floor((R.camX + v.w) / BS));
|
||||
const by0 = Math.max(0, Math.floor(R.camY / BS)), by1 = Math.min(BH - 1, Math.floor((R.camY + v.h) / BS));
|
||||
for (let by = by0; by <= by1; by++) for (let bx = bx0; bx <= bx1; bx++) {
|
||||
const b = by * BW + bx, ghost = ghostBlocks.get(b), code = ghost ? ghost[0] : blockP[b], vv = ghost ? ghost[1] : blockV[b];
|
||||
if (!code || !pieceEnds(code, vv).length) continue;
|
||||
for (let end = 0; end < 2; end++) if (nearMiss(bx, by, end, ghostBlocks.size ? ghostBlocks : null)) drawJoinMark(bx, by, end, code, vv);
|
||||
}
|
||||
}
|
||||
// Outline a run of blocks: strong while it is being edited, faint when pointed at
|
||||
function drawRunOutline(run, strong) {
|
||||
if (!run || !run.length) return;
|
||||
|
||||
@@ -103,3 +103,23 @@ function joinSnap(code, v, cells) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// "Doesn't connect": an end with no join that would join seamlessly, with a diagonal piece
|
||||
// involved, if its block sat one higher (-1) or lower (+1) in empty space. 0 when no near miss.
|
||||
// A drop join counts as connected. The moved block is tried through a small override view of
|
||||
// `planned`, so ghost maps are never copied.
|
||||
const NO_PIECE = [0, 0];
|
||||
function nearMiss(bx, by, end, planned = null) {
|
||||
const b = by * BW + bx, p = planned && planned.get(b), code = p ? p[0] : blockP[b], v = p ? p[1] : blockV[b];
|
||||
const own = pieceEnds(code, v);
|
||||
if (!own[end] || endJoin(bx, by, end, planned) >= 0) return 0;
|
||||
const entry = [code, v];
|
||||
for (const dy of [-1, 1]) {
|
||||
const y = by + dy, nb = y * BW + bx;
|
||||
if (y < 0 || y >= BH || blockP[nb] || (planned && planned.get(nb))) continue;
|
||||
const view = { get: k => k === b ? NO_PIECE : k === nb ? entry : planned ? planned.get(k) : undefined };
|
||||
view.has = k => view.get(k) !== undefined;
|
||||
const j = endJoin(bx, y, end, view);
|
||||
if (j >= 0 && !joinIsDrop(bx, y, end, j, view) && (own[end].diagonal || endAt(j >> 1, j & 1, view).diagonal)) return dy;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -132,6 +132,11 @@ function hoverInfo(ax, ay) {
|
||||
if (b === BP_OUTLET) t2.push(v & 4 ? 'closed · press F' : 'open · F closes it');
|
||||
}
|
||||
else if (isWall(b) && PH[m] === PH_SOLID && !(flags[i] & F_NAT)) t1 = `${MD[m].name} ${isSlope(b) ? 'sloped wall' : 'block'}`;
|
||||
const jb = ((ay / BS) | 0) * BW + ((ax / BS) | 0);
|
||||
for (let end = 0; end < 2 && !id && !bar; end++) {
|
||||
const miss = nearMiss(jb % BW, (jb / BW) | 0, end);
|
||||
if (miss) { t2.push(`doesn't connect: place it one block ${miss < 0 ? 'higher' : 'lower'}`); warn = warn || "doesn't connect"; break; }
|
||||
}
|
||||
const n = nets[netId[i]];
|
||||
if (n && isPow[i] && !POWER_FREE) t2.push(`network ${n.supply.toFixed(1)} supply / ${n.demand.toFixed(1)} demand`);
|
||||
if (player.lens && !bar) t2.push(fmtT(temp[i]));
|
||||
|
||||
@@ -71,6 +71,7 @@ function frame(now) {
|
||||
const hb = GAME.mouse.in || GAME.usingPad ? filterBlockAt(Math.floor(GAME.aim.x), Math.floor(GAME.aim.y)) : -1;
|
||||
if (GAME.editRun) drawRunOutline(GAME.editRun, true); else if (hb >= 0) drawRunOutline(filterRun(hb), false);
|
||||
if (GAME.infoOverlay) drawFlowArrows();
|
||||
drawJoinMarks();
|
||||
drawFilterTags(!!GAME.infoOverlay, GAME.editRun ? GAME.editRun[0] : hb);
|
||||
drawFloaters();
|
||||
drawRain();
|
||||
|
||||
@@ -129,6 +129,9 @@ function drawPreviews() {
|
||||
chev(); ctx.strokeStyle = 'rgba(255,224,160,0.98)'; ctx.lineWidth = Math.max(1.2, zp * 0.45); chev();
|
||||
}
|
||||
}
|
||||
// ends of the line that would join one block up or down get the "doesn't connect" mark
|
||||
for (const [bx, by] of cells.length > 1 ? [cells[0], cells[cells.length - 1]] : cells)
|
||||
for (let end = 0; end < 2; end++) if (nearMiss(bx, by, end, planned)) drawJoinMark(bx, by, end, code, v);
|
||||
if (GAME.drag && cells.length > 1) {
|
||||
const label = `${cells.length} × ${costText(pieceCostNow(P), 1)}`;
|
||||
ctx.font = `600 12px ui-monospace, monospace`; ctx.fillStyle = 'rgba(14,12,11,0.85)';
|
||||
|
||||
Reference in New Issue
Block a user