点击上方“程序员黑叔”,选择“置顶或者星标”

期待你的关注!

用Vue、Vuex 做俄罗斯方块


本项目灵感来源于 React 版的俄罗斯方块,由于对其实现原理较感兴趣,而且相比于 React 更喜欢 Vue, 于是把 React 版的重构为了 Vue 版的,大致思路是把组件当成一个个函数,保证一个输入(props)能得到一个确定的输出(view),然后对不同方法也是做同样处理,对于 Redux 使用 Vuex 精简化


效果预览

效果预览

正常速度的录制,体验流畅。

响应式

响应式

不仅指屏幕的自适应,而是在PC使用键盘、在手机使用手指的响应式操作

手机

数据持久化

视频

玩单机游戏最怕什么?断电。通过订阅 store.subscribe,将state储存在localStorage,精确记录所有状态。网页关了刷新了、程序崩溃了、手机没电了,重新打开连接,都可以继续。

Vuex 状态预览(Vue DevTools extension)

preview

视频

Vuex 设计管理了所有应存的状态,这是上面持久化的保证。


游戏框架使用的是 Vue + Vuex

1、Web Audio Api

游戏里有很多不同的音效,而实际上只引用了一个音效文件:/build/music.mp3。借助Web Audio Api能够以毫秒级精确、高频率的播放音效,这是<audio>标签所做不到的。在游戏进行中按住方向键移动方块,便可以听到高频率的音效。

网页音效进阶

WAA 是一套全新的相对独立的接口系统,对音频文件拥有更高的处理权限以及更专业的内置音频效果,是W3C的推荐接口,能专业处理“音速、音量、环境、音色可视化、高频、音向”等需求,下图介绍了WAA的使用流程。

流程

其中Source代表一个音频源,Destination代表最终的输出,多个Source合成出了Destination。源代码:/src/unit/music.js 实现了ajax加载mp3,并转为WAA,控制播放的过程。

WAA 在各个浏览器的最新2个版本下的支持情况(CanIUse)

浏览器兼容

可以看到IE阵营与大部分安卓机不能使用,其他ok。

Web Audio Api 学习资料:

  • Web API 接口| MDN

  • Getting Started with Web Audio API


3、游戏在体验上的优化

  • 技术:

    • 按下方向键水平移动和竖直移动的触发频率是不同的,游戏可以定义触发频率,代替原生的事件频率,源代码:/src/unit/event.js ;

    • 左右移动可以 delay 掉落的速度,但在撞墙移动的时候 delay 的稍小;在速度为6级时 通过delay 会保证在一行内水平完整移动一次;

    • 对按钮同时注册touchstartmousedown事件,以供响应式游戏。当touchstart发生时,不会触发mousedown,而当mousedown发生时,由于鼠标移开事件元素可以不触发mouseup,将同时监听mouseout 模拟 mouseup。源代码:/src/components/keyboard/index.js;

    • 监听了 visibilitychange 事件,当页面被隐藏\切换的时候,游戏将不会进行,切换回来将继续,这个focus状态也被写进了 Vuex 中。所以当用手机玩来电话时,游戏进度将保存;PC开着游戏干别的也不会听到gameover,这有点像 ios 应用的切换。

    • 任意时刻刷新网页,(比如消除方块时、游戏结束时)也能还原当前状态;

    • 游戏中唯一用到的图片是,其他都是CSS;

    • 游戏兼容 Chrome、Firefox、IE9+、Edge等;

  • 玩法:

    • 可以在游戏未开始时制定初始的棋盘(十个级别)和速度(六个级别);

    • 一次消除1行得100分、2行得300分、3行得700分、4行得1500分;

    • 方块掉落速度会随着消除的行数增加(每20行增加一个级别);


4、开发中的经验梳理,以及如何把 React 项目重构为 Vue 版本

Vue 版本和 React 版本核心代码基本相同,但在编写组件的时候遇到了几个问题,比如:

  1. 如何把 React 组件改写成 Vue 的,我的思路是把组件当成函数,保证一个输入(props)能得到一个确定的输出(view),然后对不同方法也是做同样处理, React 的 setState 会触发 render 方法,所以可以在 methods 自定义 render 方法再在 state 变化后手动触发 render 方法

  2. 生命周期,简单来说, React 的 componentWillMount 对应 Vue 的 beforeMount, React 的 componentDidMount 对应 Vue 的 mounted,React 的用来优化性能的 shouldComponentUpdate 在 Vue 里并不需要,不需要手动优化这也是我喜欢 Vue 的一点

  3. Vue 没有 React 的componentWillReceiveProps 的生命周期,我的解决方法是使用 watch 配合 deep:true 来监听 props 的变化,如:

  watch: {$props: {deep: true,handler(nextProps) {//xxx}}}
  1. 在必要时候使用 jsx 和 'render' 函数,是的, vue 支持 jsx,在这个项目中matrix 组件 的功能逻辑较复杂,使用 template 模版来渲染组件已经不合适了, React 每次 setState 会触发 'render' 方法,所以我们可以在 methods自定义 'render' 方法再在 state 变化后手动触发 'render' 方法,但是这个方法对有复杂逻辑的组件来说会变得很繁琐,我的解决方法是通过 Vue 的 jsx 转换插件babel-plugin-transform-vue-jsx来使用 jsx 语法对页面进行渲染,当 props 或 state 变化了自动触发 'render' 方法,另外要注意的是 vue 的 jsx 和 React 的 jsx 书写上有一点的差异, 当 'render' 方法存在时,template 语法会失效. 'render' 函数一个比较实用的用处是在开发类似 React-log 之类的不需要渲染 html 只需要执行一些方法的组件时 template 会显得很多余,因为这时候并不需要渲染 dom 了,如果用了 'render' 函数,简单的在 'render' 函数里 return false 就行,如: react-log

5、架构差异

Redux 的数据流向是通过 mapStateToProps 把 store 的状态转化为 props 然后通过connect 函数注入到 根组件,根组件再把这些 props 传入不同组件,当 store 的状态变化,根组件会重新 render, 更新子组件上的 props,子组件再 根据新 props重新 render 引用知乎一个答友的回答https://www.zhihu.com/question/47686258来说就是:

“单例store的数据在react中可以通过view组件的属性(props)不断由父模块“单向”传递给子模块,形成一个树状分流结构。如果我们把redux比作整个应用的“心肺” (redux的flux功能像心脏,reducer功能像肺部毛细血管),那么这个过程可以比作心脏(store)将氧分子(数据)通过动脉毛细血管(props)送到各个器官组织(view组件)末端的view组件,又可以通过flux机制,将携带交互意图信息的action反馈给store。这个过程有点像将携带代谢产物的“红细胞”(action)通过静脉毛细血管又泵回心脏(store)action流回到store以后,action以参数的形式又被分流到各个具体的reducer组件中,这些reducer同样构成一个树状的hierarchy。这个过程像静脉血中的红细胞(action)被运输到肺部毛细血管(reducer组件)接收到action后,各个child reducer以返回值的形式,将最新的state返回给parent reducer,最终确保整个单例store的所有数据是最新的。这个过程可以比作肺部毛细血管的血液充氧后,又被重新泵回了心脏”

而 vuex 的思路则不同,任何组件都随时可以通过 this.$store.state.xxx 获取 store 上的数据,更自由,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:

computed: {keyboard () {return this.store.state.keyboard}}

调用 store.commit 提交 payload修改数据 或者 store.dispatch 提交 mutation 间接修改 store 上的数据, commit 和 dispatch 的区别在于 commit 用于同步修改状态, dispatch 用于异步修改状态,异步完成需要再调用 commit,一般简单的需求只需要 commit 一个 payload 就行,只要 store 上的数据变了,组件都会自动重新渲染

6、开发

  • 安装 npm install

  • 运行 npm run dev

  • 浏览自动打开 http://localhost:8080

  • 多语言 在 i18n.json 配置多语言环境,使用"lan"参数匹配语言如:https://Binaryify.github.io/vue-tetris/?lan=enhttp://binaryify.github.io/vue-tetris/?lan=zh

  • 打包编译 npm run build

  • dist 文件夹下生成结果。

7、幸福时刻

8、一起嗨起来

戳左下"阅读原文"即可玩一玩!

一个niubility的Vue游戏,真厉害!(收藏)相关推荐

  1. 一个niubility的Vue游戏,真厉害!

    点击上方"程序员黑叔",选择"置顶或者星标" 期待你的关注! 用Vue.Vuex 做俄罗斯方块 本项目灵感来源于 React 版的俄罗斯方块,由于对其实现原理较 ...

  2. 收藏了一个免费的手机游戏下载站

    收藏一个免费的手机游戏下载站 很多热门的免费手机游戏,都是破解的! 网址是:http://www.wcplym.com

  3. 用Python编一个打小怪兽游戏

    用Python编一个打小怪兽游戏 代码供大家参考 import random import time while True:input("请按回车键开始游戏")print(&quo ...

  4. 100行代码,使用 Pygame 制作一个贪吃蛇小游戏!

    作者 | 周萝卜 来源 | 萝卜大杂烩 相信我们大家都玩过贪吃蛇游戏,今天我们就从头一起来写一个贪吃蛇小游戏,只需要100多行的代码就完成了. 用到的 Pygame 函数 贪吃蛇小游戏用到的函数 功能 ...

  5. (转)一个古老的编程游戏:Python Challenge全通攻略

    为什么80%的码农都做不了架构师?>>>    Python Challenge是一个网页闯关游戏,通过一些提示找出下一关的网页地址.与众不同的是,它是专门为程序员设计的,因为大多数 ...

  6. (五)Vue 面试真题演练

    Vue 面试真题演练 v-show和v-if的区别 为何在v-for中用key 描述vue组件生命周期(父子组件) vue组件如何通讯(常见) 描述组件渲染和更新的过程 双向数据绑定v-model的实 ...

  7. 这是我第一次使用代码创建出一个窗口【python 游戏实战 01】

    前言 本系列文章将会以通俗易懂的对话方式进行教学,对话中将涵盖了新手在学习中的一般问题.此系列将会持续更新,包括别的语言以及实战都将使用对话的方式进行教学,基础编程语言教学适用于零基础小白,之后实战课 ...

  8. 这本轻小说真厉害 2016

    傲娇御坂美琴成轻小说女王一姐 轻小说排名公布 到了年底,作为轻小说的粉丝就没有理由不关注"这本轻小说真厉害!"的相关评选吧?腾讯动漫此前曾经报道过<OVERLORD>以 ...

  9. Java摇骰子比大小_还在摇骰子比大小?这几款火热的KTV喝酒游戏你值得收藏

    原标题:还在摇骰子比大小?这几款火热的KTV喝酒游戏你值得收藏 嗨,此时屏幕前的你, 是否正在包厢里和客人尽情高歌. 曲也唱了两三首了, 不如来点酒桌游戏助助兴. 今天带来6种当下最流行的喝酒游戏, ...

最新文章

  1. IntelliJ中的main函数、for循环、System.out.println()快捷键
  2. 国行 lg g3 D858 刷 lg g3 D858hk 教程(备忘)
  3. 小程序 Typescript 最佳实践
  4. 树莓派C语言点灯,树莓派3 b GPIO 点亮小灯泡
  5. linux acl库编译与使用,linux的ACL-rds数据删除了可恢复吗?-WinFrom控件库|.net开源控件库|HZHControls官网...
  6. CRC源码生成工具,可生成Verilog和VHDL
  7. 集体智慧编程 - 读书笔记
  8. FPGA教程和allegro教程-链接
  9. jQ UI 后台管理系统基础UI
  10. java char表_char码值对应列表大全
  11. python爬虫运行时电脑无响应_Python爬虫爬资源时由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。怎么破?...
  12. c++文件的读取和写入
  13. ros-noetic-yocs-cmd-vel-mux
  14. python 涨停统计_Python采集选股宝涨停信息
  15. 求解立方根 java
  16. 智慧城市每年商机超2万亿美元;中德嘉宾共话智慧城市建设 | 智慧城市周报
  17. 企业管理软件领域的核心竞争力
  18. ps流 转发_一种国标PS流转RTMP直播流的实时转换方法与流程
  19. 如何实现超大文件(60G)传输给别人?
  20. 码云的上传、下载项目

热门文章

  1. 【MySQL5.7指南】第三章——教程
  2. exit status 145: The directory is not empty,exit status 5: �ܾ����ʡ� ,nvm切换node版本问题汇总
  3. 微处理机就是微型计算机,他们是《微型计算机》改版20年的历史见证者
  4. 怎样一键制作设计毛笔字体?
  5. JS判断搜索引擎来路跳转代码---百度,360,sogou收录
  6. 聊聊iOS中的网络加密
  7. 阴阳鱼之周期性振幅,与面积
  8. 华科提出首个用于伪装实例分割的一阶段框架OSFormer
  9. 检测国内大型网游戏交易站
  10. 为何优秀的程序员不断离开?