🎮ArcadeLab

DON'T TOUCH THE RED

by BoldPenguin14
358 lines5.5 KB
▶ Play

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>DON'T TOUCH THE RED</title>
<style>
*{box-sizing:border-box}
body{
 margin:0;
 background:#080817;
 color:white;
 font-family:Arial;
 display:flex;
 justify-content:center;
 align-items:center;
 min-height:100vh
}
#game{
 width:min(95vw,440px);
 background:#12122c;
 border:2px solid #5145ad;
 border-radius:18px;
 overflow:hidden
}
header{
 display:flex;
 justify-content:space-around;
 padding:15px;
 color:#69edff;
 font-weight:bold
}
canvas{width:100%;display:block}
#controls{
 display:flex;
 justify-content:space-around;
 padding:12px
}
button{
 border:0;
 border-radius:25px;
 padding:14px 24px;
 background:#7045ff;
 color:white;
 font-weight:bold;
 font-size:17px;
 cursor:pointer;
 touch-action:none
}
#menu{
 position:fixed;
 inset:0;
 background:#080817;
 display:flex;
 align-items:center;
 justify-content:center;
 flex-direction:column;
 text-align:center;
 z-index:10;
 padding:20px
}
h1{
 font-size:38px;
 color:#6af5ff;
 text-shadow:0 0 20px cyan
}
#menu button{
 background:linear-gradient(90deg,#00d9ff,#a52cff);
 padding:18px 45px
}
</style>
</head>
<body>

<div id="game">
<header>
<div>SCORE <span id="score">0</span></div>
<div>BEST <span id="best">0</span></div>
<div>LEVEL <span id="level">1</span></div>
</header>

<canvas id="c" width="400" height="550"></canvas>

<div id="controls">
<button id="left">◀ LEFT</button>
<button id="right">RIGHT ▶</button>
</div>
</div>

<div id="menu">
<h1 id="heading">DON'T TOUCH<br>THE RED!</h1>
<p id="message">Dodge the danger. Survive the chaos!</p>
<button id="start">PLAY NOW</button>
</div>

<script>
(function(){

const canvas=document.getElementById("c");
const ctx=canvas.getContext("2d");
const $=id=>document.getElementById(id);

let player,reds,score,frame,level;
let running=false,direction=0,raf=0;
let best=0;

// Load best score
try{
 best=Number(localStorage.getItem("redBest"))||0;
}catch(e){}

$("best").textContent=best;

function startGame(){

 cancelAnimationFrame(raf);

 player={x:200,y:475,r:16};
 reds=[];
 score=0;
 frame=0;
 level=1;
 direction=0;
 running=true;

 $("menu").style.display="none";
 $("score").textContent="0";
 $("level").textContent="1";

 loop();
}

function gameOver(){

 running=false;
 cancelAnimationFrame(raf);

 best=Math.max(best,score);

 try{
 localStorage.setItem("redBest",best);
 }catch(e){}

 $("best").textContent=best;

 $("heading").innerHTML="GAME OVER!";
 $("message").innerHTML=
 "⭐ Score: "+score+
 "<br>Best: "+best;

 $("start").textContent="PLAY AGAIN";
 $("menu").style.display="flex";
}

function loop(){

 if(!running)return;

 frame++;
 score++;

 // Level increases every 10 seconds
 level=1+Math.floor(score/600);

 $("score").textContent=score;
 $("level").textContent=level;

 // Move player
 player.x=Math.max(
 17,
 Math.min(383,player.x+direction*5)
 );

 // Increasing spawn rate
 // Starts at 60 frames, gradually drops to 8
 let spawnRate=Math.max(
 8,
 60-Math.floor(level*5)
 );

 // Additional spawn chance as score increases
 if(frame%spawnRate===0){

  // More objects per spawn at higher levels
  let amount=Math.min(
   1+Math.floor(level/3),
   8
  );

  for(let n=0;n<amount;n++){

   reds.push({
    x:20+Math.random()*360,
    y:-20-Math.random()*100,
    r:12+Math.random()*12,

    // Faster falling at higher levels
    v:3+Math.random()*2+level*0.8
   });
  }
 }

 // Move red objects and check collisions
 for(let i=reds.length-1;i>=0;i--){

  let o=reds[i];

  // Gradually accelerate falling objects
  o.y+=o.v;

  if(o.y>570){
   reds.splice(i,1);
   continue;
  }

  if(Math.hypot(
   player.x-o.x,
   player.y-o.y
  )<player.r+o.r-3){

   gameOver();
   return;
  }
 }

 // Draw background
 ctx.fillStyle="#12122c";
 ctx.fillRect(0,0,400,550);

 // Grid
 ctx.strokeStyle="#282852";

 for(let x=0;x<400;x+=40){
  ctx.beginPath();
  ctx.moveTo(x,0);
  ctx.lineTo(x,550);
  ctx.stroke();
 }

 // Draw red objects
 reds.forEach(o=>{

  ctx.shadowColor="#ff174f";
  ctx.shadowBlur=20;
  ctx.fillStyle="#ff174f";

  ctx.beginPath();
  ctx.arc(o.x,o.y,o.r,0,Math.PI*2);
  ctx.fill();

 });

 // Draw player
 ctx.shadowColor="#00eaff";
 ctx.shadowBlur=25;
 ctx.fillStyle="#65f5ff";

 ctx.beginPath();
 ctx.arc(
  player.x,
  player.y,
  player.r,
  0,
  Math.PI*2
 );
 ctx.fill();

 ctx.shadowBlur=0;

 // Player eyes
 ctx.fillStyle="#111";

 ctx.beginPath();

 ctx.arc(
  player.x-5,
  player.y-3,
  2.5,
  0,
  Math.PI*2
 );

 ctx.arc(
  player.x+5,
  player.y-3,
  2.5,
  0,
  Math.PI*2
 );

 ctx.fill();

 raf=requestAnimationFrame(loop);
}

// Mobile controls
function bind(id,dir){

 const button=$(id);

 button.addEventListener("pointerdown",e=>{
  e.preventDefault();
  direction=dir;
 });

 button.addEventListener("pointerup",()=>{
  if(direction===dir)direction=0;
 });

 button.addEventListener("pointercancel",()=>{
  if(direction===dir)direction=0;
 });

 button.addEventListener("pointerleave",()=>{
  if(direction===dir)direction=0;
 });
}

bind("left",-1);
bind("right",1);

// Keyboard controls
document.addEventListener("keydown",e=>{

 if(e.key==="ArrowLeft"||e.key==="a")
  direction=-1;

 if(e.key==="ArrowRight"||e.key==="d")
  direction=1;

});

document.addEventListener("keyup",e=>{

 if(["ArrowLeft","ArrowRight","a","d"].includes(e.key))
  direction=0;

});

// Start button
$("start").addEventListener("click",startGame);

$("start").addEventListener("touchend",e=>{
 e.preventDefault();
 startGame();
},{passive:false});

// Initial canvas
ctx.fillStyle="#12122c";
ctx.fillRect(0,0,400,550);

})();
</script>

</body>
</html>

Game Source: DON'T TOUCH THE RED

Creator: BoldPenguin14

Libraries: none

Complexity: complex (358 lines, 5.5 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: don-t-touch-the-red-boldpenguin14" to link back to the original. Then publish at arcadelab.ai/publish.