Files
erqiwang_youle/client/index.html
T
joywayerandClaude Opus 5 bc75e40acc 二七王:新增图集叠绘数字能力(SpriteManager 源矩形 API + NumberRenderer)
多帧图片精灵一次只显示一帧=只能显示一位数,两位数就得两个精灵,
14 个叫分档位(13 档两位数)每档只配一个精灵时根本渲染不出来。

- SpriteManager.drawImageRegion:把 GameABCUtils.Draw.drawImage 的源矩形
  能力暴露到业务层(drawImage 只透传了整图版),校验/日志/返回值风格照现有
  drawImage 一致;注明必须在精灵绘制回调中调用。
- gameabc-framework/ui/NumberRenderer.js:游戏中立,bind/setValue/clear/unbind,
  绘制回调里按字宽逐位裁源矩形画在同一个精灵上;layout 抽为纯函数可脱离引擎单测;
  字符映射不到显式抛错,不静默跳过。
- EQW_Layout.NUM_STYLE:5 套数字的字宽/字高/字间距/对齐/绘制区宽集中配置(零裸值),
  资源只存键名(与 CARD_SIZE.res 同一约定)。
- client/tests/test_numberrenderer.js:43 checks(多位/单位/正负号/三种对齐/负字间距/
  空值/自定义 charMap/非法字符与非法样式抛错/5 套真实样式画得下)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 23:52:56 +08:00

