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,检测到人物向上抬头即向上跳动
相关推荐
秃顶老男孩.26 分钟前
异步处理(前端面试)
前端·面试·职场和发展
烛阴33 分钟前
【TS 设计模式完全指南】用适配器模式优雅地“兼容”一切
javascript·设计模式·typescript
三脚猫的喵42 分钟前
微信小程序中实现AI对话、生成3D图像并使用xr-frame演示
前端·javascript·ai作画·微信小程序
文心快码BaiduComate1 小时前
文心快码3.5S全新升级,体验多智能体协同开发,最高赢无人机!
前端·后端·程序员
安卓开发者1 小时前
鸿蒙Next ArkWeb进程解析:多进程架构如何提升Web体验
前端·架构·harmonyos
炒毛豆1 小时前
移动端响应式px转换插件PostCSS的使用~
前端·javascript·postcss
Swift社区1 小时前
为什么 socket.io 客户端在浏览器能连上,但在 Node.js 中报错 transport close?
javascript·node.js
恋猫de小郭1 小时前
Flutter Riverpod 3.0 发布,大规模重构下的全新状态管理框架
android·前端·flutter
wordbaby1 小时前
用 window.matchMedia 实现高级响应式开发:API 全面解析与实战技巧
前端·javascript
薄雾晚晴1 小时前
Rspack 实战,构建流程升级:自动版本管理 + 命令行美化 + dist 压缩,一键输出生产包
前端·javascript