GEOMETRY RUSH
by BoldPenguin14485 lines7.6 KB
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>GEOMETRY RUSH</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;
overflow:hidden;
}
#game{
width:min(95vw,440px);
background:#11112b;
border:2px solid #744cff;
border-radius:18px;
overflow:hidden;
box-shadow:0 0 35px #623cff55;
}
header{
display:flex;
justify-content:space-around;
padding:16px 5px;
color:#65f5ff;
font-weight:bold;
}
canvas{
width:100%;
display:block;
background:#10102b;
touch-action:none;
}
#controls{
padding:13px;
display:flex;
justify-content:center;
}
button{
border:0;
border-radius:30px;
padding:16px 55px;
background:linear-gradient(90deg,#00d9ff,#9745ff);
color:white;
font-size:19px;
font-weight:bold;
cursor:pointer;
touch-action:none;
}
#menu{
position:fixed;
inset:0;
background:#080817ee;
display:flex;
justify-content:center;
align-items:center;
flex-direction:column;
text-align:center;
z-index:5;
padding:20px;
}
h1{
color:#65f5ff;
font-size:39px;
text-shadow:0 0 20px cyan;
}
#menu p{color:#ccc;line-height:1.6}
#menu button{padding:18px 45px}
</style>
</head>
<body>
<div id="game">
<header>
<div>SCORE<br><span id="score">0</span></div>
<div>BEST<br><span id="best">0</span></div>
<div>LEVEL<br><span id="level">1</span></div>
</header>
<canvas id="c" width="400" height="500"></canvas>
<div id="controls">
<button id="jump">JUMP! ▲</button>
</div>
</div>
<div id="menu">
<h1 id="heading">GEOMETRY<br>RUSH!</h1>
<p id="message">
Jump over spikes.<br>
Don't crash!<br><br>
Tap or press SPACE to jump.
</p>
<button id="start">PLAY NOW</button>
</div>
<script>
(()=>{
const canvas=document.getElementById("c");
const ctx=canvas.getContext("2d");
const $=id=>document.getElementById(id);
const W=400,H=500,ground=410;
let player,obstacles,coins;
let score=0,best=0,level=1;
let speed=5,frame=0;
let running=false,raf=0;
let particles=[];
try{
best=Number(localStorage.getItem("geometryBest"))||0;
}catch(e){}
$("best").textContent=best;
function startGame(){
cancelAnimationFrame(raf);
player={
x:75,
y:ground-30,
size:30,
vy:0,
grounded:true,
rotation:0
};
obstacles=[];
coins=[];
particles=[];
score=0;
level=1;
speed=5;
frame=0;
running=true;
$("menu").style.display="none";
$("score").textContent=0;
$("level").textContent=1;
loop();
}
function jump(){
if(!running)return;
if(player.grounded){
player.vy=-12.5;
player.grounded=false;
burst(player.x+15,player.y+25,"#65f5ff",7);
}
}
function burst(x,y,color,count){
for(let i=0;i<count;i++){
particles.push({
x,y,
vx:(Math.random()-.5)*6,
vy:(Math.random()-.5)*6,
life:25,
color
});
}
}
function gameOver(){
running=false;
cancelAnimationFrame(raf);
best=Math.max(best,score);
try{
localStorage.setItem("geometryBest",best);
}catch(e){}
$("best").textContent=best;
$("heading").innerHTML="YOU CRASHED!";
$("message").innerHTML=
"⭐ Score: "+score+
"<br>🏆 Best: "+best+
"<br>Level reached: "+level;
$("start").textContent="TRY AGAIN";
$("menu").style.display="flex";
}
function spawnObstacle(){
const type=Math.random();
if(type<.75){
obstacles.push({
x:420,
y:ground,
w:30+Math.random()*12,
h:35+Math.random()*15,
type:"spike"
});
}else{
obstacles.push({
x:420,
y:ground-35,
w:35,
h:35,
type:"block"
});
}
}
function drawBackground(){
ctx.fillStyle="#10102b";
ctx.fillRect(0,0,W,H);
// Background grid
ctx.strokeStyle="#25254b";
ctx.lineWidth=1;
for(let x=0;x<W;x+=40){
ctx.beginPath();
ctx.moveTo(x,0);
ctx.lineTo(x,H);
ctx.stroke();
}
for(let y=0;y<H;y+=40){
ctx.beginPath();
ctx.moveTo(0,y);
ctx.lineTo(W,y);
ctx.stroke();
}
// Moving background decoration
ctx.fillStyle="#29245c";
for(let i=0;i<8;i++){
let x=(i*90-frame*0.5)%480;
if(x<0)x+=480;
ctx.fillRect(x,300,3,70);
}
// Ground
ctx.fillStyle="#27245b";
ctx.fillRect(0,ground,W,H-ground);
ctx.fillStyle="#65f5ff";
ctx.fillRect(0,ground,W,3);
}
function drawPlayer(){
ctx.save();
ctx.translate(
player.x+15,
player.y+15
);
ctx.rotate(player.rotation);
ctx.shadowColor="#00eaff";
ctx.shadowBlur=20;
ctx.fillStyle="#65f5ff";
ctx.fillRect(-15,-15,30,30);
ctx.shadowBlur=0;
ctx.fillStyle="#171735";
ctx.fillRect(-9,-7,5,7);
ctx.fillRect(4,-7,5,7);
ctx.restore();
}
function loop(){
if(!running)return;
frame++;
score++;
level=1+Math.floor(score/500);
speed=5+level*.65;
$("score").textContent=score;
$("level").textContent=level;
// Gravity and jumping
player.vy+=.65;
player.y+=player.vy;
if(player.y>=ground-player.size){
player.y=ground-player.size;
player.vy=0;
player.grounded=true;
}
if(!player.grounded){
player.rotation+=.09;
}else{
player.rotation=Math.round(player.rotation/(Math.PI/2))*(Math.PI/2);
}
// Spawn obstacles
let spawnRate=Math.max(35,90-level*4);
if(frame%spawnRate===0){
spawnObstacle();
}
// Spawn coins
if(frame%110===0){
coins.push({
x:430,
y:ground-90-Math.random()*70,
r:9
});
}
// Move obstacles
for(let i=obstacles.length-1;i>=0;i--){
let o=obstacles[i];
o.x-=speed;
// Collision detection
let px=player.x+5;
let py=player.y+5;
let pw=player.size-10;
let ph=player.size-10;
if(o.type==="block"){
if(px<o.x+o.w &&
px+pw>o.x &&
py<o.y+o.h &&
py+ph>o.y){
gameOver();
return;
}
}else{
// Spike collision
let hitX=px+pw>o.x+5 && px<o.x+o.w-5;
let hitY=py+ph>ground-o.h+12;
if(hitX && hitY){
gameOver();
return;
}
}
if(o.x+o.w<0){
obstacles.splice(i,1);
}
}
// Move coins
for(let i=coins.length-1;i>=0;i--){
let c=coins[i];
c.x-=speed;
let distance=Math.hypot(
player.x+15-c.x,
player.y+15-c.y
);
if(distance<25){
score+=50;
burst(c.x,c.y,"#ffe45c",12);
coins.splice(i,1);
continue;
}
if(c.x<0)coins.splice(i,1);
}
// Particles
for(let i=particles.length-1;i>=0;i--){
let p=particles[i];
p.x+=p.vx;
p.y+=p.vy;
p.life--;
if(p.life<=0)particles.splice(i,1);
}
drawBackground();
// Obstacles
obstacles.forEach(o=>{
if(o.type==="spike"){
ctx.shadowColor="#ff2255";
ctx.shadowBlur=18;
ctx.fillStyle="#ff285c";
ctx.beginPath();
ctx.moveTo(o.x,ground);
ctx.lineTo(o.x+o.w/2,ground-o.h);
ctx.lineTo(o.x+o.w,ground);
ctx.closePath();
ctx.fill();
}else{
ctx.shadowColor="#ff2255";
ctx.shadowBlur=18;
ctx.fillStyle="#ff285c";
ctx.fillRect(o.x,o.y,o.w,o.h);
}
});
ctx.shadowBlur=0;
// Coins
coins.forEach(c=>{
ctx.shadowColor="#ffe45c";
ctx.shadowBlur=20;
ctx.fillStyle="#ffe45c";
ctx.beginPath();
ctx.arc(c.x,c.y,c.r,0,Math.PI*2);
ctx.fill();
ctx.shadowBlur=0;
});
// Player
drawPlayer();
// Particles
particles.forEach(p=>{
ctx.globalAlpha=Math.max(0,p.life/25);
ctx.fillStyle=p.color;
ctx.fillRect(p.x,p.y,5,5);
});
ctx.globalAlpha=1;
// Speed indicator
ctx.fillStyle="#65f5ff";
ctx.font="bold 13px Arial";
ctx.fillText("SPEED x"+(speed/5).toFixed(1),15,25);
raf=requestAnimationFrame(loop);
}
// Controls
$("jump").addEventListener("pointerdown",e=>{
e.preventDefault();
jump();
});
canvas.addEventListener("pointerdown",e=>{
e.preventDefault();
jump();
});
document.addEventListener("keydown",e=>{
if(["Space","ArrowUp","KeyW"].includes(e.code)){
e.preventDefault();
jump();
}
});
$("start").addEventListener("click",startGame);
$("menu").addEventListener("click",e=>{
if(e.target===$("menu") && !running)startGame();
});
drawBackground();
})();
</script>
</body>
</html>
Game Source: GEOMETRY RUSH
Creator: BoldPenguin14
Libraries: none
Complexity: complex (485 lines, 7.6 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: geometry-rush-boldpenguin14" to link back to the original. Then publish at arcadelab.ai/publish.