@maoyugames/phaser-framework 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +53 -34
- package/dist/index.d.ts +61 -3
- package/dist/index.js +119 -34
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1218,7 +1218,13 @@ async function runVerify(target, opts = {}) {
|
|
|
1218
1218
|
const { server, port } = await serveDist(distDir);
|
|
1219
1219
|
const url = `http://127.0.0.1:${port}/`;
|
|
1220
1220
|
console.log(pc6.cyan(pc6.bold(`\u25B6 [verify] \u65E0\u5934\u6D4F\u89C8\u5668\u6253\u5F00 ${platform} \u4EA7\u7269`)));
|
|
1221
|
-
const launchArgs = [
|
|
1221
|
+
const launchArgs = [
|
|
1222
|
+
"--no-sandbox",
|
|
1223
|
+
"--use-gl=angle",
|
|
1224
|
+
"--use-angle=swiftshader",
|
|
1225
|
+
"--enable-unsafe-swiftshader",
|
|
1226
|
+
"--ignore-gpu-blocklist"
|
|
1227
|
+
];
|
|
1222
1228
|
let browser;
|
|
1223
1229
|
try {
|
|
1224
1230
|
browser = await pw.chromium.launch({ channel: "chrome", headless: true, args: launchArgs });
|
|
@@ -1235,7 +1241,11 @@ async function runVerify(target, opts = {}) {
|
|
|
1235
1241
|
const errors = [];
|
|
1236
1242
|
let rendered = false;
|
|
1237
1243
|
let distinctColors = 0;
|
|
1244
|
+
let canvasInView = false;
|
|
1238
1245
|
let canvasInfo = null;
|
|
1246
|
+
const outDir = join(ctx.root, ".pf-verify");
|
|
1247
|
+
mkdirSync(outDir, { recursive: true });
|
|
1248
|
+
const shot = join(outDir, `${platform}.png`);
|
|
1239
1249
|
try {
|
|
1240
1250
|
const page = await browser.newPage({ viewport });
|
|
1241
1251
|
page.on("pageerror", (e) => errors.push("PAGEERROR: " + e.message));
|
|
@@ -1245,41 +1255,47 @@ async function runVerify(target, opts = {}) {
|
|
|
1245
1255
|
await page.goto(url, { waitUntil: "load", timeout: 3e4 });
|
|
1246
1256
|
for (let i = 0; i < 20; i++) {
|
|
1247
1257
|
await page.waitForTimeout(1e3);
|
|
1248
|
-
const
|
|
1258
|
+
const buf = await page.screenshot({ type: "png" }).catch(() => null);
|
|
1259
|
+
if (buf) writeFileSync(shot, buf);
|
|
1260
|
+
if (buf) {
|
|
1261
|
+
const dataUrl = "data:image/png;base64," + buf.toString("base64");
|
|
1262
|
+
distinctColors = await page.evaluate(async (u) => {
|
|
1263
|
+
const img = new Image();
|
|
1264
|
+
img.src = u;
|
|
1265
|
+
await img.decode();
|
|
1266
|
+
const cv = document.createElement("canvas");
|
|
1267
|
+
cv.width = img.width;
|
|
1268
|
+
cv.height = img.height;
|
|
1269
|
+
const cx = cv.getContext("2d");
|
|
1270
|
+
if (!cx) return 0;
|
|
1271
|
+
cx.drawImage(img, 0, 0);
|
|
1272
|
+
const data = cx.getImageData(0, 0, cv.width, cv.height).data;
|
|
1273
|
+
const colors = /* @__PURE__ */ new Set();
|
|
1274
|
+
const total = cv.width * cv.height;
|
|
1275
|
+
const step = Math.max(1, Math.floor(total / 5e3));
|
|
1276
|
+
for (let k = 0; k < total && colors.size < 40; k += step) {
|
|
1277
|
+
const o = k * 4;
|
|
1278
|
+
colors.add(`${data[o]},${data[o + 1]},${data[o + 2]}`);
|
|
1279
|
+
}
|
|
1280
|
+
return colors.size;
|
|
1281
|
+
}, dataUrl).catch(() => 0);
|
|
1282
|
+
}
|
|
1283
|
+
const vis = await page.evaluate(() => {
|
|
1249
1284
|
const c = document.querySelector("canvas");
|
|
1250
|
-
if (!c) return {
|
|
1251
|
-
const
|
|
1252
|
-
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
for (let k = 0; k < total && colors.size < 40; k += step) {
|
|
1260
|
-
const o = k * 4;
|
|
1261
|
-
colors.add(`${data[o]},${data[o + 1]},${data[o + 2]}`);
|
|
1262
|
-
}
|
|
1263
|
-
return { ok: true, distinct: colors.size, w, h };
|
|
1264
|
-
}).catch(() => ({ ok: false, distinct: 0, w: 0, h: 0 }));
|
|
1265
|
-
canvasInfo = stat.w ? { w: stat.w, h: stat.h } : canvasInfo;
|
|
1266
|
-
distinctColors = stat.distinct;
|
|
1267
|
-
if (stat.ok && stat.distinct > 3) {
|
|
1285
|
+
if (!c) return { has: false, inView: false, w: 0, h: 0 };
|
|
1286
|
+
const r = c.getBoundingClientRect();
|
|
1287
|
+
const st = getComputedStyle(c);
|
|
1288
|
+
const inView = r.bottom > 0 && r.right > 0 && r.top < innerHeight && r.left < innerWidth && r.width > 1 && r.height > 1 && st.display !== "none" && st.visibility !== "hidden" && Number(st.opacity) > 0;
|
|
1289
|
+
return { has: true, inView, w: Math.round(r.width), h: Math.round(r.height) };
|
|
1290
|
+
}).catch(() => ({ has: false, inView: false, w: 0, h: 0 }));
|
|
1291
|
+
canvasInfo = vis.has ? { w: vis.w, h: vis.h } : canvasInfo;
|
|
1292
|
+
canvasInView = vis.inView;
|
|
1293
|
+
if (distinctColors > 3 && canvasInView) {
|
|
1268
1294
|
rendered = true;
|
|
1269
1295
|
break;
|
|
1270
1296
|
}
|
|
1271
1297
|
}
|
|
1272
|
-
|
|
1273
|
-
const c = document.querySelector("canvas");
|
|
1274
|
-
return c ? c.toDataURL("image/png") : "";
|
|
1275
|
-
}).catch(() => "");
|
|
1276
|
-
if (durl) {
|
|
1277
|
-
const outDir = join(ctx.root, ".pf-verify");
|
|
1278
|
-
mkdirSync(outDir, { recursive: true });
|
|
1279
|
-
const shot = join(outDir, `${platform}.png`);
|
|
1280
|
-
writeFileSync(shot, Buffer.from(durl.split(",")[1], "base64"));
|
|
1281
|
-
console.log(pc6.gray(` \u622A\u56FE:${shot}`));
|
|
1282
|
-
}
|
|
1298
|
+
console.log(pc6.gray(` \u622A\u56FE(\u5C4F\u5E55\u5B9E\u62CD):${shot}`));
|
|
1283
1299
|
} catch (e) {
|
|
1284
1300
|
errors.push("VERIFY: " + e.message);
|
|
1285
1301
|
} finally {
|
|
@@ -1289,7 +1305,9 @@ async function runVerify(target, opts = {}) {
|
|
|
1289
1305
|
const ok = errors.length === 0 && rendered;
|
|
1290
1306
|
console.log("");
|
|
1291
1307
|
console.log(pc6.bold("\u25B6 [verify] \u7ED3\u679C"));
|
|
1292
|
-
console.log(
|
|
1308
|
+
console.log(
|
|
1309
|
+
` canvas:${canvasInfo ? `${canvasInfo.w}\xD7${canvasInfo.h}` : "\u65E0"};\u5728\u89C6\u53E3\u5185:${canvasInView ? "\u662F" : "\u5426"};\u5C4F\u5E55\u989C\u8272\u6570:${distinctColors}(>3 \u89C6\u4E3A\u5DF2\u6E32\u67D3)`
|
|
1310
|
+
);
|
|
1293
1311
|
if (errors.length) {
|
|
1294
1312
|
console.log(pc6.red(` \u63A7\u5236\u53F0/\u9875\u9762\u9519\u8BEF(${errors.length}):`));
|
|
1295
1313
|
errors.slice(0, 12).forEach((e) => console.log(pc6.red(" " + e)));
|
|
@@ -1298,10 +1316,11 @@ async function runVerify(target, opts = {}) {
|
|
|
1298
1316
|
}
|
|
1299
1317
|
if (ok) {
|
|
1300
1318
|
console.log(pc6.green(pc6.bold(`
|
|
1301
|
-
\u2713 [verify] ${platform} \u5B9E\u8DD1\u901A\u8FC7(\u6E32\u67D3\u6B63\u5E38\u3001\u65E0\u8FD0\u884C\u671F\u9519\u8BEF)`)));
|
|
1319
|
+
\u2713 [verify] ${platform} \u5B9E\u8DD1\u901A\u8FC7(\u5C4F\u5E55\u6E32\u67D3\u6B63\u5E38\u3001\u65E0\u8FD0\u884C\u671F\u9519\u8BEF)`)));
|
|
1302
1320
|
} else {
|
|
1321
|
+
const reason = errors.length ? "\u5B58\u5728\u8FD0\u884C\u671F\u9519\u8BEF" : !canvasInView ? "canvas \u4E0D\u5728\u89C6\u53E3\u5185(\u88AB\u5E03\u5C40\u63A8\u51FA\u5C4F\u5E55/\u9690\u85CF \u2192 \u7528\u6237\u770B\u5230\u9ED1\u5C4F)" : "\u5C4F\u5E55\u753B\u9762\u672A\u6E32\u67D3\u51FA\u5185\u5BB9(\u7591\u4F3C\u5D29\u6E83/\u9ED1\u5C4F)";
|
|
1303
1322
|
console.log(pc6.red(pc6.bold(`
|
|
1304
|
-
\u2717 [verify] ${platform} \u672A\u901A\u8FC7:${
|
|
1323
|
+
\u2717 [verify] ${platform} \u672A\u901A\u8FC7:${reason}`)));
|
|
1305
1324
|
}
|
|
1306
1325
|
return ok;
|
|
1307
1326
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -620,7 +620,7 @@ declare abstract class BasePanel extends Phaser.GameObjects.Container {
|
|
|
620
620
|
color?: number;
|
|
621
621
|
alpha?: number;
|
|
622
622
|
closeOnClick?: boolean;
|
|
623
|
-
}): Phaser.GameObjects.
|
|
623
|
+
}): Phaser.GameObjects.Image;
|
|
624
624
|
/**
|
|
625
625
|
* 把一个子对象放到设计稿正中(以设计稿坐标系)。
|
|
626
626
|
* 仅设置坐标,不负责 add(由调用方决定何时 add 进容器)。
|
|
@@ -1057,6 +1057,13 @@ interface ButtonConfig extends ButtonStyle {
|
|
|
1057
1057
|
declare class Button extends Phaser.GameObjects.Container {
|
|
1058
1058
|
private readonly bg;
|
|
1059
1059
|
private readonly label;
|
|
1060
|
+
/**
|
|
1061
|
+
* 透明输入命中层(Image,使用默认 frame 命中区)。
|
|
1062
|
+
* 不直接在容器上 setInteractive(自定义 Rectangle) 的原因:真机/高分屏 Phaser FIT
|
|
1063
|
+
* 非整数缩放时,容器自定义矩形命中区会随离中心距离产生偏移,小按钮点不准;
|
|
1064
|
+
* Image 的 frame 命中区不受此影响。故输入统一走这一层。
|
|
1065
|
+
*/
|
|
1066
|
+
private readonly hit;
|
|
1060
1067
|
private readonly style;
|
|
1061
1068
|
private readonly onClick?;
|
|
1062
1069
|
/** 是否禁用 */
|
|
@@ -1071,7 +1078,58 @@ declare class Button extends Phaser.GameObjects.Container {
|
|
|
1071
1078
|
get disabled(): boolean;
|
|
1072
1079
|
/** 绘制圆角背景(以中心为原点) */
|
|
1073
1080
|
private drawBackground;
|
|
1074
|
-
/** 绑定指针交互:悬停/按下/抬起,实现按下态与点击触发 */
|
|
1081
|
+
/** 绑定指针交互:悬停/按下/抬起,实现按下态与点击触发(事件挂在命中层 hit 上) */
|
|
1082
|
+
private bindEvents;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/**
|
|
1086
|
+
* 圆形图标按钮 IconButton(基于 Phaser.GameObjects.Container)。
|
|
1087
|
+
*
|
|
1088
|
+
* 与 Button 的区别:Button 是「圆角矩形 + 文字」,IconButton 是「圆底 + 图标纹理」,
|
|
1089
|
+
* 适合返回/设置/帮助等小图标按钮。
|
|
1090
|
+
*
|
|
1091
|
+
* 输入用透明 Image 命中层(默认 frame 命中区)+ down/up 触发——在真机/高分屏
|
|
1092
|
+
* (Phaser FIT 非整数缩放)下命中可靠,规避「容器自定义 Rectangle 命中区小按钮点不准」的坑。
|
|
1093
|
+
*
|
|
1094
|
+
* 用法:
|
|
1095
|
+
* new IconButton(this, { x, y, size: 88, texture: 'icon_home', onClick: () => goMain() });
|
|
1096
|
+
*/
|
|
1097
|
+
|
|
1098
|
+
interface IconButtonConfig {
|
|
1099
|
+
x?: number;
|
|
1100
|
+
y?: number;
|
|
1101
|
+
/** 直径(圆底与命中区尺寸),默认 88 */
|
|
1102
|
+
size?: number;
|
|
1103
|
+
/** 图标纹理 key */
|
|
1104
|
+
texture: string;
|
|
1105
|
+
/** 图标帧(图集时用,可选) */
|
|
1106
|
+
frame?: string | number;
|
|
1107
|
+
/** 图标相对 size 的比例,默认 0.56 */
|
|
1108
|
+
iconScale?: number;
|
|
1109
|
+
/** 圆底颜色;传 null 不绘制底,默认深灰 0x232c44 */
|
|
1110
|
+
bgColor?: number | null;
|
|
1111
|
+
/** 圆底不透明度,默认 1 */
|
|
1112
|
+
bgAlpha?: number;
|
|
1113
|
+
/** 水平翻转图标(如用「下一关」箭头翻成「上一关」) */
|
|
1114
|
+
flipX?: boolean;
|
|
1115
|
+
/** 图标着色 */
|
|
1116
|
+
iconTint?: number;
|
|
1117
|
+
/** 点击回调(按下并在按钮内抬起才触发) */
|
|
1118
|
+
onClick?: () => void;
|
|
1119
|
+
}
|
|
1120
|
+
declare class IconButton extends Phaser.GameObjects.Container {
|
|
1121
|
+
private readonly icon;
|
|
1122
|
+
/** 透明命中层(frame 命中区,真机/高分屏可靠) */
|
|
1123
|
+
private readonly hit;
|
|
1124
|
+
private readonly onClick?;
|
|
1125
|
+
private _disabled;
|
|
1126
|
+
private pressed;
|
|
1127
|
+
constructor(scene: Phaser.Scene, config: IconButtonConfig);
|
|
1128
|
+
/** 更新图标纹理 */
|
|
1129
|
+
setIcon(texture: string, frame?: string | number): this;
|
|
1130
|
+
/** 设置禁用态 */
|
|
1131
|
+
setDisabled(disabled: boolean): this;
|
|
1132
|
+
get disabled(): boolean;
|
|
1075
1133
|
private bindEvents;
|
|
1076
1134
|
}
|
|
1077
1135
|
|
|
@@ -1777,4 +1835,4 @@ interface PlatformConfig {
|
|
|
1777
1835
|
capacitor?: CapacitorPlatformConfig;
|
|
1778
1836
|
}
|
|
1779
1837
|
|
|
1780
|
-
export { AdResult, type AdsConfig, App, type AppConfig, BaseModule, BasePanel, BaseScene, Button, type ButtonConfig, type ButtonStyle, type CapacitorPlatformConfig, ConfigTable, ConfigTableManager, ErrorCode, type FacebookPlatformConfig, FrameworkError, Handler, HttpClient, type HttpClientConfig, HttpError, type HttpInterceptors, HttpRequestOptions, I18n, type I18nOptions, type IAccountService, type IAdsManager, type IAnalyticsManager, type IApp, type IAssetLoader, type IAudioManager, type IConfigService, type IEventBus, type IHttpClient, type IKcpTransport, type ILogger, type INetManager, type IPanelManager, type IPaymentManager, IPlatform, IPlatformLifecycle, type ISceneManager, type ISocketClient, type IStorageManager, JsonCodec, KcpClient, type KcpClientConfig, type KcpTransportFactory, type LayerName, Layers, LogLevel, LoginResult, MessageChannel, type MessageChannelOptions, type MessageCodec, type MessageEnvelope, MessageError, ModuleRegistry, NetManager, type NetManagerOptions, type NetProtocol, ObjectPool, type Orientation, type PanelCtor, PanelManager, type PlatformConfig, PlatformContext, PurchaseResult, SafeArea, SaveManager, type SaveSlot, type SaveSlotOptions, type ScheduleHandle, Scheduler, type SocketClientConfig, type SocketState, type StartGameOptions, type Store, type TikTokPlatformConfig, TypedEventBus, Unsubscribe, type WeChatPlatformConfig, type WebPlatformConfig, WebSocketClient, createStore, createTypedEventBus, isFrameworkError, normalizeLocale, startGame };
|
|
1838
|
+
export { AdResult, type AdsConfig, App, type AppConfig, BaseModule, BasePanel, BaseScene, Button, type ButtonConfig, type ButtonStyle, type CapacitorPlatformConfig, ConfigTable, ConfigTableManager, ErrorCode, type FacebookPlatformConfig, FrameworkError, Handler, HttpClient, type HttpClientConfig, HttpError, type HttpInterceptors, HttpRequestOptions, I18n, type I18nOptions, type IAccountService, type IAdsManager, type IAnalyticsManager, type IApp, type IAssetLoader, type IAudioManager, type IConfigService, type IEventBus, type IHttpClient, type IKcpTransport, type ILogger, type INetManager, type IPanelManager, type IPaymentManager, IPlatform, IPlatformLifecycle, type ISceneManager, type ISocketClient, type IStorageManager, IconButton, type IconButtonConfig, JsonCodec, KcpClient, type KcpClientConfig, type KcpTransportFactory, type LayerName, Layers, LogLevel, LoginResult, MessageChannel, type MessageChannelOptions, type MessageCodec, type MessageEnvelope, MessageError, ModuleRegistry, NetManager, type NetManagerOptions, type NetProtocol, ObjectPool, type Orientation, type PanelCtor, PanelManager, type PlatformConfig, PlatformContext, PurchaseResult, SafeArea, SaveManager, type SaveSlot, type SaveSlotOptions, type ScheduleHandle, Scheduler, type SocketClientConfig, type SocketState, type StartGameOptions, type Store, type TikTokPlatformConfig, TypedEventBus, Unsubscribe, type WeChatPlatformConfig, type WebPlatformConfig, WebSocketClient, createStore, createTypedEventBus, isFrameworkError, normalizeLocale, startGame };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PlatformUnsupportedError } from './chunk-II3JM4R3.js';
|
|
2
2
|
export { PlatformUnsupportedError } from './chunk-II3JM4R3.js';
|
|
3
3
|
import { __publicField } from './chunk-PKBMQBKP.js';
|
|
4
|
-
import
|
|
4
|
+
import Phaser2 from 'phaser';
|
|
5
5
|
|
|
6
6
|
// src/App.ts
|
|
7
7
|
var parts = null;
|
|
@@ -2598,7 +2598,7 @@ var ModuleRegistry = class {
|
|
|
2598
2598
|
return this.modules.size;
|
|
2599
2599
|
}
|
|
2600
2600
|
};
|
|
2601
|
-
var BasePanel = class extends
|
|
2601
|
+
var BasePanel = class extends Phaser2.GameObjects.Container {
|
|
2602
2602
|
constructor(scene) {
|
|
2603
2603
|
super(scene, 0, 0);
|
|
2604
2604
|
/** 打开本面板时所属的 key(由 PanelManager 在创建后注入,用于自我关闭) */
|
|
@@ -2683,12 +2683,11 @@ var BasePanel = class extends Phaser4.GameObjects.Container {
|
|
|
2683
2683
|
const h = this.designHeight;
|
|
2684
2684
|
const color = opts?.color ?? 0;
|
|
2685
2685
|
const alpha = opts?.alpha ?? 0.6;
|
|
2686
|
-
const dim = this.scene.make.
|
|
2687
|
-
dim.
|
|
2688
|
-
dim.fillRect(0, 0, w, h);
|
|
2686
|
+
const dim = this.scene.make.image({ x: w / 2, y: h / 2, key: "__WHITE" }, false);
|
|
2687
|
+
dim.setDisplaySize(w, h).setTint(color).setAlpha(alpha);
|
|
2689
2688
|
if (opts?.closeOnClick) {
|
|
2690
|
-
dim.setInteractive(
|
|
2691
|
-
dim.on(
|
|
2689
|
+
dim.setInteractive();
|
|
2690
|
+
dim.on(Phaser2.Input.Events.POINTER_UP, () => this.close());
|
|
2692
2691
|
}
|
|
2693
2692
|
this.addAt(dim, 0);
|
|
2694
2693
|
return dim;
|
|
@@ -2947,24 +2946,33 @@ async function startGame(opts) {
|
|
|
2947
2946
|
}
|
|
2948
2947
|
function createPhaserGameInstance(config, scenes) {
|
|
2949
2948
|
const gameConfig = {
|
|
2950
|
-
type:
|
|
2949
|
+
type: Phaser2.AUTO,
|
|
2950
|
+
// 关键:把 canvas 挂进各平台外壳的 #game-root(外壳已为它写好布局/居中 CSS)。
|
|
2951
|
+
// 不设 parent 时 Phaser 把 canvas 追加到 document.body —— 而外壳里 #game-root 占满
|
|
2952
|
+
// 100% 高度,canvas 作为其后的块级兄弟会被挤到视口外,再被 body 的 overflow:hidden
|
|
2953
|
+
// 裁掉 → 屏幕全黑(但 canvas 后备缓冲其实已渲染,故 toDataURL/getImageData 读不出问题)。
|
|
2954
|
+
// wechat 无 DOM(weapp-adapter),'game-root' 不存在时 Phaser 自动回退,安全。
|
|
2955
|
+
parent: "game-root",
|
|
2951
2956
|
// 透明背景占位;业务场景自行绘制背景
|
|
2952
2957
|
backgroundColor: "#1f2937",
|
|
2953
2958
|
scale: {
|
|
2954
2959
|
// FIT:按设计分辨率等比缩放铺满容器(保持比例,留黑边);CENTER_BOTH:居中
|
|
2955
|
-
mode:
|
|
2956
|
-
autoCenter:
|
|
2960
|
+
mode: Phaser2.Scale.FIT,
|
|
2961
|
+
autoCenter: Phaser2.Scale.CENTER_BOTH,
|
|
2957
2962
|
width: config.designWidth,
|
|
2963
|
+
// autoRound:把缩放后画布尺寸取整,避免非整数缩放(如真机 1.866x)产生亚像素偏移,
|
|
2964
|
+
// 渲染更清晰、指针命中更准(配合 UI 组件用 frame 命中区,彻底解决高分屏小按钮点不准)。
|
|
2965
|
+
autoRound: true,
|
|
2958
2966
|
height: config.designHeight
|
|
2959
2967
|
},
|
|
2960
2968
|
scene: scenes
|
|
2961
2969
|
// 微信等无 DOM 平台由 weapp-adapter 提供 canvas;有 DOM 平台 Phaser 自动建 canvas
|
|
2962
2970
|
};
|
|
2963
|
-
return new
|
|
2971
|
+
return new Phaser2.Game(gameConfig);
|
|
2964
2972
|
}
|
|
2965
2973
|
function waitForGameReady(game) {
|
|
2966
2974
|
return new Promise((resolve) => {
|
|
2967
|
-
game.events.once(
|
|
2975
|
+
game.events.once(Phaser2.Core.Events.READY, () => resolve());
|
|
2968
2976
|
});
|
|
2969
2977
|
}
|
|
2970
2978
|
|
|
@@ -3070,7 +3078,7 @@ var Scheduler = class {
|
|
|
3070
3078
|
};
|
|
3071
3079
|
|
|
3072
3080
|
// src/scene/BaseScene.ts
|
|
3073
|
-
var BaseScene = class extends
|
|
3081
|
+
var BaseScene = class extends Phaser2.Scene {
|
|
3074
3082
|
constructor(config) {
|
|
3075
3083
|
super(config);
|
|
3076
3084
|
/* --------------------------- 自动清理 / 调度 --------------------------- */
|
|
@@ -3120,10 +3128,10 @@ var BaseScene = class extends Phaser4.Scene {
|
|
|
3120
3128
|
this._cleanupArmed = true;
|
|
3121
3129
|
const onShutdown = () => {
|
|
3122
3130
|
this.runCleanup();
|
|
3123
|
-
this.events.once(
|
|
3131
|
+
this.events.once(Phaser2.Scenes.Events.SHUTDOWN, onShutdown);
|
|
3124
3132
|
};
|
|
3125
|
-
this.events.once(
|
|
3126
|
-
this.events.once(
|
|
3133
|
+
this.events.once(Phaser2.Scenes.Events.SHUTDOWN, onShutdown);
|
|
3134
|
+
this.events.once(Phaser2.Scenes.Events.DESTROY, () => this.runCleanup());
|
|
3127
3135
|
}
|
|
3128
3136
|
/** 执行全部清理:解绑所有 bind 的订阅 + 清空场景调度器,并重置登记表 */
|
|
3129
3137
|
runCleanup() {
|
|
@@ -3207,11 +3215,18 @@ var DEFAULTS = {
|
|
|
3207
3215
|
fontSize: 32,
|
|
3208
3216
|
fontFamily: "sans-serif"
|
|
3209
3217
|
};
|
|
3210
|
-
var Button = class extends
|
|
3218
|
+
var Button = class extends Phaser2.GameObjects.Container {
|
|
3211
3219
|
constructor(scene, config) {
|
|
3212
3220
|
super(scene, config.x ?? 0, config.y ?? 0);
|
|
3213
3221
|
__publicField(this, "bg");
|
|
3214
3222
|
__publicField(this, "label");
|
|
3223
|
+
/**
|
|
3224
|
+
* 透明输入命中层(Image,使用默认 frame 命中区)。
|
|
3225
|
+
* 不直接在容器上 setInteractive(自定义 Rectangle) 的原因:真机/高分屏 Phaser FIT
|
|
3226
|
+
* 非整数缩放时,容器自定义矩形命中区会随离中心距离产生偏移,小按钮点不准;
|
|
3227
|
+
* Image 的 frame 命中区不受此影响。故输入统一走这一层。
|
|
3228
|
+
*/
|
|
3229
|
+
__publicField(this, "hit");
|
|
3215
3230
|
__publicField(this, "style");
|
|
3216
3231
|
__publicField(this, "onClick");
|
|
3217
3232
|
/** 是否禁用 */
|
|
@@ -3248,15 +3263,10 @@ var Button = class extends Phaser4.GameObjects.Container {
|
|
|
3248
3263
|
this.label.setOrigin(0.5, 0.5);
|
|
3249
3264
|
this.add(this.label);
|
|
3250
3265
|
this.setSize(this.style.width, this.style.height);
|
|
3251
|
-
this.
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
this.style.width,
|
|
3256
|
-
this.style.height
|
|
3257
|
-
),
|
|
3258
|
-
Phaser4.Geom.Rectangle.Contains
|
|
3259
|
-
);
|
|
3266
|
+
this.hit = scene.make.image({ x: 0, y: 0, key: "__WHITE" }, false);
|
|
3267
|
+
this.hit.setDisplaySize(this.style.width, this.style.height).setAlpha(1e-3);
|
|
3268
|
+
this.hit.setInteractive({ useHandCursor: true });
|
|
3269
|
+
this.add(this.hit);
|
|
3260
3270
|
this.bindEvents();
|
|
3261
3271
|
scene.add.existing(this);
|
|
3262
3272
|
}
|
|
@@ -3270,12 +3280,12 @@ var Button = class extends Phaser4.GameObjects.Container {
|
|
|
3270
3280
|
this._disabled = disabled;
|
|
3271
3281
|
this.setAlpha(disabled ? 0.5 : 1);
|
|
3272
3282
|
if (disabled) {
|
|
3273
|
-
this.disableInteractive();
|
|
3283
|
+
this.hit.disableInteractive();
|
|
3274
3284
|
this.pressed = false;
|
|
3275
3285
|
this.drawBackground(this.style.backgroundColor);
|
|
3276
3286
|
this.setScale(1);
|
|
3277
3287
|
} else {
|
|
3278
|
-
this.setInteractive();
|
|
3288
|
+
this.hit.setInteractive({ useHandCursor: true });
|
|
3279
3289
|
}
|
|
3280
3290
|
return this;
|
|
3281
3291
|
}
|
|
@@ -3289,25 +3299,25 @@ var Button = class extends Phaser4.GameObjects.Container {
|
|
|
3289
3299
|
this.bg.fillStyle(color, 1);
|
|
3290
3300
|
this.bg.fillRoundedRect(-width / 2, -height / 2, width, height, radius);
|
|
3291
3301
|
}
|
|
3292
|
-
/** 绑定指针交互:悬停/按下/抬起,实现按下态与点击触发 */
|
|
3302
|
+
/** 绑定指针交互:悬停/按下/抬起,实现按下态与点击触发(事件挂在命中层 hit 上) */
|
|
3293
3303
|
bindEvents() {
|
|
3294
|
-
this.on(
|
|
3304
|
+
this.hit.on(Phaser2.Input.Events.POINTER_OVER, () => {
|
|
3295
3305
|
if (this._disabled) return;
|
|
3296
3306
|
this.drawBackground(this.style.backgroundColorActive);
|
|
3297
3307
|
});
|
|
3298
|
-
this.on(
|
|
3308
|
+
this.hit.on(Phaser2.Input.Events.POINTER_OUT, () => {
|
|
3299
3309
|
if (this._disabled) return;
|
|
3300
3310
|
this.pressed = false;
|
|
3301
3311
|
this.drawBackground(this.style.backgroundColor);
|
|
3302
3312
|
this.setScale(1);
|
|
3303
3313
|
});
|
|
3304
|
-
this.on(
|
|
3314
|
+
this.hit.on(Phaser2.Input.Events.POINTER_DOWN, () => {
|
|
3305
3315
|
if (this._disabled) return;
|
|
3306
3316
|
this.pressed = true;
|
|
3307
3317
|
this.drawBackground(this.style.backgroundColorActive);
|
|
3308
3318
|
this.setScale(0.96);
|
|
3309
3319
|
});
|
|
3310
|
-
this.on(
|
|
3320
|
+
this.hit.on(Phaser2.Input.Events.POINTER_UP, () => {
|
|
3311
3321
|
if (this._disabled) return;
|
|
3312
3322
|
this.setScale(1);
|
|
3313
3323
|
this.drawBackground(this.style.backgroundColor);
|
|
@@ -3318,6 +3328,81 @@ var Button = class extends Phaser4.GameObjects.Container {
|
|
|
3318
3328
|
});
|
|
3319
3329
|
}
|
|
3320
3330
|
};
|
|
3331
|
+
var DEFAULT_SIZE = 88;
|
|
3332
|
+
var DEFAULT_BG = 2305092;
|
|
3333
|
+
var IconButton = class extends Phaser2.GameObjects.Container {
|
|
3334
|
+
constructor(scene, config) {
|
|
3335
|
+
super(scene, config.x ?? 0, config.y ?? 0);
|
|
3336
|
+
__publicField(this, "icon");
|
|
3337
|
+
/** 透明命中层(frame 命中区,真机/高分屏可靠) */
|
|
3338
|
+
__publicField(this, "hit");
|
|
3339
|
+
__publicField(this, "onClick");
|
|
3340
|
+
__publicField(this, "_disabled", false);
|
|
3341
|
+
__publicField(this, "pressed", false);
|
|
3342
|
+
const size = config.size ?? DEFAULT_SIZE;
|
|
3343
|
+
this.onClick = config.onClick;
|
|
3344
|
+
if (config.bgColor !== null) {
|
|
3345
|
+
const bg = scene.make.graphics({}, false);
|
|
3346
|
+
bg.fillStyle(config.bgColor ?? DEFAULT_BG, config.bgAlpha ?? 1);
|
|
3347
|
+
bg.fillCircle(0, 0, size / 2);
|
|
3348
|
+
this.add(bg);
|
|
3349
|
+
}
|
|
3350
|
+
this.icon = scene.make.image({ x: 0, y: 0, key: config.texture, frame: config.frame }, false);
|
|
3351
|
+
const target = size * (config.iconScale ?? 0.56);
|
|
3352
|
+
this.icon.setScale(target / Math.max(this.icon.width, this.icon.height || 1));
|
|
3353
|
+
if (config.flipX) this.icon.setFlipX(true);
|
|
3354
|
+
if (config.iconTint !== void 0) this.icon.setTint(config.iconTint);
|
|
3355
|
+
this.add(this.icon);
|
|
3356
|
+
this.hit = scene.make.image({ x: 0, y: 0, key: "__WHITE" }, false);
|
|
3357
|
+
this.hit.setDisplaySize(size, size).setAlpha(1e-3);
|
|
3358
|
+
this.hit.setInteractive({ useHandCursor: true });
|
|
3359
|
+
this.add(this.hit);
|
|
3360
|
+
this.setSize(size, size);
|
|
3361
|
+
this.bindEvents();
|
|
3362
|
+
scene.add.existing(this);
|
|
3363
|
+
}
|
|
3364
|
+
/** 更新图标纹理 */
|
|
3365
|
+
setIcon(texture, frame) {
|
|
3366
|
+
this.icon.setTexture(texture, frame);
|
|
3367
|
+
return this;
|
|
3368
|
+
}
|
|
3369
|
+
/** 设置禁用态 */
|
|
3370
|
+
setDisabled(disabled) {
|
|
3371
|
+
this._disabled = disabled;
|
|
3372
|
+
this.setAlpha(disabled ? 0.5 : 1);
|
|
3373
|
+
if (disabled) {
|
|
3374
|
+
this.hit.disableInteractive();
|
|
3375
|
+
this.pressed = false;
|
|
3376
|
+
this.setScale(1);
|
|
3377
|
+
} else {
|
|
3378
|
+
this.hit.setInteractive({ useHandCursor: true });
|
|
3379
|
+
}
|
|
3380
|
+
return this;
|
|
3381
|
+
}
|
|
3382
|
+
get disabled() {
|
|
3383
|
+
return this._disabled;
|
|
3384
|
+
}
|
|
3385
|
+
bindEvents() {
|
|
3386
|
+
this.hit.on(Phaser2.Input.Events.POINTER_DOWN, () => {
|
|
3387
|
+
if (this._disabled) return;
|
|
3388
|
+
this.pressed = true;
|
|
3389
|
+
this.setScale(0.92);
|
|
3390
|
+
});
|
|
3391
|
+
this.hit.on(Phaser2.Input.Events.POINTER_OUT, () => {
|
|
3392
|
+
if (this._disabled) return;
|
|
3393
|
+
this.pressed = false;
|
|
3394
|
+
this.setScale(1);
|
|
3395
|
+
});
|
|
3396
|
+
this.hit.on(Phaser2.Input.Events.POINTER_UP, () => {
|
|
3397
|
+
if (this._disabled) return;
|
|
3398
|
+
this.setScale(1);
|
|
3399
|
+
if (this.pressed) {
|
|
3400
|
+
this.pressed = false;
|
|
3401
|
+
this.onClick?.();
|
|
3402
|
+
}
|
|
3403
|
+
});
|
|
3404
|
+
}
|
|
3405
|
+
};
|
|
3321
3406
|
|
|
3322
3407
|
// src/store/Store.ts
|
|
3323
3408
|
function deepClone2(value) {
|
|
@@ -3806,4 +3891,4 @@ var MessageChannel = class {
|
|
|
3806
3891
|
}
|
|
3807
3892
|
};
|
|
3808
3893
|
|
|
3809
|
-
export { App, BaseModule, BasePanel, BaseScene, Button, ConfigTable, ConfigTableManager, ErrorCode, FrameworkError, HttpClient, HttpError, I18n, JsonCodec, KcpClient, Layers, LogLevel, MessageChannel, MessageError, ModuleRegistry, NetManager, ObjectPool, PanelManager, PlatformContext, SaveManager, Scheduler, TypedEventBus, WebSocketClient, createStore, createTypedEventBus, err, isFrameworkError, normalizeLocale, ok, startGame };
|
|
3894
|
+
export { App, BaseModule, BasePanel, BaseScene, Button, ConfigTable, ConfigTableManager, ErrorCode, FrameworkError, HttpClient, HttpError, I18n, IconButton, JsonCodec, KcpClient, Layers, LogLevel, MessageChannel, MessageError, ModuleRegistry, NetManager, ObjectPool, PanelManager, PlatformContext, SaveManager, Scheduler, TypedEventBus, WebSocketClient, createStore, createTypedEventBus, err, isFrameworkError, normalizeLocale, ok, startGame };
|