Jungle Battle Ground
by WildDragon12746 lines20.7 KB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Jungle Battle Ground</title>
<style>
*{box-sizing:border-box}
html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#07120d;color:white;font-family:Arial,sans-serif;touch-action:none}
#gameWrap{position:fixed;inset:0;width:100%;height:100%;height:100dvh;background:#07120d}
canvas{display:block;width:100%;height:100%;object-fit:fill}
#hud{position:absolute;top:8px;left:8px;right:8px;display:flex;justify-content:space-between;gap:5px;flex-wrap:wrap;pointer-events:none}
.stat{background:#07140ee8;border:1px solid #7bdb8a;padding:7px 10px;border-radius:9px;font-weight:bold;font-size:clamp(11px,2vw,15px)}
button{border:2px solid #c9ffb3;border-radius:10px;background:#207d35;color:white;font-size:15px;font-weight:bold;padding:11px 15px;cursor:pointer;touch-action:manipulation}
#pauseBtn,#fullBtn{position:absolute;right:9px;padding:8px 10px;font-size:13px}
#pauseBtn{top:53px}
#fullBtn{top:96px}
#menu{position:absolute;inset:0;background:#020b08dd;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:20px;overflow:auto}
#menu h1{font-size:clamp(25px,5vw,45px);margin:5px;color:#b8ff8b;text-shadow:0 0 15px #44ff52}
#menu p{max-width:550px;line-height:1.5}
#nextBtn,#restartBtn{display:none}
#message{position:absolute;top:20%;width:100%;text-align:center;font-size:clamp(20px,5vw,38px);font-weight:bold;text-shadow:0 2px 7px black;pointer-events:none}
#controls{position:absolute;bottom:max(8px,env(safe-area-inset-bottom));left:0;right:0;display:flex;justify-content:space-between;align-items:end;padding:0 12px;pointer-events:none}
.group{display:flex;gap:7px;pointer-events:auto}
.ctrl{width:clamp(45px,9vw,65px);height:clamp(45px,9vw,65px);padding:0;border-radius:50%;background:#142a22df;border:2px solid #b6ffae;color:white;font-size:22px;user-select:none;-webkit-user-select:none}
@media(orientation:portrait){
#controls{padding:0 8px}
.ctrl{width:48px;height:48px}
}
</style>
</head>
<body>
<div id="gameWrap">
<canvas id="game"></canvas>
<div id="hud">
<div class="stat" id="levelText">LEVEL 1</div>
<div class="stat" id="scoreText">SCORE: 0</div>
<div class="stat" id="coinText">COINS: 0</div>
<div class="stat" id="hpText">HP: ♥♥♥</div>
</div>
<button id="pauseBtn">Ⅱ PAUSE</button>
<button id="fullBtn">⛶ FULL</button>
<div id="message"></div>
<div id="controls">
<div class="group">
<button class="ctrl" data-key="left">◀</button>
<button class="ctrl" data-key="right">▶</button>
<button class="ctrl" data-key="down">▼</button>
</div>
<div class="group">
<button class="ctrl" data-key="attack">⚔</button>
<button class="ctrl" data-key="jump">⬆</button>
</div>
</div>
<div id="menu">
<h1 id="menuTitle">🌴 JUNGLE BATTLE GROUND</h1>
<p id="menuText">Jump, fight enemies and collect coins.<br>
Level 3: Deep water 🌊<br>
Level 6: Dangerous lava 🔥<br>
Every new level gets harder!</p>
<button id="startBtn">START GAME</button>
<button id="nextBtn">NEXT LEVEL ➜</button>
<button id="restartBtn">PLAY AGAIN</button>
</div>
</div>
<script>
const canvas=document.getElementById("game");
const ctx=canvas.getContext("2d");
const W=960,H=540;
let dpr=1;
function resizeCanvas(){
dpr=Math.min(window.devicePixelRatio||1,2);
canvas.width=Math.round(W*dpr);
canvas.height=Math.round(H*dpr);
ctx.setTransform(dpr,0,0,dpr,0,0);
}
window.addEventListener("resize",resizeCanvas);
resizeCanvas();
const $=id=>document.getElementById(id);
const menu=$("menu"),message=$("message");
const keys={left:false,right:false,down:false,jump:false,attack:false};
let level=1,score=0,coins=0,hp=3;
let running=false,paused=false,gameOver=false,won=false;
let camera=0,worldWidth=3000,frame=0;
let platforms=[],pits=[],coinItems=[],enemies=[],particles=[];
let invulnerable=0,lastJump=false,lastAttack=false;
let finishLock=false;
const player={x:60,y:300,w:32,h:48,vx:0,vy:0,onGround:false,face:1,attackTime:0};
function hazardType(){
if(level>=6)return "lava";
if(level>=3)return "water";
return "pit";
}
function makeLevel(){
worldWidth=2800+level*260;
platforms=[];
pits=[];
coinItems=[];
enemies=[];
particles=[];
camera=0;
finishLock=false;
const groundY=440;
const type=hazardType();
// Generate a continuous route of safe ground, pits and bridges.
let x=0;
let index=0;
const finalSafeStart=worldWidth-500;
while(x<finalSafeStart){
const safeLength=Math.max(205,275-Math.min(level*3,45)+Math.random()*45);
const actualSafeLength=Math.min(safeLength,finalSafeStart-x);
if(actualSafeLength>0){
platforms.push({
x:x,y:groundY,w:actualSafeLength,h:100,floating:false
});
}
x+=actualSafeLength;
if(x>=finalSafeStart)break;
// Keep hazards moderate enough to jump across.
const pitW=Math.min(75+level*4+Math.random()*18,125);
pits.push({
x:x,y:groundY,w:pitW,type:type,phase:Math.random()*6
});
x+=pitW;
// Guaranteed bridge across each hazard.
// The bridge is wide and high enough for the player to land on.
platforms.push({
x:x-pitW+8,
y:groundY-72,
w:pitW+62,
h:16,
floating:true
});
// Extra stepping stone on harder levels.
if(level>=4){
platforms.push({
x:x-pitW+pitW*.25,
y:groundY-125,
w:55,
h:14,
floating:true
});
}
// A short safe strip immediately after every pit.
const landingLength=85;
platforms.push({
x:x+5,y:groundY,w:landingLength,h:100,floating:false
});
x+=landingLength;
index++;
}
// Wide, continuous final safe ground after the last hazard.
platforms.push({
x:finalSafeStart,
y:groundY,
w:worldWidth-finalSafeStart+200,
h:100,
floating:false
});
// Sort ground and floating platforms by x.
platforms.sort((a,b)=>a.x-b.x);
// Coins placed above the route.
for(let cx=145;cx<worldWidth-140;cx+=105+Math.random()*25){
coinItems.push({
x:cx,
y:330+Math.random()*55,
r:10,
taken:false
});
}
// Enemies increase with level but stay on the safe route.
const enemyCount=Math.min(3+level*2,24);
for(let i=0;i<enemyCount;i++){
const ex=350+i*((worldWidth-750)/Math.max(1,enemyCount));
enemies.push({
x:ex,y:390,w:30,h:40,
vx:(Math.random()<.5?-1:1)*(1+level*.12),
minX:Math.max(10,ex-45),
maxX:Math.min(worldWidth-100,ex+45),
alive:true
});
}
player.x=60;
player.y=groundY-player.h;
player.vx=0;
player.vy=0;
player.onGround=true;
player.h=48;
player.attackTime=0;
invulnerable=70;
lastJump=false;
lastAttack=false;
updateHud();
}
function updateHud(){
$("levelText").textContent="LEVEL "+level;
$("scoreText").textContent="SCORE: "+score;
$("coinText").textContent="COINS: "+coins;
$("hpText").textContent="HP: "+("♥".repeat(Math.max(0,hp)))+("♡".repeat(Math.max(0,3-hp)));
}
function showMenu(title,text,buttons){
$("menuTitle").textContent=title;
$("menuText").innerHTML=text;
menu.style.display="flex";
$("startBtn").style.display=buttons.start?"inline-block":"none";
$("nextBtn").style.display=buttons.next?"inline-block":"none";
$("restartBtn").style.display=buttons.restart?"inline-block":"none";
}
function startGame(){
level=1;score=0;coins=0;hp=3;
gameOver=false;won=false;paused=false;
makeLevel();
running=true;
menu.style.display="none";
message.textContent="";
}
function nextLevel(){
if(!won)return;
level++;
won=false;
paused=false;
makeLevel();
running=true;
menu.style.display="none";
message.textContent="LEVEL "+level;
setTimeout(()=>{
if(running&&!paused)message.textContent="";
},1200);
}
function finishLevel(){
if(finishLock||!running)return;
finishLock=true;
running=false;
won=true;
message.textContent="";
showMenu(
"🏆 LEVEL "+level+" COMPLETE!",
"Shabash! Level "+level+" complete ho gaya.<br>Kya aap Level "+(level+1)+" khelna chahte hain?<br>Agla level aur mushkil hoga!",
{start:false,next:true,restart:false}
);
$("nextBtn").textContent="YES — NEXT LEVEL ➜";
}
function endGame(){
running=false;
gameOver=true;
won=false;
showMenu(
"💀 GAME OVER",
"Aap Level "+level+" tak pohnche!<br>Score: "+score+" | Coins: "+coins,
{start:false,next:false,restart:true}
);
}
$("startBtn").onclick=startGame;
$("restartBtn").onclick=startGame;
$("nextBtn").onclick=nextLevel;
$("pauseBtn").onclick=()=>{
if(!running)return;
paused=!paused;
message.textContent=paused?"PAUSED":"";
$("pauseBtn").textContent=paused?"▶ RESUME":"Ⅱ PAUSE";
};
$("fullBtn").onclick=async()=>{
const el=$("gameWrap");
try{
if(!document.fullscreenElement){
if(el.requestFullscreen)await el.requestFullscreen();
}else{
await document.exitFullscreen();
}
}catch(e){
message.textContent="Use browser menu for full screen";
setTimeout(()=>message.textContent="",1800);
}
};
document.addEventListener("keydown",e=>{
if(["ArrowLeft","ArrowRight","ArrowUp","ArrowDown"," "].includes(e.key))e.preventDefault();
if(e.key==="ArrowLeft"||e.key.toLowerCase()==="a")keys.left=true;
if(e.key==="ArrowRight"||e.key.toLowerCase()==="d")keys.right=true;
if(e.key==="ArrowDown"||e.key.toLowerCase()==="s")keys.down=true;
if(e.key==="ArrowUp"||e.key===" ")keys.jump=true;
if(e.key.toLowerCase()==="j")keys.attack=true;
});
document.addEventListener("keyup",e=>{
if(e.key==="ArrowLeft"||e.key.toLowerCase()==="a")keys.left=false;
if(e.key==="ArrowRight"||e.key.toLowerCase()==="d")keys.right=false;
if(e.key==="ArrowDown"||e.key.toLowerCase()==="s")keys.down=false;
if(e.key==="ArrowUp"||e.key===" ")keys.jump=false;
if(e.key.toLowerCase()==="j")keys.attack=false;
});
document.querySelectorAll(".ctrl").forEach(btn=>{
const k=btn.dataset.key;
const press=e=>{e.preventDefault();keys[k]=true};
const release=e=>{e.preventDefault();keys[k]=false};
btn.addEventListener("pointerdown",press);
btn.addEventListener("pointerup",release);
btn.addEventListener("pointercancel",release);
btn.addEventListener("lostpointercapture",release);
btn.addEventListener("contextmenu",e=>e.preventDefault());
});
function overlaps(a,b){
return a.x<b.x+b.w&&a.x+a.w>b.x&&a.y<b.y+b.h&&a.y+a.h>b.y;
}
function addParticles(x,y,color,n=8){
for(let i=0;i<n;i++){
particles.push({
x,y,vx:(Math.random()-.5)*5,
vy:(Math.random()-.8)*5,
life:25+Math.random()*18,color
});
}
}
function hurt(){
if(invulnerable>0||!running)return;
hp--;
invulnerable=90;
player.vx=-player.face*2;
player.vy=-4;
updateHud();
if(hp<=0)endGame();
}
// Return true if the player has fallen into a hazard.
function checkHazards(){
const foot=player.y+player.h;
for(const pit of pits){
const horizontal=player.x+player.w>pit.x+4&&player.x<pit.x+pit.w-4;
if(horizontal&&foot>pit.y+3){
if(pit.type==="water"){
addParticles(player.x+player.w/2,pit.y,"#72eaff",10);
}else if(pit.type==="lava"){
addParticles(player.x+player.w/2,pit.y,"#ff5511",12);
}else{
addParticles(player.x+player.w/2,pit.y,"#b7a58b",7);
}
// Lose HP and return to the safe bank before the hazard.
hurt();
if(running){
player.x=Math.max(5,pit.x-player.w-12);
player.y=440-player.h;
player.vy=0;
player.vx=0;
player.onGround=true;
}
return true;
}
}
return false;
}
function update(){
if(!running||paused)return;
frame++;
const speed=3.2+Math.min(level*.12,2.4);
player.vx=0;
if(keys.left){player.vx=-speed;player.face=-1}
if(keys.right){player.vx=speed;player.face=1}
player.h=(keys.down&&player.onGround)?32:48;
if(keys.jump&&!lastJump&&player.onGround){
player.vy=-11.5;
player.onGround=false;
}
lastJump=keys.jump;
if(keys.attack&&!lastAttack){
player.attackTime=12;
const box={
x:player.face===1?player.x+player.w:player.x-35,
y:player.y+5,w:36,h:35
};
for(const en of enemies){
if(en.alive&&overlaps(box,en)){
en.alive=false;
score+=20;
addParticles(en.x,en.y,"#ffcc4d",12);
}
}
}
lastAttack=keys.attack;
if(player.attackTime>0)player.attackTime--;
const previousBottom=player.y+player.h;
player.x+=player.vx;
player.x=Math.max(0,Math.min(worldWidth-player.w,player.x));
player.vy=Math.min(player.vy+.52,13);
player.y+=player.vy;
player.onGround=false;
// Land only when crossing a platform top from above.
for(const p of platforms){
if(player.x+player.w>p.x&&player.x<p.x+p.w&&
previousBottom<=p.y+5&&player.y+player.h>=p.y&&player.vy>=0){
player.y=p.y-player.h;
player.vy=0;
player.onGround=true;
}
}
// Hazards are checked after landing physics.
if(checkHazards())return;
// Falling off the map also costs HP.
if(player.y>H+60){
hurt();
if(running){
player.x=Math.max(5,player.x-120);
player.y=440-player.h;
player.vy=0;
player.onGround=true;
}
}
for(const c of coinItems){
if(!c.taken&&Math.abs(player.x+player.w/2-c.x)<24&&
Math.abs(player.y+player.h/2-c.y)<30){
c.taken=true;
coins++;
score+=10;
addParticles(c.x,c.y,"#ffe96b",6);
}
}
for(const en of enemies){
if(!en.alive)continue;
en.x+=en.vx;
if(en.x<en.minX||en.x>en.maxX)en.vx*=-1;
if(overlaps(player,en)){
if(player.vy>1&&player.y+player.h<en.y+24){
en.alive=false;
player.vy=-7;
score+=20;
addParticles(en.x,en.y,"#ffae53",10);
}else{
hurt();
}
}
}
if(invulnerable>0)invulnerable--;
for(const p of particles){
p.x+=p.vx;p.y+=p.vy;p.vy+=.12;p.life--;
}
particles=particles.filter(p=>p.life>0);
camera=Math.max(0,Math.min(worldWidth-W,player.x-W*.34));
if(player.x+player.w>=worldWidth-90)finishLevel();
updateHud();
}
function drawBackground(){
let g=ctx.createLinearGradient(0,0,0,H);
g.addColorStop(0,"#092d4a");
g.addColorStop(.5,"#167b78");
g.addColorStop(1,"#a3c66b");
ctx.fillStyle=g;ctx.fillRect(0,0,W,H);
let sun=ctx.createRadialGradient(760,95,5,760,95,125);
sun.addColorStop(0,"#fff8bb");
sun.addColorStop(.35,"#ffdc7c88");
sun.addColorStop(1,"#ffdf7000");
ctx.fillStyle=sun;ctx.fillRect(600,0,320,240);
ctx.fillStyle="#fff3a5";
ctx.beginPath();ctx.arc(760,95,27,0,Math.PI*2);ctx.fill();
for(let layer=0;layer<3;layer++){
ctx.beginPath();ctx.moveTo(0,H);
for(let x=-20;x<=W+40;x+=40){
const y=220+layer*55+
Math.sin((x+camera*.12+layer*90)*.012)*32+
Math.sin(x*.035)*12;
ctx.lineTo(x,y);
}
ctx.lineTo(W,H);ctx.closePath();
ctx.fillStyle=["#346b65","#24564a","#183f32"][layer];
ctx.fill();
}
for(let i=0;i<24;i++){
const x=((i*97-camera*.22)%(W+120)+W+120)%(W+120)-60;
const h=90+(i*37%100);
ctx.fillStyle=i%2?"#123e2b":"#0d3325";
ctx.fillRect(x,350-h*.25,12,h);
for(let j=0;j<4;j++){
ctx.beginPath();
ctx.ellipse(x+6,350-h*.25+j*17,27-j*3,30-j*3,0,0,Math.PI*2);
ctx.fill();
}
}
}
function drawPit(p){
const x=p.x-camera;
if(x+p.w<0||x>W)return;
ctx.fillStyle="#07110e";ctx.fillRect(x,p.y,p.w,H-p.y);
if(p.type==="water"){
let water=ctx.createLinearGradient(0,p.y,0,H);
water.addColorStop(0,"#45e6ff");
water.addColorStop(.35,"#087ec3");
water.addColorStop(1,"#031b54");
ctx.fillStyle=water;ctx.fillRect(x,p.y,p.w,H-p.y);
ctx.save();
ctx.beginPath();ctx.rect(x,p.y,p.w,H-p.y);ctx.clip();
for(let i=0;i<5;i++){
ctx.beginPath();
ctx.ellipse(x+p.w/2+Math.sin(frame*.045+i)*p.w*.22,
p.y+12+i*28,p.w*.32,3,0,0,Math.PI*2);
ctx.strokeStyle="#b9fbff99";ctx.lineWidth=2;ctx.stroke();
}
ctx.restore();
ctx.fillStyle="#bafaff";ctx.fillRect(x,p.y,p.w,3);
}else if(p.type==="lava"){
let lava=ctx.createLinearGradient(0,p.y,0,H);
lava.addColorStop(0,"#ffec4a");
lava.addColorStop(.22,"#ff6a00");
lava.addColorStop(1,"#9b0800");
ctx.fillStyle=lava;ctx.fillRect(x,p.y,p.w,H-p.y);
ctx.save();
ctx.beginPath();ctx.rect(x,p.y,p.w,H-p.y);ctx.clip();
for(let i=0;i<8;i++){
const bx=x+((i*37+frame*1.5)%(p.w+20))-10;
const by=p.y+8+Math.abs(Math.sin(frame*.06+i))*40;
ctx.fillStyle=i%2?"#fff176":"#ff3c00";
ctx.beginPath();
ctx.ellipse(bx,by,4+Math.sin(frame*.1+i)*2,3,0,0,Math.PI*2);
ctx.fill();
}
ctx.restore();
ctx.fillStyle="#fff27b";ctx.fillRect(x,p.y,p.w,4);
}else{
ctx.fillStyle="#17120e";ctx.fillRect(x,p.y,p.w,H-p.y);
}
}
function drawPlatform(p){
const x=p.x-camera;
if(x+p.w<0||x>W)return;
if(p.floating){
ctx.fillStyle="#432a17";ctx.fillRect(x,p.y,p.w,p.h);
ctx.fillStyle="#76c63f";ctx.fillRect(x,p.y,p.w,5);
ctx.fillStyle="#b5e979";ctx.fillRect(x,p.y,p.w,2);
return;
}
let soil=ctx.createLinearGradient(0,p.y,0,p.y+p.h);
soil.addColorStop(0,"#76502a");
soil.addColorStop(.18,"#4b321f");
soil.addColorStop(1,"#1b2519");
ctx.fillStyle=soil;ctx.fillRect(x,p.y,p.w,p.h);
ctx.fillStyle="#58a832";ctx.fillRect(x,p.y,p.w,10);
ctx.fillStyle="#b3e96b";ctx.fillRect(x,p.y,p.w,3);
for(let i=0;i<p.w;i+=13){
ctx.fillStyle=i%2?"#397f29":"#8acb44";
ctx.beginPath();
ctx.moveTo(x+i,p.y+7);
ctx.lineTo(x+i+3,p.y-3-(i%4));
ctx.lineTo(x+i+5,p.y+7);
ctx.fill();
}
for(let i=0;i<p.w;i+=29){
ctx.fillStyle="#98734b";ctx.fillRect(x+i,p.y+22+(i%27),4,3);
ctx.fillStyle="#2b271b";ctx.fillRect(x+i+12,p.y+47+(i%20),7,3);
}
}
function drawPlayer(){
const x=player.x-camera,y=player.y;
if(invulnerable>0&&Math.floor(frame/5)%2===0)return;
ctx.save();
ctx.fillStyle="#06130b99";
ctx.beginPath();ctx.ellipse(x+16,y+player.h+3,19,5,0,0,Math.PI*2);ctx.fill();
ctx.fillStyle="#252f3c";
ctx.fillRect(x+5,y+player.h-14,9,14);
ctx.fillRect(x+19,y+player.h-14,9,14);
ctx.fillStyle="#151b23";
ctx.fillRect(x+3,y+player.h-5,12,5);
ctx.fillRect(x+18,y+player.h-5,13,5);
let body=ctx.createLinearGradient(x,y,x+player.w,y);
body.addColorStop(0,"#166b45");
body.addColorStop(.5,"#39bd6c");
body.addColorStop(1,"#125638");
ctx.fillStyle=body;ctx.fillRect(x+3,y+15,26,player.h-28);
ctx.fillStyle="#dca66f";
ctx.fillRect(x,y+19,7,19);
ctx.fillRect(x+25,y+19,7,19);
ctx.fillRect(x+6,y+1,21,20);
ctx.fillStyle="#1d2924";ctx.fillRect(x+3,y,27,7);
ctx.fillStyle="#0a1712";ctx.fillRect(x+7,y-3,19,5);
ctx.fillStyle="#fff";
ctx.fillRect(x+(player.face===1?20:8),y+8,5,4);
ctx.fillStyle="#111";
ctx.fillRect(x+(player.face===1?23:9),y+9,2,3);
ctx.fillStyle="#e2d49a";
ctx.fillRect(x+4,y+player.h-17,24,4);
if(player.attackTime>0){
ctx.strokeStyle="#e7f6ff";ctx.lineWidth=5;
ctx.beginPath();
ctx.moveTo(x+16,y+27);
ctx.lineTo(x+16+player.face*40,y+8);
ctx.stroke();
ctx.strokeStyle="#70edff";ctx.lineWidth=2;
ctx.beginPath();ctx.arc(x+16+player.face*25,y+18,18,-1.1,1.1);ctx.stroke();
}
ctx.restore();
}
function drawCoin(c){
const x=c.x-camera;
if(c.taken||x<-20||x>W+20)return;
let glow=ctx.createRadialGradient(x,c.y,2,x,c.y,24);
glow.addColorStop(0,"#fffbc9");
glow.addColorStop(.3,"#ffdf32aa");
glow.addColorStop(1,"#ffdf3200");
ctx.fillStyle=glow;ctx.beginPath();ctx.arc(x,c.y,24,0,Math.PI*2);ctx.fill();
ctx.fillStyle="#ffcf16";
ctx.beginPath();ctx.ellipse(x,c.y,8,11,0,0,Math.PI*2);ctx.fill();
ctx.strokeStyle="#fff29b";ctx.lineWidth=2;ctx.stroke();
ctx.fillStyle="#fff6ba";ctx.fillRect(x-2,c.y-6,3,12);
}
function drawEnemy(en){
if(!en.alive)return;
const x=en.x-camera,y=en.y;
if(x<-40||x>W+40)return;
ctx.fillStyle="#111c13";ctx.fillRect(x+3,y+12,25,26);
ctx.fillStyle="#8c342b";ctx.fillRect(x+2,y+6,27,20);
ctx.fillStyle="#b9533d";ctx.fillRect(x+5,y+1,20,15);
ctx.fillStyle="#ffe3aa";
ctx.fillRect(x+6,y+8,5,4);ctx.fillRect(x+18,y+8,5,4);
ctx.fillStyle="#111";
ctx.fillRect(x+8,y+9,3,3);ctx.fillRect(x+20,y+9,3,3);
ctx.fillStyle="#25251e";
ctx.fillRect(x+3,y+35,10,5);ctx.fillRect(x+18,y+35,10,5);
}
function drawFinish(){
const x=worldWidth-90-camera;
if(x<-80||x>W+80)return;
ctx.fillStyle="#d8e6d8";
ctx.fillRect(x,310,8,130);
ctx.fillRect(x+70,310,8,130);
ctx.fillRect(x,310,78,8);
for(let r=0;r<5;r++)for(let c=0;c<3;c++){
ctx.fillStyle=(r+c)%2?"#f6f6e5":"#18221b";
ctx.fillRect(x+8+c*21,322+r*22,21,22);
}
ctx.fillStyle="#fff";ctx.font="bold 16px Arial";
ctx.fillText("FINISH",x-2,300);
}
function drawParticles(){
for(const p of particles){
ctx.globalAlpha=Math.max(0,p.life/40);
ctx.fillStyle=p.color;
ctx.beginPath();ctx.arc(p.x-camera,p.y,3,0,Math.PI*2);ctx.fill();
}
ctx.globalAlpha=1;
}
function draw(){
drawBackground();
for(const p of pits)drawPit(p);
for(const p of platforms)drawPlatform(p);
for(const p of pits){
const x=p.x-camera;
if(x+p.w<0||x>W)continue;
if(p.type==="water"){
ctx.fillStyle="#fff";ctx.font="bold 12px Arial";ctx.textAlign="center";
ctx.fillText("DEEP WATER",x+p.w/2,Math.min(H-20,p.y+45));
}else if(p.type==="lava"){
ctx.fillStyle="#fff4a1";ctx.font="bold 12px Arial";ctx.textAlign="center";
ctx.fillText("HOT LAVA",x+p.w/2,Math.min(H-20,p.y+45));
}
}
coinItems.forEach(drawCoin);
enemies.forEach(drawEnemy);
drawFinish();
drawPlayer();
drawParticles();
ctx.fillStyle="#07150d99";ctx.fillRect(W/2-120,10,240,7);
ctx.fillStyle="#baff78";
ctx.fillRect(W/2-120,10,240*Math.min(1,player.x/(worldWidth-90)),7);
}
function loop(){
update();
draw();
requestAnimationFrame(loop);
}
makeLevel();
draw();
loop();
</script>
</body>
</html>
Game Source: Jungle Battle Ground
Creator: WildDragon12
Libraries: none
Complexity: complex (746 lines, 20.7 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: jungle-battle-ground-wilddragon12-mvm6eld8" to link back to the original. Then publish at arcadelab.ai/publish.