微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)

微信小游戏 demo 飞机大战 代码分析(一)(main.js)

微信小游戏 demo 飞机大战 代码分析(二)(databus.js)

微信小游戏 demo 飞机大战 代码分析(三)(spirit.js, animation.js)

本博客将使用逐行代码分析的方式讲解该demo,本文适用于对其他高级语言熟悉,对js还未深入了解的同学,博主会尽可能将所有遇到的不明白的部分标注清楚,若有不正确或不清楚的地方,欢迎在评论中指正

本文的代码均由微信小游戏自动生成的demo飞机大战中获取

enemy.js

用于实现敌人对象

代码

import Animation from '../base/animation'
import DataBus from '../databus' const ENEMY_IMG_SRC = 'images/enemy.png'
const ENEMY_WIDTH = 60
const ENEMY_HEIGHT = 60 const __ = {
speed: Symbol('speed')
} let databus = new DataBus() function rnd(start, end){
return Math.floor(Math.random() * (end - start) + start)
} export default class Enemy extends Animation {
constructor() {
super(ENEMY_IMG_SRC, ENEMY_WIDTH, ENEMY_HEIGHT) this.initExplosionAnimation()
} init(speed) {
this.x = rnd(0, window.innerWidth - ENEMY_WIDTH)
this.y = -this.height this[__.speed] = speed this.visible = true
} // 预定义爆炸的帧动画
initExplosionAnimation() {
let frames = [] const EXPLO_IMG_PREFIX = 'images/explosion'
const EXPLO_FRAME_COUNT = 19 for ( let i = 0;i < EXPLO_FRAME_COUNT;i++ ) {
frames.push(EXPLO_IMG_PREFIX + (i + 1) + '.png')
} this.initFrames(frames)
} // 每一帧更新子弹位置
update() {
this.y += this[__.speed] // 对象回收
if ( this.y > window.innerHeight + this.height )
databus.removeEnemey(this)
}
}

初始化

导入相应文件

创建所需常量

分别是敌机的图片位置,高度和宽度

创建symbol常量和databus对象

rnd(start,end)

  • Math.random() 用于提供[0,1)区间的浮点数
  • Math.floor() 返回小于等于该数字最大的整数
  • 该函数的作用是返回一个start到end区间(end不取)返回内的一个随机数
  • 在后面该函数用于生成敌机的位置

Enemy

敌人类,继承与Animation类

constructor()

构造器

  • 根据提供的常量初始化敌机对象
  • 并且初始化爆炸动画,该函数在之后实现

init(speed)

初始化敌机速度

  • 获取随机生成x坐标作为起始x位置
  • 获取其本身的高度取负值作为起始y坐标(一开始整个敌机还未进入屏幕,慢慢一点一点进入)
  • js中坐标原点为屏幕左上角,以原点向左为x正方向,原点向下为y正方向,

initExplosionAnimation()

定义爆炸帧动画

  • 创建一个数组
  • 设定爆炸的每一帧动画的具体位置,以及数量
  • 创建一个frames数组,将图片按顺序读取并加入数组中
  • 将该数组作为Animation类中定义的方法initFrames的参数初始化爆炸动画

update()

逻辑更新函数,更新物体的参数,基本每个具体物体都具有该函数

  • 按速度没回合加上一定的y坐标(由于敌机是往下走的,因此加上)

  • 若发现对象移动出屏幕,则将其回收

bullet.js

子弹的实现

初始化

导入相应包

定义需要的基本常量

定义symbol和生成databus

Bullet

子弹实现类,继承于精灵类(没有继承于动画类,其无需动画)

代码

import Sprite   from '../base/sprite'
import DataBus from '../databus' const BULLET_IMG_SRC = 'images/bullet.png'
const BULLET_WIDTH = 16
const BULLET_HEIGHT = 30 const __ = {
speed: Symbol('speed')
} let databus = new DataBus() export default class Bullet extends Sprite {
constructor() {
super(BULLET_IMG_SRC, BULLET_WIDTH, BULLET_HEIGHT)
} init(x, y, speed) {
this.x = x
this.y = y this[__.speed] = speed this.visible = true
} // 每一帧更新子弹位置
update() {
this.y -= this[__.speed] // 超出屏幕外回收自身
if ( this.y < -this.height )
databus.removeBullets(this)
}
}

constructor

构造器

  • 通过预设置的常量初始化超类

init(x, y, speed)

初始化坐标位置和速度

update()

