178 lines
7.1 KiB
JavaScript
178 lines
7.1 KiB
JavaScript
// BootScene – runs once at startup to generate all shared textures, then hands
|
||
// off to MenuScene. Textures live in Phaser's global TextureManager so every
|
||
// subsequent scene can use them without re-creating them.
|
||
|
||
export default class BootScene extends Phaser.Scene {
|
||
constructor() {
|
||
super({ key: 'BootScene' });
|
||
}
|
||
|
||
preload() {
|
||
this.load.audio('title', 'js/audio/music/title.mp3');
|
||
this.load.audio('track01', 'js/audio/music/track01.mp3');
|
||
this.load.audio('track02', 'js/audio/music/track02.mp3');
|
||
this.load.audio('track03', 'js/audio/music/track03.mp3');
|
||
this.load.audio('track04', 'js/audio/music/track04.mp3');
|
||
this.load.audio('track05', 'js/audio/music/track05.mp3');
|
||
this.load.audio('track06', 'js/audio/music/track06.mp3');
|
||
this.load.audio('track07', 'js/audio/music/track07.mp3');
|
||
|
||
this.load.audio('sfx_player_shoot', 'js/audio/fx/player_shoot.mp3');
|
||
this.load.audio('sfx_player_death', 'js/audio/fx/player_death.mp3');
|
||
this.load.audio('sfx_alien_shoot', 'js/audio/fx/alien_shoot.mp3');
|
||
this.load.audio('sfx_missle', 'js/audio/fx/missle.mp3');
|
||
this.load.audio('sfx_impact', 'js/audio/fx/impact.mp3');
|
||
this.load.audio('sfx_alien_death', 'js/audio/fx/alien_death.mp3');
|
||
}
|
||
|
||
create() {
|
||
this._createTextures();
|
||
this.scene.start('MenuScene');
|
||
}
|
||
|
||
// ─── Texture Generation ───────────────────────────────────────────────────
|
||
|
||
_createTextures() {
|
||
// Player ship – 64×32, nose points right (angle 0)
|
||
let g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0x00ff44, 1);
|
||
g.strokeTriangle(56, 16, 12, 4, 12, 28);
|
||
g.generateTexture('player', 64, 32);
|
||
g.destroy();
|
||
|
||
// Player ship with thruster flame
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0x00ff44, 1);
|
||
g.strokeTriangle(56, 16, 12, 4, 12, 28);
|
||
g.lineStyle(2, 0xff6600, 1);
|
||
g.strokeTriangle(12, 11, 12, 21, 0, 16);
|
||
g.generateTexture('player_thrust', 64, 32);
|
||
g.destroy();
|
||
|
||
// Large asteroid – 120×120, radius 50, 12-sided
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0xcccccc, 1);
|
||
g.strokePoints(this._asteroidPoints(60, 60, 50, 12,
|
||
[1.0, 0.82, 1.08, 0.88, 1.0, 0.78, 1.1, 0.9, 0.94, 1.0, 0.84, 1.06]
|
||
), true);
|
||
g.generateTexture('asteroid_large', 120, 120);
|
||
g.destroy();
|
||
|
||
// Medium asteroid – 64×64, radius 26, 10-sided
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0xcccccc, 1);
|
||
g.strokePoints(this._asteroidPoints(32, 32, 26, 10,
|
||
[1.0, 0.78, 1.1, 0.88, 1.0, 0.82, 1.0, 0.92, 1.06, 0.80]
|
||
), true);
|
||
g.generateTexture('asteroid_medium', 64, 64);
|
||
g.destroy();
|
||
|
||
// Small asteroid – 32×32, radius 12, 8-sided
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0xcccccc, 1);
|
||
g.strokePoints(this._asteroidPoints(16, 16, 12, 8,
|
||
[1.0, 0.78, 1.12, 0.84, 1.0, 0.9, 0.80, 1.04]
|
||
), true);
|
||
g.generateTexture('asteroid_small', 32, 32);
|
||
g.destroy();
|
||
|
||
// Alien saucer – 64×48
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0x00ffff, 1);
|
||
g.strokeEllipse(32, 30, 52, 20);
|
||
g.strokeEllipse(32, 22, 30, 18);
|
||
g.generateTexture('alien', 64, 48);
|
||
g.destroy();
|
||
|
||
// Player bullet – 8×8 yellow circle
|
||
g = this.make.graphics({ add: false });
|
||
g.fillStyle(0xffff00, 1);
|
||
g.fillCircle(4, 4, 4);
|
||
g.generateTexture('bullet', 8, 8);
|
||
g.destroy();
|
||
|
||
// Alien bullet – 8×8 red circle
|
||
g = this.make.graphics({ add: false });
|
||
g.fillStyle(0xff4444, 1);
|
||
g.fillCircle(4, 4, 4);
|
||
g.generateTexture('alien_bullet', 8, 8);
|
||
g.destroy();
|
||
|
||
// Spread-shot alien – 72×54, orange/red menacing saucer
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0xff4400, 1);
|
||
g.strokeEllipse(36, 34, 62, 18); // wide flat hull
|
||
g.strokeEllipse(36, 24, 38, 22); // taller upper dome
|
||
g.fillStyle(0xff8800, 1);
|
||
g.fillCircle(36, 26, 5); // central cannon port
|
||
g.lineStyle(2, 0xff2200, 1);
|
||
g.beginPath(); g.moveTo(5, 34); g.lineTo(0, 27); g.strokePath(); // left spike
|
||
g.beginPath(); g.moveTo(67, 34); g.lineTo(72, 27); g.strokePath(); // right spike
|
||
g.generateTexture('alien_spread', 72, 54);
|
||
g.destroy();
|
||
|
||
// Homing-missile alien – 80×60, purple/magenta angular diamond
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(2, 0xcc00ff, 1);
|
||
g.strokePoints([
|
||
{ x: 40, y: 5 },
|
||
{ x: 72, y: 30 },
|
||
{ x: 40, y: 55 },
|
||
{ x: 8, y: 30 }
|
||
], true);
|
||
g.lineStyle(1, 0x9900cc, 1);
|
||
g.strokePoints([
|
||
{ x: 40, y: 18 },
|
||
{ x: 58, y: 30 },
|
||
{ x: 40, y: 42 },
|
||
{ x: 22, y: 30 }
|
||
], true);
|
||
g.fillStyle(0xff00ff, 1);
|
||
g.fillCircle(40, 30, 5);
|
||
g.generateTexture('alien_missile', 80, 60);
|
||
g.destroy();
|
||
|
||
// Homing missile projectile – 14×6, magenta body + orange nose
|
||
g = this.make.graphics({ add: false });
|
||
g.fillStyle(0xff00ff, 1);
|
||
g.fillRect(0, 1, 10, 4);
|
||
g.fillStyle(0xff8800, 1);
|
||
g.fillRect(10, 0, 4, 6);
|
||
g.generateTexture('homing_missile', 14, 6);
|
||
g.destroy();
|
||
|
||
// Reticle outer layer – outer ring + diagonal ticks (rotates one way)
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(1.5, 0x00ff44, 1);
|
||
g.strokeCircle(32, 32, 28);
|
||
g.lineStyle(1, 0x00ff44, 0.5);
|
||
g.beginPath(); g.moveTo(12, 12); g.lineTo(18, 18); g.strokePath();
|
||
g.beginPath(); g.moveTo(52, 12); g.lineTo(46, 18); g.strokePath();
|
||
g.beginPath(); g.moveTo(12, 52); g.lineTo(18, 46); g.strokePath();
|
||
g.beginPath(); g.moveTo(52, 52); g.lineTo(46, 46); g.strokePath();
|
||
g.generateTexture('reticle_outer', 64, 64);
|
||
g.destroy();
|
||
|
||
// Reticle inner layer – inner ring + cross lines (rotates opposite way)
|
||
g = this.make.graphics({ add: false });
|
||
g.lineStyle(1.5, 0x00ff44, 1);
|
||
g.strokeCircle(32, 32, 6);
|
||
g.beginPath(); g.moveTo(32, 2); g.lineTo(32, 24); g.strokePath(); // top
|
||
g.beginPath(); g.moveTo(32, 40); g.lineTo(32, 62); g.strokePath(); // bottom
|
||
g.beginPath(); g.moveTo( 2, 32); g.lineTo(24, 32); g.strokePath(); // left
|
||
g.beginPath(); g.moveTo(40, 32); g.lineTo(62, 32); g.strokePath(); // right
|
||
g.generateTexture('reticle_inner', 64, 64);
|
||
g.destroy();
|
||
}
|
||
|
||
_asteroidPoints(cx, cy, radius, numPoints, offsets) {
|
||
return offsets.map((scale, i) => {
|
||
const angle = (i / numPoints) * Math.PI * 2;
|
||
return {
|
||
x: cx + Math.cos(angle) * radius * scale,
|
||
y: cy + Math.sin(angle) * radius * scale
|
||
};
|
||
});
|
||
}
|
||
}
|