微信小程序过后,腾讯又刮起了微信小游戏的,就在不久前,腾讯开放了个人的微信小游戏,也就意味着个人开发者可以开发自己的微信小游戏并上架,让个人'创业'成为可能。
对于微信小游戏,我自己也一直关注着,时时刻刻的也在学习。下面是我自己开发的一个微信小游戏,开源以供大家参考学习(本人能力有限,不足之处请及时指出),效果图如下。
游戏源码放在github上,以及自己的个人博客上
注意: 该项目采用ES6进行编写。
1.1 小游戏结构目录
小游戏的结构目录,参考微信官网的示例游戏——打飞机,其目录结构如下
./js
├── game.js //游戏入口函数
├── game.json //配置文件
├── Main.js //游戏入口主函数
├─audio
│ └──bgm.mp3 //音乐文件
│
├─js
│ ├── Director.js //导演类
│ │
│ ├─ base
│ │ ├── DataStore.js //数据存储类
│ │ ├── ResourceLoader.js //资源加载类
│ │ ├── Resources.js //资源类
│ │ └── Sprite.js //游戏基本元素精灵类
│ │
│ ├─ player
│ │ ├── Move.js //移动者类
│ │ ├── Score.js //分数统计类
│ │ └── StartButton.js //开始按钮类
│ │
│ └─runtime
│ ├── Background.js //背景图片类
│ ├── Coin.js //金币类
│ ├── Fire.js //火类
│ └── Land.js //陆地类
│
└─res //资源文件夹
此目录结构仅供参考,根据自己的实际情况进行修改
1.2 部分源码介绍
1.2.1 DataStore.js
此文件用于管理全局的变量。
//变量缓存器
export class DataStore {
//该类的静态方法,用于创建单利模式
static getInstance() {
if (!DataStore.instance) {
DataStore.instance = new DataStore();
}
return DataStore.instance;
}
constructor() {
this.map = new Map();
}
//添加变量的方法
put(key, value) {
if (typeof value === 'function') {
value = new value();
}
this.map.set(key, value);
return this;
}
//获取变量的方法
get(key) {
return this.map.get(key);
}
//清除所有变量
destroy() {
this.map.clear();
}
}
该类主要用于保存变量,把全局的变量都可以往该类上进行挂载,方便其他类中使用。游戏结束需要回收的资源以key==>value的形式放在Map中,游戏结束不回收的资源作为类变量保存;
1.2.2 ResourceLoader.js
此文件用于加载资源
//加载资源的类
export class ResourceLoader {
constructor() {
this.map = new Map(Resources);
for (let [key, value] of this.map) {
const image = wx.createImage();
image.src = value;
this.map.set(key, image);
}
}
//资源加载方法,确保资源加载完成
onLoaded(callback) {
let loadedCount = 0;
for (let value of this.map.values()) {
value.onload = () => {
loadedCount++;
if (loadedCount >= this.map.size) {
callback(this.map)
}
}
}
}
static create() {
return new ResourceLoader()
}
}
该类主要用于加载资源,确保在资源加载完成的情况下再开始游戏。
1.2.2 Director.js
在Direcotor.js文件中,主要是游戏逻辑,大致主要划分为:创建金币、火,碰撞检测,计分系统,向Canvas上渲染图片
创建金币、火
createFire() {
const X1 = Math.random() * (this.dataStore.canvas.width - 54);
this.dataStore.get('fires').push(new Fire(X1));
}
createCoin() {
const X1 = Math.random() * (this.dataStore.canvas.width - 54);
this.dataStore.get('coins').push(new Coin(X1));
}
碰撞检测
/**
* 落物存在两种:
* 1.如果是金币碰撞就加分。
* 2.如果是火碰撞就游戏结束。
* @param {*} fall 落物对象
* @param {*} mover 移动对象
* @param {*} type 落物类型
*/
static isCollision(fall, mover) {
let s = false;
//落物碰撞检测
if (fall.bottom > mover.top &&
fall.top < mover.bottom &&
fall.right > mover.left &&
fall.left < mover.right) {
s = true;
}
return s;
}
渲染图片
this.dataStore.get('background').draw();
const coins = this.dataStore.get('coins');
const fires = this.dataStore.get('fires');
if (this.INIT_FIRE_NUM <= 4) {
this.createFire();
this.INIT_FIRE_NUM++;
} else {
for (let i = 0; i < this.INIT_FIRE_NUM; i++) {
if (fires[i].Y > this.dataStore.canvas.height) {
fires.splice(i, 1);
this.INIT_FIRE_NUM--;
}
};
}
if (this.INIT_COIN_NUM <= 3) {
this.createCoin();
this.INIT_COIN_NUM++;
} else {
for (let i = 0; i < this.INIT_COIN_NUM; i++) {
if (coins[i].Y > this.dataStore.canvas.height) {
coins.splice(i, 1);
this.INIT_COIN_NUM--;
}
}
}
this.dataStore.get('coins').forEach((value) => {
value.draw();
})
this.dataStore.get('fires').forEach((value) => {
value.draw();
})
this.dataStore.get('land').draw();
this.dataStore.get('move').draw();
this.dataStore.get('score').draw();
let timer = requestAnimationFrame(() => this.run());
this.dataStore.put('timer', timer);
项目的每个文件就不一一介绍了。