|
|
@@ -37,6 +37,8 @@ const SYMBOL_RULES = GENERATED_CONFIG.symbols || [];
|
|
|
const MATH_MODEL = GENERATED_CONFIG.mathModel || {};
|
|
|
const PAYOUT_SCALE = MATH_MODEL.payoutScale ?? 1;
|
|
|
const REEL_STRIPS = MATH_MODEL.reelStrips || [];
|
|
|
+const BOSS_CONFIG = GENERATED_CONFIG.boss || { enabled: false };
|
|
|
+const BOSS_ID = BOSS_CONFIG.id || 'boss_demon_lord';
|
|
|
|
|
|
// ============ 文字样式表(统一定义,按角色取用)============
|
|
|
// size<=1 表示相对所在容器高度的比例;否则按像素。ow=描边宽。
|
|
|
@@ -120,6 +122,8 @@ export class SlotGame extends Component {
|
|
|
private t = 0;
|
|
|
private turbo = false; private auto = false;
|
|
|
private turboBtn!: Node; private autoBtn!: Node;
|
|
|
+ private bossNode: Node | null = null;
|
|
|
+ private bossSk: sp.Skeleton | null = null;
|
|
|
|
|
|
onLoad() {
|
|
|
try { (cc as any).profiler?.hideStats?.(); } catch (e) {}
|
|
|
@@ -149,11 +153,12 @@ export class SlotGame extends Component {
|
|
|
this.buildArt(W, H);
|
|
|
this.buildHud(W, H);
|
|
|
this.buildControls(W, H);
|
|
|
- let left = SYMBOLS.length;
|
|
|
- SYMBOLS.forEach((id) => {
|
|
|
+ const loadIds = BOSS_CONFIG.enabled ? SYMBOLS.concat([BOSS_ID]) : SYMBOLS;
|
|
|
+ let left = loadIds.length;
|
|
|
+ loadIds.forEach((id) => {
|
|
|
resources.load(`characters/${id}`, sp.SkeletonData, (err, data) => {
|
|
|
if (!err) this.dataMap[id] = data;
|
|
|
- if (--left === 0) this.buildGrid();
|
|
|
+ if (--left === 0) { this.buildGrid(); this.buildBoss(); }
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
@@ -205,6 +210,19 @@ export class SlotGame extends Component {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private buildBoss() {
|
|
|
+ if (!BOSS_CONFIG.enabled || !this.dataMap[BOSS_ID]) return;
|
|
|
+ const node = new Node('boss'); node.parent = this.node; node.setSiblingIndex(8);
|
|
|
+ const sk = node.addComponent(sp.Skeleton);
|
|
|
+ sk.skeletonData = this.dataMap[BOSS_ID];
|
|
|
+ sk.premultipliedAlpha = false;
|
|
|
+ sk.setAnimation(0, 'idle', true);
|
|
|
+ const scale = Math.min(0.22, this.W / 3900);
|
|
|
+ node.setScale(scale, scale, 1);
|
|
|
+ node.setPosition(this.frameW * 0.40, this.frameCY + this.frameH * 0.32, 0);
|
|
|
+ this.bossNode = node; this.bossSk = sk;
|
|
|
+ }
|
|
|
+
|
|
|
// ---------------- HUD:用 hud_pill 美术 ----------------
|
|
|
private buildHud(W: number, H: number) {
|
|
|
const y = H * LAYOUT.hud.cy;
|
|
|
@@ -345,6 +363,31 @@ export class SlotGame extends Component {
|
|
|
tween(op).delay(0.95).to(0.35, { opacity: 0 }).call(() => n.destroy()).start();
|
|
|
this.coinShower(Math.max(12, Math.min(40, Math.floor(amount / 15))));
|
|
|
}
|
|
|
+
|
|
|
+ private bossDefeated() {
|
|
|
+ if (!this.bossNode || !this.bossSk) return;
|
|
|
+ this.bossSk.setAnimation(0, 'hurt', false);
|
|
|
+ this.bossSk.addAnimation(0, 'idle', true, 0.2);
|
|
|
+ this.playParticle('boss_explosion');
|
|
|
+ const n = this.bossNode;
|
|
|
+ const base = n.scale.x;
|
|
|
+ tween(n).to(0.10, { scale: new Vec3(base * 1.18, base * 0.86, 1), angle: -7 })
|
|
|
+ .to(0.12, { scale: new Vec3(base * 0.82, base * 1.18, 1), angle: 8 })
|
|
|
+ .to(0.18, { scale: new Vec3(base, base, 1), angle: 0 }, { easing: 'backOut' }).start();
|
|
|
+ this.flashMult('大魔王裂开爆炸!');
|
|
|
+ }
|
|
|
+
|
|
|
+ private bossTaunt() {
|
|
|
+ if (!this.bossNode || !this.bossSk) return;
|
|
|
+ this.bossSk.setAnimation(0, 'attack', false);
|
|
|
+ this.bossSk.addAnimation(0, 'idle', true, 0);
|
|
|
+ const n = this.bossNode;
|
|
|
+ const x = n.position.x, y = n.position.y;
|
|
|
+ tween(n).to(0.12, { position: new Vec3(x - this.cell * 0.12, y + this.cell * 0.10, 0), angle: -5 })
|
|
|
+ .to(0.16, { position: new Vec3(x + this.cell * 0.10, y - this.cell * 0.18, 0), angle: 7 })
|
|
|
+ .to(0.18, { position: new Vec3(x, y, 0), angle: 0 }, { easing: 'backOut' }).start();
|
|
|
+ this.flashMult('大魔王举剑耀武扬威');
|
|
|
+ }
|
|
|
private coinShower(count: number) {
|
|
|
const sf = this.art['coin']; if (!sf) return;
|
|
|
const sz = this.cell * 0.6;
|
|
|
@@ -636,8 +679,8 @@ export class SlotGame extends Component {
|
|
|
}
|
|
|
|
|
|
private endRound() {
|
|
|
- if (this.roundWin > 0) { this.multLabel.string = ''; this.celebrate(this.roundWin); }
|
|
|
- else this.multLabel.string = '';
|
|
|
+ if (this.roundWin > 0) { this.multLabel.string = ''; this.celebrate(this.roundWin); this.bossDefeated(); }
|
|
|
+ else { this.multLabel.string = ''; this.bossTaunt(); }
|
|
|
this.spinning = false; this.setSpinEnabled(true);
|
|
|
if (this.holdActive) return;
|
|
|
if (this.freeSpins > 0) this.scheduleOnce(() => this.spin(), this.td(0.9));
|