about summary refs log blame commit diff stats
path: root/js/mountain/game.js
blob: 1b4d96e6311fe7ccd8e40a4d40f15f5a57c1e3dc (plain) (tree)
1
2
3
4
5
6
7
8
                                                              
 





                                                     


                          




                                                                               








                                                                     



















                                                                     
































































































































































































                                                                                                             
// TODO: if there are no more levels show a "game win" message

// Game constants
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;

const GRAVITY = 4;
const JUMP_STRENGTH = -33;
const MOVE_SPEED = 7;

let keys = { left: false, right: false, up: false, down: false, space: false };

let levels = [
    [
        // Next level example
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    ],
    [
        [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
        [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    ]
    // Add more levels as needed
];

let currentLevel = 0;

class Player {
    constructor(x, y) {
        this.x = x;
        this.y = y;
        this.width = 30;
        this.height = 30;
        this.velocityX = 0;
        this.velocityY = 0;
        this.jumping = false;
        this.doubleJumping = false;
    }

    update() {
        if (keys.left) this.velocityX = -MOVE_SPEED;
        if (keys.right) this.velocityX = MOVE_SPEED;
        if (!keys.left && !keys.right) this.velocityX = 0;

        this.velocityY += GRAVITY;
        this.x += this.velocityX;
        this.y += this.velocityY;

        // Collision detection
        this.checkCollision();

        // Limit falling speed
        if (this.velocityY > 10) this.velocityY = 10;
    }

    jump() {
        if (!this.jumping) {
            this.velocityY = JUMP_STRENGTH;
            this.jumping = true;
        } else if (!this.doubleJumping) {
            this.velocityY = JUMP_STRENGTH;
            this.doubleJumping = true;
        }
    }

    checkCollision() {
        let row, col, belowRow, aboveRow, leftCol, rightCol;

        // Check collision with ground from below
        row = Math.floor(this.y / 30);
        col = Math.floor(this.x / 30);
        belowRow = Math.floor((this.y + this.height) / 30);

        if (levels[currentLevel][belowRow] && levels[currentLevel][belowRow][col] === 1) {
            if (this.velocityY > 0) {
                this.y = belowRow * 30 - this.height;
                this.velocityY = 0;
                this.jumping = false;
                this.doubleJumping = false;
            }
        }

        // Check collision with ground from above
        aboveRow = Math.floor((this.y - 1) / 30);
        if (levels[currentLevel][aboveRow] && levels[currentLevel][aboveRow][col] === 1) {
            if (this.velocityY < 0) {
                this.y = (aboveRow + 1) * 30;
                this.velocityY = 0;
            }
        }

        // Check collision with ground from the left
        leftCol = Math.floor(this.x / 30);
        if (levels[currentLevel][row] && levels[currentLevel][row][leftCol] === 1) {
            if (this.velocityX < 0) {
                this.x = (leftCol + 1) * 30;
                this.velocityX = 0;
            }
        }

        // Check collision with ground from the right
        rightCol = Math.floor((this.x + this.width) / 30);
        if (levels[currentLevel][row] && levels[currentLevel][row][rightCol] === 1) {
            if (this.velocityX > 0) {
                this.x = rightCol * 30 - this.width;
                this.velocityX = 0;
            }
        }

        // Collision with lava
        if (levels[currentLevel][row] && levels[currentLevel][row][col] === 2) {
            this.reset();
        }

        // Collision with save point
        if (levels[currentLevel][row] && levels[currentLevel][row][col] === 3) {
            localStorage.setItem('savePoint', JSON.stringify({ x: this.x, y: this.y, level: currentLevel }));
        }

        // Collision with goal
        if (levels[currentLevel][row] && levels[currentLevel][row][col] === 5) {
            alert('Level Complete!');
            loadNextLevel();
        }
    }

    reset() {
        let savePoint = JSON.parse(localStorage.getItem('savePoint')) || { x: 30, y: 30, level: 0 };
        this.x = savePoint.x;
        this.y = savePoint.y;
        currentLevel = savePoint.level;
        this.velocityY = 0;
    }

    render() {
        ctx.fillStyle = 'blue';
        ctx.fillRect(this.x, this.y, this.width, this.height);
    }
}

function findPlayerStartPosition(level) {
    for (let row = 0; row < levels[level].length; row++) {
        for (let col = 0; col < levels[level][row].length; col++) {
            if (levels[level][row][col] === 4) {
                return { x: col * 30, y: row * 30 };
            }
        }
    }
    // Default position if no start point found
    return { x: 30, y: 570 };
}

function renderLevel() {
    for (let row = 0; row < levels[currentLevel].length; row++) {
        for (let col = 0; col < levels[currentLevel][row].length; col++) {
            if (levels[currentLevel][row][col] === 1) {
                ctx.fillStyle = 'brown';
                ctx.fillRect(col * 30, row * 30, 30, 30);
            } else if (levels[currentLevel][row][col] === 2) {
                ctx.fillStyle = 'red';
                ctx.fillRect(col * 30, row * 30, 30, 30);
            } else if (levels[currentLevel][row][col] === 3) {
                ctx.fillStyle = 'green';
                ctx.fillRect(col * 30, row * 30, 30, 30);
            } else if (levels[currentLevel][row][col] === 5) {
                ctx.fillStyle = 'gold';
                ctx.fillRect(col * 30, row * 30, 30, 30);
            }
        }
    }
}

function loadNextLevel() {
    currentLevel++;
    if (currentLevel >= levels.length) {
        alert("You've completed all levels!");
        currentLevel = 0;
    }
    let startPosition = findPlayerStartPosition(currentLevel);
    player.x = startPosition.x;
    player.y = startPosition.y;
    player.velocityY = 0;
    localStorage.setItem('savePoint', JSON.stringify({ x: player.x, y: player.y, level: currentLevel }));
}

let startPosition = findPlayerStartPosition(currentLevel);
let player = new Player(startPosition.x, startPosition.y);

function gameLoop() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    renderLevel();
    player.update();
    player.render();

    requestAnimationFrame(gameLoop);
}

document.addEventListener('keydown', (e) => {
    if (e.code === 'ArrowLeft') keys.left = true;
    if (e.code === 'ArrowRight') keys.right = true;
    if (e.code === 'ArrowUp') keys.up = true;
    if (e.code === 'ArrowDown') keys.down = true;
    if (e.code === 'Space') player.jump();
});

document.addEventListener('keyup', (e) => {
    if (e.code === 'ArrowLeft') keys.left = false;
    if (e.code === 'ArrowRight') keys.right = false;
    if (e.code === 'ArrowUp') keys.up = false;
    if (e.code === 'ArrowDown') keys.down = false;
});

gameLoop();