zizi 99b6c82dec feat(runner-v2): P1 王蓝莓上引擎=游戏宿主装载契约 spike 实(mini-desktop real 引擎 5 门全过)
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>
2026-06-13 18:32:50 +00:00

102 lines
4.2 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!--
index.html — 暖阳小卖部wanglanmei-ref 轮 1宿主页
用法:
· 集成段mini-desktop锁参构建见 BUILD.md产物 dist/ref-bundle.jsiife 全局 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
· 就绪标记__refBootedbootRef().then 置两通道通用real 通道额外置 __refBootedRealmain.js setupReal 内 game.init 完成后置,
CDP 取证 real 分支须等它再驱动——见 e2e-input.cdp.cjsM1
注意:页面对外文本走 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; /* 触摸全交 JSpointer 桥接),禁浏览器默认手势 */
}
#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>