{"id":21,"date":"2026-04-15T07:04:44","date_gmt":"2026-04-15T05:04:44","guid":{"rendered":"https:\/\/primacyber.fr\/?page_id=21"},"modified":"2026-04-16T00:57:39","modified_gmt":"2026-04-15T22:57:39","slug":"cibl","status":"publish","type":"page","link":"https:\/\/primacyber.fr\/index.php\/cibl\/","title":{"rendered":"Hiver paisible"},"content":{"rendered":"\n<style>\n.moutons-wrapper {\n  position: relative;\n  width: 834px;\n  margin: 20px auto;\n  font-family: Arial, Helvetica, sans-serif;\n  overflow: hidden;\n}\n\n\/* Fond *\/\n#moutons-bg {\n  position: absolute;\n  top: 0;\n  left: 117px;\n  width: 600px;\n  height: 620px;\n  object-fit: cover;\n  pointer-events: none;\n  z-index: 1;\n}\n\n\/* Cadre *\/\n#moutons-frame {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 834px;\n  height: 800px;\n  pointer-events: none;\n  z-index: 2;\n}\n\n\/* Canvas (mouches + chrono) *\/\n#moutons-canvas {\n  background: transparent;\n  display: block;\n  width: 100%;\n  height: 800px;\n  border-radius: 13px;\n  position: relative;\n  z-index: 3;\n}\n\n\/* Overlay *\/\n.moutons-overlay {\n  position: absolute;\n  bottom: 40px;\n  left: 0;\n  width: 100%;\n  display: flex;\n  justify-content: center;\n  z-index: 4;\n}\n\n.moutons-overlay.hidden {\n  display: none;\n}\n\n\/* Champ pseudo *\/\n.input-pseudo {\n  padding: 6px 10px;\n  width: 160px;\n  border-radius: 50px;\n  border: 3px solid #000;\n  background: #ff8c00;\n  color: #000;\n  margin-bottom: 10px;\n  font-size: 16px;\n  text-align: center;\n  font-weight: 700;\n}\n\n\/* Bouton *\/\n.btn {\n  background: #9cff7a;\n  color: #000;\n  padding: 8px 20px;\n  border-radius: 50px;\n  cursor: pointer;\n  border: 2px solid #000;\n  font-weight: 900;\n  font-size: 18px;\n}\n\n\/* Bloc des scores *\/\n.score-box {\n  background: #fff;\n  border: 3px solid #000;\n  border-radius: 20px;\n  padding: 20px;\n  width: 300px;\n  margin: 0 auto;\n  margin-top: -20px;\n}\n\n.score-text {\n  font-size: 22px;\n  color: #000;\n  font-weight: 700;\n}\n<\/style>\n\n<div class=\"moutons-wrapper\">\n\n  <img decoding=\"async\" id=\"moutons-bg\" src=\"\/wp-content\/uploads\/jeux\/mouton\/paysageg.jpg\">\n  <img decoding=\"async\" id=\"moutons-frame\" src=\"\/wp-content\/uploads\/jeux\/mouton\/cadreg.png\">\n\n  <canvas id=\"moutons-canvas\" width=\"834\" height=\"800\"><\/canvas>\n\n  <div id=\"moutons-overlay\" class=\"moutons-overlay\">\n    <div style=\"text-align:center;\">\n      <input id=\"moutons-pseudo\" class=\"input-pseudo\" placeholder=\"Ton pseudo\">\n      <br>\n      <button id=\"moutons-start\" class=\"btn\">Jouer<\/button>\n    <\/div>\n  <\/div>\n\n<\/div>\n\n<script>\n(function(){\n  const canvas = document.getElementById('moutons-canvas');\n  const overlay = document.getElementById('moutons-overlay');\n  const startBtn = document.getElementById('moutons-start');\n  const pseudoInput = document.getElementById('moutons-pseudo');\n  const ctx = canvas.getContext('2d');\n\n  let pseudo = \"\";\n\n  \/* \ud83d\udfe9 IMAGE MOUCHE = moutong.png *\/\n  const imgMouton = new Image();\n  imgMouton.src = \"\/wp-content\/uploads\/jeux\/mouton\/moutong.png\";\n\n  const imgPop = new Image();\n  imgPop.src = \"\/wp-content\/uploads\/jeux\/mouton\/pop.png\";\n\n  const MOUTONS_COUNT = 7;\n  const GAME_DURATION = 20000;\n\n  const PLAY_AREA = { x:117, y:0, w:600, h:600 };\n\n  \/* \ud83d\udfe9 Points mis \u00e0 jour *\/\n  const SIZE = {\n    small:{r:18,lifetime:1200,points:4,speed:150},\n    medium:{r:26,lifetime:2200,points:2,speed:90},\n    large:{r:40,lifetime:3500,points:1,speed:40}\n  };\n\n  const WEIGHTS = [0.45,0.35,0.20];\n\n  let score = 0;\n  let moutons = [];\n  let pops = [];\n  let last = 0;\n  let gameActive = false;\n  let gameEndTime = 0;\n\n  function chooseSize(){\n    let r = Math.random();\n    if (r < WEIGHTS[0]) return 'small';\n    if (r < WEIGHTS[0] + WEIGHTS[1]) return 'medium';\n    return 'large';\n  }\n\n  \/* \ud83d\udfe7 Rotation initiale al\u00e9atoire + oscillation *\/\n  function spawnMouton(){\n    let type = chooseSize();\n    let cfg = SIZE[type];\n\n    let x = PLAY_AREA.x + cfg.r + Math.random() * (PLAY_AREA.w - cfg.r*2);\n    let y = PLAY_AREA.y + cfg.r + Math.random() * (PLAY_AREA.h - cfg.r*2);\n\n    let a = Math.random() * Math.PI * 2;\n\n    return {\n      x:x, y:y,\n      vx:Math.cos(a)*cfg.speed,\n      vy:Math.sin(a)*cfg.speed,\n      r:cfg.r,\n      born:Date.now(),\n      lifetime:cfg.lifetime,\n      points:cfg.points,\n      curveOffset: Math.random() * 5000,\n\n      initialRotation: Math.random() * Math.PI * 2,\n      rotationPhase: Math.random() * Math.PI * 2\n    };\n  }\n\n  function initMoutons(){\n    moutons = [];\n    while(moutons.length < MOUTONS_COUNT) moutons.push(spawnMouton());\n  }\n\n  canvas.addEventListener('click', function(e){\n    if (!gameActive) return;\n\n    let rect = canvas.getBoundingClientRect();\n    let x = e.clientX - rect.left;\n    let y = e.clientY - rect.top;\n    let now = Date.now();\n\n    for (let i = moutons.length - 1; i >= 0; i--) {\n      let m = moutons[i];\n      if (Math.hypot(m.x - x, m.y - y) <= m.r) {\n\n        score += m.points;\n\n        pops.push({\n          x: m.x,\n          y: m.y,\n          r: m.r,\n          born: now\n        });\n\n        moutons.splice(i,1);\n        moutons.push(spawnMouton());\n        break;\n      }\n    }\n  });\n\n  \/* -------------------------\n     CHRONO CAMEMBERT + CERCLE\n  --------------------------*\/\n  function drawChrono() {\n    const now = Date.now();\n    const total = GAME_DURATION;\n    const elapsed = Math.max(0, gameEndTime - now);\n    const progress = 1 - (elapsed \/ total);\n\n    const radius = 30;\n    const cx = 834 - 150 - radius;\n    const cy = 800 - 40 - radius;\n\n    ctx.beginPath();\n    ctx.arc(cx, cy, radius, 0, Math.PI * 2);\n    ctx.fillStyle = \"#9cff7a\";\n    ctx.fill();\n\n    ctx.beginPath();\n    ctx.moveTo(cx, cy);\n    ctx.arc(cx, cy, radius, -Math.PI\/2, -Math.PI\/2 + progress * Math.PI * 2);\n    ctx.closePath();\n    ctx.fillStyle = \"#ff8c00\";\n    ctx.fill();\n\n    ctx.beginPath();\n    ctx.arc(cx, cy, radius, 0, Math.PI * 2);\n    ctx.strokeStyle = \"#000\";\n    ctx.lineWidth = 3;\n    ctx.stroke();\n  }\n\n  \/* -------------------------\n     BOUCLE DE JEU\n  --------------------------*\/\n  function loop(){\n    if (!gameActive) return;\n\n    let now = Date.now();\n\n    if (now >= gameEndTime) {\n      endGame();\n      return;\n    }\n\n    let dt = (now - last)\/1000;\n    last = now;\n\n    ctx.clearRect(0,0,canvas.width,canvas.height);\n\n    drawChrono();\n\n    moutons.forEach(m => {\n\n      m.x += m.vx * dt;\n      m.y += m.vy * dt;\n\n      if (m.x < PLAY_AREA.x + m.r || m.x > PLAY_AREA.x + PLAY_AREA.w - m.r) m.vx *= -1;\n      if (m.y < PLAY_AREA.y + m.r || m.y > PLAY_AREA.y + PLAY_AREA.h - m.r) m.vy *= -1;\n\n      if (now - m.born > m.lifetime) Object.assign(m, spawnMouton());\n\n      m.x += Math.cos((now + m.curveOffset) \/ 400) * 1.5;\n      m.y += Math.sin((now + m.curveOffset) \/ 500) * 1.5;\n\n      let rot = m.initialRotation + Math.sin((now + m.rotationPhase) \/ 300) * (Math.PI \/ 6);\n\n      ctx.save();\n      ctx.translate(m.x, m.y);\n      ctx.rotate(rot);\n      ctx.drawImage(imgMouton, -m.r, -m.r, m.r*2, m.r*2);\n      ctx.restore();\n    });\n\n    pops = pops.filter(p => now - p.born < 150);\n\n    pops.forEach(p => {\n      ctx.drawImage(imgPop, p.x - p.r, p.y - p.r, p.r * 2, p.r * 2);\n    });\n\n    requestAnimationFrame(loop);\n  }\n\n  async function saveScore(){\n    try {\n      let response = await fetch(\"\/wp-content\/mouton-api\/save_score.php\", {\n        method: \"POST\",\n        headers: { \"Content-Type\": \"application\/json\" },\n        body: JSON.stringify({ pseudo, score })\n      });\n\n      return await response.json();\n    } catch(e) {\n      return [{ pseudo, score }];\n    }\n  }\n\n  async function endGame(){\n    gameActive = false;\n\n    let scores = await saveScore();\n\n    let html = `\n      <div class=\"score-box\">\n        <div class=\"score-text\">Score de ${pseudo}<\/div>\n        <div class=\"score-text\" style=\"margin-bottom:12px\">Tu as fait : ${score} points<\/div>\n\n        <div class=\"score-text\" style=\"margin:10px 0;\">Top 10 :<\/div>\n        <div style=\"text-align:left;font-size:22px;color:#000;margin-bottom:12px\">\n    `;\n\n    scores.forEach((s,i)=>{\n      html += `${i+1}. <b>${s.pseudo}<\/b> \u2014 ${s.score}<br>`;\n    });\n\n    html += `\n        <\/div>\n        <button id=\"moutons-play\" class=\"btn\">Rejouer<\/button>\n      <\/div>\n    `;\n\n    overlay.innerHTML = html;\n    overlay.classList.remove('hidden');\n\n    document.getElementById('moutons-play').onclick = startGame;\n  }\n\n  function startGame(){\n    pseudo = pseudoInput.value.trim();\n    if (!pseudo) return;\n\n    score = 0;\n    gameActive = true;\n    last = Date.now();\n    gameEndTime = Date.now() + GAME_DURATION;\n    initMoutons();\n    pops = [];\n    overlay.classList.add('hidden');\n    requestAnimationFrame(loop);\n  }\n\n  startBtn.onclick = startGame;\n})();\n<\/script>\n\n\n\n\n\n<p class=\"wp-block-paragraph\">Les petits, plus rapides, rapportent plus de points !<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jouer Les petits, plus rapides, rapportent plus de points !<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-21","page","type-page","status-publish"],"_links":{"self":[{"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/pages\/21","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/comments?post=21"}],"version-history":[{"count":47,"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/pages\/21\/revisions"}],"predecessor-version":[{"id":87,"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/pages\/21\/revisions\/87"}],"wp:attachment":[{"href":"https:\/\/primacyber.fr\/index.php\/wp-json\/wp\/v2\/media?parent=21"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}