草庐IT

【JS入门小游戏】01-骰子游戏

lukirence 2023-03-28 原文

01-骰子游戏

游戏出自Udemy的JS课程中提到的一个游戏,课程主要是对JS部分进行详细的从0开始的讲解,本篇文章是对整个游戏的分析,包括HTMK,CSS和JS,也主要对JS进行刨析。

游戏链接:https://pig-game-v2.netlify.app/

游戏规则:开始玩家1点击ROLL DICE开始投掷骰子,如果点数为2-6,计入当前得分并可以继续投掷并累加得分到当前得分,如果点数为1,直接结束本轮交换到玩家2并清空已有当前得分,在途中可以主动选择HOLD按钮保持当前得分到个人总分,并结束本轮交换到玩家2开始游戏;两个玩家依次交换并累计总分,直到一方总分达到100分结束游戏。点击New Game可以重新开始游戏。

HTML

HTML的部分比较简单,基本布局为body>main>(section×2>h2+p2+div)+img+button×3,即:

  <main>
    <section>
      <h2></h2>
      <p2></p2>
      <div></div>
    </section>
    <section>
      <h2></h2>
      <p2></p2>
      <div></div>
    </section>
    <img src="" alt="">
    <button></button>
    <button></button>
    <button></button>
  </main>

加入类和id的详细描述

  <main>
    <!-- 玩家1 -->
    <section class="player player--0 player--active">
      <h2 class="name" id="name--0">PLAYER 1</h2>
      <!-- 总得分 -->
      <p2 class="score" id="score--0">0</p2>
      <div class="current">
        <p class="current-label">CURRENT</p>
        <!-- 当前轮得分 -->
        <p class="current-score" id="current--0">0</p>
      </div>
    </section>
    <!-- 玩家2 -->
    <section>
      <h2 class="name" id="name--1">PLAYER 2</h2>
      <p2 class="score" id="score--1">0</p2>
      <div class="current">
        <p class="current-label">CURRENT</p>
        <p class="current-score" id="current--1">0</p>
      </div>
    </section>
    <!-- 显示骰子 -->
    <img src="dice-1.png" alt="dice" class="dice">
    <button class="btn btn--new">NEW GAME</button>
    <button class="btn btn--dice">ROLL DICE</button>
    <button class="btn btn--hold">HOLD</button>
    <script src="script.js"></script>
  </main>

CSS

@import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: inherit;
}

html {
  font-size: 62.5%;
  box-sizing: border-box;
}

body {
  font-family: 'Nunito', sans-serif;
  font-weight: 400;
  height: 100vh;
  color: #333;
  background-image: linear-gradient(to top left, #753682 0%, #bf2e34 100%);
  display: flex;
  align-items: center;
  justify-content: center;
}

main {
  position: relative;
  width: 100rem;
  height: 60rem;
  background-color: rgba(255, 255, 255, 0.35);
  backdrop-filter: blur(200px);
  filter: blur();
  box-shadow: 0 3rem 5rem rgba(0, 0, 0, 0.25);
  border-radius: 9px;
  overflow: hidden;
  display: flex;
}

.player {
  flex: 50%;
  padding: 9rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: all 0.75s;
}

.name {
  position: relative;
  font-size: 4rem;
  text-transform: uppercase;
  letter-spacing: 1px;
  word-spacing: 2px;
  font-weight: 300;
  margin-bottom: 1rem;
}

.score {
  font-size: 8rem;
  font-weight: 300;
  color: #c7365f;
  margin-bottom: auto;
}

.player--active {
  background-color: rgba(255, 255, 255, 0.4);
}
.player--active .name {
  font-weight: 700;
}
.player--active .score {
  font-weight: 400;
}

.player--active .current {
  opacity: 1;
}

.current {
  background-color: #c7365f;
  opacity: 0.8;
  border-radius: 9px;
  color: #fff;
  width: 65%;
  padding: 2rem;
  text-align: center;
  transition: all 0.75s;
}

.current-label {
  text-transform: uppercase;
  margin-bottom: 1rem;
  font-size: 1.7rem;
  color: #ddd;
}

.current-score {
  font-size: 3.5rem;
}

.btn {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  color: #444;
  background: none;
  border: none;
  font-family: inherit;
  font-size: 1.8rem;
  text-transform: uppercase;
  cursor: pointer;
  font-weight: 400;
  transition: all 0.2s;

  background-color: white;
  background-color: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(10px);

  padding: 0.7rem 2.5rem;
  border-radius: 50rem;
  box-shadow: 0 1.75rem 3.5rem rgba(0, 0, 0, 0.1);
}

.btn::first-letter {
  font-size: 2.4rem;
  display: inline-block;
  margin-right: 0.7rem;
}

.btn--new {
  top: 4rem;
}
.btn--roll {
  top: 39.3rem;
}
.btn--hold {
  top: 46.1rem;
}

.btn:active {
  transform: translate(-50%, 3px);
  box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15);
}

