-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
the initial commit, modified some blanks and few comments.
- Loading branch information
0 parents
commit 27e3aa5
Showing
61 changed files
with
3,243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# 云开发小游戏 QuickStart | ||
|
||
## 快速启动步骤 | ||
|
||
1. 点击工具栏左侧 “云开发” 按钮,根据提示在控制台中开通云服务 | ||
2. 根据提示创建第一个环境(注:初始可免费拥有两个环境,建议一个为测试环境,一个为正式环境,分别命名为 test 和 release) | ||
3. 在控制台中切换到 “数据库” 管理页,创建第一个名为 “score” 的集合,用于存放分数 | ||
4. 在工具编辑器目录树中,右键目录 "cloudfunction" 选择 “更多设置”,在打开的窗口上方下拉选择刚创建的环境 | ||
5. 在编辑器 "cloudfunction" 目录下,右击目录 “login”,选择新建并上传该云函数,该云函数负责获取用户 openid | ||
6. 在编辑器 "cloudfunction" 目录下,右击目录 “uploadScore”,选择新建并上传该云函数,该云函数负责记录用户分数到数据库 | ||
7. 体验小游戏! | ||
|
||
## 云开发版 QuickStart 小游戏端与普通小游戏 QuickStart 差异一览 | ||
|
||
- `main.js`:增加了云能力初始化方法(约 11 行)、获取用户 openid(约 22 行)、获取历史最高分(约 41 行)、调用云函数上传结果(约 130 行)、调用渲染 GameOver 画面时多传入历史最高分(约 198 行) | ||
- `gameinfo.js`:增加了渲染历史最高分(约 37 行) | ||
|
||
|
||
## 小游戏源码目录介绍 | ||
|
||
``` | ||
./miniprogram/js | ||
├── base // 定义游戏开发基础类 | ||
│ ├── animatoin.js // 帧动画的简易实现 | ||
│ ├── pool.js // 对象池的简易实现 | ||
│ └── sprite.js // 游戏基本元素精灵类 | ||
├── libs | ||
│ ├── symbol.js // ES6 Symbol简易兼容 | ||
│ └── weapp-adapter.js // 小游戏适配器 | ||
├── npc | ||
│ └── enemy.js // 敌机类 | ||
├── player | ||
│ ├── bullet.js // 子弹类 | ||
│ └── index.js // 玩家类 | ||
├── runtime | ||
│ ├── background.js // 背景类 | ||
│ ├── gameinfo.js // 用于展示分数和结算界面 | ||
│ └── music.js // 全局音效管理器 | ||
├── databus.js // 管控游戏状态 | ||
└── main.js // 游戏入口主函数 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// 云函数入口函数 | ||
exports.main = async (event, context) => { | ||
return { | ||
openid: event.userInfo.openId | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "login", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"wx-server-sdk": "latest" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// 云函数入口文件 | ||
const cloud = require('wx-server-sdk') | ||
|
||
// 与小程序端一致,均需调用 init 方法初始化 | ||
cloud.init() | ||
|
||
// 可在入口函数外缓存 db 对象 | ||
const db = cloud.database() | ||
|
||
// 数据库查询更新指令对象 | ||
const _ = db.command | ||
wx.cloud = false | ||
|
||
// 云函数入口函数 | ||
exports.main = async (event, context) => { | ||
|
||
// 以 openid-score 作为记录 id | ||
const docId = `${event.userInfo.openId}-score` | ||
|
||
let userRecord | ||
|
||
try { | ||
const querResult = await db.collection('score').doc(docId).get() | ||
userRecord = querResult.data | ||
} catch(err) { | ||
// 用户第一次上传分数 | ||
} | ||
|
||
if (userRecord) { | ||
// 更新用户分数 | ||
|
||
const maxScore = userRecord.scores.concat([event.score]).reduce((acc, cur) => cur > acc ? cur : acc) | ||
|
||
const updateResult = await db.collection('score').doc(docId).update({ | ||
data: { | ||
// _.push 指往 scores 数组字段尾部添加一个记录,该操作为原子操作 | ||
scores: _.push(event.score), | ||
max: maxScore, | ||
} | ||
}) | ||
|
||
if (updateResult.stats.updated === 0) { | ||
// 没有更新成功,更新数为 0 | ||
return { | ||
success: false | ||
} | ||
} | ||
|
||
return { | ||
success: true, | ||
updated: true | ||
} | ||
|
||
} else { | ||
// 创建新的用户记录 | ||
await db.collection('score').add({ | ||
// data 是将要被插入到 score 集合的 JSON 对象 | ||
data: { | ||
// 这里指定了 _id,如果不指定,数据库会默认生成一个 | ||
_id: docId, | ||
// 这里指定了 _openid,因在云函数端创建的记录不会默认插入用户 openid,如果是在小程序端创建的记录,会默认插入 _openid 字段 | ||
_openid: event.userInfo.openId, | ||
// 分数历史 | ||
scores: [event.score], | ||
// 缓存最大值 | ||
max: event.score, | ||
} | ||
}) | ||
|
||
return { | ||
success: true, | ||
created: true, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "uploadScore", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"wx-server-sdk": "latest" | ||
} | ||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import './js/libs/weapp-adapter' | ||
import './js/libs/symbol' | ||
|
||
import Main from './js/main' | ||
|
||
new Main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"deviceOrientation": "portrait" | ||
} |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
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() | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const __ = { | ||
poolDic: Symbol('poolDic') | ||
} | ||
|
||
/** | ||
* 简易的对象池实现 | ||
* 用于对象的存贮和重复使用 | ||
* 可以有效减少对象创建开销和避免频繁的垃圾回收 | ||
* 提高游戏性能 | ||
*/ | ||
export default class Pool { | ||
constructor() { | ||
this[__.poolDic] = {} | ||
} | ||
|
||
/** | ||
* 根据对象标识符 | ||
* 获取对应的对象池 | ||
*/ | ||
getPoolBySign(name) { | ||
return this[__.poolDic][name] || ( this[__.poolDic][name] = [] ) | ||
} | ||
|
||
/** | ||
* 根据传入的对象标识符,查询对象池 | ||
* 对象池为空创建新的类,否则从对象池中取 | ||
*/ | ||
getItemByClass(name, className) { | ||
let pool = this.getPoolBySign(name) | ||
|
||
let result = ( pool.length | ||
? pool.shift() | ||
: new className() ) | ||
|
||
return result | ||
} | ||
|
||
/** | ||
* 将对象回收到对象池 | ||
* 方便后续继续使用 | ||
*/ | ||
recover(name, instance) { | ||
this.getPoolBySign(name).push(instance) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* 游戏基础的精灵类 | ||
*/ | ||
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.classification = 0 | ||
this.isLiving = 0 | ||
// Math.floor(Math.random() * 4) + 1 | ||
// console.log(this.classification) | ||
this.x = x | ||
this.y = y | ||
|
||
this.visible = true | ||
} | ||
|
||
/** | ||
* 将精灵图绘制在canvas上 | ||
*/ | ||
drawToCanvas(ctx) { | ||
// console.log(this.visible) | ||
if (!this.visible) | ||
return | ||
//ctx.strokeStyle='fgba(255,0,0,0.5)' | ||
//ctx.fillStyle='rgba(255,0,0,0.5)' | ||
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) | ||
} | ||
|
||
|
||
come(x, y, classifition) { | ||
|
||
} | ||
} |
Oops, something went wrong.