一.设计
二.创建框架类
微信小游戏中game.js和game.json是必备的两个文件。
首先创建js文件夹中存放base、player、和runtime三个文件夹用来存放相关类,以及一个导演类。
1.base
base中存放为基本类,包括变量缓冲器(DataStore)变量缓存器,方便我们在不同的类中访问和修改变量。资源文件加载器(ResourceLoader),确保canvas在图片资源加载完成后才进行渲染。Resources类,以及精灵类(Sprite)精灵的基类,负责初始化精灵加载的资源和大小以及位置。
2.player
player中存放与玩家发生交互的类。包括小鸟类(Birds),计分器类(Score),开始按钮类(StartButton)。
3.runtime
runtime类存放与游戏进行有关的类,背景类(BackGround),陆地类(Land)不断移动的陆地,上半部分障碍物类(UpPencil)这里是铅笔和下半部分铅笔类(DownPencil)。
之外js中还包括一个导演类(Director),用来控制游戏的逻辑。
外层还有一个main.js,初始化整个游戏的精灵,作为游戏开始的入口。
此时目录列表如下:
三. 导入图片文件
资源类resources:
1 /*创建一个数组 background对应的是相应的资源*/ 2 export const Resources = [ 3 ['background', 'res/background.png'], 4 ['land', 'res/land.png'], 5 ['pencilUp', 'res/pie_up.png'], 6 ['pencilDown', 'res/pie_down.png'], 7 ['birds', 'res/birds.png'], 8 ['startButton', 'res/start_button.png'] 9 ]
资源文件加载器 resourceloader:
1 //资源文件加载器,确保canvas在图片资源加载完成后才进行渲染 2 import {Resources} from "./Resources.js"; 3 4 export class ResourceLoader { 5 6 constructor() { 7 //直接this.map自动创建对象 8 /*Map是一个数据类型,实质上是一个键值对,前面是名后面是值, 9 可以通过set的方法来设置 m.set(o,'content') 10 也可以直接传入一个数组来设置,这里传入Resource数组*/ 11 this.map = new Map(Resources); 12 for (let [key, value] of this.map) { 13 //将map里的value替换,将相对路径替换为图片image本身 14 const image = new Image(); 15 image.src = value; 16 this.map.set(key, image); 17 } 18 } 19 20 /*确保所有图片加载完毕*/ 21 onLoaded(callback) { 22 let loadedCount = 0; 23 for (let value of this.map.values()) { 24 value.onload = () => { 25 //this指向外部的实力对象 26 loadedCount++; 27 if (loadedCount >= this.map.size) { 28 callback(this.map) 29 } 30 } 31 } 32 } 33 34 //静态工厂 35 static create(){ 36 return new ResourceLoader(); 37 } 38 }
四.主体开发
1、导演类单例开发
DircDirector类:
1 //导演类,控制游戏的逻辑 2 /*单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。
通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例 3 */ 4 export class Director { 5 6 //验证单例成功 即只可以有一个实例 7 constructor(){ 8 console.log('构造器初始化') 9 } 10 11 /*使用getInstance方法为定义一个单例对象,如果实例创建了则返回创建类 12 若没有创建则创建instance*/ 13 static getInstance() { 14 if (!Director.instance) { 15 Director.instance = new Director(); 16 } 17 return Director.instance; 18 } 19 }
我们可以通过主体函数Main.js中验证是否导演类为单例。如下:
1 import {ResourceLoader} from "./js/base/ResourceLoader.js"; 2 import {Director} from "./js/Director.js"; 3 4 export class Main { 5 constructor() { 6 this.canvas = document.getElementById('game_canvas'); 7 this.ctx = this.canvas.getContext('2d'); 8 const loader = ResourceLoader.create(); 9 loader.onLoaded(map => this.onResourceFirstLoaded(map)) 10 11 Director.getInstance(); 12 Director.getInstance(); 13 Director.getInstance(); 14 15 } 16 17 onResourceFirstLoaded(map) { 18 console.log(map) 19 } 20 }
我们可以看到在主体函数中我们调用了三次导演类的构造函数,而浏览器中的显示为下,说明只是创建了一个类,而之后则是反复调用之前的实例。
持续更新