.btn:focus {
  outline: none;
}

.dice {
  position: absolute;
  left: 50%;
  top: 16.5rem;
  transform: translateX(-50%);
  height: 10rem;
  box-shadow: 0 2rem 5rem rgba(0, 0, 0, 0.2);
}

.player--winner {
  background-color: #2f2f2f;
}

.player--winner .name {
  font-weight: 700;
  color: #c7365f;
}
.hidden{
  display: none;
}

其中值得关注的几个效果:

backdrop-filter属性允许您对元素后面的区域执行,诸如"模糊"或"改变颜色"等效果。因为它适用于元素后面的所有内容, 所以要查看效果, 必须使元素或其背景至少部分透明。

backdrop-filter: blur(200px);//使得后面的变模糊200px

letter-spacing字间距:添加每个字母或汉字之间的空白

word-spacing词间距:增加或减少字与字之间的空白

text-transform

描述
none 默认。定义带有小写字母和大写字母的标准的文本。
capitalize 文本中的每个单词以大写字母开头。
uppercase 定义仅有大写字母。
lowercase 定义无大写字母,仅有小写字母。
inherit 规定应该从父元素继承 text-transform 属性的值。

按钮按下动效

.btn:active {
  transform: translate(-50%, 3px);//按下下移3px
  box-shadow: 0 1rem 2rem rgba(0, 0, 0, 0.15);//按下加入阴影
}

JS

功能流程图

三个按钮可以分为3个功能:

  1. 投掷骰子:根据随机数产生1-6随机数后显示对应点数图片,并判断是否为1,为1交换玩家;不为1,点数累计入当前分并更新当前分。
  2. 保持分数:将当前累计得分计入到总分后判断是否满足达到100,没有交换玩家,有则结束游戏。
  3. 点击新游戏:将所有当前得分与总分归0,重新设置玩家1为当前玩家。

模块思想

函数封装复用

由流程图可见,在投掷骰子和保持分数功能中都可能执行到交换玩家的流程,因此将交换玩家作为一个自定函数来实现复用,另外涉及重新开始新游戏功能,游戏初始化也可作为函数复用。

代码

首先获取其中之后需要的元素,包括:

  1. 一张骰子图片;
  2. 两个玩家,玩家1,玩家2;
  3. 三个按钮,上文依次提到过;
  4. 四个分数,依次为玩家1当前得分,玩家1总分,玩家2当前得分,玩家2总分;
const diceEl = document.querySelector('.dice');
const player0El = document.querySelector('.player--0');
const player1El = document.querySelector('.player--1');
const btnNew = document.querySelector('.btn--new');
const btnRoll = document.querySelector('.btn--roll');
const btnHold = document.querySelector('.btn--hold');
const score0El = document.querySelector('#score--0');
const score1El = document.querySelector('#score--1');
const current0El = document.querySelector('#current--0');
const current1El = document.querySelector('#current--1');

init()初始化函数

let scores, currentScore, activePlayer;//分别为总分,当前得分,目前在玩玩家
let playing;//用于判断游戏是否结束
const init = function () {
  scores = [0, 0]; //两队比分
  currentScore = 0;
  activePlayer = 0;//初始玩家1为在玩玩家
  playing = true;

  current0El.textContent = 0;
  current1El.textContent = 0;
  score0El.textContent = 0;
  score1El.textContent = 0;

  diceEl.classList.add('hidden');//hidden内容为display:none;开始添加hidden为不显示图片
  player0El.classList.remove('player--winner');//以下四个为初始化类,winner为胜利类,active为当前在玩类
  player1El.classList.remove('player--winner');
  player0El.classList.add('player--active');
  player1El.classList.remove('player--active');
};
init();

投掷骰子功能

通过模板文字根据不同数字显示不同点数图片

diceEl.src = `dice-${dice}.png`;//dice为1-6的随机数

exchange()交换玩家

const exchange = function () {
  document.getElementById(`current--${activePlayer}`).textContent = 0;//交换前恢复先前玩家当前得分
  activePlayer = 1 - activePlayer;//玩家0,1切换
  currentScore = 0;//重新设置当前得分
  document.getElementById(`current--${activePlayer}`).textContent =
    currentScore;//更新当前玩家的当前分数
  player0El.classList.toggle('player--active');//toggle方法为若有该类则删除,无该类则添加
  player1El.classList.toggle('player--active');
};
btnRoll.addEventListener('click', function () {
  if (playing) {//游戏未结束
    const dice = Math.trunc(Math.random() * 6) + 1;
    diceEl.classList.remove('hidden');
    diceEl.src = `dice-${dice}.png`;

    if (dice !== 1) {
      currentScore += dice;
      document.getElementById(`current--${activePlayer}`).textContent =
        currentScore;//更新当前玩家的当前分数
    } else {
      exchange();//交换玩家
    }
  }
});

