about summary refs log tree commit diff stats
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/hill/game.js487
1 files changed, 274 insertions, 213 deletions
diff --git a/js/hill/game.js b/js/hill/game.js
index b9c2e14..0e960a9 100644
--- a/js/hill/game.js
+++ b/js/hill/game.js
@@ -4,235 +4,282 @@ canvas.height = window.innerHeight;
 canvas.style.backgroundColor = '#f0f0f0';
 const ctx = canvas.getContext('2d');
 
-/*
-const COLORS = {
-    player: '#c0c0c0',
-    particles: '#c0c0c0',
-    objects: '#e0e0e0',
-    terrain: '#e0e0e0'
-};
-*/
-
-const COLORS = {
-    player: '#2d2d2d',
-    particles: '#2d2d2d',
-    objects: '#2d2d2d',
-    terrain: '#2d2d2d'
-};
-
-
-const gravity = 1;
-const jumpForce = 14.75;
-
-const player = {
-    x: 200,
-    y: 0,
-    vx: 16,
-    vy: 16,
-    vm: 32,
-    jumpForce: gravity + jumpForce,
-    onGround: false,
-    width: 20,
-    height: 20
-};
-
-const terrain = {
-    start: { x: 0, y: 0 },
-    end: { x: canvas.width, y: canvas.height },
-    height: 8
-};
-
-const objects = [];
-let lastObjectX = 0;
-
-const getRandomInterval = (min, max) => {
-    return Math.floor(Math.random() * (max - min + 1) + min);
-}
-
-const createObject = () => {
-    const object = {
-        x: lastObjectX + 10 * canvas.width / 10,
-        width: Math.random() * 100,
-        height: Math.random() * 22
+(function(){
+
+    const COLORS = {
+        player: '#2d2d2d',
+        particles: '#2d2d2d',
+        objects: '#2d2d2d',
+        terrain: '#2d2d2d'
     };
 
-    let terrainY = ((terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x)) * (object.x - terrain.start.x) + terrain.start.y;
+    const gravity = 1;
+    const jumpForce = 14.75;
+
+    const player = {
+        x: 200,
+        y: 0,
+        vx: 16,
+        vy: 16,
+        vm: 32,
+        jumpForce: gravity + jumpForce,
+        onGround: false,
+        width: 20,
+        height: 20,
+        distanceTraveled: 0
+    };
 
-    object.y = terrainY - object.height;
+    const terrain = {
+        start: { x: 0, y: 0 },
+        end: { x: canvas.width, y: canvas.height },
+        height: 8
+    };
 
-    objects.push(object);
+    const objects = [];
+    let lastObjectX = 0;
 
-    lastObjectX = object.x;
-};
+    const particles = [];
 
+    const createObject = () => {
+        const object = {
+            x: lastObjectX + 10 * canvas.width / 10,
+            width: Math.random() * 100,
+            height: Math.random() * 22
+        };
 
-// Shout out to Josh Grams!
-let lastUpdateTime = 0;
-const fps = 60;
-const frameDelay = 1000 / fps; 
+        let terrainY = ((terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x)) * (object.x - terrain.start.x) + terrain.start.y;
 
-const update = (currentTime = 0) => {
-    const deltaTime = currentTime - lastUpdateTime;
+        object.y = terrainY - object.height;
 
-    if (deltaTime >= frameDelay) {
-        createObject();
-        lastUpdateTime = currentTime;
-    }
+        objects.push(object);
 
-    requestAnimationFrame(update);
-};
+        lastObjectX = object.x;
+    };
 
-update();
+    const isColliding = (obj1, obj2) => (
+        obj1.x < obj2.x + obj2.width &&
+        obj1.x + obj1.width > obj2.x &&
+        obj1.y < obj2.y + obj2.height &&
+        obj1.y + obj1.height > obj2.y
+    );
+
+    const checkCollision = () => {
+        objects.forEach(object => {
+            if (isColliding(player, object)) {
+                if (player.vx >= 1) {
+                    player.vx -= 0.5;
+                    player.vy -= 0.5;
+                }
+            }
+        });
+    };
 
-const initialize = () => {
-    terrain.start = { x: 0, y: 0 };
-    terrain.end = { x: canvas.width, y: canvas.height };
-};
+    const updatePlayer = () => {
+        player.vy += gravity;
 
-const drawPlayer = () => {
+        player.x += player.vx;
+        player.y += player.vy;
 
-    if (player.vx < 4) {
-        ctx.fillStyle = COLORS.player;
-        ctx.font = '22px Arial';
-        const text = 'Jump to build up speed!';
-        ctx.fillText(text, player.x, player.y - 12);
-    }
-
-    ctx.fillStyle = COLORS.player;
-    ctx.fillRect(player.x, player.y, player.width, player.height);
-};
-
-const drawObjects = () => {
-    ctx.fillStyle = COLORS.objects;
-    objects.forEach(object => {
-        ctx.beginPath();
-        ctx.arc(object.x, object.y, object.width / 2, 0, Math.PI * 2, true);
-        ctx.fill();
-    });
-};
-
-const drawTerrain = () => {
-    ctx.beginPath();
-    ctx.moveTo(terrain.start.x, terrain.start.y);
-    ctx.lineTo(terrain.end.x, terrain.end.y);
-    ctx.strokeStyle = COLORS.terrain;
-    ctx.lineWidth = terrain.height;
-    ctx.stroke();
-};
-
-const drawParticles = () => {
-    ctx.fillStyle = COLORS.particles;
-    particles.forEach((particle, index) => {
-        ctx.fillRect(particle.x, particle.y, 5, 5);
-        particle.x += particle.vx;
-        particle.y += particle.vy;
-        particle.lifespan--;
-        if (particle.lifespan === 0) {
-            particles.splice(index, 1);
+        const terrainY = (terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x) * (player.x - terrain.start.x) + terrain.start.y;
+
+        if (player.y + player.height > terrainY) {
+            player.y = terrainY - player.height;
+            player.vy = 0;
         }
-    });
-};
-
-const draw = () => {
-    ctx.clearRect(0, 0, canvas.width, canvas.height);
-    ctx.save();
-    ctx.translate(-player.x + canvas.width / 4, -player.y + canvas.height / 2);
-    drawPlayer();
-    terrain.start.x = player.x - canvas.width;
-    terrain.end.x = player.x + canvas.width;
-    drawObjects();
-    drawTerrain();
-    drawParticles();
-    ctx.restore();
-};
-
-const isColliding = (obj1, obj2) => (
-    obj1.x < obj2.x + obj2.width &&
-    obj1.x + obj1.width > obj2.x &&
-    obj1.y < obj2.y + obj2.height &&
-    obj1.y + obj1.height > obj2.y
-);
-
-const checkCollision = () => {
-    objects.forEach(object => {
-        if (isColliding(player, object)) {
-            if (player.vx >= 1) {
-                player.vx -= 0.5;
-                player.vy -= 0.5;
+
+        if (particlesEnabled) {
+            particles.push({
+                x: player.x,
+                y: player.y,
+                vx: Math.random() * 2 - 1,
+                vy: Math.random() * 2 - 1,
+                lifespan: player.vx * 4
+            });
+        }
+    };
+
+    const updateObjects = () => {
+        for (let object of objects) {
+            object.y += gravity;
+
+            let terrainY = ((terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x)) * (object.x - terrain.start.x) + terrain.start.y;
+
+            if (object.y + object.height > terrainY) {
+                object.y = terrainY - object.height;
             }
         }
-    });
-};
+    };
 
-const particles = [];
+    const drawPlayer = () => {
+
+        if (player.vx < 4) {
+            ctx.fillStyle = COLORS.player;
+            ctx.font = '22px Arial';
+            const text = 'Jump to build up speed!';
+            ctx.fillText(text, player.x, player.y - 12);
+        } else {
+            if (distanceMeterEnabled) {
+                ctx.fillStyle = '#aaa';
+                ctx.font = '22px Arial';
+                const text = player.distanceTraveled.toFixed(0) + ' px';
+                ctx.fillText(text, player.x, player.y - 12);
+            }
+        }
+
+        ctx.fillStyle = COLORS.player;
+        ctx.fillRect(player.x, player.y, player.width, player.height);
+    };
 
-const gameLoop = () => {
-    player.vy += gravity;
+    const drawObjects = () => {
+        ctx.fillStyle = COLORS.objects;
+        objects.forEach(object => {
+            ctx.beginPath();
+            ctx.arc(object.x, object.y, object.width / 2, 0, Math.PI * 2, true);
+            ctx.fill();
+        });
+    };
 
-    player.x += player.vx;
-    player.y += player.vy;
+    const drawTerrain = () => {
+        ctx.beginPath();
+        ctx.moveTo(terrain.start.x, terrain.start.y);
+        ctx.lineTo(terrain.end.x, terrain.end.y);
+        ctx.strokeStyle = COLORS.terrain;
+        ctx.lineWidth = terrain.height;
+        ctx.stroke();
+    };
 
-    const terrainY = (terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x) * (player.x - terrain.start.x) + terrain.start.y;
+    const drawParticles = () => {
+        if (particlesEnabled) {
+            ctx.fillStyle = COLORS.particles;
+            particles.forEach((particle, index) => {
+                ctx.fillRect(particle.x, particle.y, 5, 5);
+                particle.x += particle.vx;
+                particle.y += particle.vy;
+                particle.lifespan--;
+                if (particle.lifespan === 0) {
+                    particles.splice(index, 1);
+                }
+            });
+        }
+    };
 
-    if (player.y + player.height > terrainY) {
-        player.y = terrainY - player.height;
-        player.vy = 0;
-    }
 
-    for (let object of objects) {
-        object.y += gravity;
+    const draw = () => {
+        ctx.clearRect(0, 0, canvas.width, canvas.height);
+        ctx.save();
+        ctx.translate(-player.x + canvas.width / 4, -player.y + canvas.height / 2);
+        drawPlayer();
+        terrain.start.x = player.x - canvas.width;
+        terrain.end.x = player.x + canvas.width;
+        drawObjects();
+        drawTerrain();
+        drawParticles();
+        ctx.restore();
+    };
 
-        let terrainY = ((terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x)) * (object.x - terrain.start.x) + terrain.start.y;
+    const update = (currentTime = 0) => {
+        const deltaTime = currentTime - lastUpdateTime;
 
-        if (object.y + object.height > terrainY) {
-            object.y = terrainY - object.height;
+        player.distanceTraveled = Math.abs(player.x - 200);
+
+        if (deltaTime >= frameDelay) {
+            createObject();
+            updatePlayer();
+            updateObjects();
+            checkCollision();
+            lastUpdateTime = currentTime;
         }
-    }
-
-     particles.push({
-        x: player.x,
-        y: player.y,
-        vx: Math.random() * 2 - 1,
-        vy: Math.random() * 2 - 1,
-        lifespan: player.vx * 4
-    });
 
-    checkCollision();
-    initialize();
-    draw();
-    requestAnimationFrame(gameLoop);
-};
+        requestAnimationFrame(update);
+    };
+
+    const initialize = () => {
+        terrain.start = { x: 0, y: 0 };
+        terrain.end = { x: canvas.width, y: canvas.height };
+    };
+
+    const gameLoop = () => {
+        initialize();
+        draw();
+        requestAnimationFrame(gameLoop);
+    };
 
-gameLoop();
+    const playerDoJump = () => {
+        const terrainY = (terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x) * (player.x - terrain.start.x) + terrain.start.y;
+        if (player.y + player.height >= terrainY) {
+            player.vy = player.jumpForce * -1;
+            if (player.vx < player.vm) {
+                player.vx += 0.5;
+            }
+        }
+    };
 
-const playerDoJump = () => {
-    const terrainY = (terrain.end.y - terrain.start.y) / (terrain.end.x - terrain.start.x) * (player.x - terrain.start.x) + terrain.start.y;
-    if (player.y + player.height >= terrainY) {
-        player.vy = player.jumpForce * -1;
-        if (player.vx < player.vm) {
-            player.vx += 0.5;
+    const handleKeyDown = event => {
+        if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowUp' || event.key === 'w' || event.key === 'W') {
+            playerDoJump();
         }
-    }
-};
-
-const handleKeyDown = event => {
-    if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowUp' || event.key === 'w' || event.key === 'W') {
-        playerDoJump();
-    }
-};
-
-canvas.addEventListener('click', playerDoJump);
-canvas.addEventListener('touchstart', playerDoJump);
-window.addEventListener('keydown', handleKeyDown);
-
-window.addEventListener('resize', () => {
-    canvas.width = window.innerWidth;
-    canvas.height = window.innerHeight;
-    draw();
-});
-
-document.addEventListener('keydown', function(event) {
-    if (event.key === 'f') {
+    };
+
+    canvas.addEventListener('click', playerDoJump);
+    canvas.addEventListener('touchstart', playerDoJump);
+    window.addEventListener('keydown', handleKeyDown);
+
+    window.addEventListener('resize', () => {
+        canvas.width = window.innerWidth;
+        canvas.height = window.innerHeight;
+        draw();
+    });
+
+    const helpText = 'Controls:\n\nJump: space, up arrow, w or tap the screen on mobile\nFullscreen: f or the button in the upper-right\nParticles: p\nDistance: d\nHelp: h'
+
+    document.addEventListener('keydown', function(event) {
+        if (event.key === 'f') {
+            if (canvas.requestFullscreen) {
+                canvas.requestFullscreen();
+            } else if (canvas.mozRequestFullScreen) {
+                canvas.mozRequestFullScreen();
+            } else if (canvas.webkitRequestFullscreen) {
+                canvas.webkitRequestFullscreen();
+            } else if (canvas.msRequestFullscreen) {
+                canvas.msRequestFullscreen();
+            }
+        } else if (event.key === 'p' || event.key === 'P') {
+            particlesEnabled = !particlesEnabled;
+        } else if (event.key === 'h' || event.key === 'H') {
+            alert(helpText);
+        } else if (event.key === 'd' || event.key === 'D') {
+            distanceMeterEnabled = !distanceMeterEnabled;
+        }
+    });
+
+    let particlesEnabled = true;
+    let distanceMeterEnabled = false;
+
+    const fullscreenButton = document.createElement('button');
+    fullscreenButton.style.position = 'absolute';
+    fullscreenButton.style.top = '10px';
+    fullscreenButton.style.right = '10px';
+    fullscreenButton.textContent = 'Fullscreen';
+
+    const distanceMeterButton = document.createElement('button');
+    distanceMeterButton.style.position = 'absolute';
+    distanceMeterButton.style.top = '40px';
+    distanceMeterButton.style.right = '10px';
+    distanceMeterButton.textContent = 'Distance';
+
+    const particlesButton = document.createElement('button');
+    particlesButton.style.position = 'absolute';
+    particlesButton.style.top = '70px';
+    particlesButton.style.right = '10px';
+    particlesButton.textContent = 'Particles';
+
+    const helpButton = document.createElement('button');
+    helpButton.style.position = 'absolute';
+    helpButton.style.top = '100px';
+    helpButton.style.right = '10px';
+    helpButton.textContent = 'Help';
+
+    fullscreenButton.addEventListener('click', function() {
         if (canvas.requestFullscreen) {
             canvas.requestFullscreen();
         } else if (canvas.mozRequestFullScreen) {
@@ -242,17 +289,31 @@ document.addEventListener('keydown', function(event) {
         } else if (canvas.msRequestFullscreen) {
             canvas.msRequestFullscreen();
         }
-    }
-});
-
-canvas.addEventListener('touchstart', function(event) {
-    if (canvas.requestFullscreen) {
-        canvas.requestFullscreen();
-    } else if (canvas.mozRequestFullScreen) {
-        canvas.mozRequestFullScreen();
-    } else if (canvas.webkitRequestFullscreen) {
-        canvas.webkitRequestFullscreen();
-    } else if (canvas.msRequestFullscreen) {
-        canvas.msRequestFullscreen();
-    }
-});
+    });
+
+    distanceMeterButton.addEventListener('click', function() {
+        distanceMeterEnabled = !distanceMeterEnabled;
+    });
+
+    particlesButton.addEventListener('click', function() {
+        particlesEnabled = !particlesEnabled;
+    });
+
+    helpButton.addEventListener('click', function() {
+        alert(helpText);
+    });
+
+    canvas.parentNode.appendChild(fullscreenButton);
+    canvas.parentNode.appendChild(distanceMeterButton);
+    canvas.parentNode.appendChild(particlesButton);
+    canvas.parentNode.appendChild(helpButton);
+
+
+    let lastUpdateTime = 0;
+    const fps = 60;
+    const frameDelay = 1000 / fps; 
+
+    update();
+    gameLoop();
+
+} )();
\ No newline at end of file