🎮ArcadeLab

草地小人闯关跑酷

by CosmicBear11
224 lines4.8 KB🛠️ p5.js (creative coding)
▶ Play
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body{margin:0;display:flex;justify-content:center;background:#111}
canvas{border:2px solid white}
</style>
</head>
<body>
<script>
//玩家数据
let playerX = 80;
let playerY;
let playerW = 36;
let playerH = 50;
let jumpPower = -14;
let gravity = 0.6;
let ySpeed = 0;
let isGround = false;

//游戏物体
let ghosts = [];
let coins = [];
let groundY;
let scrollSpeed = 4;
let score = 0;
let level = 1;
const maxLevel = 100;

//游戏状态:playing游戏中 / gameOver失败 / win通关100关
let gameState = "playing";
let restartBtn = {x:0,y:0,w:130,h:50};

function setup(){
  createCanvas(400, 600);
  groundY = height - 80;
  resetGame();
}

//重置游戏函数(重新开始)
function resetGame(){
  playerY = groundY - playerH;
  ySpeed = 0;
  ghosts = [];
  coins = [];
  scrollSpeed = 4;
  if(gameState === "gameOver") level = 1;
  gameState = "playing";
  loop();
}

function draw(){
  background(120,190,255);
  drawGrass();
  textAlign(LEFT);
  fill(255);
  textSize(22);
  text("关卡:"+level+"/"+maxLevel,15,30);
  text("分数:"+score,15,58);

  if(gameState === "playing"){
    playerPhysics();
    spawnObstacleCoin();
    updateGhosts();
    updateCoins();
    drawPlayer();

    //本关清除所有障碍,进入下一关
    if(ghosts.length === 0 && frameCount > 120){
      level++;
      scrollSpeed += 0.35;
      if(level > maxLevel){
        gameState = "win";
        noLoop();
      }
    }
  }else if(gameState === "gameOver"){
    drawGameOverUI();
  }else if(gameState === "win"){
    drawWinUI();
  }

  //点击按钮重新开始
  if(mouseIsPressed && checkMouseOnButton()){
    resetGame();
  }
}

//人物重力、跳跃逻辑
function playerPhysics(){
  ySpeed += gravity;
  playerY += ySpeed;
  if(playerY >= groundY - playerH){
    playerY = groundY - playerH;
    ySpeed = 0;
    isGround = true;
  }else isGround = false;

  if(mouseIsPressed && isGround) ySpeed = jumpPower;
}

//生成小鬼柱子、金币(柱子高度最高52,保证能跳过去)
function spawnObstacleCoin(){
  if(frameCount % Math.floor(85-level*0.6) === 0){
    let gh = random(32,52);
    ghosts.push({x:width+20,y:groundY-gh,w:30,h:gh});
  }
  if(frameCount % Math.floor(95-level*0.7) === 0){
    coins.push({x:width+20,y:groundY-random(65,135),size:23});
  }
}

//更新小鬼障碍
function updateGhosts(){
  for(let i=ghosts.length-1;i>=0;i--){
    let g = ghosts[i];
    g.x -= scrollSpeed;
    fill(70,70,70);
    rect(g.x,g.y,g.w,g.h,3);
    fill(255);
    ellipse(g.x+7,g.y+11,5,5);
    ellipse(g.x+23,g.y+11,5,5);

    if(checkRectHit(playerX,playerY,playerW,playerH,g.x,g.y,g.w,g.h)){
      gameState = "gameOver";
      noLoop();
    }
    if(g.x < -g.w) ghosts.splice(i,1);
  }
}

//更新金币
function updateCoins(){
  for(let i=coins.length-1;i>=0;i--){
    let c = coins[i];
    c.x -= scrollSpeed;
    fill(255,205,0);
    ellipse(c.x,c.y,c.size);
    fill(210,150,0);
    text("$",c.x-7,c.y+8);

    if(dist(playerX+playerW/2,playerY+playerH/2,c.x,c.y)<28){
      coins.splice(i,1);
      score += 8;
    }
    if(c.x < -c.size) coins.splice(i,1);
  }
}

//绘制玩家小人
function drawPlayer(){
  fill(255,230,190);
  rect(playerX+8,playerY,playerW-16,playerH-18,6);
  ellipse(playerX+playerW/2,playerY-6,18,18);
  fill(40,40,40);
  rect(playerX+10,playerY+34,7,16);
  rect(playerX+19,playerY+34,7,16);
}

//草地地面
function drawGrass(){
  fill(75,170,40);
  rect(0,groundY,width,height-groundY);
  stroke(50,140,20);
  strokeWeight(2);
  for(let x=0;x<width;x+=12){
    line(x,groundY,x+4,groundY-12);
  }
  noStroke();
}

//碰撞检测
function checkRectHit(x1,y1,w1,h1,x2,y2,w2,h2){
  return x1<x2+w2 && x1+w1>x2 && y1<y2+h2 && y1+h1>y2;
}

//游戏结束界面
function drawGameOverUI(){
  fill(0,0,0,160);
  rect(0,0,width,height);
  textAlign(CENTER);
  fill(255,40,40);
  textSize(46);
  text("游戏结束",width/2,height/2-60);

  //重新开始按钮
  restartBtn.x = width/2 - restartBtn.w/2;
  restartBtn.y = height/2;
  fill(30,160,50);
  rect(restartBtn.x,restartBtn.y,restartBtn.w,restartBtn.h,10);
  fill(255);
  textSize(24);
  text("重新开始",width/2,restartBtn.y+32);
}

//通关100关界面
function drawWinUI(){
  fill(0,0,0,160);
  rect(0,0,width,height);
  textAlign(CENTER);
  fill(255,220,0);
  textSize(44);
  text("恭喜通关100关!",width/2,height/2-60);

  restartBtn.x = width/2 - restartBtn.w/2;
  restartBtn.y = height/2;
  fill(30,160,50);
  rect(restartBtn.x,restartBtn.y,restartBtn.w,restartBtn.h,10);
  fill(255);
  textSize(24);
  text("重新开始",width/2,restartBtn.y+32);
}

//检测鼠标是否点按钮
function checkMouseOnButton(){
  return mouseX>restartBtn.x && mouseX<restartBtn.x+restartBtn.w
      && mouseY>restartBtn.y && mouseY<restartBtn.y+restartBtn.h;
}
</script>
</body>
</html>

Game Source: 草地小人闯关跑酷

Creator: CosmicBear11

Libraries: p5

Complexity: complex (224 lines, 4.8 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-cosmicbear11-mum65fzr" to link back to the original. Then publish at arcadelab.ai/publish.