晶块探险家
by PixelCaptain55204 lines5.4 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no">
<title>晶块探险家</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#222;overflow:hidden}
canvas{display:block;margin:0 auto;background:#67b6ff}
</style>
</head>
<body>
<canvas id="game"></canvas>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 450;
//玩家
const player = {
x:50,y:300,w:32,h:40,
vx:0,vy:0,speed:4,jumpPower:-12,gravity:0.5,
grounded:false,big:false,hp:1,score:0
}
//按键
const keys = {left:false,right:false,jump:false}
//平台
const platforms = [
{x:0,y:400,w:800,h:50},
{x:180,y:320,w:120,h:20},
{x:350,y:260,w:100,h:20},
{x:520,y:200,w:130,h:20},
{x:650,y:300,w:80,h:20}
]
//能量晶块(替代金币)
const crystals = [
{x:220,y:280,collected:false},
{x:380,y:220,collected:false},
{x:560,y:160,collected:false},
{x:680,y:260,collected:false}
]
//孢子(替代蘑菇)
const spores = [
{x:200,y:300,type:"grow",alive:true},
{x:540,y:180,type:"dash",alive:true}
]
//史莱姆敌人
const slimes = [
{x:300,y:370,w:36,h:30,vx:-1,alive:true}
]
//终点传送门
const goal = {x:720,y:340,w:50,h:60}
//碰撞检测
function rectOverlap(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 loop(){
//移动
if(keys.left) player.vx = -player.speed
else if(keys.right) player.vx = player.speed
else player.vx = 0
if(keys.jump && player.grounded){
player.vy = player.jumpPower; player.grounded=false;
}
player.vy += player.gravity;
player.x += player.vx;
player.y += player.vy;
//边界
if(player.x<0) player.x=0;
if(player.x>canvas.width-player.w) player.x=canvas.width-player.w;
//平台碰撞
player.grounded = false;
for(let p of platforms){
if(rectOverlap(player,p)){
if(player.vy>0 && player.y+player.h-player.vy <= p.y){
player.y = p.y-player.h;
player.vy=0;
player.grounded=true;
}
}
}
//收集晶块
for(let c of crystals){
if(!c.collected && rectOverlap(player,{x:c.x,y:c.y,w:24,h:24})){
c.collected=true; player.score+=100;
}
}
//拾取孢子
for(let s of spores){
if(s.alive && rectOverlap(player,{x:s.x,y:s.y,w:28,h:28})){
s.alive=false;
if(s.type==="grow"){
player.big=true; player.hp=2;
}else{
player.x += 80; //瞬移冲刺
}
}
}
//史莱姆
for(let sl of slimes){
if(!sl.alive) continue;
sl.x += sl.vx;
if(sl.x<50 || sl.x>700) sl.vx *= -1;
//踩头
if(rectOverlap(player,sl)){
if(player.vy>0 && player.y+player.h < sl.y+sl.h/2){
sl.alive=false; player.vy=-8; player.score+=200;
}else{
//被撞到
if(player.big){
player.big=false; player.hp=1;
}else{
alert("游戏结束!得分:"+player.score);
location.reload();
}
}
}
}
//到达终点
if(rectOverlap(player,goal)){
alert("🎉通关!得分:"+player.score);
location.reload();
}
//渲染
ctx.clearRect(0,0,canvas.width,canvas.height);
//平台
ctx.fillStyle="#7b5428";
platforms.forEach(p=>ctx.fillRect(p.x,p.y,p.w,p.h));
//晶块
ctx.fillStyle="#33ccff";
crystals.forEach(c=>{
if(!c.collected){
ctx.beginPath(); ctx.arc(c.x+12,c.y+12,12,0,Math.PI*2); ctx.fill();
}
})
//孢子
spores.forEach(s=>{
if(s.alive){
ctx.fillStyle = s.type=="grow"?"#38d050":"#c760ff";
ctx.beginPath(); ctx.arc(s.x+14,s.y+14,14,0,Math.PI*2); ctx.fill();
}
})
//史莱姆
ctx.fillStyle="#44bb44";
slimes.forEach(sl=>{
if(sl.alive) ctx.fillRect(sl.x,sl.y,sl.w,sl.h);
})
//传送门终点
ctx.fillStyle="#9944ff";
ctx.fillRect(goal.x,goal.y,goal.w,goal.h);
//玩家
ctx.fillStyle="#ff4444";
if(player.big) ctx.fillRect(player.x,player.y,player.w+8,player.h+8);
else ctx.fillRect(player.x,player.y,player.w,player.h);
//分数
ctx.fillStyle="#fff";
ctx.font="24px sans-serif";
ctx.fillText("得分:"+player.score,20,30);
requestAnimationFrame(loop);
}
//键盘控制
document.addEventListener('keydown',e=>{
if(e.key==="ArrowLeft") keys.left=true;
if(e.key==="ArrowRight") keys.right=true;
if(e.key==="ArrowUp") keys.jump=true;
})
document.addEventListener('keyup',e=>{
if(e.key==="ArrowLeft") keys.left=false;
if(e.key==="ArrowRight") keys.right=false;
if(e.key==="ArrowUp") keys.jump=false;
})
//手机触屏按钮(左右跳)
let touchDiv = document.createElement("div");
touchDiv.style="position:fixed;bottom:10px;left:0;right:0;display:flex;justify-content:space-between;padding:0 20px";
let btnL=document.createElement("button");btnL.innerText="←";btnL.style="width:70px;height:70px;font-size:30px";
let btnR=document.createElement("button");btnR.innerText="→";btnR.style="width:70px;height:70px;font-size:30px";
let btnJ=document.createElement("button");btnJ.innerText="跳";btnJ.style="width:70px;height:70px;font-size:30px";
touchDiv.appendChild(btnL);touchDiv.appendChild(btnR);touchDiv.appendChild(btnJ);
document.body.appendChild(touchDiv);
btnL.ontouchstart=()=>keys.left=true; btnL.ontouchend=()=>keys.left=false;
btnR.ontouchstart=()=>keys.right=true; btnR.ontouchend=()=>keys.right=false;
btnJ.ontouchstart=()=>keys.jump=true; btnJ.ontouchend=()=>keys.jump=false;
loop();
</script>
</body>
</html>
Game Source: 晶块探险家
Creator: PixelCaptain55
Libraries: none
Complexity: complex (204 lines, 5.4 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: game-pixelcaptain55" to link back to the original. Then publish at arcadelab.ai/publish.