super-mario / lib /engine /Level3.ts
asemxin
Add multiple levels and sound effects system
4539eae
// Level 3 - Castle Theme
import { Level, Block, Enemy } from './types';
import { GAME_CONFIG } from '../constants';
const { TILE_SIZE, LEVEL_HEIGHT } = GAME_CONFIG;
const LEVEL_3_WIDTH = 4000;
export function createLevel3(): Level {
const blocks: Block[] = [];
const enemies: Enemy[] = [];
// Ground blocks with lava pits
for (let x = 0; x < LEVEL_3_WIDTH; x += TILE_SIZE) {
// Lava pit positions (deadly gaps)
const lavaPits = [
{ start: 600, end: 750 },
{ start: 1200, end: 1400 },
{ start: 1800, end: 1950 },
{ start: 2400, end: 2600 },
{ start: 3000, end: 3150 },
];
const inLava = lavaPits.some(pit => x >= pit.start && x < pit.end);
if (inLava) continue;
// Castle floor (darker ground)
blocks.push({
x,
y: LEVEL_HEIGHT - TILE_SIZE,
width: TILE_SIZE,
height: TILE_SIZE,
type: 'ground',
});
blocks.push({
x,
y: LEVEL_HEIGHT - TILE_SIZE * 2,
width: TILE_SIZE,
height: TILE_SIZE,
type: 'ground',
});
}
// Castle walls and platforms
const platforms = [
// Early section - stepping platforms
{ x: 200, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 300, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 400, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'question' as const, hasCoin: true },
{ x: 500, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Over first lava pit
{ x: 620, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 680, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
{ x: 740, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Mid section
{ x: 850, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 950, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
{ x: 1050, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
{ x: 1100, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
// Over second lava pit - tricky jumps
{ x: 1220, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 1280, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'brick' as const },
{ x: 1340, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Question block cluster
{ x: 1500, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
{ x: 1532, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
{ x: 1564, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
// High platform section
{ x: 1650, y: LEVEL_HEIGHT - TILE_SIZE * 8, type: 'brick' as const },
{ x: 1682, y: LEVEL_HEIGHT - TILE_SIZE * 8, type: 'brick' as const },
{ x: 1714, y: LEVEL_HEIGHT - TILE_SIZE * 8, type: 'brick' as const },
// Over third lava pit
{ x: 1820, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 1880, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
{ x: 1940, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Long platform run
{ x: 2050, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2082, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2114, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2146, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2178, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2210, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2242, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2274, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
// Over fourth lava pit
{ x: 2420, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 2480, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'question' as const, hasCoin: true },
{ x: 2540, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Pre-boss section
{ x: 2700, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2800, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 2900, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
// Over fifth lava pit
{ x: 3020, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 3080, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
{ x: 3140, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Final staircase to flag
{ x: 3300, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3332, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3332, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3364, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3364, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3364, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'ground' as const },
{ x: 3396, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3396, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3396, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'ground' as const },
{ x: 3396, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'ground' as const },
{ x: 3428, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3428, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3428, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'ground' as const },
{ x: 3428, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'ground' as const },
{ x: 3428, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'ground' as const },
];
platforms.forEach(p => {
blocks.push({
x: p.x,
y: p.y,
width: TILE_SIZE,
height: TILE_SIZE,
type: p.type,
hasCoin: p.hasCoin,
});
});
// Fewer pipes in castle
const pipes = [
{ x: 800, height: 2 },
{ x: 2000, height: 2 },
{ x: 2650, height: 3 },
];
pipes.forEach(pipe => {
for (let h = 0; h < pipe.height; h++) {
blocks.push({
x: pipe.x,
y: LEVEL_HEIGHT - TILE_SIZE * 2 - (h * TILE_SIZE),
width: TILE_SIZE * 2,
height: TILE_SIZE,
type: 'pipe',
});
}
});
// Floating coins - harder to get
const coinPositions = [
{ x: 680, y: LEVEL_HEIGHT - TILE_SIZE * 8 },
{ x: 1280, y: LEVEL_HEIGHT - TILE_SIZE * 9 },
{ x: 1880, y: LEVEL_HEIGHT - TILE_SIZE * 8 },
{ x: 2480, y: LEVEL_HEIGHT - TILE_SIZE * 9 },
{ x: 3080, y: LEVEL_HEIGHT - TILE_SIZE * 8 },
];
coinPositions.forEach(pos => {
blocks.push({
x: pos.x,
y: pos.y,
width: 24,
height: 24,
type: 'coin',
});
});
// Many enemies - challenging!
const enemyPositions = [
{ x: 250, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 450, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'koopa' as const },
{ x: 900, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 1000, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 1450, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'koopa' as const },
{ x: 1700, y: LEVEL_HEIGHT - TILE_SIZE * 10, type: 'goomba' as const },
{ x: 2100, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'goomba' as const },
{ x: 2200, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'koopa' as const },
{ x: 2750, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 2850, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 3200, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'koopa' as const },
];
enemyPositions.forEach(pos => {
enemies.push({
x: pos.x,
y: pos.y,
vx: -1,
vy: 0,
width: 32,
height: pos.type === 'koopa' ? 40 : 32,
type: pos.type,
isAlive: true,
direction: -1,
});
});
return {
width: LEVEL_3_WIDTH,
height: LEVEL_HEIGHT,
blocks,
enemies,
startPosition: { x: 64, y: LEVEL_HEIGHT - TILE_SIZE * 4 },
flagPosition: { x: 3550, y: LEVEL_HEIGHT - TILE_SIZE * 10 },
};
}