原生js做h5小游戏之打砖块-阿里云开发者社区

开发者社区> 哈你真皮> 正文

原生js做h5小游戏之打砖块

简介: 前言 首先,先说明一下做这个系列的目的:其实主要源于博主希望熟练使用 canvas 的相关 api ,同时对小游戏的实现逻辑比较感兴趣,所以希望通过这一系列的小游戏来提升自身编程能力;关于 es6 语法,个人认为以后 es6 语法会越来越普及,所以算是提前熟悉语法使用技巧。
+关注继续查看

前言

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

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

线上演示地址:https://yangyunhe369.github.io/h5-game-blockBreaker/
github地址:https://github.com/yangyunhe369/h5-game-blockBreaker
ps:github地址有代码演示,以及源码可供参考,线上演示地址可供预览

先上一个游戏完成后的截图
这里写图片描述

游戏工程目录如下

.
├─ 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)
  }
}

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

作者: 弦云孤赫 原文链接: http://www.yangyunhe.me/2017/h5-game-blockBreaker/
本文可以转载,但务必注明原作者和原出处。
ps:博主在本次项目中使用了大量 es6 语法,故对于 es6 语法不太熟悉的小伙伴最好能先了解一些基本的原理再继续阅读。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
8769 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
2862 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11061 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10593 0
使用OpenApi弹性释放和设置云服务器ECS释放
云服务器ECS的一个重要特性就是按需创建资源。您可以在业务高峰期按需弹性的自定义规则进行资源创建,在完成业务计算的时候释放资源。本篇将提供几个Tips帮助您更加容易和自动化的完成云服务器的释放和弹性设置。
11959 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
12440 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
8886 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
4575 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
21766 0
+关注
355
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载