保持分数功能

btnHold.addEventListener('click', function () {
  if (playing) {
    scores[activePlayer] += currentScore;//添加到对应玩家总分
    document.getElementById(`score--${activePlayer}`).textContent =
      scores[activePlayer];//更新总分
    if (scores[activePlayer] >= 100) {
      playing = false;
      document
        .querySelector(`.player--${activePlayer}`)
        .classList.add('player--winner');
      document
        .querySelector(`.player--${activePlayer}`)
        .classList.remove('player--active');
      diceEl.classList.add('hidden');
    } else {
      exchange();
    }
  }
});

重新开始游戏

btnNew.addEventListener('click', init);

有关【JS入门小游戏】01-骰子游戏的更多相关文章

  1. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  2. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  3. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  4. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  5. ruby - 我需要从 facebook 游戏中抓取数据——使用 ruby - 2

    修改(澄清问题)我已经花了几天时间试图弄清楚如何从Facebook游戏中抓取特定信息;但是,我遇到了一堵又一堵砖墙。据我所知,主要问题如下。我可以使用Chrome的检查元素工具手动查找我需要的html-它似乎位于iframe中。但是,当我尝试抓取该iframe时,它​​是空的(属性除外):如果我使用浏览器的“查看页面源代码”工具,这与我看到的输出相同。我不明白为什么我看不到iframe中的数据。答案不是它是由AJAX之后添加的。(我知道这既是因为“查看页面源代码”可以读取Ajax添加的数据,也是因为我有b/c我一直等到我可以看到数据页面之后才抓取它,但它仍然不存在)。发生这种情况是因为

  6. ruby-on-rails - Assets 管道损坏 : Not compiling on the fly css and js files - 2

    我开始了一个新的Rails3.2.5项目,Assets管道不再工作了。CSS和Javascript文件不再编译。这是尝试生成Assets时日志的输出:StartedGET"/assets/application.css?body=1"for127.0.0.1at2012-06-1623:59:11-0700Servedasset/application.css-200OK(0ms)[2012-06-1623:59:11]ERRORNoMethodError:undefinedmethod`each'fornil:NilClass/Users/greg/.rbenv/versions/1

  7. ruby-on-rails - Rails - 理解 application.js 和 application.css - 2

    rails新手。只是想了解\assests目录中的这两个文件。例如,application.js文件有如下行://=requirejquery//=requirejquery_ujs//=require_tree.我理解require_tree。只是将所有JS文件添加到当前目录中。根据上下文,我可以看出requirejquery添加了jQuery库。但是它从哪里得到这些jQuery库呢?我没有在我的Assets文件夹中看到任何jquery.js文件——或者直接在我的整个应用程序中没有看到任何jquery.js文件?同样,我正在按照一些说明安装TwitterBootstrap(http:

  8. python - Ruby 或 Python 的 3d 游戏引擎? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion是否有适用于这些的3d游戏引擎?

  9. node.js - 如何在 Travis CI 上的一个项目中运行 Node.js 和 Ruby 测试 - 2

    我有一个包含多个组件的存储库,其中大部分是用JavaScript(Node.js)编写的,一个是用Ruby(RubyonRails)编写的。我想要一个.travis.yml文件来触发一个运行每个组件的所有测试的构建。根据thisTravisCIGoogleGroupthread,目前还没有官方支持。我的目录结构是这样的:.├──构建服务器├──核心├──扩展├──网络应用├──流浪文件├──package.json├──.travis.yml└──生成文件我希望能够运行特定版本的Ruby(2.2.2)和Node.js(0.12.2)。我已经有了一个make目标,所以maketest在每

  10. 区块链入门教程(6)--WeBASE-Front节点前置服务安装 - 2

    文章目录1.任务背景2.任务目标3.相关知识点4.任务实操4.1安装配置JDK4.2启动FISCOBCOS4.3下载解压WeBASE-Front4.4拷贝sdk证书文件4.5启动节点4.6访问节点4.7检查运行状态5.任务总结1.任务背景FISCOBCOS其实是有控制台管理工具,用来对区块链系统进行各种管理操作。但是对于初学者来说,还是可视化界面更友好,本节就来介绍WeBASE管理平台,这是一款微众银行开源的自研区块链中间件平台,可以降低区块链使用的门槛,大幅提高区块链应用的开发效率。微众银行是腾讯牵头设立的民营银行,在国内民营银行里还是比较出名的。微众银行参与FISCOBCOS生态建设,一定

随机推荐