From b08a7074b84223fc92d3a24b7758cf222f3f97ef Mon Sep 17 00:00:00 2001 From: elioat Date: Tue, 24 Dec 2024 14:43:49 -0500 Subject: * --- html/rogue/js/rogue.js | 8 +++ html/rogue/js/world.js | 167 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 172 insertions(+), 3 deletions(-) (limited to 'html/rogue') diff --git a/html/rogue/js/rogue.js b/html/rogue/js/rogue.js index 8276d8d..f441bbd 100644 --- a/html/rogue/js/rogue.js +++ b/html/rogue/js/rogue.js @@ -72,6 +72,10 @@ const render = (ctx, state) => { state.world.backgroundRocks.forEach(rock => { renderRock(ctx, rock, ctx.canvas.height - state.world.groundHeight); }); + + state.world.backgroundGrass.forEach(grass => { + renderGrass(ctx, grass, ctx.canvas.height - state.world.groundHeight, state.time); + }); // 2. Render platforms state.world.platforms.forEach(platform => { @@ -91,6 +95,10 @@ const render = (ctx, state) => { renderRock(ctx, rock, ctx.canvas.height - state.world.groundHeight); }); + state.world.foregroundGrass.forEach(grass => { + renderGrass(ctx, grass, ctx.canvas.height - state.world.groundHeight, state.time); + }); + // 5. Render ground const groundY = ctx.canvas.height - state.world.groundHeight; ctx.fillStyle = '#4a4'; diff --git a/html/rogue/js/world.js b/html/rogue/js/world.js index 1a54853..ad25e9d 100644 --- a/html/rogue/js/world.js +++ b/html/rogue/js/world.js @@ -6,7 +6,9 @@ const WORLD_OBJECTS = { MAPLE_BACKGROUND: 'maple_background', MAPLE_FOREGROUND: 'maple_foreground', ROCK_BACKGROUND: 'rock_background', - ROCK_FOREGROUND: 'rock_foreground' + ROCK_FOREGROUND: 'rock_foreground', + GRASS_BACKGROUND: 'grass_background', + GRASS_FOREGROUND: 'grass_foreground' }; // Separate configurations for different tree types @@ -74,11 +76,41 @@ const ROCK_TYPES = { } }; +// Add grass configurations +const GRASS_TYPES = { + TALL: { + type: 'grass', + width: 30, + height: 40, + blades: 5, + color: '#3a5', + shadowColor: '#294' + }, + SHORT: { + type: 'grass', + width: 20, + height: 25, + blades: 4, + color: '#3b6', + shadowColor: '#2a5' + } +}; + // Create a world with platforms, trees, and rocks const createWorld = () => ({ groundHeight: 12, // Separate arrays for different layers backgroundTrees: [ + { + type: WORLD_OBJECTS.FIR_BACKGROUND, + x: -400, + config: FIR_TYPES.LARGE + }, + { + type: WORLD_OBJECTS.MAPLE_BACKGROUND, + x: -250, + config: MAPLE_TYPES.SMALL + }, { type: WORLD_OBJECTS.FIR_BACKGROUND, x: 50, @@ -98,9 +130,29 @@ const createWorld = () => ({ type: WORLD_OBJECTS.MAPLE_BACKGROUND, x: 650, config: MAPLE_TYPES.SMALL + }, + { + type: WORLD_OBJECTS.FIR_BACKGROUND, + x: 900, + config: FIR_TYPES.LARGE + }, + { + type: WORLD_OBJECTS.MAPLE_BACKGROUND, + x: 1100, + config: MAPLE_TYPES.LARGE } ], backgroundRocks: [ + { + type: WORLD_OBJECTS.ROCK_BACKGROUND, + x: -300, + config: ROCK_TYPES.MEDIUM + }, + { + type: WORLD_OBJECTS.ROCK_BACKGROUND, + x: -100, + config: ROCK_TYPES.SMALL + }, { type: WORLD_OBJECTS.ROCK_BACKGROUND, x: 150, @@ -110,6 +162,16 @@ const createWorld = () => ({ type: WORLD_OBJECTS.ROCK_BACKGROUND, x: 400, config: ROCK_TYPES.SMALL + }, + { + type: WORLD_OBJECTS.ROCK_BACKGROUND, + x: 750, + config: ROCK_TYPES.MEDIUM + }, + { + type: WORLD_OBJECTS.ROCK_BACKGROUND, + x: 1000, + config: ROCK_TYPES.SMALL } ], platforms: [ @@ -141,16 +203,36 @@ const createWorld = () => ({ foregroundTrees: [ { type: WORLD_OBJECTS.MAPLE_FOREGROUND, - x: 200, + x: -150, config: MAPLE_TYPES.SMALL }, + { + type: WORLD_OBJECTS.FIR_FOREGROUND, + x: 200, + config: FIR_TYPES.SMALL + }, + { + type: WORLD_OBJECTS.MAPLE_FOREGROUND, + x: 450, + config: MAPLE_TYPES.LARGE + }, { type: WORLD_OBJECTS.FIR_FOREGROUND, x: 800, config: FIR_TYPES.LARGE + }, + { + type: WORLD_OBJECTS.MAPLE_FOREGROUND, + x: 1200, + config: MAPLE_TYPES.SMALL } ], foregroundRocks: [ + { + type: WORLD_OBJECTS.ROCK_FOREGROUND, + x: 0, + config: ROCK_TYPES.SMALL + }, { type: WORLD_OBJECTS.ROCK_FOREGROUND, x: 300, @@ -160,8 +242,34 @@ const createWorld = () => ({ type: WORLD_OBJECTS.ROCK_FOREGROUND, x: 700, config: ROCK_TYPES.SMALL + }, + { + type: WORLD_OBJECTS.ROCK_FOREGROUND, + x: 950, + config: ROCK_TYPES.LARGE } - ] + ], + backgroundGrass: [ + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -350, config: GRASS_TYPES.SHORT }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: -180, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 100, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 320, config: GRASS_TYPES.SHORT }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 580, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 750, config: GRASS_TYPES.SHORT }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 950, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_BACKGROUND, x: 1050, config: GRASS_TYPES.SHORT } + ], + foregroundGrass: [ + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: -280, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: -50, config: GRASS_TYPES.SHORT }, + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 150, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 420, config: GRASS_TYPES.SHORT }, + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 680, config: GRASS_TYPES.TALL }, + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 880, config: GRASS_TYPES.SHORT }, + { type: WORLD_OBJECTS.GRASS_FOREGROUND, x: 1150, config: GRASS_TYPES.TALL } + ], + // Track grass animation states + grassStates: {} }); // Rename current tree render function @@ -265,6 +373,59 @@ const renderRock = (ctx, rock, groundY) => { ctx.fill(); }; +// Add grass rendering function +const renderGrass = (ctx, grass, groundY, time) => { + const { x, config } = grass; + const { width, height, blades, color, shadowColor } = config; + + // Get or initialize grass state + const stateKey = `grass_${x}`; + if (!window.gameState.world.grassStates[stateKey]) { + window.gameState.world.grassStates[stateKey] = { + rustleAmount: 0, + rustleDecay: 0.95 + }; + } + const state = window.gameState.world.grassStates[stateKey]; + + // Check for player interaction + const player = window.gameState.player; + const interactionDistance = width; + const distanceToPlayer = Math.abs(player.x + player.width/2 - x); + + if (distanceToPlayer < interactionDistance) { + state.rustleAmount = Math.min(1, state.rustleAmount + 0.3); + } else { + state.rustleAmount *= state.rustleDecay; + } + + // Draw each blade of grass + for (let i = 0; i < blades; i++) { + const bladeX = x + (i - blades/2) * (width/blades); + const bladeWidth = width / blades * 0.7; + + // Calculate blade curve based on rustle and time + const rustleOffset = Math.sin(time/300 + i) * 5 * state.rustleAmount; + const baseWave = Math.sin(time/1000 + i) * 2; // Gentle wave motion + + // Draw blade + ctx.fillStyle = i % 2 === 0 ? color : shadowColor; + ctx.beginPath(); + ctx.moveTo(bladeX, groundY); + + // Control points for quadratic curve + const cp1x = bladeX + rustleOffset + baseWave; + const cp1y = groundY - height/2; + const cp2x = bladeX + rustleOffset * 1.5 + baseWave; + const cp2y = groundY - height; + + // Draw curved blade + ctx.quadraticCurveTo(cp1x, cp1y, cp2x, cp2y); + ctx.quadraticCurveTo(cp1x + bladeWidth, cp1y, bladeX + bladeWidth, groundY); + ctx.fill(); + } +}; + // Collision detection helper const checkCollision = (player, platform) => { return player.x < platform.x + platform.width && -- cgit 1.4.1-2-gfad0