Chrome Dinosaur Game 简单复现

前言

灵感来源:如上图。我们使用谷歌浏览器的时候,在断网的情况下,按下空格键就会唤起恐龙🦕在沙漠中躲避仙人掌🌵的小游戏

本文,我们就来实现下这个游戏的逻辑。

矮油,不错哦!

当然,我们并不会一一复现

实现

我们简单布局下:

html 复制代码
<div id="jumpGame">
  <div id="dinosaur"></div>
  <div id="cactus"></div>
  <div id="score-container">Score: <span id="score"></span></div>
</div>

html 中,我们简单得设定了恐龙🦕 dinosaur 的占位和 cactus 仙人掌障碍物的占位。然后游戏的分数显示在页面上。

我们先简单初始化样式:

css 复制代码
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
/* 游戏区间 */
#jumpGame {
  width: 500px;
  height: 200px;
  border: 1px solid black;
  margin: auto;
  margin-top: 24px;
  position: relative;
}
/* 恐龙玩家 */
#dinosaur {
  width: 20px;
  height: 60px;
  background-color: chartreuse;
  position: absolute;
  top: 140px;
  left: 0;
}
/* 仙人掌障碍物 */
#cactus {
  background-color: red;
  width: 20px;
  height: 20px;
  position: absolute;
  top: 180px;
  left: 500px;
}
/* 分数展示 */
#score-container {
  position: absolute;
  top: 24px;
  right: 24px;
}

我们设置整个游戏的区间,然后恐龙🦕玩家固定在区间的左侧,然后仙人掌障碍物初始化在区间的右侧底部。然后获得的分数展示在空间的右上角。效果如下:

我们实现的这个游戏的规则如下:

  • 恐龙🦕玩家在左侧上下跳动
  • 仙人掌🌵障碍物自右向左运动,当超出左侧的区间,则重新从右边开始运动
  • 当玩家跳起躲避了一个障碍物,则分数 +1;否则碰到障碍物,则玩家死亡,游戏结束

So easy~ 是吧。

Ok,我们添加障碍物的移动效果,我们使用动画帧 keyframes 来实现:

css 复制代码
#cactus {
  animation: move 1s infinite linear;
}

@keyframes move {
  0% {
    left: 500px;
  }
  100% {
    left: -20px;
  }
}

同样的,对于恐龙的跳动,我们也是使用动画帧 keyframes 来实现:

css 复制代码
#dinosaur {
  animation: jump 0.3s linear infinite;
}

@keyframes jump {
  0% {
    top: 140px;
  }
  30% {
    top: 80px;
  }
  70% {
    top: 80px;
  }
  100% {
    top: 140px;
  }
}

当然,玩家的跳动需要玩家触发,我们这里例起来个类:

css 复制代码
#dinosaur {
  /* animation: jump 0.3s linear infinite; */
}
.jump {
  animation: jump 0.3s linear;
}

然后通过 javascript 控制玩家跳动躲避障碍物:

javascript 复制代码
// 玩家跳动
let dinosaurDom = document.getElementById('dinosaur');
document.addEventListener('keydown', function(event) {
  if(event.key == ' ') {
    let _classList = dinosaurDom.classList;
    if(_classList.contains('jump')) { return }
    _classList.add('jump');
    let temp = setTimeout(function() {
      _classList.remove('jump');
      clearTimeout(temp);
    }, 300)
  }
})

这里,我们实现了,玩家通过点击空格键来进行跳动。

接下来,就是进行碰撞检测并计算获得的分数。

为了方便计算,我们将样式中的 box-sizing: border-box; 改为 box-sizing: content-box;

javascript 复制代码
// 检测碰撞和分数计算
let cactusDom = document.getElementById('cactus');
let scoreDom = document.getElementById('score');
let count = 0; // 分数
scoreDom.innerText = count;
function checkCollision() {
  let timer = setInterval(() => {
    let dinosaurDomBottom = parseInt(window.getComputedStyle(dinosaurDom).getPropertyValue('bottom'));
    let cactusDomLeft = parseInt(window.getComputedStyle(cactusDom).getPropertyValue('left'));
    // 碰撞条件
    if(dinosaurDomBottom < 20 && cactusDomLeft > -20 && cactusDomLeft < 20) {
      cactusDom.style.animation = "none";
      cactusDom.style.left = cactusDomLeft + 'px'
      clearInterval(timer);
    } else {
      count += 1;
      scoreDom.innerText =  Math.floor(count / 100);
      // 为什么需要 count / 100 呢? 因为障碍物滚动完的事件是 1 秒钟,而 setInterval 中的间隔时间是 10 毫秒。那么则有 1000 / 10 = 100
    }
  }, 10);
}
checkCollision();

这里我们使用了 setInterval 进行碰撞检测和分数的计算。为什么需要 count / 100 呢?我们在代码上进行了解析。当然,读者也可以使用 requestAnimationFrame 来实现。

最终的效果如下:

后话

我们可以对该游戏进行改良,比如:

  • 使用 canvas 去绘制
  • 游戏是否可以设定等级?比如,障碍物移动的速度调整之类的
  • 结合 AI,检测到人物向上抬头即向上跳动
相关推荐
JefferyXZF3 分钟前
Next.js 15 数据获取指南:掌握服务器组件与客户端数据流(七)
前端·全栈·next.js
王柏龙24 分钟前
css 属性@font-face介绍
前端·css
羊锦磊24 分钟前
[ HTML 前端 ] 语法介绍和HBuilderX安装
java·开发语言·前端·html
鸢栀w25 分钟前
前端css学习笔记5:列表&表格&背景样式设置
前端·css·笔记·学习
&白帝&30 分钟前
Uniapp 自定义头部导航栏
前端·javascript·uni-app
掘金安东尼31 分钟前
TypeScript条件类型与infer构建类型安全的fetch
前端·javascript·typescript
领创工作室39 分钟前
npm介绍,指令合集,换源指令
前端·npm·node.js
whysqwhw3 小时前
js之Promise
前端
恋猫de小郭6 小时前
Flutter 3.35 发布,快来看看有什么更新吧
android·前端·flutter
chinahcp20087 小时前
CSS保持元素宽高比,固定元素宽高比
前端·css·html·css3·html5