<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>2D Top-Down Snowy Forest</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background-color: #87CEEB; /* Light blue sky */
        }
        canvas {
            display: block;
            background-color: #FFFFFF; /* White snow ground */
        }
    </style>
</head>
<body>
<canvas id="gameCanvas"></canvas>

<script>
// Get the canvas and context
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');

// Set canvas to full window size
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// Character properties
const character = {
    x: canvas.width / 2 - 25, // Starting X position
    y: canvas.height / 2 - 25, // Starting Y position
    size: 50, // Size of the square
    color: 'blue',
    speed: 5,
    dx: 0,
    dy: 0
};

// Handle keyboard input
const keys = {
    ArrowUp: false,
    ArrowDown: false,
    ArrowLeft: false,
    ArrowRight: false
};

window.addEventListener('keydown', function(e) {
    if (keys.hasOwnProperty(e.key)) {
        keys[e.key] = true;
    }
});

window.addEventListener('keyup', function(e) {
    if (keys.hasOwnProperty(e.key)) {
        keys[e.key] = false;
    }
});

// Update character position
function updateCharacter() {
    character.dx = 0;
    character.dy = 0;

    if (keys.ArrowUp) character.dy = -character.speed;
    if (keys.ArrowDown) character.dy = character.speed;
    if (keys.ArrowLeft) character.dx = -character.speed;
    if (keys.ArrowRight) character.dx = character.speed;

    character.x += character.dx;
    character.y += character.dy;

    // Keep character within canvas boundaries
    if (character.x < 0) character.x = 0;
    if (character.y < 0) character.y = 0;
    if (character.x + character.size > canvas.width) character.x = canvas.width - character.size;
    if (character.y + character.size > canvas.height) character.y = canvas.height - character.size;
}

// Draw the character
function drawCharacter() {
    ctx.fillStyle = character.color;
    ctx.fillRect(character.x, character.y, character.size, character.size);
}

// Tree properties and generation
const trees = [];
const treeCount = 50; // Adjust number for density

function generateTrees() {
    for (let i = 0; i < treeCount; i++) {
        let tree = {
            x: Math.random() * canvas.width,
            y: Math.random() * canvas.height,
            height: 50 + Math.random() * 50,
            width: 25 + Math.random() * 25
        };

        // Avoid placing trees too close to the character's starting position
        const buffer = 150; // Distance from character
        if (
            tree.x > character.x - buffer && tree.x < character.x + character.size + buffer &&
            tree.y > character.y - buffer && tree.y < character.y + character.size + buffer
        ) {
            i--; // Retry placing this tree
            continue;
        }

        trees.push(tree);
    }
}

// Draw trees from the stored array
function drawTrees() {
    trees.forEach(tree => {
        // Draw the trunk
        ctx.fillStyle = '#8B4513'; // Brown color
        ctx.fillRect(tree.x - tree.width / 8, tree.y, tree.width / 4, tree.height / 2);

        // Draw the foliage
        ctx.fillStyle = 'green';
        ctx.beginPath();
        ctx.moveTo(tree.x, tree.y - tree.height / 2);
        ctx.lineTo(tree.x - tree.width / 2, tree.y);
        ctx.lineTo(tree.x + tree.width / 2, tree.y);
        ctx.closePath();
        ctx.fill();
    });
}

// Snowflake properties and generation
const snowflakes = [];
const snowflakeCount = 100;

function generateSnowflakes() {
    for (let i = 0; i < snowflakeCount; i++) {
        let snowflake = {
            x: Math.random() * canvas.width,
            y: Math.random() * canvas.height,
            radius: Math.random() * 2 + 1,
            speed: Math.random() * 1 + 0.5
        };
        snowflakes.push(snowflake);
    }
}

// Animate snowflakes
function drawSnowflakes() {
    ctx.fillStyle = 'white';
    snowflakes.forEach(snowflake => {
        ctx.beginPath();
        ctx.arc(snowflake.x, snowflake.y, snowflake.radius, 0, Math.PI * 2);
        ctx.fill();

        // Update snowflake position
        snowflake.y += snowflake.speed;
        if (snowflake.y > canvas.height) {
            snowflake.y = 0;
            snowflake.x = Math.random() * canvas.width;
        }
    });
}

// Draw the ground (optional if you want a color different from canvas background)
function drawGround() {
    ctx.fillStyle = '#FFFFFF'; // White snow
    ctx.fillRect(0, canvas.height / 2, canvas.width, canvas.height / 2);
}

// Initialize the environment
generateTrees();
generateSnowflakes();

// Main draw function
function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawSnowflakes();
    drawTrees();
    drawCharacter();
    // drawGround(); // Uncomment if you want to draw a separate ground
}

// Update game objects
function update() {
    updateCharacter();
    draw();
    requestAnimationFrame(update);
}

// Start the game loop
update();

// Handle window resize
window.addEventListener('resize', function() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    // Optionally reset character position or other elements
    // Clear existing trees and regenerate them to fit new window size
    trees.length = 0;
    generateTrees();

    // Similarly, reset snowflakes
    snowflakes.length = 0;
    generateSnowflakes();
});
</script>
</body>
</html>

Add snowlakes, add impulse to camera when character moves, add camera following, provide full updated code