Skip to content

Commit

Permalink
the initial commit, modified some blanks and few comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
BigSaltyFish committed Feb 3, 2019
0 parents commit 27e3aa5
Show file tree
Hide file tree
Showing 61 changed files with 3,243 additions and 0 deletions.
42 changes: 42 additions & 0 deletions README.md
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 // 游戏入口主函数
```
6 changes: 6 additions & 0 deletions cloudfunction/login/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// 云函数入口函数
exports.main = async (event, context) => {
return {
openid: event.userInfo.openId
}
}
14 changes: 14 additions & 0 deletions cloudfunction/login/package.json
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"
}
}
75 changes: 75 additions & 0 deletions cloudfunction/uploadScore/index.js
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,
}
}
}
14 changes: 14 additions & 0 deletions cloudfunction/uploadScore/package.json
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 added miniprogram/audio/bgm.mp3
Binary file not shown.
Binary file added miniprogram/audio/boom.mp3
Binary file not shown.
Binary file added miniprogram/audio/bullet.mp3
Binary file not shown.
6 changes: 6 additions & 0 deletions miniprogram/game.js
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()
3 changes: 3 additions & 0 deletions miniprogram/game.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"deviceOrientation": "portrait"
}
Binary file added miniprogram/images/.DS_Store
Binary file not shown.
Binary file added miniprogram/images/Common.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/bg.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/.DS_Store
Binary file not shown.
Binary file added miniprogram/images/garbages/dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/dry_ashcan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/dry_garbage/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/dry_garbage/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/dry_garbage/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/dry_garbage/4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/dry_garbage/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/harmful_ashcan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/harmful_garbage/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/harmful_garbage/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/harmful_garbage/3.png
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 added miniprogram/images/garbages/harmful_garbage/5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/harmful_garbage/6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/home_page.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/life.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added miniprogram/images/garbages/recyclable_ashcan.png
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.
Binary file added miniprogram/images/garbages/wet_ashcan.png
Binary file added miniprogram/images/garbages/wet_garbage/1.png
Binary file added miniprogram/images/garbages/wet_garbage/2.png
Binary file added miniprogram/images/garbages/wet_garbage/3.png
Binary file added miniprogram/images/garbages/wet_garbage/4.png
Binary file added miniprogram/images/garbages/wet_garbage/5.png
112 changes: 112 additions & 0 deletions miniprogram/js/base/animation.js
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()
}
}
}
}
45 changes: 45 additions & 0 deletions miniprogram/js/base/pool.js
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)
}
}
63 changes: 63 additions & 0 deletions miniprogram/js/base/sprite.js
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) {

}
}
Loading

0 comments on commit 27e3aa5

Please sign in to comment.