feat: enhance card armor values and add retro VHS menu effects
- Updated `data/cards.json` to significantly increase armor values across all card tiers and types for better survivability balance. - Refined skill descriptions in `data/skills.json` (Pierce, Berserk, Protect, Jam, Enfeeble) to clarify mechanics like "this turn" vs "permanent" effects and added flavor text. - Added video background support to `MainMenuScene.js` using the new `tyrants-edge-menu.mp4` asset. - Implemented retro VHS visual overlays on the menu: scanlines, stepped vignette, rolling tracking bar, and random screen flickers for atmospheric effect.
This commit is contained in:
parent
e9b7a51b32
commit
e012cda336
Binary file not shown.
264
data/cards.json
264
data/cards.json
File diff suppressed because it is too large
Load Diff
|
|
@ -15,8 +15,8 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "pierce",
|
"name": "pierce",
|
||||||
"description": "Before attacking: reduce the target's armor by value for this attack, then restore it after.",
|
"description": "Before attacking: Find a weakpoint to reduce the target's armor by value for this attack.",
|
||||||
"allDescription": "Before attacking: reduce ALL enemy cards' armor by value for this attack, then restore after.",
|
"allDescription": "Before attacking: reduce ALL enemy cards' armor by value for this attack.",
|
||||||
"trigger": "preAttack",
|
"trigger": "preAttack",
|
||||||
"category": "offense",
|
"category": "offense",
|
||||||
"supportsAll": true
|
"supportsAll": true
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "berserk",
|
"name": "berserk",
|
||||||
"description": "On damage: permanently gain value attack power for this battle.",
|
"description": "On damage: RAGE! Permanently gain value attack power for this battle.",
|
||||||
"trigger": "on_attack",
|
"trigger": "on_attack",
|
||||||
"category": "offense"
|
"category": "offense"
|
||||||
},
|
},
|
||||||
|
|
@ -59,20 +59,20 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "protect",
|
"name": "protect",
|
||||||
"description": "Before battle: grant +value armor to self and adjacent lane cards. Removed after battle.",
|
"description": "Before battle: grant +value armor to self and adjacent lane cards. Removed after each turn.",
|
||||||
"trigger": "preBattle",
|
"trigger": "preBattle",
|
||||||
"category": "defense"
|
"category": "defense"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "jam",
|
"name": "jam",
|
||||||
"description": "Prevent the target card from attacking for value turns.",
|
"description": "Jam their signals! Reduce opponent skill abilities by value this turn, also has reduced effect on opponent neighbors.",
|
||||||
"trigger": "on_attack",
|
"trigger": "on_attack",
|
||||||
"category": "control"
|
"category": "control"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "enfeeble",
|
"name": "enfeeble",
|
||||||
"description": "Reduce target's attack by value permanently.",
|
"description": "Reduce target's attack by value for this turn.",
|
||||||
"allDescription": "Reduce ALL enemy cards' attack by value. Restored after battle.",
|
"allDescription": "Reduce ALL enemy cards' attack by value. Restored after turn.",
|
||||||
"trigger": "on_attack",
|
"trigger": "on_attack",
|
||||||
"category": "control",
|
"category": "control",
|
||||||
"supportsAll": true
|
"supportsAll": true
|
||||||
|
|
@ -165,4 +165,4 @@
|
||||||
"trigger": "passive",
|
"trigger": "passive",
|
||||||
"category": "offense"
|
"category": "offense"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
export class MainMenuScene extends Phaser.Scene {
|
export class MainMenuScene extends Phaser.Scene {
|
||||||
constructor() { super('MainMenuScene'); }
|
constructor() { super('MainMenuScene'); }
|
||||||
|
|
||||||
|
preload() {
|
||||||
|
this.load.video('menu_bg', 'assets/video/tyrants-edge-menu.mp4');
|
||||||
|
}
|
||||||
|
|
||||||
create() {
|
create() {
|
||||||
const save = this.registry.get('save');
|
const save = this.registry.get('save');
|
||||||
const { width, height } = this.scale;
|
const { width, height } = this.scale;
|
||||||
|
|
@ -9,11 +13,65 @@ export class MainMenuScene extends Phaser.Scene {
|
||||||
const menuMusic = this.registry.get('music_main_menu');
|
const menuMusic = this.registry.get('music_main_menu');
|
||||||
if (menuMusic && !menuMusic.isPlaying) menuMusic.play();
|
if (menuMusic && !menuMusic.isPlaying) menuMusic.play();
|
||||||
|
|
||||||
// Background
|
// ── Video background ──────────────────────────────────────────────────────
|
||||||
this.add.rectangle(width / 2, height / 2, width, height, 0x0d1b2a);
|
const video = this.add.video(width / 2, height / 2, 'menu_bg');
|
||||||
|
video.setMute(true);
|
||||||
|
// setDisplaySize reads frame.realWidth which is null until the first frame
|
||||||
|
// is decoded — defer sizing to the 'created' event.
|
||||||
|
video.on('created', () => {
|
||||||
|
if (video.scene) video.setDisplaySize(width, height);
|
||||||
|
});
|
||||||
|
video.play(true); // true = loop
|
||||||
|
|
||||||
// Decorative elements
|
// ── VHS / retro overlay effects ───────────────────────────────────────────
|
||||||
this.add.rectangle(width / 2, height / 2, width, 2, 0x1a3a5c).setAlpha(0.5);
|
|
||||||
|
// 1. Dark tint so UI stays readable over whatever the video shows
|
||||||
|
this.add.rectangle(width / 2, height / 2, width, height, 0x000000, 0.42);
|
||||||
|
|
||||||
|
// 2. Scanlines — one dark horizontal pixel every 3 rows, baked into graphics
|
||||||
|
const scanlines = this.add.graphics();
|
||||||
|
for (let y = 0; y < height; y += 3) {
|
||||||
|
scanlines.fillStyle(0x000000, 0.22);
|
||||||
|
scanlines.fillRect(0, y, width, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Vignette — stepped gradient darkening from each edge inward
|
||||||
|
const vig = this.add.graphics();
|
||||||
|
const steps = 12;
|
||||||
|
const vigSize = 180;
|
||||||
|
for (let i = 0; i < steps; i++) {
|
||||||
|
const a = (1 - i / steps) * 0.65;
|
||||||
|
const t = Math.round((vigSize / steps) * i);
|
||||||
|
const s = Math.ceil(vigSize / steps);
|
||||||
|
vig.fillStyle(0x000000, a);
|
||||||
|
vig.fillRect(t, 0, s, height); // left
|
||||||
|
vig.fillRect(width - t - s, 0, s, height); // right
|
||||||
|
vig.fillRect(0, t, width, s); // top
|
||||||
|
vig.fillRect(0, height - t - s, width, s); // bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Rolling VHS tracking bar — thin translucent band drifts down the screen
|
||||||
|
const scanBar = this.add.rectangle(width / 2, -30, width, 60, 0xffffff, 0.045);
|
||||||
|
this.tweens.add({
|
||||||
|
targets: scanBar,
|
||||||
|
y: height + 30,
|
||||||
|
duration: 7500,
|
||||||
|
repeat: -1,
|
||||||
|
ease: 'Linear'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. Occasional screen flicker — random brief brightness pulse
|
||||||
|
const scheduleFlicker = () => {
|
||||||
|
this.time.delayedCall(Phaser.Math.Between(2500, 7000), () => {
|
||||||
|
if (!this.scene.isActive('MainMenuScene')) return;
|
||||||
|
const flash = this.add.rectangle(width / 2, height / 2, width, height, 0xffffff, 0.06);
|
||||||
|
this.time.delayedCall(60, () => {
|
||||||
|
if (flash.scene) flash.destroy();
|
||||||
|
scheduleFlicker();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
scheduleFlicker();
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
this.add.text(width / 2, 120, "TYRANT'S EDGE", {
|
this.add.text(width / 2, 120, "TYRANT'S EDGE", {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue