Skip to content

Commit

Permalink
refactor landscape rendering; update star rendering to include viewpo…
Browse files Browse the repository at this point in the history
…rt for parallax effect and simplify mountain rendering logic
  • Loading branch information
gtanczyk committed Dec 3, 2024
1 parent 6d541f2 commit 8998b66
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function renderLandscape(ctx: CanvasRenderingContext2D, state: LandscapeS
ctx.imageSmoothingEnabled = false;

// Render stars (background)
renderStars(ctx, state.stars.stars);
renderStars(ctx, state.stars.stars, viewport);

// Render mountains (with parallax)
if (devConfig.renderMountains) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,33 +9,25 @@ function applyParallaxTranslation(
x: number,
y: number,
viewport: ViewportState,
parallaxFactor: number
parallaxFactor: number,
): { x: number; y: number } {
return {
x: Math.round(x + viewport.x * parallaxFactor),
y: Math.round(y + viewport.y * parallaxFactor)
x: Math.round(x + viewport.x * parallaxFactor - viewport.x),
y: Math.round(y + viewport.y * parallaxFactor - viewport.y),
};
}

/**
* Get color for specific mountain layer
*/
function getLayerColor(layer: number): string {
return layer === 0
? MOUNTAIN_COLORS.DISTANT
: layer === 1
? MOUNTAIN_COLORS.MIDDLE
: MOUNTAIN_COLORS.NEAR;
return layer === 0 ? MOUNTAIN_COLORS.DISTANT : layer === 1 ? MOUNTAIN_COLORS.MIDDLE : MOUNTAIN_COLORS.NEAR;
}

/**
* Render a single mountain using pixel art style with parallax effect
*/
function renderMountain(
ctx: CanvasRenderingContext2D,
mountain: Mountain,
viewport: ViewportState
): void {
function renderMountain(ctx: CanvasRenderingContext2D, mountain: Mountain, viewport: ViewportState): void {
// Begin mountain path
ctx.beginPath();

Expand All @@ -44,7 +36,7 @@ function renderMountain(
mountain.points[0].x,
mountain.points[0].y,
viewport,
mountain.parallaxFactor
mountain.parallaxFactor,
);
ctx.moveTo(firstPoint.x, firstPoint.y);

Expand All @@ -54,7 +46,7 @@ function renderMountain(
mountain.points[i].x,
mountain.points[i].y,
viewport,
mountain.parallaxFactor
mountain.parallaxFactor,
);
ctx.lineTo(point.x, point.y);
}
Expand All @@ -67,11 +59,7 @@ function renderMountain(
/**
* Render mountains by layer with parallax effect
*/
export function renderMountains(
ctx: CanvasRenderingContext2D,
mountains: Mountain[],
viewport: ViewportState
): void {
export function renderMountains(ctx: CanvasRenderingContext2D, mountains: Mountain[], viewport: ViewportState): void {
// Sort mountains by layer (back to front)
const sortedMountains = [...mountains].sort((a, b) => a.layer - b.layer);

Expand All @@ -96,4 +84,4 @@ export function renderMountains(

// Restore context state
ctx.restore();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { GAME_WORLD_HEIGHT, GAME_WORLD_WIDTH } from '../../../game-world/game-wo
// Mountain silhouette colors from back to front
export const MOUNTAIN_COLORS = {
DISTANT: '#000066', // Most distant mountains
MIDDLE: '#000044', // Middle layer mountains
NEAR: '#000022', // Nearest mountains
MIDDLE: '#000044', // Middle layer mountains
NEAR: '#000022', // Nearest mountains
} as const;

// Mountain configuration
Expand All @@ -16,32 +16,33 @@ export const MOUNTAINS = {
PEAKS: {
// Peaks per layer (more peaks in distant layers for depth perception)
DISTANT: Math.floor(GAME_WORLD_WIDTH / 400), // Fewest peaks, most distant
MIDDLE: Math.floor(GAME_WORLD_WIDTH / 300), // Medium number of peaks
NEAR: Math.floor(GAME_WORLD_WIDTH / 200), // Most peaks, nearest layer
MIDDLE: Math.floor(GAME_WORLD_WIDTH / 300), // Medium number of peaks
NEAR: Math.floor(GAME_WORLD_WIDTH / 200), // Most peaks, nearest layer
},
PARALLAX: {
// Parallax factors for each layer (0 = no movement, 1 = full movement)
DISTANT: 0.2, // Slowest movement, most distant
MIDDLE: 0.4, // Medium movement
NEAR: 0.6, // Fastest movement, nearest layer
VARIATION: 0.05, // Random variation in parallax factor
DISTANT: 0.2, // Slowest movement, most distant
MIDDLE: 0.4, // Medium movement
NEAR: 0.9, // Fastest movement, nearest layer
VARIATION: 0.01, // Random variation in parallax factor
},
// Height multipliers for each layer
HEIGHT_MULTIPLIER: {
DISTANT: 1.0, // Full height for distant mountains
MIDDLE: 0.85, // Slightly shorter middle mountains
NEAR: 0.7, // Shortest nearest mountains
DISTANT: 1.0, // Full height for distant mountains
MIDDLE: 0.85, // Slightly shorter middle mountains
NEAR: 0.7, // Shortest nearest mountains
},
} as const;

// Mountain type definition
export type Mountain = {
x: number; // Base x position
width: number; // Width of the mountain
height: number; // Height of the mountain
layer: number; // Which layer (0 = distant, 1 = middle, 2 = near)
x: number; // Base x position
width: number; // Width of the mountain
height: number; // Height of the mountain
layer: number; // Which layer (0 = distant, 1 = middle, 2 = near)
parallaxFactor: number; // Factor affecting parallax movement
points: Array<{ // Points defining the mountain shape
points: Array<{
// Points defining the mountain shape
x: number;
y: number;
}>;
Expand All @@ -50,4 +51,4 @@ export type Mountain = {
// Mountain state type
export type MountainState = {
mountains: Mountain[];
};
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { ViewportState } from '../../render-state';
import { Star, STARS } from './star-types';

/**
* Render twinkling stars
*/
export function renderStars(ctx: CanvasRenderingContext2D, stars: Star[]): void {
export function renderStars(ctx: CanvasRenderingContext2D, stars: Star[], viewport: ViewportState): void {
ctx.fillStyle = STARS.COLOR;

for (const star of stars) {
Expand All @@ -13,8 +14,8 @@ export function renderStars(ctx: CanvasRenderingContext2D, stars: Star[]): void
ctx.globalAlpha = brightness;

// Round positions to nearest pixel for crisp rendering
const x = Math.round(star.x);
const y = Math.round(star.y);
const x = Math.round(star.x) - viewport.x + STARS.PARALLAX_FACTOR * viewport.x;
const y = Math.round(star.y) - viewport.y + STARS.PARALLAX_FACTOR * viewport.y;
const size = Math.round(star.size);

// Set shadow properties to add glow effect, with blur increasing with star size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const STARS = {
MIN_BRIGHTNESS: 0.3, // Minimum star brightness
MAX_BRIGHTNESS: 0.5, // Maximum star brightness
SKY_HEIGHT_RATIO: 0.7, // Stars only in upper 70% of sky
PARALLAX_FACTOR: 0.1, // Parallax factor for stars
} as const;

// Star type definition
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { GAME_WORLD_HEIGHT, GAME_WORLD_WIDTH } from '../../../game-world/game-world-consts';

// Tree silhouette color
export const TREE_COLOR = '#000022'; // Dark blue color for tree silhouettes
export const TREE_COLOR = '#002211'; // Dark blue color for tree silhouettes

// Tree configuration
export const TREES = {
// Tree dimensions
MAX_HEIGHT: GAME_WORLD_HEIGHT * 0.15, // Maximum tree height (15% of world height)
MIN_HEIGHT: GAME_WORLD_HEIGHT * 0.1, // Minimum tree height (10% of world height)
WIDTH_RATIO: 0.6, // Tree width as ratio of height
MIN_HEIGHT: GAME_WORLD_HEIGHT * 0.1, // Minimum tree height (10% of world height)
WIDTH_RATIO: 0.6, // Tree width as ratio of height

// Tree distribution
DENSITY: Math.floor(GAME_WORLD_WIDTH / 75), // Number of trees across the world
SPACING_VARIATION: 0.3, // Random variation in tree spacing (30%)
SPACING_VARIATION: 0.3, // Random variation in tree spacing (30%)
} as const;

// Tree type definition
export type Tree = {
x: number; // Base x position
x: number; // Base x position
height: number; // Height of the tree
width: number; // Width of the tree
width: number; // Width of the tree
};

// Tree state type
export type TreeState = {
trees: Tree[];
};
};

0 comments on commit 8998b66

Please sign in to comment.