299 lines
13 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>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0,viewport-fit=cover"/>
<title>jxmahjong</title>
<style>
body {
padding-top: constant(safe-area-inset-top);
padding-left: constant(safe-area-inset-left);
padding-right: constant(safe-area-inset-right);
padding-bottom: constant(safe-area-inset-bottom);
}
</style>
</head>
<body style='position:fixed;bottom:0;'>
<div id="ifastgame2" style="position:absolute;left:0px;top:0px;z-index:10">
<canvas id="bg1" width="1" height="1">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<div id="ifastgame_4" style="position:absolute;left:0px;top:0px;z-index:1">
<canvas id="ifastgame_bg" width="1" height="1">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<div id="ifastgame3" style="position:absolute;left:0px;top:0px;z-index:11">
<canvas id="bg2" width="1" height="1">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<div id="ifastgame" style="position:absolute;left:0px;top:0px;z-index:2">
<canvas id="canvas" width="6000" height="3000">
<p>Your browser does not support the canvas element.</p>
</canvas>
</div>
<!-- Spine WebGL 叠加层:z-index 3 夹在主画布(2)与 bg1(10)之间,
精确复刻"Spine 画在主画布内部、被 bg1/bg2 遮挡"的既有层级关系。
pointer-events:none 保证不抢主画布的触摸输入。-->
<div id="ifastgame_spine" style="position:absolute;left:0px;top:0px;z-index:3;pointer-events:none">
<canvas id="spine_gl" width="1" height="1"></canvas>
</div>
<style type="text/css">
* { margin: 0; padding: 0; }
html, body { height: 100%; width: 100%;
overflow-x:hidden;overflow-y:hidden;
backgroundColor:"rab(255,0,0)";
}
canvas { display: block; }
</style>
<script>
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
setupWebViewJavascriptBridge(function(bridge){});
</script>
<!-- <script>
returnCitySN={
ip:'127.1.1.1',
province:'',
city:''
};
</script> -->
<script src="http://47.98.203.17:8085/cityjson" ></script>
<script type="text/javascript" src="js/vendor/jquery-2.1.1.min.js"></script>
<script language='javascript'>var gameabc_face = gameabc_face||{};</script>
<script language='javascript'>gameabc_face.path="assets/bmp";</script>
<!-- Spine 运行时按需加载。
spine-canvas.js 与 spine-webgl.js 都以 var spine = (() => {...})() 暴露
同一个全局名 spine,同时加载会互相覆盖,故只能二选一。
强制切换(验证用):在本段之前设 window.__spineForceBackend = 'canvas' 或 'webgl'。-->
<script type="text/javascript">
(function(){
var forced = window.__spineForceBackend;
var useWebGL;
var reason;
if (forced === "webgl" || forced === "canvas") {
useWebGL = (forced === "webgl");
reason = "被 window.__spineForceBackend 强制指定为 " + forced;
} else if (location.protocol === "file:") {
// file:// 下 <img> 会被标记 tainted,texImage2D 拒绝上传
// (Canvas2D 的 drawImage 则允许,故 canvas 后端仍可工作)。
// 项目文档要求 HTTP 环境调试;此处兜住误用 file:// 的情形,
// 回退 canvas 保证特效可见,而不是抛一片 DOMException。
useWebGL = false;
reason = "file:// 协议下 WebGL 无法上传纹理,强制回退 canvas";
} else {
useWebGL = false;
reason = "WebGL 探测失败(getContext 返回空)";
try {
var probe = document.createElement("canvas");
var gl = probe.getContext("webgl") || probe.getContext("experimental-webgl");
if (gl) {
useWebGL = true;
reason = "WebGL 探测通过";
// 释放探测用 context:浏览器对并发 WebGL context 数量有限制,
// 泄漏会导致叠加层拿不到 context。
var lose = gl.getExtension("WEBGL_lose_context");
if (lose) lose.loseContext();
}
} catch (err) {
useWebGL = false;
reason = "WebGL 探测抛异常: " + err.message;
}
}
if (typeof console !== "undefined" && console.log) {
console.log("[Spine] 运行时选择: " + (useWebGL ? "spine-webgl.js" : "spine-canvas.js") + "(" + reason + ")");
}
document.write('<script type="text/javascript" src="js/vendor/spine-'
+ (useWebGL ? "webgl" : "canvas") + '.js"><\/script>');
})();
</script>
<script type="text/javascript" src="js/vendor/gameabc.min.js"></script>
<!-- Spine 资源清单:列出需要预加载的 Spine 资源基础名 -->
<script type="text/javascript" src="generated/spine_assets.js"></script>
<!-- Spine 文本数据嵌入(解决 file:// 协议 CORS 问题) -->
<script type="text/javascript" src="generated/spine_data.js"></script>
<!-- Spine 渲染后端:必须在 SpineMgr.js 之前加载(SpineMgr 末尾会立即执行预加载块)-->
<script type="text/javascript" src="js/gameabc-framework/spine/SpineOverlayTransform.js"></script>
<script type="text/javascript" src="js/gameabc-framework/spine/SpineBackendCanvas.js"></script>
<script type="text/javascript" src="js/gameabc-framework/spine/SpineBackendWebGL.js"></script>
<!-- SpineMgr: 自动初始化+自动渲染,必须在 gamemain.js 之前加载 -->
<script type="text/javascript" src="js/gameabc-framework/spine/SpineMgr.js"></script>
<script type="text/javascript" src="app_data.js"></script>
<script type="text/javascript" src="app_battery.js"></script>
<script type="text/javascript" src="app_network.js"></script>
<script type="text/javascript" src="app_gamesname.js"></script>
<script type="text/javascript" src="js/gamemain.js"></script>
<script type="text/javascript" src="js/00_Surface/02_Const.js"></script>
<script type="text/javascript" src="js/00_Surface/04_Data.js"></script>
<script type="text/javascript" src="version.js"></script>
<script type="text/javascript" src="js/00_Surface/08_Utl_Output.js"></script>
<script type="text/javascript" src="js/00_Surface/07_Desk.js"></script>
<script type="text/javascript" src="js/00_Surface/05_Func.js"></script>
<script type="text/javascript" src="js/00_Surface/10_Game.js"></script>
<script type="text/javascript" src="js/00_Surface/11_GameUI.js"></script>
<script type="text/javascript" src="js/00_Surface/12_Logic.js"></script>
<script type="text/javascript" src="js/00_Surface/00_minhttp.js"></script>
<script type="text/javascript" src="js/00_Surface/09_Net.js"></script>
<script type="text/javascript" src="js/00_Surface/06_Player.js"></script>
<script type="text/javascript" src="js/00_Surface/03_Banwords.js"></script>
<!-- 阶段0: 强制工具类(必须最先加载) -->
<script type="text/javascript" src="js/gameabc-framework/core/GameABCUtils.js"></script>
<script type="text/javascript" src="js/gameabc-framework/network/RpcHelper.js"></script>
<script type="text/javascript" src="js/gameabc-framework/system/EventBus.js"></script>
<!-- 精灵事件控制器(框架 system):须早于任何使用精灵交互的组件/回放/JingMark 加载 -->
<script type="text/javascript" src="js/gameabc-framework/system/SpriteEventController.js"></script>
<!-- 精灵手势识别器(框架 system):双击/滑动/点击判定,建立在 SpriteEventController 之上 -->
<script type="text/javascript" src="js/gameabc-framework/system/SpriteGestureRecognizer.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/AlignmentUtils.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/SpriteCopyUtils.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/DynamicSpriteList.js"></script>
<!-- UI组件 -->
<script type="text/javascript" src="js/gameabc-framework/core/SpriteManager.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/BaseComponent.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/UIManager.js"></script>
<!-- 通用战绩页组件(依赖 DynamicSpriteList/SpriteEventController/SpriteManager,均已在前加载) -->
<script type="text/javascript" src="js/gameabc-framework/ui/RecordViewDefaultConfig.js"></script>
<script type="text/javascript" src="js/gameabc-framework/ui/RecordView.js"></script>
<!-- 图集叠绘数字(一个精灵画多位美术字;依赖 SpriteManager/SpriteEventController,均已在前加载) -->
<script type="text/javascript" src="js/gameabc-framework/ui/NumberRenderer.js"></script>
<!-- 动画系统 (Phase 5) -->
<script type="text/javascript" src="js/gameabc-framework/system/AnimationManager.js"></script>
<!-- 音频系统 -->
<script type="text/javascript" src="js/gameabc-framework/system/AudioManager.js"></script>
<!-- 阶段5: 二七王子游戏实现层 -->
<!-- 5.1 配置常量(纯数据,无依赖,最先加载) -->
<script type="text/javascript" src="js/01_SubGame/codes/config/Layers.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Groups.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/ImageResources.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/SoundResources.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Table.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Cards.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Action.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_Result.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Sprites_CreateRoom.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/LayoutConstants.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Table.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Cards.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Action.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_Result.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/Layout_CreateRoom.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/config/AnimConstants.js"></script>
<!-- 5.2 前后端共享算法(只读副本,改动落在服务端 shared/,跑根目录 sync_shared.cmd 同步) -->
<script type="text/javascript" src="js/01_SubGame/codes/shared/cards.js"></script>
<!-- 5.3 纯逻辑核心 -->
<script type="text/javascript" src="js/01_SubGame/codes/core/CardCodec.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/SeatMap.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/CardOrder.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/CardMark.js"></script>
<script type="text/javascript" src="js/01_SubGame/codes/core/SpriteIndex.js"></script>
<!-- 5.4 布局求解 -->
<script type="text/javascript" src="js/01_SubGame/codes/ui/LayoutSolver.js"></script>
<!-- 5.5 平台接入(须在依赖之后、三文件转发壳之前) -->
<script type="text/javascript" src="js/01_SubGame/codes/SubGameHooks.js"></script>
<!-- 子游戏 Hooks 实现(转发壳三文件转发到此;须在依赖的 controllers/handlers 之后、三文件之前)-->
<script type="text/javascript" src="js/01_SubGame/00_SubGame_Config.js"></script>
<script type="text/javascript" src="js/01_SubGame/01_SubGame_modify.js"></script>
<script type="text/javascript" src="js/01_SubGame/02_SubGame_Input.js"></script>
<!----------------------------------------------------------------------------->
<script type="text/javascript" src="output/gameabc_data.min.js"></script>
</body>
</html>