微信小遊戲 demo 飛機大戰 代碼分析(一)(main.js)html
微信小遊戲 demo 飛機大戰 代碼分析(二)(databus.js)canvas
微信小遊戲 demo 飛機大戰 代碼分析(四)(enemy.js, bullet.js, index.js)數組
本博客將使用逐行代碼分析的方式講解該demo,本文適用於對其餘高級語言熟悉,對js還未深刻了解的同窗,博主會盡量將全部遇到的不明白的部分標註清楚,如有不正確或不清楚的地方,歡迎在評論中指正微信
本文的代碼均由微信小遊戲自動生成的demo飛機大戰中獲取ide
遊戲基礎的精靈類函數
代碼oop
/** * 遊戲基礎的精靈類 */ export default class Sprite { constructor(imgSrc = '', width= 0, height = 0, x = 0, y = 0) { this.img = new Image() this.img.src = imgSrc this.width = width this.height = height this.x = x this.y = y this.visible = true } /** * 將精靈圖繪製在canvas上 */ drawToCanvas(ctx) { if ( !this.visible ) return ctx.drawImage( this.img, this.x, this.y, this.width, this.height ) } /** * 簡單的碰撞檢測定義: * 另外一個精靈的中心點處於本精靈所在的矩形內便可 * @param{Sprite} sp: Sptite的實例 */ isCollideWith(sp) { let spX = sp.x + sp.width / 2 let spY = sp.y + sp.height / 2 if ( !this.visible || !sp.visible ) return false return !!( spX >= this.x && spX <= this.x + this.width && spY >= this.y && spY <= this.y + this.height ) } }
構造器動畫
將精靈畫於畫布上this
動畫類所在文件code
代碼
import Sprite from './sprite' import DataBus from '../databus' let databus = new DataBus() const __ = { timer: Symbol('timer'), } /** * 簡易的幀動畫類實現 */ export default class Animation extends Sprite { constructor(imgSrc, width, height) { super(imgSrc, width, height) // 當前動畫是否播放中 this.isPlaying = false // 動畫是否須要循環播放 this.loop = false // 每一幀的時間間隔 this.interval = 1000 / 60 // 幀定時器 this[__.timer] = null // 當前播放的幀 this.index = -1 // 總幀數 this.count = 0 // 幀圖片集合 this.imgList = [] /** * 推入到全局動畫池裏面 * 便於全局繪圖的時候遍歷和繪製當前動畫幀 */ databus.animations.push(this) } /** * 初始化幀動畫的全部幀 * 爲了簡單,只支持一個幀動畫 */ initFrames(imgList) { imgList.forEach((imgSrc) => { let img = new Image() img.src = imgSrc this.imgList.push(img) }) this.count = imgList.length } // 將播放中的幀繪製到canvas上 aniRender(ctx) { ctx.drawImage( this.imgList[this.index], this.x, this.y, this.width * 1.2, this.height * 1.2 ) } // 播放預約的幀動畫 playAnimation(index = 0, loop = false) { // 動畫播放的時候精靈圖再也不展現,播放幀動畫的具體幀 this.visible = false this.isPlaying = true this.loop = loop this.index = index if ( this.interval > 0 && this.count ) { this[__.timer] = setInterval( this.frameLoop.bind(this), this.interval ) } } // 中止幀動畫播放 stop() { this.isPlaying = false if ( this[__.timer] ) clearInterval(this[__.timer]) } // 幀遍歷 frameLoop() { this.index++ if ( this.index > this.count - 1 ) { if ( this.loop ) { this.index = 0 } else { this.index-- this.stop() } } } }
繼承於Sprite類
構造器
初始化幀動畫的全部幀
把播放中的幀畫到畫布上
中止幀動畫播放
幀遍歷