🎮ArcadeLab

Smile Jump

by SparkTurtle66
341 lines8.2 KB
▶ Play
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  <title>Smile Jump</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      background: #111;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
      font-family: Arial, sans-serif;
      color: white;
      overflow: hidden;
    }
    canvas {
      background: linear-gradient(to bottom, #1a2a6c, #b21f1f);
      border-radius: 12px;
      box-shadow: 0 0 25px rgba(0,0,0,0.5);
      max-width: 100%;
    }
    #ui {
      margin-top: 12px;
      text-align: center;
      font-size: 18px;
    }
    #jumpBtn {
      margin-top: 15px;
      padding: 16px 60px;
      font-size: 22px;
      font-weight: bold;
      background: #00c3ff;
      color: white;
      border: none;
      border-radius: 50px;
      cursor: pointer;
      box-shadow: 0 6px 0 #0090c0;
      user-select: none;
      -webkit-tap-highlight-color: transparent;
    }
    #jumpBtn:active {
      transform: translateY(4px);
      box-shadow: 0 2px 0 #0090c0;
    }
    #message {
      font-size: 22px;
      font-weight: bold;
      margin-top: 8px;
      height: 32px;
      color: #fff;
    }
  </style>
</head>
<body>

  <canvas id="gameCanvas" width="800" height="450"></canvas>

  <div id="ui">
    <div>Level: <span id="level">1</span> | Rods: <span id="rods">0</span> / <span id="needed">10</span></div>
    <div id="message"></div>
  </div>

  <button id="jumpBtn">JUMP</button>

  <script>
    const canvas = document.getElementById("gameCanvas");
    const ctx = canvas.getContext("2d");

    // Game settings
    const GRAVITY = 0.7;
    const JUMP_FORCE = -15;
    const GROUND_Y = 380;

    let player = {
      x: 130,
      y: GROUND_Y - 50,
      width: 50,
      height: 50,
      velocityY: 0,
      onGround: true,
      scaleX: 1,
      scaleY: 1,
      rotation: 0
    };

    let rods = [];
    let level = 1;
    let rodsPassed = 0;
    let rodsNeeded = 10;
    let gameSpeed = 5.5;
    let gameState = "playing";
    let spawnTimer = 0;

    // Jump function
    function jump() {
      if (gameState === "playing" && player.onGround) {
        player.velocityY = JUMP_FORCE;
        player.onGround = false;
        player.scaleX = 0.75;
        player.scaleY = 1.3;
        player.rotation = -0.2;
      } 
      else if (gameState === "levelComplete") {
        nextLevel();
      } 
      else if (gameState === "gameOver" || gameState === "finished") {
        restartGame();
      }
    }

    document.getElementById("jumpBtn").addEventListener("click", jump);
    document.addEventListener("keydown", (e) => {
      if (e.code === "Space" || e.code === "ArrowUp") {
        e.preventDefault();
        jump();
      }
    });

    // Create blue rod
    function createRod() {
      const h = 55 + Math.random() * 55;
      rods.push({
        x: canvas.width + 30,
        y: GROUND_Y - h,
        width: 28,
        height: h,
        passed: false
      });
    }

    // Collision check
    function checkCollision(p, r) {
      return (
        p.x < r.x + r.width &&
        p.x + p.width > r.x &&
        p.y < r.y + r.height &&
        p.y + p.height > r.y
      );
    }

    // Update game
    function update() {
      if (gameState !== "playing") return;

      // Physics
      player.velocityY += GRAVITY;
      player.y += player.velocityY;

      if (player.y + player.height >= GROUND_Y) {
        player.y = GROUND_Y - player.height;
        player.velocityY = 0;
        player.onGround = true;
        player.scaleX = 1.3;
        player.scaleY = 0.7;
        player.rotation = 0;
      }

      // Smooth animation return
      player.scaleX += (1 - player.scaleX) * 0.18;
      player.scaleY += (1 - player.scaleY) * 0.18;
      player.rotation += (0 - player.rotation) * 0.15;

      if (!player.onGround) {
        player.rotation = player.velocityY * 0.018;
      }

      // Spawn rods
      spawnTimer++;
      if (spawnTimer > Math.max(50, 95 - level * 2.2)) {
        createRod();
        spawnTimer = 0;
      }

      // Move rods
      for (let i = rods.length - 1; i >= 0; i--) {
        let rod = rods[i];
        rod.x -= gameSpeed;

        if (!rod.passed && rod.x + rod.width < player.x) {
          rod.passed = true;
          rodsPassed++;
          document.getElementById("rods").textContent = rodsPassed;

          if (rodsPassed >= rodsNeeded) {
            levelComplete();
          }
        }

        if (checkCollision(player, rod)) {
          gameOver();
        }

        if (rod.x + rod.width < 0) {
          rods.splice(i, 1);
        }
      }
    }

    // Level complete
    function levelComplete() {
      gameState = "levelComplete";
      if (level >= 20) {
        gameState = "finished";
        document.getElementById("message").textContent = "YOU BEAT ALL 20 LEVELS!";
      } else {
        document.getElementById("message").textContent = `Level ${level} Complete! Tap JUMP`;
      }
    }

    function nextLevel() {
      level++;
      rodsPassed = 0;
      rodsNeeded = level * 10;
      gameSpeed = 5.5 + level * 0.32;
      rods = [];
      spawnTimer = 0;
      player.y = GROUND_Y - player.height;
      player.velocityY = 0;
      player.onGround = true;
      player.scaleX = 1;
      player.scaleY = 1;
      player.rotation = 0;
      gameState = "playing";

      document.getElementById("level").textContent = level;
      document.getElementById("rods").textContent = 0;
      document.getElementById("needed").textContent = rodsNeeded;
      document.getElementById("message").textContent = "";
    }

    function gameOver() {
      gameState = "gameOver";
      document.getElementById("message").textContent = "Game Over! Tap JUMP to retry";
    }

    function restartGame() {
      level = 1;
      rodsPassed = 0;
      rodsNeeded = 10;
      gameSpeed = 5.5;
      rods = [];
      spawnTimer = 0;
      player.y = GROUND_Y - player.height;
      player.velocityY = 0;
      player.onGround = true;
      player.scaleX = 1;
      player.scaleY = 1;
      player.rotation = 0;
      gameState = "playing";

      document.getElementById("level").textContent = 1;
      document.getElementById("rods").textContent = 0;
      document.getElementById("needed").textContent = 10;
      document.getElementById("message").textContent = "";
    }

    // Draw smiling face player
    function drawPlayer() {
      ctx.save();

      const cx = player.x + player.width / 2;
      const cy = player.y + player.height / 2;

      ctx.translate(cx, cy);
      ctx.rotate(player.rotation);
      ctx.scale(player.scaleX, player.scaleY);

      // yellow face
      ctx.beginPath();
      ctx.arc(0, 0, 26, 0, Math.PI * 2);
      ctx.fillStyle = "#FFD93D";
      ctx.fill();
      ctx.lineWidth = 3;
      ctx.strokeStyle = "#E6B800";
      ctx.stroke();

      // Eyes
      ctx.fillStyle = "#333";
      ctx.beginPath();
      ctx.arc(-9, -6, 4.5, 0, Math.PI * 2);
      ctx.arc(9, -6, 4.5, 0, Math.PI * 2);
      ctx.fill();

      // Big smile
      ctx.beginPath();
      ctx.arc(0, 4, 14, 0.15 * Math.PI, 0.85 * Math.PI);
      ctx.lineWidth = 3.5;
      ctx.strokeStyle = "#333";
      ctx.stroke();

      ctx.restore();
    }

    // Main draw
    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // Ground line
      ctx.strokeStyle = "rgba(255,255,255,0.4)";
      ctx.lineWidth = 3;
      ctx.beginPath();
      ctx.moveTo(0, GROUND_Y);
      ctx.lineTo(canvas.width, GROUND_Y);
      ctx.stroke();

      // Blue rods
      rods.forEach(rod => {
        // Main rod
        ctx.fillStyle = "#00B7FF";
        ctx.fillRect(rod.x, rod.y, rod.width, rod.height);

        // Light edge
        ctx.fillStyle = "#7DE2FF";
        ctx.fillRect(rod.x, rod.y, 8, rod.height);
      });

      // Draw the player
      drawPlayer();

      // Dark overlay when paused
      if (gameState !== "playing") {
        ctx.fillStyle = "rgba(0, 0, 0, 0.55)";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    }

    // Game loop
    function gameLoop() {
      update();
      draw();
      requestAnimationFrame(gameLoop);
    }

    gameLoop();
  </script>
</body>
</html>

Game Source: Smile Jump

Creator: SparkTurtle66

Libraries: none

Complexity: complex (341 lines, 8.2 KB)

The full source code is displayed above on this page.

Remix Instructions

To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: smile-jump-sparkturtle66" to link back to the original. Then publish at arcadelab.ai/publish.