Initial commit: Naddie Jump — Monad Edition

This commit is contained in:
2026-05-23 15:33:42 +07:00
commit 7439f8f267
57 changed files with 2765 additions and 0 deletions

164
src/scenes/MenuScene.js Normal file
View File

@@ -0,0 +1,164 @@
import { Scene } from 'phaser';
export class MenuScene extends Scene {
constructor() {
super({ key: 'MenuScene' });
}
create() {
const { width, height } = this.scale;
// Background
this.add.tileSprite(width / 2, height / 2, width, height, 'gridBg');
// Title
this.add.text(width / 2, height * 0.18, 'NADDIE JUMP', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '38px',
color: '#d8b4fe',
align: 'center',
}).setOrigin(0.5).setShadow(4, 4, '#581c87', 0, false, true);
this.add.text(width / 2, height * 0.27, 'MONAD EDITION', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '14px',
color: '#a855f7',
align: 'center',
}).setOrigin(0.5);
// Floating Naddie preview
const preview = this.add.image(width / 2, height * 0.48, 'player_idle')
.setScale(0.55);
this.tweens.add({
targets: preview,
y: height * 0.48 - 15,
duration: 1400,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
});
this.tweens.add({
targets: preview,
angle: 5,
duration: 2000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut',
});
// Start button
this.createButton(width / 2, height * 0.68, 'START GAME', () => {
this.scene.start('GameScene');
});
this.add.text(width / 2, height * 0.74, 'Press ENTER or SPACE to start', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '10px',
color: '#888',
align: 'center',
}).setOrigin(0.5);
this.input.keyboard.on('keydown-ENTER', () => {
this.scene.start('GameScene');
});
this.input.keyboard.on('keydown-SPACE', () => {
this.scene.start('GameScene');
});
// Leaderboard button
this.createButton(width / 2, height * 0.78, 'LEADERBOARD', () => {
this.showLeaderboard();
});
this.add.text(width / 2, height * 0.92, 'Web3 integration coming soon', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '9px',
color: '#444',
align: 'center',
}).setOrigin(0.5);
this.createAmbientParticles();
}
createButton(x, y, text, callback) {
const bg = this.add.rectangle(x, y, 280, 56, 0x581c87)
.setStrokeStyle(3, 0xa855f7)
.setInteractive({ useHandCursor: true });
const label = this.add.text(x, y, text, {
fontFamily: '"Press Start 2P", monospace',
fontSize: '15px',
color: '#ffffff',
}).setOrigin(0.5);
bg.on('pointerover', () => {
bg.setFillStyle(0x7e22ce);
this.tweens.add({ targets: [bg, label], scaleX: 1.05, scaleY: 1.05, duration: 100 });
});
bg.on('pointerout', () => {
bg.setFillStyle(0x581c87);
this.tweens.add({ targets: [bg, label], scaleX: 1, scaleY: 1, duration: 100 });
});
bg.on('pointerdown', callback);
return { bg, label };
}
showLeaderboard() {
const { width, height } = this.scale;
const overlay = this.add.rectangle(width / 2, height / 2, width, height, 0x000000, 0.7).setDepth(100);
const panel = this.add.rectangle(width / 2, height / 2, 400, 440, 0x1a0533).setStrokeStyle(3, 0xa855f7).setDepth(101);
const title = this.add.text(width / 2, height * 0.22, 'LEADERBOARD', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '18px',
color: '#d8b4fe',
}).setOrigin(0.5).setDepth(102);
const close = this.add.text(width / 2 + 170, height * 0.22 - 80, 'X', {
fontFamily: '"Press Start 2P", monospace',
fontSize: '18px',
color: '#fff',
}).setOrigin(0.5).setDepth(102).setInteractive({ useHandCursor: true });
const rows = [];
const mock = [
{ rank: 1, addr: '0xMonad...Dev', score: 99999 },
{ rank: 2, addr: '0xAlice...xyz', score: 87500 },
{ rank: 3, addr: '0xBob...abc', score: 74200 },
{ rank: 4, addr: '0xYou', score: parseInt(localStorage.getItem('naddie_best_score') || '0', 10) },
];
mock.forEach((entry, i) => {
const y = height * 0.32 + i * 55;
rows.push({
rank: this.add.text(width / 2 - 160, y, `#${entry.rank}`, { fontFamily: '"Press Start 2P", monospace', fontSize: '12px', color: '#a855f7' }).setOrigin(0.5).setDepth(102),
addr: this.add.text(width / 2, y, entry.addr, { fontFamily: '"Press Start 2P", monospace', fontSize: '10px', color: '#fff' }).setOrigin(0.5).setDepth(102),
score: this.add.text(width / 2 + 150, y, String(entry.score), { fontFamily: '"Press Start 2P", monospace', fontSize: '12px', color: '#d8b4fe' }).setOrigin(0.5).setDepth(102),
});
});
close.on('pointerdown', () => {
overlay.destroy();
panel.destroy();
title.destroy();
close.destroy();
rows.forEach(r => { r.rank.destroy(); r.addr.destroy(); r.score.destroy(); });
});
}
createAmbientParticles() {
const { width, height } = this.scale;
for (let i = 0; i < 40; i++) {
const s = this.add.image(Phaser.Math.Between(0, width), Phaser.Math.Between(0, height), 'star');
s.setAlpha(Phaser.Math.FloatBetween(0.15, 0.7));
this.tweens.add({
targets: s,
y: s.y - Phaser.Math.Between(50, 250),
alpha: 0,
duration: Phaser.Math.Between(2000, 6000),
repeat: -1,
delay: Phaser.Math.Between(0, 3000),
});
}
}
}