super-mario / lib /engine /Level2.ts
asemxin
Add multiple levels and sound effects system
4539eae
// Level 2 - Underground Cave Theme
import { Level, Block, Enemy } from './types';
import { GAME_CONFIG } from '../constants';
const { TILE_SIZE, LEVEL_HEIGHT } = GAME_CONFIG;
const LEVEL_2_WIDTH = 3600;
export function createLevel2(): Level {
const blocks: Block[] = [];
const enemies: Enemy[] = [];
// Ground blocks with more gaps
for (let x = 0; x < LEVEL_2_WIDTH; x += TILE_SIZE) {
// Multiple gaps for underground feel
const gaps = [
{ start: 800, end: 900 },
{ start: 1400, end: 1550 },
{ start: 2200, end: 2350 },
{ start: 2800, end: 2900 },
];
const inGap = gaps.some(gap => x >= gap.start && x < gap.end);
if (inGap) continue;
// Ground layer (2 blocks high)
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',
});
}
// Ceiling blocks for underground feel
for (let x = 0; x < LEVEL_2_WIDTH; x += TILE_SIZE) {
blocks.push({
x,
y: 0,
width: TILE_SIZE,
height: TILE_SIZE,
type: 'ground',
});
blocks.push({
x,
y: TILE_SIZE,
width: TILE_SIZE,
height: TILE_SIZE,
type: 'ground',
});
}
// Underground platforms - brick style
const platforms = [
// First section - stepping stones
{ x: 200, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 280, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 360, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
// Question blocks with coins
{ x: 500, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
{ x: 600, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
// Long platform section
{ x: 700, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 732, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 764, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
// After first gap
{ x: 950, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 1000, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'question' as const, hasCoin: true },
{ x: 1050, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
// Mid-level platforms
{ x: 1200, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 1232, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 1264, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 1296, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
// High platform section
{ x: 1600, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'brick' as const },
{ x: 1632, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'brick' as const },
{ x: 1664, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'question' as const, hasCoin: true },
{ x: 1696, y: LEVEL_HEIGHT - TILE_SIZE * 7, type: 'brick' as const },
// Low platforms
{ x: 1800, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 1900, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'brick' as const },
{ x: 2000, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
// After gaps section
{ x: 2400, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'brick' as const },
{ x: 2500, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'question' as const, hasCoin: true },
{ x: 2600, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'brick' as const },
// Final staircase
{ x: 3000, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3032, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3032, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3064, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3064, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3064, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'ground' as const },
{ x: 3096, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'ground' as const },
{ x: 3096, y: LEVEL_HEIGHT - TILE_SIZE * 4, type: 'ground' as const },
{ x: 3096, y: LEVEL_HEIGHT - TILE_SIZE * 5, type: 'ground' as const },
{ x: 3096, y: LEVEL_HEIGHT - TILE_SIZE * 6, 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,
});
});
// More pipes in underground
const pipes = [
{ x: 400, height: 2 },
{ x: 1100, height: 3 },
{ x: 1750, height: 2 },
{ x: 2100, height: 4 },
{ x: 2700, height: 2 },
];
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
const coinPositions = [
{ x: 250, y: LEVEL_HEIGHT - TILE_SIZE * 7 },
{ x: 282, y: LEVEL_HEIGHT - TILE_SIZE * 8 },
{ x: 314, y: LEVEL_HEIGHT - TILE_SIZE * 7 },
{ x: 1650, y: LEVEL_HEIGHT - TILE_SIZE * 9 },
{ x: 2550, y: LEVEL_HEIGHT - TILE_SIZE * 8 },
];
coinPositions.forEach(pos => {
blocks.push({
x: pos.x,
y: pos.y,
width: 24,
height: 24,
type: 'coin',
});
});
// More enemies - including Koopas
const enemyPositions = [
{ x: 350, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 650, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 750, y: LEVEL_HEIGHT - TILE_SIZE * 6, type: 'goomba' as const },
{ x: 1050, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'koopa' as const },
{ x: 1350, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 1650, y: LEVEL_HEIGHT - TILE_SIZE * 9, type: 'goomba' as const },
{ x: 1950, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'koopa' as const },
{ x: 2450, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' as const },
{ x: 2650, y: LEVEL_HEIGHT - TILE_SIZE * 3, type: 'goomba' 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_2_WIDTH,
height: LEVEL_HEIGHT,
blocks,
enemies,
startPosition: { x: 64, y: LEVEL_HEIGHT - TILE_SIZE * 4 },
flagPosition: { x: 3200, y: LEVEL_HEIGHT - TILE_SIZE * 10 },
};
}