OneCompiler

why DID I MAKE THIS

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Tower Tim</title> <style> body { margin: 0; background-color: #f0f8ff; overflow: hidden; font-family: Arial, sans-serif; text-align: center; } canvas { display: block; background-color: #000; } h4 { color: white; font-size: 48px; text-shadow: 2px 2px 4px #000000; } p { color: white; font-size: 15px; text-shadow: 2px 2px 4px #000000; } button { padding: 15px 30px; font-size: 24px; cursor: grab; border: none; border-radius: 5px; background-color: #ff4500; color: white; box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5); transition: background-color 0.3s; } button:hover { background-color: #e03c00; } </style> </head> <body> <div id="homeMenu" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1;"> <h4>Tower Tim THE GAME ABOUT CLIMBING A TOWER</h1> <button id="startButton">Start Game</button> <p></p> <button id="startButton">Level Editor Coming Soon</button> <p>MADE BY plasma studios</p> <p>Version-Alfa 1.011</p> <p>Playtest</p> </div> <canvas id="gameCanvas"></canvas>
<script>
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    const homeMenu = document.getElementById('homeMenu');
    const startButton = document.getElementById('startButton');

    // Game states
    const GAME_STATE = {
        MENU: 'menu',
        PLAYING: 'playing'
    };
    let currentState = GAME_STATE.MENU;

    // Game constants
    const GRAVITY = 0.5;
    const JUMP_POWER = -12;
    const PLAYER_SPEED = 9;
    const TILE_SIZE = 40;
    const DASH_SPEED = 25;
    const DASH_DURATION = 10; // frames
    const DASH_COOLDOWN = 30; // frames
    const MAX_JUMPS = 3; // For double jump

    // Map constants
    const mapWidthInTiles = 50;
    const mapHeightInTiles = 100;
    
    // Game map data (50 wide x 100 high)
    // 0 = empty space
    // 1 = platform
    // 2 = spikes (top)
    // 3 = finish line
    // 4 = lava (animated)
    // 5 = spikes (down)
    // 6 = spikes (left)
    // 7 = spikes (right)
    const gameMap = new Array(mapHeightInTiles).fill(null).map(() => new Array(mapWidthInTiles).fill(0));

    // Player object
    const player = {
        x: TILE_SIZE * 2,
        y: TILE_SIZE * 90,
        width: TILE_SIZE * 0.65,
        height: TILE_SIZE * 0.65,
        dx: 0,
        dy: 0,
        onGround: false,
        jumpCount: 0,
        canDash: true,
        isDashing: false,
        dashTimer: 0,
        dashCooldown: 0,
        facingDirection: 1, // 1 for right, -1 for left
        onWall: false,
        spawnX: TILE_SIZE * 2,
        spawnY: TILE_SIZE * 90
    };

    // --- EDITED MAP FOR A DIFFICULT LEVEL ---
    function createMap() {
        // Start area
        for (let x = 0; x < 5; x++) { gameMap[95][x] = 1; }
        for (let y = 96; y < mapHeightInTiles; y++) { gameMap[y][0] = 1; gameMap[y][4] = 1; }
        gameMap[90][5] = 1; gameMap[90][6] = 4;
        gameMap[90][7] = 4; gameMap[90][8] = 4;
        gameMap[90][5] = 1; gameMap[91][6] = 1;
        gameMap[91][7] = 1; gameMap[91][8] = 1;
        gameMap[91][7] = 1; gameMap[91][9] = 1;
        gameMap[91][7] = 1; gameMap[91][10] = 1;
        gameMap[91][7] = 1; gameMap[91][5] = 1;
        gameMap[90][9] = 1; gameMap[90][10] = 1;

        // Long jump with spikes
        gameMap[85][15] = 1;
        for (let x = 16; x < 20; x++) { gameMap[85][x] = 4; }
        gameMap[85][20] = 1;

        // Vertical climbing section
        gameMap[80][25] = 1; gameMap[80][26] = 1; gameMap[79][26] = 2;
        gameMap[75][30] = 1; gameMap[75][31] = 1; gameMap[74][30] = 2;
        gameMap[70][25] = 1; gameMap[70][26] = 1; gameMap[69][26] = 2;
        gameMap[65][30] = 1; gameMap[65][31] = 1; gameMap[64][30] = 2;

        // Wall jump challenge
        for (let y = 60; y < 65; y++) { gameMap[y][10] = 1; gameMap[y][15] = 1; }
        for (let x = 11; x < 15; x++) { gameMap[65][x] = 2; }
        gameMap[60][12] = 1; gameMap[60][13] = 1;
        gameMap[55][12] = 1; gameMap[55][13] = 1;

        // Dash tunnel with low ceiling
        for (let x = 18; x < 30; x++) { gameMap[50][x] = 1; gameMap[47][x] = 1; }
        for (let x = 20; x < 28; x++) { gameMap[49][x] = 2; }
        for (let x = 21; x < 27; x++) { gameMap[48][x] = 5; }
        
        // Lava pit with tight platforms
        for (let x = 0; x < 50; x++) { gameMap[45][x] = 1; }
        gameMap[44][5] = 1; gameMap[44][10] = 1; gameMap[44][15] = 1;
        gameMap[44][20] = 1; gameMap[44][25] = 1; gameMap[44][30] = 1;
        
        // Final wall climb
        for (let y = 35; y < 44; y++) { gameMap[y][40] = 1; }
        for (let y = 35; y < 44; y++) { gameMap[y][44] = 1; }
        for (let y = 30; y < 50; y++) { gameMap[y][47] = 1; }
        for (let y = 30; y < 52; y++) { gameMap[y][49] = 4; }
        gameMap[30][40] = 1; 
        gameMap[29][40] = 1; 
        gameMap[28][40] = 1; 
        gameMap[27][40] = 1; 
        gameMap[26][40] = 1; 
        gameMap[25][40] = 1; 
        gameMap[24][40] = 1;
        gameMap[23][40] = 1; 
        gameMap[22][40] = 1; 
        gameMap[21][40] = 1; 
        gameMap[20][40] = 1; 
        gameMap[19][40] = 1; 
        gameMap[18][40] = 1; 
        gameMap[17][40] = 1;
        gameMap[16][40] = 1;
        gameMap[15][42] = 2;
        gameMap[16][41] = 1;
        gameMap[16][42] = 1;
        gameMap[31][40] = 1; 
        gameMap[32][40] = 1;
        gameMap[33][40] = 1;
        gameMap[34][40] = 1;
        gameMap[35][40] = 1;
        gameMap[36][40] = 1;
        gameMap[34][39] = 1;
        gameMap[34][38] = 1;
        gameMap[43][40] = 1;
        // The Finish Line
        gameMap[35][42] = 3;
        gameMap[44][42] = 2;
        gameMap[44][43] = 2;
        gameMap[44][41] = 2;
        gameMap[44][40] = 1;
        gameMap[44][39] = 6;
        gameMap[43][39] = 6;
        gameMap[42][39] = 6;
        gameMap[41][39] = 6;
        gameMap[32][39] = 6;
        gameMap[31][39] = 6;
        gameMap[33][39] = 6;
        gameMap[90][4] = 6;
        gameMap[90][5] = 1;
        for (let x = 0; x < 90; x++) { gameMap[99][x] = 4; }
    }
    createMap();
    // --- END OF MAP EDITING AREA ---

    let cameraX = 0;
    let cameraY = 0;
    const mapWidth = mapWidthInTiles * TILE_SIZE;
    const mapHeight = mapHeightInTiles * TILE_SIZE;
    let lavaAnimationFrame = 0;

    // Key states
    const keys = {
        right: false,
        left: false,
        up: false,
        dash: false
    };

    // Event listeners for key presses
    window.addEventListener('keydown', (e) => {
        if (currentState === GAME_STATE.PLAYING) {
            if (e.key === 'ArrowRight') keys.right = true;
            if (e.key === 'ArrowLeft') keys.left = true;
            if (e.key === 'ArrowUp') {
                if (player.onGround || player.jumpCount < MAX_JUMPS -1) {
                    player.dy = JUMP_POWER;
                    player.onGround = false;
                    player.jumpCount++;
                } else if (player.onWall) {
                    // Wall jump
                    player.dy = JUMP_POWER;
                    player.dx = -player.facingDirection * PLAYER_SPEED * 1.5; // Push away from the wall
                    player.jumpCount = 1; // Reset jump count for double jump
                    player.onWall = false;
                }
            }
            if (e.key === 'z' && player.canDash) {
                keys.dash = true;
            }
        }
    });

    window.addEventListener('keyup', (e) => {
        if (currentState === GAME_STATE.PLAYING) {
            if (e.key === 'ArrowRight') keys.right = false;
            if (e.key === 'ArrowLeft') keys.left = false;
            if (e.key === 'z') keys.dash = false;
        }
    });

    // Start button handler
    startButton.addEventListener('click', () => {
        currentState = GAME_STATE.PLAYING;
        homeMenu.style.display = 'none';
    });

    // Main game loop
    function gameLoop() {
        if (currentState === GAME_STATE.PLAYING) {
            update();
            draw();
        } else {
            drawMenu();
        }
        requestAnimationFrame(gameLoop);
    }

    // Draw menu
    function drawMenu() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }

    // Update game state
    function update() {
        // Player horizontal movement
        if (!player.isDashing) {
            player.dx = 0;
            if (keys.right) {
                player.dx = PLAYER_SPEED;
                player.facingDirection = 1;
            }
            if (keys.left) {
                player.dx = -PLAYER_SPEED;
                player.facingDirection = -1;
            }
        }

        // Dash logic
        if (keys.dash && player.canDash) {
            player.isDashing = true;
            player.canDash = false;
            player.dashTimer = DASH_DURATION;
            player.dx = DASH_SPEED * player.facingDirection;
        }

        if (player.isDashing) {
            player.dashTimer--;
            if (player.dashTimer <= 0) {
                player.isDashing = false;
                player.dx = 0;
            }
        }
        if (!player.canDash) {
            player.dashCooldown++;
            if (player.dashCooldown >= DASH_COOLDOWN) {
                player.canDash = true;
                player.dashCooldown = 0;
            }
        }
        
        // Apply gravity if not dashing
        if (!player.isDashing) {
            player.dy += GRAVITY;
        }
        
        // Update player position
        player.x += player.dx;
        player.y += player.dy;
        
        // Increment lava animation frame
        lavaAnimationFrame = (lavaAnimationFrame + 1) % 60; // 60 frames per second

        // Handle collision with map tiles
        player.onGround = false;
        player.onWall = false;
        const tileX = Math.floor(player.x / TILE_SIZE);
        const tileY = Math.floor(player.y / TILE_SIZE);
        
        for (let y = Math.max(0, tileY - 2); y < Math.min(gameMap.length, tileY + 3); y++) {
            for (let x = Math.max(0, tileX - 2); x < Math.min(gameMap[y].length, tileX + 3); x++) {
                if (y >= 0 && y < mapHeightInTiles && x >= 0 && x < mapWidthInTiles) {
                    const tile = gameMap[y][x];
                    if (tile !== 0) {
                        const tileRect = {
                            x: x * TILE_SIZE,
                            y: y * TILE_SIZE,
                            width: TILE_SIZE,
                            height: TILE_SIZE
                        };
                        
                        // Check for collision with deadly tiles first
                        if (tile === 2 || tile === 4 || tile === 5 || tile === 6 || tile === 7) {
                             if (
                                player.x < tileRect.x + tileRect.width &&
                                player.x + player.width > tileRect.x &&
                                player.y < tileRect.y + tileRect.height &&
                                player.y + player.height > tileRect.y
                            ) {
                                resetGame();
                            }
                        }

                        // Check for platform or finish line collision
                        if (tile === 1 || tile === 3) {
                            if (
                                player.x < tileRect.x + tileRect.width &&
                                player.x + player.width > tileRect.x &&
                                player.y + player.height > tileRect.y &&
                                player.y + player.height <= tileRect.y + tileRect.height &&
                                player.dy >= 0
                            ) {
                                player.y = tileRect.y - player.height;
                                player.dy = 0;
                                player.onGround = true;
                                player.jumpCount = 0; // Reset jumps on landing
                            }
                            // Wall collision
                            if (
                                player.y < tileRect.y + tileRect.height &&
                                player.y + player.height > tileRect.y
                            ) {
                                // Left wall
                                if (player.x + player.width > tileRect.x && player.x < tileRect.x && player.dx >= 0) {
                                    player.x = tileRect.x - player.width;
                                    if (player.onGround === false) player.onWall = true;
                                }
                                // Right wall
                                if (player.x < tileRect.x + tileRect.width && player.x + player.width > tileRect.x + tileRect.width && player.dx <= 0) {
                                    player.x = tileRect.x + tileRect.width;
                                    if (player.onGround === false) player.onWall = true;
                                }
                            }
                        }
                        
                        if (tile === 3) { // Finish line
                            if (
                                player.x < tileRect.x + tileRect.width &&
                                player.x + player.width > tileRect.x &&
                                player.y < tileRect.y + tileRect.height &&
                                player.y + player.height > tileRect.y
                            ) {
                                alert("You Win!");
                                resetGame();
                            }
                        }
                    }
                }
            }
        }
        
        // Keep player within map bounds
        if (player.x < 0) player.x = 0;
        if (player.x + player.width > mapWidth) player.x = mapWidth - player.width;
        
        // Handle falling off the map
        if (player.y > mapHeight) {
            resetGame();
        }
        
        // Update camera position to follow the player
        cameraX = player.x - canvas.width / 2;
        cameraY = player.y - canvas.height / 2;

        // Clamp camera to map bounds
        if (cameraX < 0) cameraX = 0;
        if (cameraX + canvas.width > mapWidth) cameraX = mapWidth - canvas.width;
        if (cameraY < 0) cameraY = 0;
        if (cameraY + canvas.height > mapHeight) cameraY = mapHeight - canvas.height;
    }

    // Draw game objects
    function draw() {
        // Adjust canvas size based on window size
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        // Clear canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // Draw game map with camera offset
        for (let y = 0; y < mapHeightInTiles; y++) {
            for (let x = 0; x < mapWidthInTiles; x++) {
                const tile = gameMap[y][x];
                const screenX = x * TILE_SIZE - cameraX;
                const screenY = y * TILE_SIZE - cameraY;

                // Only draw tiles visible on screen
                if (
                    screenX + TILE_SIZE > 0 && screenX < canvas.width &&
                    screenY + TILE_SIZE > 0 && screenY < canvas.height
                ) {
                    ctx.save();
                    if (tile === 1) {
                        ctx.fillStyle = '#6b6252'; // Platform
                        ctx.fillRect(screenX, screenY, TILE_SIZE, TILE_SIZE);
                    } else if (tile === 2) {
                        ctx.fillStyle = '#ff0000'; // Spikes (top)
                        drawSpikes(screenX, screenY, 'top');
                    } else if (tile === 3) {
                        ctx.fillStyle = '#00ff00'; // Finish line
                        ctx.fillRect(screenX, screenY, TILE_SIZE, TILE_SIZE);
                    } else if (tile === 4) {
                        drawLava(screenX, screenY); // Animated lava
                    } else if (tile === 5) {
                        ctx.fillStyle = '#ff0000'; // Spikes (down)
                        drawSpikes(screenX, screenY, 'down');
                    } else if (tile === 6) {
                        ctx.fillStyle = '#ff0000'; // Spikes (left)
                        drawSpikes(screenX, screenY, 'left');
                    } else if (tile === 7) {
                        ctx.fillStyle = '#ff0000'; // Spikes (right)
                        drawSpikes(screenX, screenY, 'right');
                    }
                    ctx.restore();
                }
            }
        }

        // Draw player
        ctx.fillStyle = '#fc1303';
        ctx.fillRect(player.x - cameraX, player.y - cameraY, player.width, player.height);
    }

    // Helper function to draw spikes
    function drawSpikes(x, y, direction) {
        ctx.beginPath();
        if (direction === 'top') {
            ctx.moveTo(x, y + TILE_SIZE);
            ctx.lineTo(x + TILE_SIZE / 2, y);
            ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE);
        } else if (direction === 'down') {
            ctx.moveTo(x, y);
            ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE);
            ctx.lineTo(x + TILE_SIZE, y);
        } else if (direction === 'left') {
            ctx.moveTo(x + TILE_SIZE, y);
            ctx.lineTo(x, y + TILE_SIZE / 2);
            ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE);
        } else if (direction === 'right') {
            ctx.moveTo(x, y);
            ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE / 2);
            ctx.lineTo(x, y + TILE_SIZE);
        }
        ctx.closePath();
        ctx.fill();
    }
    
    // Helper function to draw animated lava
    function drawLava(x, y) {
        const waveHeight = 5 + Math.sin(lavaAnimationFrame * 0.1) * 3;
        ctx.fillStyle = '#ff6600'; // Orange lava
        ctx.fillRect(x, y + waveHeight, TILE_SIZE, TILE_SIZE - waveHeight);
        
        ctx.fillStyle = '#ff4500'; // Red lava highlight
        ctx.fillRect(x, y + TILE_SIZE - 5, TILE_SIZE, 5);

        ctx.beginPath();
        ctx.fillStyle = '#ff9900'; // Yellow lava wave
        ctx.moveTo(x, y + waveHeight);
        for (let i = 0; i <= TILE_SIZE; i++) {
            ctx.lineTo(x + i, y + waveHeight + Math.sin((i + lavaAnimationFrame) * 0.3) * 3);
        }
        ctx.lineTo(x + TILE_SIZE, y + waveHeight);
        ctx.fill();
    }

    // Reset game function
    function resetGame() {
        player.x = player.spawnX;
        player.y = player.spawnY;
        player.dx = 0;
        player.dy = 0;
        player.jumpCount = 0;
        player.canDash = true;
        player.isDashing = false;
        player.dashTimer = 0;
        player.dashCooldown = 0;
    }

    // Start the game loop
    gameLoop();
</script>
<style>
    /* Apply the 'crosshair' cursor to the entire body of the webpage */
    body {
        cursor: crosshair;
    }

    /*
    Optional: If you want to change the cursor only for a specific
    element, you could use a class or ID like this:
    .specific-element {
        cursor: crosshair;
    }
    */
</style>
</body> </html>

1 Answer

4 months ago by

EEEEEEEEEEEEEEEEEEEEEEEEEEEEEE

2 months ago by Winthrop Giles