-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
enhance landscape rendering; add snow ground rendering with parallax …
…effects and state management
- Loading branch information
Showing
6 changed files
with
236 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
games/xmas/src/screens/play/game-render/landscape/snow-ground/snow-ground-renderer.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { GAME_WORLD_HEIGHT } from '../../../game-world/game-world-consts'; | ||
import { SnowGround, SNOW_GROUND } from './snow-ground-types'; | ||
import { ViewportState } from '../../render-state'; | ||
|
||
/** | ||
* Apply parallax translation to a point based on viewport position and parallax factor | ||
* Returns pixel-perfect coordinates for smooth rendering | ||
*/ | ||
function applyParallaxTranslation( | ||
x: number, | ||
y: number, | ||
viewport: ViewportState, | ||
parallaxFactor: number, | ||
): { x: number; y: number } { | ||
return { | ||
x: Math.round(x + viewport.x * parallaxFactor), | ||
y: Math.round(y + viewport.y * parallaxFactor), | ||
}; | ||
} | ||
|
||
/** | ||
* Get color for specific snow ground layer | ||
*/ | ||
function getLayerColor(layer: number): string { | ||
return layer === 0 ? SNOW_GROUND.COLORS.DISTANT : layer === 1 ? SNOW_GROUND.COLORS.MIDDLE : SNOW_GROUND.COLORS.NEAR; | ||
} | ||
|
||
/** | ||
* Render a single snow ground piece using pixel art style with parallax effect | ||
*/ | ||
function renderSnowGround(ctx: CanvasRenderingContext2D, ground: SnowGround, viewport: ViewportState): void { | ||
// Calculate base position with parallax | ||
const basePosition = applyParallaxTranslation(ground.x, GAME_WORLD_HEIGHT, viewport, ground.parallaxFactor); | ||
|
||
// Calculate dimensions | ||
const width = Math.round(ground.width); | ||
const height = Math.round(GAME_WORLD_HEIGHT * 0.025); // 10% of world height for snow ground | ||
|
||
// Draw rectangular snow ground piece | ||
ctx.beginPath(); | ||
ctx.rect(basePosition.x, basePosition.y - height, width, height); | ||
ctx.fill(); | ||
} | ||
|
||
/** | ||
* Render snow grounds by layer with parallax effect | ||
*/ | ||
export function renderSnowGrounds(ctx: CanvasRenderingContext2D, grounds: SnowGround[], viewport: ViewportState): void { | ||
// Sort grounds by layer (back to front) | ||
const sortedGrounds = [...grounds].sort((a, b) => a.layer - b.layer); | ||
|
||
// Group grounds by layer for efficient rendering | ||
const groundsByLayer = sortedGrounds.reduce((acc, ground) => { | ||
acc[ground.layer] = acc[ground.layer] || []; | ||
acc[ground.layer].push(ground); | ||
return acc; | ||
}, {} as Record<number, SnowGround[]>); | ||
|
||
// Save current context state | ||
ctx.save(); | ||
|
||
// Render each layer with its color | ||
Object.entries(groundsByLayer).forEach(([layer, layerGrounds]) => { | ||
// Set layer-specific color | ||
ctx.fillStyle = getLayerColor(Number(layer)); | ||
|
||
// Render all grounds in this layer | ||
layerGrounds.forEach((ground) => renderSnowGround(ctx, ground, viewport)); | ||
}); | ||
|
||
// Restore context state | ||
ctx.restore(); | ||
} |
78 changes: 78 additions & 0 deletions
78
games/xmas/src/screens/play/game-render/landscape/snow-ground/snow-ground-state.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { GAME_WORLD_WIDTH } from '../../../game-world/game-world-consts'; | ||
import { GameWorldState } from '../../../game-world/game-world-types'; | ||
import { SnowGround, SNOW_GROUND, SnowGroundState } from './snow-ground-types'; | ||
|
||
/** | ||
* Get parallax factor for a specific layer with slight randomization | ||
*/ | ||
function getParallaxFactor(layer: number): number { | ||
// Get base parallax factor for the layer | ||
const baseParallax = | ||
layer === 0 ? SNOW_GROUND.PARALLAX.DISTANT : layer === 1 ? SNOW_GROUND.PARALLAX.MIDDLE : SNOW_GROUND.PARALLAX.NEAR; | ||
|
||
// Add random variation within the specified range | ||
const variation = (Math.random() * 2 - 1) * SNOW_GROUND.PARALLAX.VARIATION; | ||
return Math.max(0, Math.min(1, baseParallax + variation)); | ||
} | ||
|
||
/** | ||
* Get number of snow ground pieces for a specific layer | ||
*/ | ||
function getGroundDensityForLayer(layer: number): number { | ||
return layer === 0 | ||
? SNOW_GROUND.DENSITY.DISTANT | ||
: layer === 1 | ||
? SNOW_GROUND.DENSITY.MIDDLE | ||
: SNOW_GROUND.DENSITY.NEAR; | ||
} | ||
|
||
/** | ||
* Generate snow ground pieces for a specific layer | ||
*/ | ||
function generateGrounds(layer: number): SnowGround[] { | ||
const grounds: SnowGround[] = []; | ||
const count = getGroundDensityForLayer(layer); | ||
const baseSpacing = GAME_WORLD_WIDTH / count; | ||
|
||
for (let i = 0; i < count; i++) { | ||
// Calculate width with random variation | ||
const width = SNOW_GROUND.MIN_WIDTH + Math.random() * (SNOW_GROUND.MAX_WIDTH - SNOW_GROUND.MIN_WIDTH); | ||
|
||
// Calculate position with spacing variation | ||
const baseX = (i * GAME_WORLD_WIDTH) / count; | ||
const spacingVariation = baseSpacing * SNOW_GROUND.SPACING_VARIATION; | ||
const x = baseX + (Math.random() - 0.5) * spacingVariation; | ||
|
||
grounds.push({ | ||
x, | ||
width, | ||
layer, | ||
parallaxFactor: getParallaxFactor(layer), | ||
}); | ||
} | ||
|
||
return grounds; | ||
} | ||
|
||
/** | ||
* Create initial snow ground state | ||
*/ | ||
export function createSnowGroundState(): SnowGroundState { | ||
const grounds: SnowGround[] = []; | ||
|
||
// Generate snow ground pieces for each layer | ||
for (let layer = 0; layer < SNOW_GROUND.LAYERS; layer++) { | ||
grounds.push(...generateGrounds(layer)); | ||
} | ||
|
||
return { grounds }; | ||
} | ||
|
||
/** | ||
* Update snow ground state | ||
* Currently snow grounds are static, but this function is included for consistency | ||
* and potential future animations | ||
*/ | ||
export function updateSnowGroundState(_world: GameWorldState, state: SnowGroundState): SnowGroundState { | ||
return state; | ||
} |
57 changes: 57 additions & 0 deletions
57
games/xmas/src/screens/play/game-render/landscape/snow-ground/snow-ground-types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { GAME_WORLD_WIDTH } from '../../../game-world/game-world-consts'; | ||
|
||
/** | ||
* Snow ground piece interface | ||
* Represents a single piece of snow ground with position, width, and layer information | ||
*/ | ||
export interface SnowGround { | ||
x: number; // X position of the snow ground piece | ||
width: number; // Width of the snow ground piece | ||
layer: number; // Layer number (0: distant, 1: middle, 2: near) | ||
parallaxFactor: number; // Factor for parallax movement | ||
} | ||
|
||
/** | ||
* Snow ground state interface | ||
* Contains all snow ground pieces | ||
*/ | ||
export interface SnowGroundState { | ||
grounds: SnowGround[]; | ||
} | ||
|
||
/** | ||
* Snow ground constants | ||
*/ | ||
export const SNOW_GROUND = { | ||
// Number of layers for depth perception | ||
LAYERS: 3, | ||
|
||
// Width configuration | ||
MIN_WIDTH: GAME_WORLD_WIDTH / 8, | ||
MAX_WIDTH: GAME_WORLD_WIDTH / 4, | ||
|
||
// Spacing between snow ground pieces | ||
SPACING_VARIATION: 0.2, // 20% variation in spacing | ||
|
||
// Density (number of pieces) per layer | ||
DENSITY: { | ||
DISTANT: 8, // Fewer pieces in the distance | ||
MIDDLE: 10, // Medium density in the middle | ||
NEAR: 12, // More pieces in the foreground | ||
}, | ||
|
||
// Parallax movement factors | ||
PARALLAX: { | ||
DISTANT: 0.2, // Slowest movement in the background | ||
MIDDLE: 0.5, // Medium movement in the middle | ||
NEAR: 0.8, // Fastest movement in the foreground | ||
VARIATION: 0.05, // Small random variation in parallax | ||
}, | ||
|
||
// Colors for each layer | ||
COLORS: { | ||
DISTANT: '#a3b5c7', // Light grayish blue for distant snow | ||
MIDDLE: '#cad5e0', // Lighter grayish blue for middle ground | ||
NEAR: '#ffffff', // Pure white for nearest snow | ||
}, | ||
} as const; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters