利用原生js实现html5小游戏之打砖块(附源码)


Posted in Javascript onJanuary 03, 2018

前言

PS:本次项目中使用了大量 es6 语法,故对于 es6 语法不太熟悉的小伙伴最好能先了解一些基本的原理再继续阅读。

首先,先说明一下做这个系列的目的:其实主要源于博主希望熟练使用 canvas 的相关 api ,同时对小游戏的实现逻辑比较感兴趣,所以希望通过这一系列的小游戏来提升自身编程能力;关于 es6 语法,个人认为以后 es6 语法会越来越普及,所以算是提前熟悉语法使用技巧。小游戏的实现逻辑上可能并不完善,也许会有一些 bug ,但是毕竟只是为了提升编程能力与技巧,希望大家不要太较真

作为第一次分享,我选择打砖块这个逻辑不算太复杂的小游戏。同时,为了接近真实游戏效果,在游戏中也添加了关卡,砖块血量,以及物理碰撞模型的简略实现。其实关注游戏实现逻辑就好了

线上演示地址:http://demo.3water.com/js/2018/h5-game-blockBreaker

github地址:https://github.com/yangyunhe369/h5-game-blockBreaker

本地下载地址:http://xiazai.3water.com/201801/yuanma/h5-game-blockBreaker(3water.com).rar

ps:github地址和本地下载有代码演示,以及源码可供参考,线上演示地址可供预览

先上一个游戏完成后的截图

利用原生js实现html5小游戏之打砖块(附源码)

游戏工程目录如下

.
├─ index.html // 首页html
│ 
├─ css // css样式资源文件
├─ images // 图片资源文件 
└─ js
 ├─ common.js // 公共js方法
 ├─ game.js // 游戏主要运行逻辑
 └─ scene.js // 游戏场景相关类

游戏实现逻辑

这里对游戏中需要绘制的挡板、小球、砖块、计分板都进行了实例化,并将游戏主要运行逻辑单独进行实例化

挡板 Paddle

class Paddle {
 constructor (_main) {
 let p = {
 x: _main.paddle_x,  // x 轴坐标
 y: _main.paddle_y,  // y 轴坐标
 w: 102,  // 图片宽度
 h: 22,  // 图片高度
 speed: 10,  // x轴移动速度
 ballSpeedMax: 8,  // 小球反弹速度最大值
 image: imageFromPath(allImg.paddle), // 引入图片对象
 isLeftMove: true,  // 能否左移
 isRightMove: true,  // 能否右移
 }
 Object.assign(this, p)
 }
 // 向左移动
 moveLeft () {
 ...
 }
 // 向右移动
 moveRight () {
 ...
 }
 // 小球、挡板碰撞检测
 collide (ball) {
 ...
 }
 // 计算小球、挡板碰撞后x轴速度值
 collideRange (ball) {
 ...
 }
}

挡板类:主要会定义其坐标位置、图片大小、x 轴位移速度、对小球反弹速度的控制等,再根据不同按键响应 moveLeft 和 moveRight 移动事件,collide 方法检测小球与挡板是否碰撞,并返回布尔值

小球 Ball

class Ball {
 constructor (_main) {
 let b = {
 x: _main.ball_x, // x 轴坐标
 y: _main.ball_y, // y 轴坐标
 w: 18, // 图片宽度
 h: 18, // 图片高度
 speedX: 1, // x 轴速度
 speedY: 5, // y 轴速度
 image: imageFromPath(allImg.ball), // 图片对象
 fired: false, // 是否运动,默认静止不动
 }
 Object.assign(this, b)
 }
 move (game) {
 ...
 }
}

小球类:其大部分属性与挡板类似,主要通过 move 方法控制小球运动轨迹

砖块 Block

class Block {
 constructor (x, y, life = 1) {
 let bk = {
 x: x,     // x 轴坐标
 y: y,     // y 轴坐标
 w: 50,     // 图片宽度
 h: 20,     // 图片高度
 image: life == 1 ? imageFromPath(allImg.block1) : imageFromPath(allImg.block2), // 图片对象
 life: life,     // 生命值
 alive: true,     // 是否存活
 }
 Object.assign(this, bk)
 }
 // 消除砖块
 kill () {
 ...
 }
 // 小球、砖块碰撞检测
 collide (ball) {
 ...
 }
 // 计算小球、砖块碰撞后x轴速度方向
 collideBlockHorn (ball) {
 ...
 }
}

砖块类:会有两个属性不同,分别是 life 和 是否存活。然后,在小球和砖块撞击时,调用 kill 方法扣除当前砖块血量,当血量为0时,清除砖块。collide 方法检测小球与砖块是否碰撞,并返回布尔值

计分板 Score

class Score {
 constructor (_main) {
 let s = {
 x: _main.score_x,  // x 轴坐标
 y: _main.score_y,  // y 轴坐标
 text: '分数:',   // 文本分数
 textLv: '关卡:',  // 关卡文本
 score: 200,   // 每个砖块对应分数
 allScore: 0,   // 总分
 blockList: _main.blockList,  // 砖块对象集合
 blockListLen: _main.blockList.length, // 砖块总数量
 lv: _main.LV,   // 当前关卡
 }
 Object.assign(this, s)
 }
 // 计算总分
 computeScore () {
 ...
 }
}

分数类:会记录当前分数、关卡数,其中 computeScore 方法会在小球碰撞砖块且砖块血量为0时调用,并累加总分

场景 Scene

class Scene {
 constructor (lv) {
 let s = {
 lv: lv,   // 游戏难度级别
 canvas: document.getElementById("canvas"), // canvas 对象
 blockList: [],   // 砖块坐标集合
 }
 Object.assign(this, s)
 }
 // 实例化所有砖块对象
 initBlockList () {
 ...
 }
 // 创建砖块坐标二维数组,并生成不同关卡
 creatBlockList () {
 ...
 }
}

场景类:主要是根据游戏难度级别,绘制不同关卡及砖块集合(目前只生成了三个关卡)。其中 creatBlockList 方法先生成所有砖块的二维坐标数组,再调用 initBlockList 方法进行所有砖块的实例化

游戏主逻辑 Game

class Game {
 constructor (fps = 60) {
 let g = {
 actions: {},    // 记录按键动作
 keydowns: {},    // 记录按键 keycode
 state: 1,    // 游戏状态值,初始默认为1
 state_START: 1,   // 开始游戏
 state_RUNNING: 2,   // 游戏开始运行
 state_STOP: 3,   // 暂停游戏
 state_GAMEOVER: 4,   // 游戏结束
 state_UPDATE: 5,   // 游戏通关
 canvas: document.getElementById("canvas"),  // canvas 元素
 context: document.getElementById("canvas").getContext("2d"), // canvas 画布
 timer: null,    // 轮询定时器
 fps: fps,    // 动画帧数,默认60
 }
 Object.assign(this, g)
 }
 ...
}

游戏核心类:这里包括游戏主要运行逻辑,包括但不限于以下几点

  • 绘制游戏整个场景
  • 调用定时器逐帧绘制动画
  • 游戏通关及游戏结束判定
  • 绑定按钮事件
  • 边界检测处理函数
  • 碰撞检测处理函数

入口函数 _main

let _main = {
 LV: 1,  // 初始关卡
 MAXLV: 3,  // 最终关卡
 scene: null,  // 场景对象
 blockList: null,  // 所有砖块对象集合
 ball: null,  // 小球对象
 paddle: null,  // 挡板对象
 score: null,  // 计分板对象
 ball_x: 491,  // 小球默认 x 轴坐标
 ball_y: 432,  // 小球默认 y 轴坐标
 paddle_x: 449,  // 挡板默认 x 轴坐标
 paddle_y: 450,  // 挡板默认 y 轴坐标
 score_x: 10,  // 计分板默认 x 轴坐标
 score_y: 30,  // 计分板默认 y 轴坐标
 fps: 60,  // 游戏运行帧数
 game: null,  // 游戏主要逻辑对象
 start: function () {
 let self = this
 /**
 * 生成场景(根据游戏难度级别不同,生成不同关卡)
 */
 self.scene = new Scene(self.LV)
 // 实例化所有砖块对象集合
 self.blockList = self.scene.initBlockList()
 /**
 * 小球
 */
 self.ball = new Ball(self)
 /**
 * 挡板
 */
 self.paddle = new Paddle(self)
 /**
 * 计分板
 */
 self.score = new Score(self)
 /**
 * 游戏主要逻辑
 */
 self.game = new Game(self.fps)
 /**
 * 游戏初始化
 */
 self.game.init(self)
 }
}

入口函数:实现了游戏中需要的所有类的实例化,并进行游戏的初始化

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JS实现控制表格单元格垂直对齐的方法
Mar 30 Javascript
高效的jquery数字滚动特效
Dec 17 Javascript
JavaScript中apply方法的应用技巧小结
Sep 29 Javascript
node.js中的事件处理机制详解
Nov 26 Javascript
最好用的Bootstrap fileinput.js文件上传组件
Dec 12 Javascript
JavaScript实现翻页功能(附效果图)
Feb 16 Javascript
JS中利用FileReader实现上传图片前本地预览功能
Mar 02 Javascript
Moment.js实现多个同时倒计时
Aug 26 Javascript
详解vue中使用axios对同一个接口连续请求导致返回数据混乱的问题
Nov 06 Javascript
使用JavaScript实现网页秒表功能(含开始、暂停、继续、重置功能)
Jun 05 Javascript
Element Popover 弹出框的使用示例
Jul 26 Javascript
原生js实现表格循环滚动
Nov 24 Javascript
js判断文件类型大小并给出提示的实现方法
Jan 03 #Javascript
js登录滑动验证的实现(不滑动无法登陆)
Jan 03 #Javascript
Angular实现下拉框模糊查询功能示例
Jan 03 #Javascript
Node使用Sequlize连接Mysql报错:Access denied for user ‘xxx’@‘localhost’
Jan 03 #Javascript
angularjs实现分页和搜索功能
Jan 03 #Javascript
vue引入ueditor及node后台配置详解
Jan 03 #Javascript
Node.js搭建小程序后台服务
Jan 03 #Javascript
You might like
php上传、管理照片示例
2006/10/09 PHP
用PHPdig打造属于你自己的Google[图文教程]
2007/02/14 PHP
PHP实现手机归属地查询API接口实现代码
2012/08/27 PHP
php打开本地exe程序,js打开本地exe应用程序,并传递相关参数方法
2018/02/06 PHP
图像替换新技术 状态域方法
2010/01/28 Javascript
jQuery LigerUI 使用教程表格篇(1)
2012/01/18 Javascript
jQuery 插件仿百度搜索框智能提示(带Value值)
2013/01/22 Javascript
js的2种继承方式详解
2014/03/04 Javascript
JavaScript中数据结构与算法(五):经典KMP算法
2015/06/19 Javascript
jquery实现的点击翻书效果代码
2015/11/04 Javascript
详解javascript传统方法实现异步校验
2016/01/22 Javascript
AngularJS基础 ng-keyup 指令简单示例
2016/08/02 Javascript
Select2.js下拉框使用小结
2016/10/24 Javascript
微信公众号 摇一摇周边功能开发
2016/12/08 Javascript
js实现简单的网页换肤效果
2017/01/18 Javascript
Angular.js与node.js项目里用cookie校验账户登录详解
2017/02/22 Javascript
基于 Bootstrap Datetimepicker 联动
2017/08/03 Javascript
jquery根据name取得select选中的值实例(超简单)
2018/01/25 jQuery
javascript中的隐式调用
2018/02/10 Javascript
js实现贪吃蛇小游戏
2019/10/29 Javascript
python实现bucket排序算法实例分析
2015/05/04 Python
python语言使用技巧分享
2016/05/31 Python
Python读取实时数据流示例
2019/12/02 Python
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
Python loguru日志库之高效输出控制台日志和日志记录
2020/03/07 Python
python的setattr函数实例用法
2020/12/16 Python
jupyter 添加不同内核的操作
2021/02/06 Python
德国奢侈品网上商城:Mytheresa
2016/08/24 全球购物
中国京东和泰国中央集团合资的网站:JD CENTRAL
2020/08/22 全球购物
Vuori官网:运动服装的终级表现
2021/01/27 全球购物
C语言中一个结构不能包含指向自己的指针吗
2012/05/25 面试题
马智宇结婚主持词
2014/04/01 职场文书
实习协议书范本
2014/04/22 职场文书
航海技术专业毕业生推荐信
2014/07/09 职场文书
行政执法作风整顿剖析材料
2014/10/11 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书