Initial commit: Game Maker phase 1

Canvas-only 2D game editor/runtime built on PixiJS v8 + Vite + TypeScript.

- core: asset model (Scene/Camera/Sprite), scene objects with sparse
  overrides, property schema + resolve, command stack (undo/redo),
  serialization and project store interface (16 unit tests)
- ui: custom in-canvas widget toolkit (panels, fields, color picker,
  list/scroll, popup) with a hidden <input> keyboard bridge
- editor: asset/hierarchy panels, schema-driven inspector, toolbar
- viewport: box rendering, camera frame, selection gizmo, drag/zoom/pan
- runtime: world/entity instantiation for play mode, input, camera follow
- api: PHP JSON project store with revision counter (409 on conflict)
- tools: CDP-based e2e smoke test

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
rootandClaude Fable 5.1 committed 2026-09-07 10:07:06 +02:00
commit 5a46124454
65 files changed
+7193

No files matched your search

+41
View File
@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/** JSON response helpers. Every API answer goes through here. */
final class Response
{
public static function json(mixed $data, int $status = 200): never
{
http_response_code($status);
header('Content-Type: application/json; charset=utf-8');
header('Cache-Control: no-store');
echo json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
public static function error(string $message, int $status, array $extra = []): never
{
self::json(['error' => $message] + $extra, $status);
}
public static function noContent(): never
{
http_response_code(204);
header('Cache-Control: no-store');
exit;
}
/** Decoded JSON request body or an error response when it is not an object. */
public static function body(): array
{
$raw = file_get_contents('php://input');
if ($raw === false || $raw === '') {
self::error('Request body must be JSON', 400);
}
$data = json_decode($raw, true);
if (!is_array($data)) {
self::error('Request body must be a JSON object', 400);
}
return $data;
}
}