逻辑更新函数

  • 为y坐标向上增加速度的大小,即应该减去速度的数值
  • 将整个子弹超出屏幕外的(因此是小于-this.height而不是0)移入对象池中,即出游戏

index.js

玩家类

代码

import Sprite   from '../base/sprite'
import Bullet from './bullet'
import DataBus from '../databus' const screenWidth = window.innerWidth
const screenHeight = window.innerHeight // 玩家相关常量设置
const PLAYER_IMG_SRC = 'images/hero.png'
const PLAYER_WIDTH = 80
const PLAYER_HEIGHT = 80 let databus = new DataBus() export default class Player extends Sprite {
constructor() {
super(PLAYER_IMG_SRC, PLAYER_WIDTH, PLAYER_HEIGHT) // 玩家默认处于屏幕底部居中位置
this.x = screenWidth / 2 - this.width / 2
this.y = screenHeight - this.height - 30 // 用于在手指移动的时候标识手指是否已经在飞机上了
this.touched = false this.bullets = [] // 初始化事件监听
this.initEvent()
} /**
* 当手指触摸屏幕的时候
* 判断手指是否在飞机上
* @param {Number} x: 手指的X轴坐标
* @param {Number} y: 手指的Y轴坐标
* @return {Boolean}: 用于标识手指是否在飞机上的布尔值
*/
checkIsFingerOnAir(x, y) {
const deviation = 30 return !!( x >= this.x - deviation
&& y >= this.y - deviation
&& x <= this.x + this.width + deviation
&& y <= this.y + this.height + deviation )
} /**
* 根据手指的位置设置飞机的位置
* 保证手指处于飞机中间
* 同时限定飞机的活动范围限制在屏幕中
*/
setAirPosAcrossFingerPosZ(x, y) {
let disX = x - this.width / 2
let disY = y - this.height / 2 if ( disX < 0 )
disX = 0 else if ( disX > screenWidth - this.width )
disX = screenWidth - this.width if ( disY <= 0 )
disY = 0 else if ( disY > screenHeight - this.height )
disY = screenHeight - this.height this.x = disX
this.y = disY
} /**
* 玩家响应手指的触摸事件
* 改变战机的位置
*/
initEvent() {
canvas.addEventListener('touchstart', ((e) => {
e.preventDefault() let x = e.touches[0].clientX
let y = e.touches[0].clientY //
if ( this.checkIsFingerOnAir(x, y) ) {
this.touched = true this.setAirPosAcrossFingerPosZ(x, y)
} }).bind(this)) canvas.addEventListener('touchmove', ((e) => {
e.preventDefault() let x = e.touches[0].clientX
let y = e.touches[0].clientY if ( this.touched )
this.setAirPosAcrossFingerPosZ(x, y) }).bind(this)) canvas.addEventListener('touchend', ((e) => {
e.preventDefault() this.touched = false
}).bind(this))
} /**
* 玩家射击操作
* 射击时机由外部决定
*/
shoot() {
let bullet = databus.pool.getItemByClass('bullet', Bullet) bullet.init(
this.x + this.width / 2 - bullet.width / 2,
this.y - 10,
10
) databus.bullets.push(bullet)
}
}

初始化

导入相应文件

获取屏幕大小作为常量

创建基本常量

Player

玩家类,继承于Spirit类

构造器

  • 初始化超类
  • 设置玩家初始位置,位于屏幕底部并且居中(应注意判断位置是判断其左上角位置)
  • 设定判断是否有触碰的变量和子弹数组
  • 初始化事件监听函数
    • 事件监听相当于是在等待事件的发生,一旦发生就会随之执行的函数

checkIsFingerOnAir(x, y)

判断玩家手指是否在飞机上

  • deviation变量相当于是扩展玩家手指对飞机控制的范围设定的参数
  • 判断手指与飞机的关系和位置

setAirPosAcrossFingerPosZ(x, y)

根据手指的位置设置飞机的位置

保证手指处于飞机中间

同时限定飞机的活动范围限制在屏幕中

initEvent()

监听函数

  • 绑定touchstart事件, 即开始触碰事件,并传入一个匿名函数作为回调函数,作为触发该事件时的回调

    • 若触碰时触碰的是飞机则将飞机被触碰设置为真并且将飞机中心移动到手指中心
    • e.preventDefault() 这是取消事件本身的默认动作的函数
  • 绑定touchmove事件,即触碰移动
    • 若触碰飞机情况为真,则将飞机移动到相应位置
  • 绑定touchend事件,即触碰结束

shoot()

