Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Autonomous development — Claude works on it daily, deploying improvements.
## Day 10 — Premium Polish
- [x] Loading screen with pixel art progress bar
- [x] Settings panel (toggle sounds, particles, animations)
- [ ] Export office as PNG screenshot
- [x] Export office as PNG screenshot
- [ ] Export as GIF animation (5 second loop)

## Day 11 — Social Features
Expand Down
28 changes: 18 additions & 10 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@ import { launchCoffeeGame } from "./minigames/coffee.js";
import { launchWhiteboardGame } from "./minigames/whiteboard.js";
import { launchPlantGame } from "./minigames/plant.js";
import { launchJukeboxGame } from "./minigames/jukebox.js";
import { launchFoosballGame } from "./minigames/foosball.js";

// ════════════════════════════════════════════════════════════════
// CONSTANTS
// ════════════════════════════════════════════════════════════════
let CW = 1400;
const T = 32; // tile size px
const OX = 150; // canvas left margin
const OX = 180; // canvas left margin (left side panel width)
const OX_RIGHT = 160; // canvas right margin (right side panel width)
const OY = 12; // canvas top margin
let COLS = 35; // room width in tiles (mutable for wall editor)
let ROWS = 14;
Expand Down Expand Up @@ -7121,7 +7123,7 @@ function buildBackground() {
lg.addColorStop(0, "#fffff0");
lg.addColorStop(1, "transparent");
ctx.fillStyle = lg;
ctx.fillRect(OX, ly, CW - OX * 2, T * 8);
ctx.fillRect(OX, ly, CW - OX - OX_RIGHT, T * 8);
ctx.restore();
}

Expand Down Expand Up @@ -12396,8 +12398,8 @@ function drawLeftPanel(ctx, tick) {
}

function drawRightPanel(ctx, tick) {
const panelX = CW - OX + 3;
const W = OX - 6,
const panelX = CW - OX_RIGHT + 3;
const W = OX_RIGHT - 6,
H = CH;

// Background
Expand Down Expand Up @@ -15386,7 +15388,7 @@ function applyWallPositions() {
if (saved.wall_zone !== undefined) ACT_ZONE_Y = Math.round(saved.wall_zone);
if (saved.wall_right !== undefined) {
COLS = Math.round(saved.wall_right);
CW = OX + COLS * T + OX;
CW = OX + COLS * T + OX_RIGHT;
const cv = document.getElementById("office");
if (cv) cv.width = CW;
bgBuf.width = CW;
Expand Down Expand Up @@ -15711,7 +15713,7 @@ canvas.addEventListener("mousemove", (e) => {
// Live-resize canvas when dragging outer walls (no rebuild during drag)
if (w.id === "wall_right") {
COLS = Math.round(w.pos);
CW = OX + COLS * T + OX;
CW = OX + COLS * T + OX_RIGHT;
canvas.width = CW;
bgBuf.width = CW;
}
Expand Down Expand Up @@ -15783,7 +15785,7 @@ document.addEventListener("mousemove", (e) => {
}
if (w.id === "wall_right") {
COLS = Math.round(w.pos);
CW = OX + COLS * T + OX;
CW = OX + COLS * T + OX_RIGHT;
canvas.width = CW;
bgBuf.width = CW;
}
Expand Down Expand Up @@ -15811,7 +15813,7 @@ document.addEventListener("mouseup", (e) => {
if (w2.id === "wall_zone") ACT_ZONE_Y = Math.round(w2.pos);
if (w2.id === "wall_right") {
COLS = Math.round(w2.pos);
CW = OX + COLS * T + OX;
CW = OX + COLS * T + OX_RIGHT;
canvas.width = CW;
bgBuf.width = CW;
}
Expand Down Expand Up @@ -15846,7 +15848,7 @@ canvas.addEventListener("mouseup", (e) => {
if (w.id === "wall_zone") ACT_ZONE_Y = Math.round(w.pos);
if (w.id === "wall_right") {
COLS = Math.round(w.pos);
CW = OX + COLS * T + OX;
CW = OX + COLS * T + OX_RIGHT;
canvas.width = CW;
bgBuf.width = CW;
}
Expand Down Expand Up @@ -16363,6 +16365,12 @@ canvas.addEventListener("click", (e) => {
setTimeout(() => blip(659, 0.08, "sine", 0.03), 200);
return;
}
if (hit.type === "foosball") {
launchFoosballGame();
blip(440, 0.08, "square", 0.04);
setTimeout(() => blip(660, 0.06, "square", 0.03), 80);
return;
}
if (clickAnims.some((a) => a.id === hit.id)) return;
clickAnims.push({
id: hit.id,
Expand Down Expand Up @@ -17924,7 +17932,7 @@ document.getElementById("admin-start-pos").onclick = () => {
window._adminPos = Object.assign({}, BUILTIN_POSITIONS);
// Reset walls to default sizes
COLS = 35;
CW = OX + COLS * T + OX;
CW = OX + COLS * T + OX_RIGHT;
canvas.width = CW;
bgBuf.width = CW;
generateLayout(Math.max(12, Object.keys(agentsData).length));
Expand Down
1 change: 1 addition & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
</div>
<span id="agent-count">0 agents</span>
<button id="btn-leaderboard">🏆 TOP</button>
<button id="btn-screenshot">📸 PNG</button>
<button id="btn-settings">⚙ SET</button>
<a id="public-url" class="loading" href="#" target="_blank">⏳ tunnel...</a>
</header>
Expand Down
42 changes: 42 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,3 +550,45 @@ if (typeof window !== "undefined") {
localStorage.setItem(key, JSON.stringify(lb));
};
})();

// ════════════════════════════════════════════════════════════════
// SCREENSHOT EXPORT — capture office canvas as PNG
// ════════════════════════════════════════════════════════════════
(function initScreenshot() {
const btn = document.getElementById("btn-screenshot");
if (!btn) return;

btn.addEventListener("click", () => {
const canvas = document.getElementById("office");
if (!canvas) return;

// Flash effect
btn.textContent = "⏳";
btn.disabled = true;

// Use timeout so the current frame finishes rendering
setTimeout(() => {
try {
const dataUrl = canvas.toDataURL("image/png");
const link = document.createElement("a");
const now = new Date();
const stamp =
now.getFullYear() +
String(now.getMonth() + 1).padStart(2, "0") +
String(now.getDate()).padStart(2, "0") +
"_" +
String(now.getHours()).padStart(2, "0") +
String(now.getMinutes()).padStart(2, "0") +
String(now.getSeconds()).padStart(2, "0");
link.download = "agent-office_" + stamp + ".png";
link.href = dataUrl;
link.click();
} catch (e) {
console.error("[screenshot] failed:", e);
} finally {
btn.textContent = "📸 PNG";
btn.disabled = false;
}
}, 50);
});
})();
Loading
Loading