{"id":86,"date":"2025-10-26T21:48:42","date_gmt":"2025-10-26T21:48:42","guid":{"rendered":"https:\/\/makeyour.life\/?page_id=86"},"modified":"2026-01-02T18:24:42","modified_gmt":"2026-01-02T23:24:42","slug":"frog-jump","status":"publish","type":"page","link":"https:\/\/makeyour.life\/index.php\/frog-jump\/","title":{"rendered":"Frog Jump"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"86\" class=\"elementor elementor-86\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-11dda83 e-flex e-con-boxed e-con e-parent\" data-id=\"11dda83\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-7818872 elementor-widget__width-inherit elementor-widget elementor-widget-html\" data-id=\"7818872\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- ===== FROG JUMP (LANE SWITCH) \ud83d\udc38 ===== -->\r\n<div id=\"fj-wrap\" style=\"max-width:380px;margin:0 auto;padding:10px;font-family:system-ui,-apple-system,Segoe UI,sans-serif;direction:ltr;\">\r\n\r\n  <!-- HUD -->\r\n  <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;font-size:14px;\">\r\n    <div>\u23f1 <span id=\"fj-time\">03:00<\/span><\/div>\r\n    <div>\u2b50 Score: <span id=\"fj-score\">0<\/span><\/div>\r\n  <\/div>\r\n\r\n  <div style=\"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;font-size:12px;\">\r\n    <div>Lives: <span id=\"fj-lives\">\u2764\ufe0f\u2764\ufe0f\u2764\ufe0f<\/span><\/div>\r\n    <div style=\"display:flex;gap:6px;\">\r\n      <button id=\"fj-pause\" style=\"padding:3px 8px;border:none;border-radius:999px;background:#607d8b;color:#fff;font-size:11px;cursor:pointer;\">Pause<\/button>\r\n      <button id=\"fj-restart\" style=\"padding:3px 8px;border:none;border-radius:999px;background:#9c27b0;color:#fff;font-size:11px;cursor:pointer;\">Restart<\/button>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Game Area -->\r\n  <div id=\"fj-stage\" style=\"\r\n    position:relative;\r\n    width:100%;\r\n    padding-top:120%;\r\n    background:linear-gradient(#071427,#071b2f);\r\n    border-radius:14px;\r\n    overflow:hidden;\r\n    touch-action:manipulation;\r\n    user-select:none;\r\n  \">\r\n    <!-- lanes -->\r\n    <div style=\"position:absolute;inset:0;display:flex;opacity:.18;\">\r\n      <div style=\"flex:1;border-right:1px dashed rgba(255,255,255,.25)\"><\/div>\r\n      <div style=\"flex:1;border-right:1px dashed rgba(255,255,255,.25)\"><\/div>\r\n      <div style=\"flex:1;\"><\/div>\r\n    <\/div>\r\n\r\n    <!-- frog -->\r\n    <div id=\"fj-frog\" aria-label=\"frog\"><\/div>\r\n\r\n    <!-- overlay message -->\r\n    <div id=\"fj-msg\" style=\"\r\n      position:absolute;inset:0;display:flex;align-items:center;justify-content:center;\r\n      color:#fff;font-weight:800;font-size:22px;text-align:center;\r\n      background:linear-gradient(rgba(0,0,0,.25),rgba(0,0,0,.25));\r\n      padding:18px; pointer-events:none;\r\n    \">Press Start<\/div>\r\n  <\/div>\r\n\r\n  <!-- Controls -->\r\n  <div style=\"text-align:center;margin-top:12px;\">\r\n    <button id=\"fj-start\" style=\"padding:10px 20px;border:none;border-radius:22px;background:#ff6f61;color:#fff;font-size:15px;cursor:pointer;\">\r\n      Start Game\r\n    <\/button>\r\n    <div style=\"margin-top:6px;font-size:12px;color:#6b7280;\">\r\n      Tap left\/middle\/right to move lanes.\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<style>\r\n  #fj-frog{\r\n    position:absolute;\r\n    width:56px;height:44px;\r\n    bottom:14px;\r\n    left:50%;\r\n    transform:translateX(-50%);\r\n    border-radius:18px 18px 16px 16px;\r\n    background:linear-gradient(135deg,#66bb6a,#2e7d32);\r\n    box-shadow:0 0 14px rgba(102,187,106,.55);\r\n    transition:left 120ms ease;\r\n  }\r\n  \/* eyes *\/\r\n  #fj-frog::before, #fj-frog::after{\r\n    content:'';\r\n    position:absolute;\r\n    top:-10px;\r\n    width:16px;height:16px;border-radius:50%;\r\n    background:linear-gradient(135deg,#a5d6a7,#43a047);\r\n    box-shadow:0 0 10px rgba(102,187,106,.45);\r\n  }\r\n  #fj-frog::before{ left:6px; }\r\n  #fj-frog::after{ right:6px; }\r\n  \/* pupils *\/\r\n  #fj-frog .pupil{\r\n    position:absolute;top:-5px;width:6px;height:6px;border-radius:50%;\r\n    background:#0b1020;\r\n  }\r\n\r\n  .fj-item{\r\n    position:absolute;\r\n    width:26px;height:26px;border-radius:50%;\r\n    top:-40px;\r\n    will-change:transform;\r\n  }\r\n  .fj-star{\r\n    background:radial-gradient(circle,#fff9c4,#ffca28,#f57f17);\r\n    box-shadow:0 0 10px rgba(255,202,40,.75);\r\n  }\r\n  .fj-bomb{\r\n    background:radial-gradient(circle,#b0bec5,#37474f,#111827);\r\n    box-shadow:0 0 10px rgba(176,190,197,.35);\r\n  }\r\n  .fj-bomb::after{\r\n    content:'';\r\n    position:absolute;right:-6px;top:6px;\r\n    width:10px;height:6px;border-radius:6px;\r\n    background:#ff7043;\r\n    box-shadow:0 0 8px rgba(255,112,67,.6);\r\n  }\r\n\r\n  .fj-pop{\r\n    position:absolute;border-radius:50%;\r\n    background:radial-gradient(circle,#fff59d,#ffb74d,#f4511e);\r\n    pointer-events:none;\r\n    animation:fj-pop .35s ease-out forwards;\r\n  }\r\n  @keyframes fj-pop{\r\n    0%{transform:scale(.4);opacity:1;}\r\n    100%{transform:scale(2.1);opacity:0;}\r\n  }\r\n<\/style>\r\n\r\n<script>\r\n(function(){\r\n  const TOTAL_TIME = 360; \/\/ 6 min\r\n  const stage = document.getElementById('fj-stage');\r\n  const frogEl = document.getElementById('fj-frog');\r\n  const msgEl = document.getElementById('fj-msg');\r\n\r\n  const timeEl = document.getElementById('fj-time');\r\n  const scoreEl = document.getElementById('fj-score');\r\n  const livesEl = document.getElementById('fj-lives');\r\n\r\n  const startBtn = document.getElementById('fj-start');\r\n  const pauseBtn = document.getElementById('fj-pause');\r\n  const restartBtn = document.getElementById('fj-restart');\r\n\r\n  \/\/ game state\r\n  let running = false;\r\n  let paused = false;\r\n\r\n  let timeLeft = TOTAL_TIME;\r\n  let score = 0;\r\n  let lives = 3;\r\n\r\n  let lane = 1; \/\/ 0 left, 1 mid, 2 right\r\n  let items = [];\r\n  let rect = null;\r\n\r\n  let timer = null;\r\n  let lastSpawn = 0;\r\n  let rafId = null;\r\n\r\n  \/\/ speed ramps up over time\r\n  function progress(){\r\n    return 1 - (timeLeft \/ TOTAL_TIME); \/\/ 0..1\r\n  }\r\n\r\n  function formatTime(sec){\r\n    const m = Math.floor(sec\/60);\r\n    const s = sec % 60;\r\n    return String(m).padStart(2,'0') + ':' + String(s).padStart(2,'0');\r\n  }\r\n\r\n  function updateHUD(){\r\n    timeEl.textContent = formatTime(timeLeft);\r\n    scoreEl.textContent = score;\r\n    livesEl.textContent = '\u2764\ufe0f'.repeat(lives);\r\n  }\r\n\r\n  function laneX(l){\r\n    rect = stage.getBoundingClientRect();\r\n    const laneWidth = rect.width \/ 3;\r\n    const center = (l * laneWidth) + laneWidth\/2;\r\n    return center;\r\n  }\r\n\r\n  function setLane(l){\r\n    lane = Math.max(0, Math.min(2, l));\r\n    const x = laneX(lane);\r\n    frogEl.style.left = x + 'px';\r\n  }\r\n\r\n  function clearItems(){\r\n    items.forEach(it => it.el.remove());\r\n    items = [];\r\n  }\r\n\r\n  function popFx(x,y){\r\n    const p = document.createElement('div');\r\n    p.className = 'fj-pop';\r\n    const size = 20;\r\n    p.style.width = size + 'px';\r\n    p.style.height = size + 'px';\r\n    p.style.left = (x - size\/2) + 'px';\r\n    p.style.top = (y - size\/2) + 'px';\r\n    stage.appendChild(p);\r\n    setTimeout(()=>p.remove(), 380);\r\n  }\r\n\r\n  function spawnItem(){\r\n    if (!running || paused) return;\r\n\r\n    rect = stage.getBoundingClientRect();\r\n    const p = progress();\r\n\r\n    \/\/ spawn faster over time\r\n    const spawnInterval = 700 - p * 320; \/\/ 700ms -> ~380ms\r\n\r\n    const now = performance.now();\r\n    if (now - lastSpawn < spawnInterval) return;\r\n    lastSpawn = now;\r\n\r\n    const it = document.createElement('div');\r\n    it.className = 'fj-item';\r\n\r\n    \/\/ 70% stars, 30% bombs (slightly more bombs later)\r\n    const bombChance = 0.15 + p * 0.06;\r\n    const isBomb = Math.random() < bombChance;\r\n\r\n    it.classList.add(isBomb ? 'fj-bomb' : 'fj-star');\r\n\r\n    const l = Math.floor(Math.random() * 3);\r\n    const x = laneX(l);\r\n    it.style.left = x + 'px';\r\n\r\n    stage.appendChild(it);\r\n\r\n    \/\/ physics\r\n    const speed = 1.15 + p * 2.1; \/\/ faster later\r\n    items.push({ el: it, lane: l, y: -40, speed: speed, bomb: isBomb });\r\n  }\r\n\r\n  function collide(item){\r\n    \/\/ collision near frog area only\r\n    rect = stage.getBoundingClientRect();\r\n\r\n    const frogW = frogEl.offsetWidth;\r\n    const frogH = frogEl.offsetHeight;\r\n\r\n    const frogX = laneX(lane); \/\/ center\r\n    const frogBottom = rect.height - 14;\r\n    const frogTop = frogBottom - frogH;\r\n\r\n    const itemX = laneX(item.lane);\r\n    const itemSize = 26;\r\n    const itemTop = item.y;\r\n    const itemBottom = item.y + itemSize;\r\n\r\n    \/\/ same lane required (core mechanic)\r\n    if (item.lane !== lane) return false;\r\n\r\n    \/\/ y overlap window\r\n    const yHit = itemBottom >= frogTop && itemTop <= frogBottom;\r\n    \/\/ x is implicit by lane, but keep small tolerance\r\n    const xHit = Math.abs(itemX - frogX) <= (frogW\/2 + 6);\r\n\r\n    return yHit && xHit;\r\n  }\r\n\r\n  function endGame(reason){\r\n    running = false;\r\n    paused = false;\r\n\r\n    if (timer){ clearInterval(timer); timer = null; }\r\n    if (rafId){ cancelAnimationFrame(rafId); rafId = null; }\r\n\r\n    msgEl.style.display = 'flex';\r\n    msgEl.textContent = reason;\r\n    startBtn.textContent = 'Play Again';\r\n    pauseBtn.textContent = 'Pause';\r\n\r\n    \/\/ stop interactions softly\r\n  }\r\n\r\n  function tick(){\r\n    if (!running){\r\n      return;\r\n    }\r\n    if (!paused){\r\n      \/\/ spawn items\r\n      spawnItem();\r\n\r\n      rect = stage.getBoundingClientRect();\r\n      const p = progress();\r\n\r\n      const remove = [];\r\n      items.forEach((it, i) => {\r\n        it.y += it.speed * (1 + p * 1.5);\r\n        it.el.style.transform = 'translate(-50%, ' + it.y + 'px)';\r\n\r\n        \/\/ collision\r\n        if (collide(it)){\r\n          \/\/ explode \/ pop\r\n          const x = laneX(it.lane);\r\n          const y = Math.min(rect.height - 40, it.y + 10);\r\n          popFx(x, y);\r\n\r\n          if (it.bomb){\r\n            lives--;\r\n            updateHUD();\r\n            if (lives <= 0){\r\n              it.el.remove();\r\n              remove.push(i);\r\n              clearItems();\r\n              endGame('Game Over \ud83d\udca5\\nScore: ' + score);\r\n              return;\r\n            }\r\n          } else {\r\n            score++;\r\n            scoreEl.textContent = score;\r\n          }\r\n\r\n          it.el.remove();\r\n          remove.push(i);\r\n          return;\r\n        }\r\n\r\n        \/\/ off screen\r\n        if (it.y > rect.height + 60){\r\n          it.el.remove();\r\n          remove.push(i);\r\n        }\r\n      });\r\n\r\n      if (remove.length){\r\n        items = items.filter((_, idx) => !remove.includes(idx));\r\n      }\r\n    }\r\n\r\n    rafId = requestAnimationFrame(tick);\r\n  }\r\n\r\n  function startTimer(){\r\n    if (timer) clearInterval(timer);\r\n    timer = setInterval(()=>{\r\n      if (!running || paused) return;\r\n      timeLeft--;\r\n      updateHUD();\r\n      if (timeLeft <= 0){\r\n        timeLeft = 0;\r\n        updateHUD();\r\n        clearItems();\r\n        endGame('Time Up \u23f1\\nScore: ' + score);\r\n      }\r\n    }, 1000);\r\n  }\r\n\r\n  function resetAll(){\r\n    \/\/ stop existing\r\n    running = false;\r\n    paused = false;\r\n    if (timer){ clearInterval(timer); timer = null; }\r\n    if (rafId){ cancelAnimationFrame(rafId); rafId = null; }\r\n\r\n    \/\/ reset state\r\n    timeLeft = TOTAL_TIME;\r\n    score = 0;\r\n    lives = 3;\r\n    lastSpawn = 0;\r\n\r\n    clearItems();\r\n    updateHUD();\r\n\r\n    msgEl.style.display = 'flex';\r\n    msgEl.textContent = 'Press Start';\r\n\r\n    startBtn.textContent = 'Start Game';\r\n    pauseBtn.textContent = 'Pause';\r\n  }\r\n\r\n  function startGame(){\r\n    resetAll();\r\n    running = true;\r\n    paused = false;\r\n\r\n    msgEl.style.display = 'none';\r\n    startBtn.textContent = 'Playing...';\r\n\r\n    \/\/ position frog\r\n    setTimeout(()=>setLane(1), 0);\r\n\r\n    startTimer();\r\n    rafId = requestAnimationFrame(tick);\r\n  }\r\n\r\n  function togglePause(){\r\n    if (!running) return;\r\n    paused = !paused;\r\n    pauseBtn.textContent = paused ? 'Resume' : 'Pause';\r\n    msgEl.style.display = paused ? 'flex' : 'none';\r\n    msgEl.textContent = paused ? 'Paused' : '';\r\n  }\r\n\r\n  \/\/ Controls: tap on stage chooses lane by tap position\r\n  stage.addEventListener('click', (e)=>{\r\n    if (!running || paused) return;\r\n    rect = stage.getBoundingClientRect();\r\n    const x = e.clientX - rect.left;\r\n    const laneWidth = rect.width \/ 3;\r\n    const l = Math.floor(x \/ laneWidth);\r\n    setLane(l);\r\n  });\r\n\r\n  \/\/ Keyboard fallback\r\n  document.addEventListener('keydown', (e)=>{\r\n    if (!running || paused) return;\r\n    if (e.key === 'ArrowLeft') setLane(lane - 1);\r\n    if (e.key === 'ArrowRight') setLane(lane + 1);\r\n  });\r\n\r\n  \/\/ Buttons\r\n  startBtn.addEventListener('click', ()=>{\r\n    if (running) return;\r\n    startGame();\r\n  });\r\n  pauseBtn.addEventListener('click', togglePause);\r\n  restartBtn.addEventListener('click', ()=>{\r\n    startGame();\r\n  });\r\n\r\n  window.addEventListener('resize', ()=>setLane(lane));\r\n\r\n  \/\/ init\r\n  resetAll();\r\n  setLane(1);\r\n})();\r\n<\/script>\r\n<!-- ===== END FROG JUMP \ud83d\udc38 ===== -->\r\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>\u23f1 03:00 \u2b50 Score: 0 Lives: \u2764\ufe0f\u2764\ufe0f\u2764\ufe0f Pause Restart Press Start Start Game Tap left\/middle\/right to move lanes.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-86","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/pages\/86","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/comments?post=86"}],"version-history":[{"count":9,"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/pages\/86\/revisions"}],"predecessor-version":[{"id":1157,"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/pages\/86\/revisions\/1157"}],"wp:attachment":[{"href":"https:\/\/makeyour.life\/index.php\/wp-json\/wp\/v2\/media?parent=86"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}