玩家射击函数

  • 从对象池中取一个子弹
  • 根据玩家位置初始化子弹位置

微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)的更多相关文章

  1. 微信小游戏 demo 飞机大战 代码分析 (三)(spirit.js, animation.js)

    微信小游戏 demo 飞机大战 代码分析(三)(spirit.js, animation.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码 ...

  2. 微信小游戏 demo 飞机大战 代码分析 (二)(databus.js)

    微信小游戏 demo 飞机大战 代码分析(二)(databus.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码分析(三)(spirit. ...

  3. 微信小游戏 demo 飞机大战 代码分析 (一)(game.js, main.js)

    微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞机大战 代码分析(二)(databus.js) 微信小游戏 demo 飞机大战 代码分析(三)(spirit. ...

  4. Python小游戏之 - 飞机大战美女 !

    用Python写的"飞机大战美女"小游戏 源代码如下: # coding=utf-8 import os import random import pygame # 用一个常量来存 ...

  5. Python小游戏之 - 飞机大战 !

    用Python写的"飞机大战"小游戏 源代码如下: # coding=utf-8 import random import os import pygame # 用一个常量来存储屏 ...

  6. 微信demo小游戏:飞机大战从无到有

    微信demo游戏飞机大战从无到有 现在创建新项目会默认给飞机大战的demo,这里给大家从基础开始讲解游戏的从无到有是怎么实现的. 具体实现步骤: 创建背景图->背景图运动起来->创建飞机并 ...

  7. 微信小游戏的本地缓存和清除的使用 (text.js image.js file-util.js)

    参考: 微信小游戏,文件系统 UpdateManager-小游戏 一.Egret提供的本地缓存工具类( 备注:新版本进行了修改,并增加了sound.js等) 在微信小游戏项目中,Egret提供了fil ...

  8. 三、微信小游戏开发 --- 小游戏API调用Platform

    微信小游戏API Platform主要是Egret用于来调用平台的SDK的. 在Egret中使用接口定义Platform. Egret项目中默认的platform值是DebugPlatform. 发布 ...

  9. 二、微信小游戏开发 多线程Worker

    微信多线程Worker教程 微信多线程Worker API 一.创建Worker,并和当前线程通讯 多线程worker只能创建1个.能和当前线程互传数据. 创建worker 在微信开发者工具中,在当前 ...

随机推荐

  1. P2746 [USACO5.3]校园网Network of Schools

    传送门 把所有学校的关系构成一个图,显然一个强联通分量的所有学校只要有一个有新软件,其他学校也都会有 考虑缩点,发现入度为 0 的块一定要给,因为没有其他人给它 入度不为 0 的块一定有其他人给,我们 ...

  2. js 数据类型及检测

    js中基本数据类型有6种number.string.undefined.null.boolean,Symbol (ES6 新增,表示独一无二的值),还有一种数据类型为引用数据类型统称为Object对象 ...

  3. CentOS6.x之emacs安装配置编译

    刚开始学习linux,干学没什么意思,想在linux下写写程序,了解到linux下使用较多的是emacs和vim,在youtobe上分别看了看这两个工具进行开发的视频,个人感觉emacs比较酷一点,所 ...

  4. Python 将IP转换为int

    import socket import struct if __name__ == '__main__': ip = '127.0.0.1' int_ip = struct.unpack('!I', ...

  5. 如何让nginx支持ThinkPHP框架(重点参考)

    公司有一款即将上线的应用服务端是基于ThinkPHP写的,本地测试无异常,上传到外网服务器后无法连接.这可把我和我的小伙伴们吓死了,怎么回事儿,本地测试都是对的呀! 我和我的小伙伴们开始找原因,换了一 ...

  6. [WPF自定义控件库]简单的表单布局控件

    1. WPF布局一个表单 <Grid Width="400" HorizontalAlignment="Center" VerticalAlignment ...

  7. 设计模式--观察者模式(KVO)

    观察者模式(Observer):观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 举个例子, ...

  8. wepy-cli 开发小程序如何使用vant组件

    同样使用wepy-cli快速生成的小程序,目前可以使用组件: 直接通过 git 下载 Vant Weapp 源代码,并将dist目录拷贝到自己的项目中 git clone https://github ...

  9. JFrame 文本打印

    package tools; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import jav ...

  10. newsyslog.conf详解

    newsyslog.conf 指出了哪个日志文件要被管理,要保留多少和它们什么时候被创建.日志文件可以在它们达到一定大小或者在特定的日期被重新整理.# configuration file for n ...