Runner v2 全弧第一相(HJ-RUNNER-ARC-001 / P1):用王蓝莓把"上层游戏宿主装载契约"
从零 spike 到"引擎真掌帧 + 游戏美术与引擎粒子同屏可玩",解锁 P2 泛化 / P3 生成。
契约与共享件
- 新增装载契约 game-runtime/src/core/game-host.d.ts(第9类 additive·暂名):
GameHostBootContext / GameInstance / GameHostFactory;游戏=纯模块工厂,零引擎 import,
能力经下层 ctx.getEngine()(受控面 6 项零改),绘制面 render(g) 的 g=引擎 mainContext
- makeEngineCaps 闭包提升为可 import 模块 host-dev/engine-caps.js(createEngineCaps):
host-dev/ref/未来生成游戏共用;engineMode 短路 / __engineCalls 探针 / null-engine 语义逐行不变
王蓝莓 real 通道(games/wanglanmei-ref)
- 增 ?engine=real:主循环从浏览器 RAF 改挂 engineInit 五回调(掌帧唯一源=引擎);
游戏美术绘制面从 #game 改引擎 mainContext(同屏合并);bundle 延后到 setupReal 内以
mainContext 建(getContext2d 闭包快照修);保 ?engine=stub 逐像素确定性回滚
- game-shop.js 抽为独立 GameHostFactory(零引擎 import,P3 生成 agent 可复制范本)
- entry.js 动态 import('littlejsengine')=node-import-safe ∧ esbuild iife 入包两全
- 驱动 e2e-input.cdp.cjs real 改造:禁 stepFrames 手摇(防双掌帧),真触摸+轮询;
门②同屏像素判据(暖色 warmHits ∧ 引擎粒子 brightHits 同张 #game-engine)
真机验收(mini-desktop real 引擎,5 门)
引擎掌帧 dFrame=31∈[20,45] / 同屏 warmHits=682∧brightHits=13028 同张 #game-engine /
particles.spawnEmitter+synthSfx call-ID 运行时真调引擎 / CDP 517 真触摸跑通整局
(第1天接待18·营收¥79.9·连击9) / console 零错;本机 88 单测全绿(含修复 4 红+补回归)
证据:games/wanglanmei-ref/evidence/p1-real/(e2e-evidence.json pass=true + 5 截图肉眼复核)
诚实 caveat:门② brightHits 在结算屏混入亮 UI,同屏合并由 warmHits(美术落引擎画布)+
call-ID(粒子真调引擎)+ 引擎架构(粒子渲同一 mainContext)三证成立,非阻断。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
102 lines
4.2 KiB
HTML
102 lines
4.2 KiB
HTML
<!DOCTYPE html>
|
||
<!--
|
||
index.html — 暖阳小卖部(wanglanmei-ref 轮 1)宿主页
|
||
用法:
|
||
· 集成段(mini-desktop)锁参构建:见 BUILD.md(产物 dist/ref-bundle.js,iife 全局 WanglanmeiRef);
|
||
· serve 本目录(test/harness/static-serve.cjs),浏览器打开;
|
||
· ?seed=12345 注入主随机种子(缺省固定种子,确定可复现);
|
||
· ?engine=stub(缺省·回滚锚)/ ?engine=real(引擎掌帧·游戏美术与引擎粒子同屏,P1);
|
||
· ?mode=evidence 取证模式:stub 下不起 RAF,由 window.__refHost.stepFrames/tap 确定性驱动;
|
||
· 取证导出:window.__refForensics / window.__refChecklist(字段说明见 FORENSICS.md);
|
||
· 就绪标记:__refBooted(bootRef().then 置,两通道通用);real 通道额外置 __refBootedReal(main.js setupReal 内 game.init 完成后置,
|
||
CDP 取证 real 分支须等它再驱动——见 e2e-input.cdp.cjs;M1)。
|
||
注意:页面对外文本走 IP gate(零受保护字样);本页标题即对外名「暖阳小卖部」。
|
||
-->
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<!-- 固定取证视口:390×844 移动竖屏基准;禁缩放防像素哈希扰动。 -->
|
||
<meta name="viewport" content="width=390, height=844, initial-scale=1, user-scalable=no" />
|
||
<title>暖阳小卖部</title>
|
||
<style>
|
||
/* 暖纸底居中画布:游戏全部绘制在 canvas 内,页面壳只负责承载。 */
|
||
html, body {
|
||
margin: 0;
|
||
padding: 0;
|
||
background: #2e231b;
|
||
color: #d8c6a8;
|
||
font-family: -apple-system, "PingFang SC", "Microsoft YaHei", sans-serif;
|
||
overflow: hidden;
|
||
}
|
||
/* 收编修(轮1评估段):状态行改浮层、wrap 零内边距——canvas 必须顶在 (0,0) 满幅 390×844。
|
||
旧 flex 列布局把 canvas 下推 ≈29px:e2e 真输入坐标整体偏移,且 844 视口裁掉 canvas 底部 29px
|
||
(真机亲玩底部按钮点不到)。状态行 pointer-events:none 防截触摸。 */
|
||
#wrap {
|
||
position: relative;
|
||
width: 390px;
|
||
margin: 0 auto;
|
||
}
|
||
#game {
|
||
width: 390px;
|
||
height: 844px;
|
||
background: #f6e7c9;
|
||
display: block;
|
||
touch-action: none; /* 触摸全交 JS(pointer 桥接),禁浏览器默认手势 */
|
||
}
|
||
#status {
|
||
position: absolute; /* 浮层叠于 canvas 顶部,不占布局流 */
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 2;
|
||
pointer-events: none; /* 绝不截触摸 */
|
||
font-size: 12px;
|
||
line-height: 1.4;
|
||
min-height: 15px;
|
||
text-align: center;
|
||
word-break: break-all;
|
||
opacity: 0.85;
|
||
text-shadow: 0 1px 2px rgba(46, 35, 27, 0.8); /* 深底浮字可读性 */
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div id="wrap">
|
||
<div id="status">booting…</div>
|
||
<canvas id="game"></canvas>
|
||
</div>
|
||
|
||
<!-- 构建产物(集成段生成):iife 全局 WanglanmeiRef(含 bootRef)。 -->
|
||
<script src="./dist/ref-bundle.js"></script>
|
||
<script>
|
||
// 引导:异步 boot(含资产装载);失败把错误打到 status + 重抛(评估门要看 console 零未捕获错误)。
|
||
(function () {
|
||
'use strict';
|
||
var statusEl = document.getElementById('status');
|
||
var canvas = document.getElementById('game');
|
||
try {
|
||
var G = window.WanglanmeiRef;
|
||
if (!G || typeof G.bootRef !== 'function') {
|
||
throw new Error('WanglanmeiRef.bootRef 未找到(ref-bundle.js 未正确加载或 globalName 不符)');
|
||
}
|
||
G.bootRef({ canvas: canvas, statusEl: statusEl })
|
||
.then(function () {
|
||
window.__refBooted = true; // CDP 探活标记(区分「脚本没加载」与「boot 抛错」)
|
||
})
|
||
.catch(function (e) {
|
||
window.__refBooted = false;
|
||
window.__refBootError = String((e && e.message) || e);
|
||
if (statusEl) statusEl.textContent = 'BOOT ERROR: ' + window.__refBootError;
|
||
throw e;
|
||
});
|
||
} catch (e) {
|
||
window.__refBooted = false;
|
||
window.__refBootError = String((e && e.message) || e);
|
||
if (statusEl) statusEl.textContent = 'BOOT ERROR: ' + window.__refBootError;
|
||
throw e;
|
||
}
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|