溶洞像素跳跃
by MysticMaker96228 lines5.1 KB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>溶洞像素跳跃</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{background:#181412;color:#fff;font-family:monospace;overflow:hidden}
canvas{display:block;margin:0 auto;background:#2c2420;image-rendering:pixelated;}
.info{position:absolute;top:8px;left:12px;font-size:18px;text-shadow:1px 1px #000}
</style>
</head>
<body>
<div class="info">
💰金币:<span id="coinCount">0</span> ⭐分数:<span id="score">0</span>
</div>
<canvas id="game" width="480" height="320"></canvas>
<script>
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const coinDom = document.getElementById('coinCount');
const scoreDom = document.getElementById('score');
function drawPixel(x,y,w,h,color){
ctx.fillStyle = color;
ctx.fillRect(Math.floor(x),Math.floor(y),w,h);
}
// 玩家:紫色像素小人
const player = {
x: 60,
y: 200,
w: 12,
h: 18,
vx: 2.6, // 固定向右跑步速度
vy: 0,
jumpPower: -13,
gravity: 0.48,
onGround: false,
pixelSize: 3,
runPhase: 0, // 跑步相位
flip: 1,
coinNum: 0,
score: 0
};
const groundY = 260;
let spikes = [];
let coins = [];
// 尖刺:棕色溶洞石柱
function spawnSpike(){
const h = 28 + Math.random() * 22;
spikes.push({
x: canvas.width,
y: groundY - h,
w: 14,
h: h,
scored: false
});
}
// 普通金币
function spawnCoin(){
coins.push({
x: canvas.width,
y: groundY - 36 - Math.random()*55,
r: 5,
collected: false
});
}
// 大片金币区域
function spawnCoinWave(){
const count = 5 + Math.floor(Math.random()*4);
const startY = groundY - 40 - Math.random()*40;
for(let i=0;i<count;i++){
coins.push({
x: canvas.width + i*22,
y: startY + Math.sin(i*0.6)*10,
r: 5,
collected: false
});
}
}
// 点击画布任意位置跳跃
canvas.addEventListener('click', ()=>{
if(player.onGround){
player.vy = player.jumpPower;
player.onGround = false;
}
});
canvas.addEventListener('touchstart',e=>{
e.preventDefault();
if(player.onGround){
player.vy = player.jumpPower;
player.onGround = false;
}
});
let spawnTimer = 0;
const spawnRate = 110;
const moveSpeed = 3;
let coinWaveTimer = 0;
const coinWaveRate = 320;
function resetGame(){
player.x = 60;
player.y = 200;
player.vy = 0;
player.onGround = false;
player.coinNum = 0;
player.score = 0;
player.runPhase = 0;
spikes = [];
coins = [];
spawnTimer = 0;
coinWaveTimer = 0;
updateUI();
}
function updateUI(){
coinDom.textContent = player.coinNum;
scoreDom.textContent = Math.floor(player.score);
}
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 circleRect(c, r, rect){
let cx = Math.max(rect.x, Math.min(c.x, rect.x+rect.w));
let cy = Math.max(rect.y, Math.min(c.y, rect.y+rect.h));
let dx = c.x - cx;
let dy = c.y - cy;
return dx*dx + dy*dy < r*r;
}
function update(){
spawnTimer++;
coinWaveTimer++;
if(spawnTimer >= spawnRate){
spawnTimer = 0;
if(Math.random()<0.8) spawnSpike();
if(Math.random()<0.28) spawnCoin();
}
if(coinWaveTimer >= coinWaveRate){
coinWaveTimer = 0;
spawnCoinWave();
}
// 重力
player.vy += player.gravity;
player.y += player.vy;
// 地面碰撞
if(player.y + player.h*player.pixelSize >= groundY){
player.y = groundY - player.h*player.pixelSize;
player.vy = 0;
player.onGround = true;
}else{
player.onGround = false;
}
// 跑步动画:在地上才累积相位
if(player.onGround){
player.runPhase += 0.35;
}
// 移动尖刺和金币
for(let i=spikes.length-1;i>=0;i--){
spikes[i].x -= moveSpeed;
if(spikes[i].x + spikes[i].w < 0) spikes.splice(i,1);
}
for(let i=coins.length-1;i>=0;i--){
coins[i].x -= moveSpeed;
if(coins[i].x + coins[i].r < 0) coins.splice(i,1);
}
// 碰撞尖刺
const playerBox = {
x: player.x+2,
y: player.y+2,
w: player.w*player.pixelSize-4,
h: player.h*player.pixelSize-4
};
for(let s of spikes){
if(rectOverlap(playerBox, s)){
resetGame();
return;
}
if(!s.scored && s.x + s.w/2 < player.x){
s.scored = true;
player.score += 1;
updateUI();
}
}
// 吃金币
for(let i=coins.length-1;i>=0;i--){
const c = coins[i];
if(!c.collected && circleRect(c, c.r, playerBox)){
c.collected = true;
player.coinNum++;
player.score += 10;
coins.splice(i,1);
updateUI();
}
}
player.score += 0.02;
updateUI();
}
function drawPlayer(){
const px = player.pixelSize;
const baseX = player.x;
const baseY = player.y;
Game Source: 溶洞像素跳跃
Creator: MysticMaker96
Libraries: none
Complexity: complex (228 lines, 5.1 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-mysticmaker96-mw4lgq4g" to link back to the original. Then publish at arcadelab.ai/publish.