CHAOS BOIDS: ABSOLUTE MAYHEM
by EpicViper20683 lines10.0 KB
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>CHAOS BOIDS</title><style>
*{box-sizing:border-box}
html,body{
margin:0;
width:100%;
height:100%;
overflow:hidden;
background:#000;
color:white;
font-family:Arial,sans-serif;
touch-action:none;
}
#c{
position:fixed;
inset:0;
width:100%;
height:100%;
}
#hud{
position:fixed;
top:12px;
left:12px;
right:12px;
display:flex;
justify-content:space-between;
align-items:flex-start;
pointer-events:none;
z-index:5;
}
.box{
background:rgba(0,0,0,.65);
border:2px solid #fff;
border-radius:14px;
padding:10px 14px;
box-shadow:0 0 20px #fff;
backdrop-filter:blur(8px);
}
#title{
font-size:22px;
font-weight:1000;
letter-spacing:2px;
text-shadow:3px 3px 0 #ff00ff;
}
#score{
font-size:18px;
font-weight:bold;
}
#event{
position:fixed;
top:50%;
left:50%;
transform:translate(-50%,-50%) scale(0);
font-size:clamp(30px,9vw,90px);
font-weight:1000;
text-align:center;
z-index:10;
pointer-events:none;
text-shadow:
5px 5px 0 #ff00ff,
-5px -5px 0 #00ffff;
}
#controls{
position:fixed;
bottom:12px;
left:50%;
transform:translateX(-50%);
width:min(500px,calc(100% - 24px));
z-index:6;
display:flex;
gap:8px;
flex-wrap:wrap;
justify-content:center;
}
button{
flex:1;
min-width:110px;
padding:13px;
border:2px solid white;
border-radius:12px;
background:#111;
color:white;
font-weight:1000;
font-size:14px;
cursor:pointer;
box-shadow:0 0 12px #00ffff;
}
button:active{
transform:scale(.9) rotate(-2deg);
}
#nuke{
background:#ff0055;
box-shadow:0 0 25px #ff0055;
}
#warning{
position:fixed;
bottom:85px;
left:50%;
transform:translateX(-50%);
font-size:12px;
opacity:.7;
pointer-events:none;
text-align:center;
}
</style></head><body><canvas id="c"></canvas>
<div id="hud">
<div class="box">
<div id="title">🐦 CHAOS BOIDS</div>
<div id="mode">NORMAL REALITY</div>
</div> <div class="box">
<div id="score">SCORE: 0</div>
<div id="combo">COMBO: x1</div>
</div>
</div><div id="event"></div><div id="warning">
TAP / DRAG THE SCREEN TO CAUSE ABSOLUTE CHAOS
</div><div id="controls">
<button onclick="spawnMore()">🐦 MORE BIRDS</button>
<button onclick="randomize()">🎲 RANDOMIZE</button>
<button id="nuke" onclick="NUKE()">☢️ NUCLEAR CHAOS</button>
</div><script>
"use strict";
const canvas=document.getElementById("c");
const ctx=canvas.getContext("2d");
let W=innerWidth;
let H=innerHeight;
let dpr=Math.min(devicePixelRatio||1,2);
function resize(){
W=innerWidth;
H=innerHeight;
canvas.width=W*dpr;
canvas.height=H*dpr;
canvas.style.width=W+"px";
canvas.style.height=H+"px";
ctx.setTransform(dpr,0,0,dpr,0,0);
}
addEventListener("resize",resize);
resize();
let birds=[];
let particles=[];
let shockwaves=[];
let score=0;
let combo=1;
let chaos=1;
let mouse={
x:W/2,
y:H/2,
active:false
};
let gravity={
x:0,
y:0
};
let rainbow=0;
let screenShake=0;
const NAMES=[
"Greg",
"Bob",
"The Bird",
"Mr. Banana",
"Kevin",
"WHY",
"Bird.exe",
"Unknown Object"
];
function rand(a,b){
return a+Math.random()*(b-a);
}
function createBird(x=rand(0,W),y=rand(0,H)){
let a=rand(0,Math.PI*2);
let speed=rand(1,4);
birds.push({
x,
y,
vx:Math.cos(a)*speed,
vy:Math.sin(a)*speed,
size:rand(4,9),
hue:rand(0,360),
name:NAMES[Math.floor(Math.random()*NAMES.length)],
angry:Math.random()<.08
});
}
for(let i=0;i<160;i++) createBird();
function particle(x,y){
let a=rand(0,Math.PI*2);
let s=rand(2,12);
particles.push({
x,y,
vx:Math.cos(a)*s,
vy:Math.sin(a)*s,
life:1,
size:rand(2,8),
hue:rand(0,360)
});
}
function explosion(x,y,count=40){
for(let i=0;i<count;i++){
particle(x,y);
}
shockwaves.push({
x,y,
r:5,
life:1
});
screenShake=Math.max(screenShake,15);
}
function scatter(){
if(!mouse.active)return;
for(const b of birds){
let dx=b.x-mouse.x;
let dy=b.y-mouse.y;
let d=Math.sqrt(dx*dx+dy*dy)||1;
if(d<180){
let force=(1-d/180)*3;
b.vx+=dx/d*force;
b.vy+=dy/d*force;
b.angry=true;
}
}
explosion(mouse.x,mouse.y,4);
score+=Math.floor(combo);
combo+=.01;
}
function updateBirds(){
for(const b of birds){
let ax=0;
let ay=0;
let neighbours=0;
for(const o of birds){
if(b===o)continue;
let dx=o.x-b.x;
let dy=o.y-b.y;
let d=Math.sqrt(dx*dx+dy*dy);
if(d<70){
neighbours++;
// SEPARATION
if(d<28){
ax-=dx/(d||1)*.13*chaos;
ay-=dy/(d||1)*.13*chaos;
}
// ALIGNMENT
ax+=(o.vx-b.vx)*.008;
ay+=(o.vy-b.vy)*.008;
// COHESION
ax+=dx*.0005;
ay+=dy*.0005;
}
}
// RANDOM CHAOS
ax+=rand(-.025,.025)*chaos;
ay+=rand(-.025,.025)*chaos;
// GRAVITY
ax+=gravity.x;
ay+=gravity.y;
// MOUSE
if(mouse.active){
let dx=b.x-mouse.x;
let dy=b.y-mouse.y;
let d=Math.sqrt(dx*dx+dy*dy)||1;
if(d<250){
ax+=dx/d*(250-d)/400;
ay+=dy/d*(250-d)/400;
}
}
b.vx+=ax;
b.vy+=ay;
let maxSpeed=4+chaos*1.8;
let speed=Math.sqrt(b.vx*b.vx+b.vy*b.vy);
if(speed>maxSpeed){
b.vx=b.vx/speed*maxSpeed;
b.vy=b.vy/speed*maxSpeed;
}
b.x+=b.vx;
b.y+=b.vy;
// TELEPORT EDGES
if(b.x<-30)b.x=W+30;
if(b.x>W+30)b.x=-30;
if(b.y<-30)b.y=H+30;
if(b.y>H+30)b.y=-30;
b.hue+=chaos*.7;
if(b.angry && Math.random()<.003){
b.angry=false;
}
}
}
function drawBird(b){
let angle=Math.atan2(b.vy,b.vx);
ctx.save();
ctx.translate(b.x,b.y);
ctx.rotate(angle);
let color=
b.angry
? `hsl(${rainbow},100%,60%)`
: `hsl(${b.hue},100%,65%)`;
ctx.shadowBlur=18;
ctx.shadowColor=color;
ctx.fillStyle=color;
ctx.beginPath();
ctx.moveTo(b.size*2.2,0);
ctx.lineTo(-b.size,-b.size);
ctx.lineTo(-b.size*.3,0);
ctx.lineTo(-b.size,b.size);
ctx.closePath();
ctx.fill();
ctx.restore();
}
function draw(){
ctx.save();
if(screenShake>0){
ctx.translate(
rand(-screenShake,screenShake),
rand(-screenShake,screenShake)
);
screenShake*=.86;
}
// CRAZY BACKGROUND
rainbow+=1;
let grad=ctx.createRadialGradient(
W/2,H/2,0,
W/2,H/2,Math.max(W,H)
);
grad.addColorStop(
0,
`hsl(${rainbow%360},70%,12%)`
);
grad.addColorStop(
1,
"#000"
);
ctx.fillStyle=grad;
ctx.fillRect(-20,-20,W+40,H+40);
// GRID
ctx.globalAlpha=.12;
ctx.strokeStyle=`hsl(${(rainbow+180)%360},100%,60%)`;
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();
}
ctx.globalAlpha=1;
for(const b of birds){
drawBird(b);
}
// PARTICLES
for(const p of particles){
ctx.fillStyle=`hsl(${p.hue},100%,60%)`;
ctx.shadowBlur=12;
ctx.shadowColor=ctx.fillStyle;
ctx.beginPath();
ctx.arc(p.x,p.y,p.size,0,Math.PI*2);
ctx.fill();
p.x+=p.vx;
p.y+=p.vy;
p.vx*=.97;
p.vy*=.97;
p.life-=.025;
}
particles=particles.filter(p=>p.life>0);
// SHOCKWAVES
for(const s of shockwaves){
ctx.beginPath();
ctx.arc(
s.x,
s.y,
s.r,
0,
Math.PI*2
);
ctx.strokeStyle=
`hsla(${rainbow},100%,60%,${s.life})`;
ctx.lineWidth=5;
ctx.stroke();
s.r+=15;
s.life-=.025;
}
shockwaves=shockwaves.filter(s=>s.life>0);
ctx.restore();
}
function loop(){
updateBirds();
scatter();
draw();
document.getElementById("score").textContent=
"SCORE: "+Math.floor(score);
document.getElementById("combo").textContent=
"COMBO: x"+combo.toFixed(1);
requestAnimationFrame(loop);
}
function showEvent(text){
const e=document.getElementById("event");
e.textContent=text;
e.animate(
[
{transform:"translate(-50%,-50%) scale(0) rotate(-20deg)"},
{transform:"translate(-50%,-50%) scale(1.2) rotate(5deg)"},
{transform:"translate(-50%,-50%) scale(1) rotate(0deg)"}
],
{
duration:500,
easing:"cubic-bezier(.2,1.5,.4,1)"
}
);
}
function spawnMore(){
for(let i=0;i<30;i++){
createBird(rand(0,W),rand(0,H));
}
chaos+=.15;
explosion(W/2,H/2,30);
showEvent("MORE BIRDS");
}
function randomize(){
for(const b of birds){
b.vx*=rand(-2,2);
b.vy*=rand(-2,2);
b.hue=rand(0,360);
b.size=rand(3,15);
}
gravity.x=rand(-.03,.03);
gravity.y=rand(-.03,.03);
chaos=rand(.5,4);
explosion(
rand(0,W),
rand(0,H),
60
);
showEvent("REALITY.EXE");
}
function NUKE(){
showEvent("☢️ NUCLEAR CHAOS ☢️");
chaos=8;
screenShake=40;
for(let i=0;i<12;i++){
setTimeout(()=>{
let x=rand(0,W);
let y=rand(0,H);
explosion(x,y,80);
for(const b of birds){
let dx=b.x-x;
let dy=b.y-y;
let d=Math.sqrt(dx*dx+dy*dy)||1;
b.vx+=dx/d*rand(1,5);
b.vy+=dy/d*rand(1,5);
}
},i*100);
}
score+=1000;
combo+=5;
}
function pointer(x,y){
mouse.x=x;
mouse.y=y;
mouse.active=true;
}
canvas.addEventListener("pointerdown",e=>{
pointer(e.clientX,e.clientY);
});
canvas.addEventListener("pointermove",e=>{
if(e.buttons)pointer(e.clientX,e.clientY);
});
canvas.addEventListener("pointerup",()=>{
mouse.active=false;
});
canvas.addEventListener("pointercancel",()=>{
mouse.active=false;
});
// RANDOM EVENTS
setInterval(()=>{
let r=Math.random();
if(r<.25){
gravity.x=rand(-.08,.08);
gravity.y=rand(-.08,.08);
showEvent("GRAVITY BROKE");
}else if(r<.5){
chaos=rand(1,5);
showEvent("CHAOS +"+chaos.toFixed(1));
}else if(r<.7){
for(let i=0;i<10;i++)
createBird();
showEvent("BIRD INFLATION");
}else{
explosion(
rand(0,W),
rand(0,H),
25
);
}
},7000);
loop();
</script></body>
</html>Game Source: CHAOS BOIDS: ABSOLUTE MAYHEM
Creator: EpicViper20
Libraries: none
Complexity: complex (683 lines, 10.0 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: chaos-boids-absolute-mayhem-epicviper20" to link back to the original. Then publish at arcadelab.ai/publish.