Z1hgq před 7 roky
rodič
revize
545c1baceb

binární
Album/audio/bgm.mp3


binární
Album/audio/boom.mp3


binární
Album/audio/bullet.mp3


+ 15 - 2
Album/game.js

xqd
@@ -1,7 +1,20 @@
+import './jss/libs/weapp-adapter'
+import './jss/libs/symbol'
 import './js/libs/weapp-adapter'
 import './js/libs/symbol'
 
-import Main from './js/main.js'
-
+import Main from './jss/main.js'
 new Main()
 
+// var s 
+// var flag = true
+// if(flag == true){
+//   s = require('./jss/main.js')
+// }else{
+//   s = require('./js/main.js')
+// }
+
+
+// s.start()
+
+

+ 1 - 1
Album/game.json

xqd
@@ -1,5 +1,5 @@
 {
-  "deviceOrientation":"landscape",
+  "deviceOrientation":"",
   "networkTimeout": {
     "request": 5000
   }

binární
Album/image/bg.jpg


binární
Album/image/black.png


binární
Album/image/border.png


binární
Album/image/easy.png


binární
Album/image/hard.png


binární
Album/image/help.png


binární
Album/image/hint.png


binární
Album/image/middle.png


binární
Album/image/paper.png


binární
Album/image/puzzle-easy.jpg


binární
Album/image/puzzle-hard.jpg


binární
Album/image/puzzle-help.png


binární
Album/image/puzzle-middle.jpg


binární
Album/image/replay.png


binární
Album/image/start.png


binární
Album/image/time_bg.png


binární
Album/image/wrap.png


+ 7 - 3
Album/js/main.js

xqd xqd xqd
@@ -91,7 +91,6 @@ function init() {
   // context.fillRect(0, 0, screenWidth, screenHeight)
   // wx.setPreferredFramesPerSecond(30)
   sleep(0).then(() => {
-
     loading(percent)
     showLoading()
   })
@@ -146,7 +145,6 @@ var mobilein = '0'
 let isLoading = true
 
 function showLoading() {
-  
   let interval = window.requestAnimationFrame(function () {
     // console.log('next frame')
     if (percent < 99.6 && isLoading) {
@@ -1122,6 +1120,12 @@ function sleep(time) {
 */
 export default class Main {
   constructor() {
+    init()
     UserLogin()
   }
-}
+}
+var s = new Main()
+module.export = {
+  start: s.constructor()
+}
+

+ 28 - 0
Album/jss/base/button.js

xqd
@@ -0,0 +1,28 @@
+
+/**
+ * 一个Button基础类
+ * 
+ * @export
+ * @class Button
+ */
+export default class Button {
+  constructor(src, x, y, width, height) {
+    this.img = new Image()
+    this.img.src = src
+    this.x = x
+    this.y = y
+    this.height = height
+    this.width = width
+  }
+
+  render(ctx) {
+    ctx.drawImage(this.img, this.x, this.y, this.width, this.height)
+  }
+
+  isTapped(x, y) {
+    if (x > this.x && x < (this.x + this.width) && y > this.y && y < (this.y + this.height)) {
+      return true
+    }
+    return false
+  }
+}

+ 70 - 0
Album/jss/base/eventUtil.js

xqd
@@ -0,0 +1,70 @@
+const __ = {
+    x: Symbol('x'),
+    y: Symbol('y'),
+    onTap: Symbol('onTap'),
+    onSwipe: Symbol('onSwipe'),
+}
+const SWIPEGAP = 40
+const TYPE_TAP = 'tap'
+const TYPE_SWIPE = 'swipe'
+
+export default class EventUtil {
+    constructor(onTap = function () {}, onSwipe = function () {}) {
+        this[__.x] = 0;
+        this[__.y] = 0;
+        this[__.onTap] = onTap;
+        this[__.onSwipe] = onSwipe;
+        this.initEvent()
+    }
+
+
+    initEvent() {
+        canvas.addEventListener('touchstart', ((e) => {
+            e.preventDefault()
+
+            this[__.x] = e.changedTouches[0].clientX
+            this[__.y] = e.changedTouches[0].clientY
+        }).bind(this))
+
+        canvas.addEventListener('touchend', ((e) => {
+            e.preventDefault()
+
+            let deltaX = e.changedTouches[0].clientX - this[__.x]
+            let deltaY = e.changedTouches[0].clientY - this[__.y]
+
+            if (deltaX * deltaX + deltaY * deltaY < SWIPEGAP * SWIPEGAP) {
+                return this.fireEvent(TYPE_TAP)
+            }
+            if (Math.abs(deltaX) > Math.abs(deltaY)) {
+                if (deltaX > 0) {
+                    return this.fireEvent(TYPE_SWIPE, 'right')
+                } else {
+                    return this.fireEvent(TYPE_SWIPE, 'left')
+                }
+            } else {
+                if (deltaY > 0) {
+                    return this.fireEvent(TYPE_SWIPE, 'down')
+                } else {
+                    return this.fireEvent(TYPE_SWIPE, 'up')
+                }
+            }
+
+        }).bind(this))
+    }
+    fireEvent(type, direction) {
+        var event = {}
+        event.x = this[__.x]
+        event.y = this[__.y]
+        if (direction) {
+            event.direction = direction
+        }
+        switch (type) {
+            case TYPE_TAP:
+                return this[__.onTap](event)
+            case TYPE_SWIPE:
+                return this[__.onSwipe](event)
+            default:
+                break;
+        }
+    }
+}

+ 68 - 0
Album/jss/databus.js

xqd
@@ -0,0 +1,68 @@
+// import Pool from './base/pool'
+const screenWidth = window.innerWidth
+const screenHeight = window.innerHeight
+const contentWidth = window.innerWidth * 0.85
+
+let instance
+
+
+/**
+ * 全局状态管理器
+ * 
+ * @export
+ * @class DataBus
+ */
+export default class DataBus {
+  constructor() {
+    if (instance)
+      return instance
+
+    instance = this
+
+    this.screenWidth = screenWidth
+    this.screenHeight = screenHeight
+    this.contentWidth = contentWidth
+    this.contentPadding = (this.screenWidth - this.contentWidth) / 2
+    this.contentPaddingTop = this.screenHeight - this.contentWidth - this.contentPadding;
+    this.puzzleImg = null
+
+
+    this.reset()
+  }
+
+  /**
+   * 重启游戏,重制数据
+   * 
+   * @memberof DataBus
+   */
+  reset() {
+    this.startTime = Date.now()
+    this.pieces = []
+    this.gameStart = false        
+    this.gameOver = false
+    this.showHelp = false
+    this.showHint = false
+    this.emptyPosition = 0
+    this.puzzleImg = null
+  }
+
+  
+  /**
+   * 返回当前的游戏时间
+   * 
+   * @returns 
+   * @memberof DataBus
+   */
+  getCurrentTime(){
+    let time = Math.floor((Date.now() - this.startTime) / 1000);
+    let minute = Math.floor(time / 60)
+    if (minute < 10) {
+      minute = '0' + minute
+    }
+    let second = Math.floor(time % 60)
+    if (second < 10) {
+      second = '0' + second
+    }
+    return minute + ':' + second
+  }
+}

+ 1 - 0
Album/jss/libs/bezier.js

xqd
@@ -0,0 +1 @@
+!function(r){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=r();else if("function"==typeof define&&define.amd)define([],r);else{var n;n="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,n.BezierEasing=r()}}(function(){return function r(n,e,t){function o(u,i){if(!e[u]){if(!n[u]){var a="function"==typeof require&&require;if(!i&&a)return a(u,!0);if(f)return f(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var d=e[u]={exports:{}};n[u][0].call(d.exports,function(r){var e=n[u][1][r];return o(e||r)},d,d.exports,r,n,e,t)}return e[u].exports}for(var f="function"==typeof require&&require,u=0;u<t.length;u++)o(t[u]);return o}({1:[function(r,n,e){function t(r,n){return 1-3*n+3*r}function o(r,n){return 3*n-6*r}function f(r){return 3*r}function u(r,n,e){return((t(n,e)*r+o(n,e))*r+f(n))*r}function i(r,n,e){return 3*t(n,e)*r*r+2*o(n,e)*r+f(n)}function a(r,n,e,t,o){var f,i,a=0;do{i=n+(e-n)/2,f=u(i,t,o)-r,f>0?e=i:n=i}while(Math.abs(f)>l&&++a<p);return i}function c(r,n,e,t){for(var o=0;o<d;++o){var f=i(n,e,t);if(0===f)return n;n-=(u(n,e,t)-r)/f}return n}var d=4,l=1e-7,p=10,s=11,v=1/(s-1),y="function"==typeof Float32Array;n.exports=function(r,n,e,t){function o(n){for(var t=0,o=1,u=s-1;o!==u&&f[o]<=n;++o)t+=v;--o;var d=(n-f[o])/(f[o+1]-f[o]),l=t+d*v,p=i(l,r,e);return p>=.001?c(n,l,r,e):0===p?l:a(n,t,t+v,r,e)}if(!(0<=r&&r<=1&&0<=e&&e<=1))throw new Error("bezier x values must be in [0, 1] range");var f=y?new Float32Array(s):new Array(s);if(r!==n||e!==t)for(var d=0;d<s;++d)f[d]=u(d*v,r,e);return function(f){return r===n&&e===t?f:0===f?0:1===f?1:u(o(f),n,t)}}},{}]},{},[1])(1)});

+ 17 - 0
Album/jss/libs/symbol.js

xqd
@@ -0,0 +1,17 @@
+/**
+ * 对于ES6中Symbol的极简兼容
+ * 方便模拟私有变量
+ */
+
+let Symbol  = window.Symbol
+let idCounter = 0
+
+if (!Symbol) {
+  Symbol = function Symbol(key) {
+    return `__${key}_${Math.floor(Math.random() * 1e9)}_${++idCounter}__`
+  }
+
+  Symbol.iterator = Symbol('Symbol.iterator')
+}
+
+window.Symbol = Symbol

+ 1529 - 0
Album/jss/libs/weapp-adapter.js

xqd
@@ -0,0 +1,1529 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {}
+
+/******/ 	// The require function
+/******/ 	function __webpack_require__(moduleId) {
+
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId])
+/******/ 			return installedModules[moduleId].exports
+
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			exports: {},
+/******/ 			id: moduleId,
+/******/ 			loaded: false
+/******/ 		}
+
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)
+
+/******/ 		// Flag the module as loaded
+/******/ 		module.loaded = true
+
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports
+/******/ 	}
+
+
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__webpack_require__.m = modules
+
+/******/ 	// expose the module cache
+/******/ 	__webpack_require__.c = installedModules
+
+/******/ 	// __webpack_public_path__
+/******/ 	__webpack_require__.p = ""
+
+/******/ 	// Load entry module and return exports
+/******/ 	return __webpack_require__(0)
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	var _window2 = __webpack_require__(1)
+
+	var _window = _interopRequireWildcard(_window2)
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key] } } newObj.default = obj; return newObj } }
+
+	var global = GameGlobal
+
+	function inject() {
+	  _window.addEventListener = _window.canvas.addEventListener = function (type, listener) {
+	    _window.document.addEventListener(type, listener)
+	  }
+	  _window.removeEventListener = _window.canvas.removeEventListener = function (type, listener) {
+	    _window.document.removeEventListener(type, listener)
+	  }
+
+	  var _wx$getSystemInfoSync = wx.getSystemInfoSync(),
+	      platform = _wx$getSystemInfoSync.platform
+
+	  // 开发者工具无法重定义 window
+
+
+	  if (typeof __devtoolssubcontext === 'undefined' && platform === 'devtools') {
+	    for (var key in _window) {
+	      var descriptor = Object.getOwnPropertyDescriptor(global, key)
+
+	      if (!descriptor || descriptor.configurable === true) {
+	        Object.defineProperty(window, key, {
+	          value: _window[key]
+	        })
+	      }
+	    }
+
+	    for (var _key in _window.document) {
+	      var _descriptor = Object.getOwnPropertyDescriptor(global.document, _key)
+
+	      if (!_descriptor || _descriptor.configurable === true) {
+	        Object.defineProperty(global.document, _key, {
+	          value: _window.document[_key]
+	        })
+	      }
+	    }
+	    window.parent = window
+	  } else {
+	    for (var _key2 in _window) {
+	      global[_key2] = _window[_key2]
+	    }
+	    global.window = _window
+	    window = global
+	    window.top = window.parent = window
+	  }
+	}
+
+	if (!GameGlobal.__isAdapterInjected) {
+	  GameGlobal.__isAdapterInjected = true
+	  inject()
+	}
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	exports.cancelAnimationFrame = exports.requestAnimationFrame = exports.clearInterval = exports.clearTimeout = exports.setInterval = exports.setTimeout = exports.canvas = exports.location = exports.localStorage = exports.HTMLElement = exports.FileReader = exports.Audio = exports.Image = exports.WebSocket = exports.XMLHttpRequest = exports.navigator = exports.document = undefined
+
+	var _WindowProperties = __webpack_require__(2)
+
+	Object.keys(_WindowProperties).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _WindowProperties[key]
+	    }
+	  })
+	})
+
+	var _constructor = __webpack_require__(3)
+
+	Object.keys(_constructor).forEach(function (key) {
+	  if (key === "default" || key === "__esModule") return
+	  Object.defineProperty(exports, key, {
+	    enumerable: true,
+	    get: function get() {
+	      return _constructor[key]
+	    }
+	  })
+	})
+
+	var _Canvas = __webpack_require__(9)
+
+	var _Canvas2 = _interopRequireDefault(_Canvas)
+
+	var _document2 = __webpack_require__(10)
+
+	var _document3 = _interopRequireDefault(_document2)
+
+	var _navigator2 = __webpack_require__(17)
+
+	var _navigator3 = _interopRequireDefault(_navigator2)
+
+	var _XMLHttpRequest2 = __webpack_require__(18)
+
+	var _XMLHttpRequest3 = _interopRequireDefault(_XMLHttpRequest2)
+
+	var _WebSocket2 = __webpack_require__(19)
+
+	var _WebSocket3 = _interopRequireDefault(_WebSocket2)
+
+	var _Image2 = __webpack_require__(11)
+
+	var _Image3 = _interopRequireDefault(_Image2)
+
+	var _Audio2 = __webpack_require__(12)
+
+	var _Audio3 = _interopRequireDefault(_Audio2)
+
+	var _FileReader2 = __webpack_require__(20)
+
+	var _FileReader3 = _interopRequireDefault(_FileReader2)
+
+	var _HTMLElement2 = __webpack_require__(4)
+
+	var _HTMLElement3 = _interopRequireDefault(_HTMLElement2)
+
+	var _localStorage2 = __webpack_require__(21)
+
+	var _localStorage3 = _interopRequireDefault(_localStorage2)
+
+	var _location2 = __webpack_require__(22)
+
+	var _location3 = _interopRequireDefault(_location2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	exports.document = _document3.default
+	exports.navigator = _navigator3.default
+	exports.XMLHttpRequest = _XMLHttpRequest3.default
+	exports.WebSocket = _WebSocket3.default
+	exports.Image = _Image3.default
+	exports.Audio = _Audio3.default
+	exports.FileReader = _FileReader3.default
+	exports.HTMLElement = _HTMLElement3.default
+	exports.localStorage = _localStorage3.default
+	exports.location = _location3.default
+
+
+	// 暴露全局的 canvas
+	var canvas = new _Canvas2.default()
+
+	exports.canvas = canvas
+	exports.setTimeout = setTimeout
+	exports.setInterval = setInterval
+	exports.clearTimeout = clearTimeout
+	exports.clearInterval = clearInterval
+	exports.requestAnimationFrame = requestAnimationFrame
+	exports.cancelAnimationFrame = cancelAnimationFrame
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports) {
+
+	"use strict"
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _wx$getSystemInfoSync = wx.getSystemInfoSync(),
+	    screenWidth = _wx$getSystemInfoSync.screenWidth,
+	    screenHeight = _wx$getSystemInfoSync.screenHeight,
+	    devicePixelRatio = _wx$getSystemInfoSync.devicePixelRatio
+
+	var innerWidth = exports.innerWidth = screenWidth
+	var innerHeight = exports.innerHeight = screenHeight
+	exports.devicePixelRatio = devicePixelRatio
+	var screen = exports.screen = {
+	  availWidth: innerWidth,
+	  availHeight: innerHeight
+	}
+	var performance = exports.performance = {
+	  now: function now() {
+	    return Date.now() / 1000
+	  }
+	}
+	var ontouchstart = exports.ontouchstart = null
+	var ontouchmove = exports.ontouchmove = null
+	var ontouchend = exports.ontouchend = null
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	exports.HTMLCanvasElement = exports.HTMLImageElement = undefined
+
+	var _HTMLElement3 = __webpack_require__(4)
+
+	var _HTMLElement4 = _interopRequireDefault(_HTMLElement3)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var HTMLImageElement = exports.HTMLImageElement = function (_HTMLElement) {
+	  _inherits(HTMLImageElement, _HTMLElement)
+
+	  function HTMLImageElement() {
+	    _classCallCheck(this, HTMLImageElement)
+
+	    return _possibleConstructorReturn(this, (HTMLImageElement.__proto__ || Object.getPrototypeOf(HTMLImageElement)).call(this, 'img'))
+	  }
+
+	  return HTMLImageElement
+	}(_HTMLElement4.default)
+
+	var HTMLCanvasElement = exports.HTMLCanvasElement = function (_HTMLElement2) {
+	  _inherits(HTMLCanvasElement, _HTMLElement2)
+
+	  function HTMLCanvasElement() {
+	    _classCallCheck(this, HTMLCanvasElement)
+
+	    return _possibleConstructorReturn(this, (HTMLCanvasElement.__proto__ || Object.getPrototypeOf(HTMLCanvasElement)).call(this, 'canvas'))
+	  }
+
+	  return HTMLCanvasElement
+	}(_HTMLElement4.default)
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	var _Element2 = __webpack_require__(5)
+
+	var _Element3 = _interopRequireDefault(_Element2)
+
+	var _util = __webpack_require__(8)
+
+	var _WindowProperties = __webpack_require__(2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var HTMLElement = function (_Element) {
+	  _inherits(HTMLElement, _Element)
+
+	  function HTMLElement() {
+	    var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''
+
+	    _classCallCheck(this, HTMLElement)
+
+	    var _this = _possibleConstructorReturn(this, (HTMLElement.__proto__ || Object.getPrototypeOf(HTMLElement)).call(this))
+
+	    _this.className = ''
+	    _this.childern = []
+	    _this.style = {
+	      width: _WindowProperties.innerWidth + 'px',
+	      height: _WindowProperties.innerHeight + 'px'
+	    }
+	    _this.insertBefore = _util.noop
+	    _this.innerHTML = ''
+
+	    _this.tagName = tagName.toUpperCase()
+	    return _this
+	  }
+
+	  _createClass(HTMLElement, [{
+	    key: 'setAttribute',
+	    value: function setAttribute(name, value) {
+	      this[name] = value
+	    }
+	  }, {
+	    key: 'getAttribute',
+	    value: function getAttribute(name) {
+	      return this[name]
+	    }
+	  }, {
+	    key: 'getBoundingClientRect',
+	    value: function getBoundingClientRect() {
+	      return {
+	        top: 0,
+	        left: 0,
+	        width: _WindowProperties.innerWidth,
+	        height: _WindowProperties.innerHeight
+	      }
+	    }
+	  }, {
+	    key: 'focus',
+	    value: function focus() {}
+	  }, {
+	    key: 'clientWidth',
+	    get: function get() {
+	      var ret = parseInt(this.style.fontSize, 10) * this.innerHTML.length
+
+	      return Number.isNaN(ret) ? 0 : ret
+	    }
+	  }, {
+	    key: 'clientHeight',
+	    get: function get() {
+	      var ret = parseInt(this.style.fontSize, 10)
+
+	      return Number.isNaN(ret) ? 0 : ret
+	    }
+	  }])
+
+	  return HTMLElement
+	}(_Element3.default)
+
+	exports.default = HTMLElement
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _Node2 = __webpack_require__(6)
+
+	var _Node3 = _interopRequireDefault(_Node2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var ELement = function (_Node) {
+	  _inherits(ELement, _Node)
+
+	  function ELement() {
+	    _classCallCheck(this, ELement)
+
+	    var _this = _possibleConstructorReturn(this, (ELement.__proto__ || Object.getPrototypeOf(ELement)).call(this))
+
+	    _this.className = ''
+	    _this.children = []
+	    return _this
+	  }
+
+	  return ELement
+	}(_Node3.default)
+
+	exports.default = ELement
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	var _EventTarget2 = __webpack_require__(7)
+
+	var _EventTarget3 = _interopRequireDefault(_EventTarget2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var Node = function (_EventTarget) {
+	  _inherits(Node, _EventTarget)
+
+	  function Node() {
+	    _classCallCheck(this, Node)
+
+	    var _this = _possibleConstructorReturn(this, (Node.__proto__ || Object.getPrototypeOf(Node)).call(this))
+
+	    _this.childNodes = []
+	    return _this
+	  }
+
+	  _createClass(Node, [{
+	    key: 'appendChild',
+	    value: function appendChild(node) {
+	      if (node instanceof Node) {
+	        this.childNodes.push(node)
+	      } else {
+	        throw new TypeError('Failed to executed \'appendChild\' on \'Node\': parameter 1 is not of type \'Node\'.')
+	      }
+	    }
+	  }, {
+	    key: 'cloneNode',
+	    value: function cloneNode() {
+	      var copyNode = Object.create(this)
+
+	      Object.assign(copyNode, this)
+	      return copyNode
+	    }
+	  }, {
+	    key: 'removeChild',
+	    value: function removeChild(node) {
+	      var index = this.childNodes.findIndex(function (child) {
+	        return child === node
+	      })
+
+	      if (index > -1) {
+	        return this.childNodes.splice(index, 1)
+	      }
+	      return null
+	    }
+	  }])
+
+	  return Node
+	}(_EventTarget3.default)
+
+	exports.default = Node
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	var _events = new WeakMap()
+
+	var EventTarget = function () {
+	  function EventTarget() {
+	    _classCallCheck(this, EventTarget)
+
+	    _events.set(this, {})
+	  }
+
+	  _createClass(EventTarget, [{
+	    key: 'addEventListener',
+	    value: function addEventListener(type, listener) {
+	      var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}
+
+	      var events = _events.get(this)
+
+	      if (!events) {
+	        events = {}
+	        _events.set(this, events)
+	      }
+	      if (!events[type]) {
+	        events[type] = []
+	      }
+	      events[type].push(listener)
+
+	      if (options.capture) {
+	        console.warn('EventTarget.addEventListener: options.capture is not implemented.')
+	      }
+	      if (options.once) {
+	        console.warn('EventTarget.addEventListener: options.once is not implemented.')
+	      }
+	      if (options.passive) {
+	        console.warn('EventTarget.addEventListener: options.passive is not implemented.')
+	      }
+	    }
+	  }, {
+	    key: 'removeEventListener',
+	    value: function removeEventListener(type, listener) {
+	      var listeners = _events.get(this)[type]
+
+	      if (listeners && listeners.length > 0) {
+	        for (var i = listeners.length; i--; i > 0) {
+	          if (listeners[i] === listener) {
+	            listeners.splice(i, 1)
+	            break
+	          }
+	        }
+	      }
+	    }
+	  }, {
+	    key: 'dispatchEvent',
+	    value: function dispatchEvent() {
+	      var event = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}
+
+	      var listeners = _events.get(this)[event.type]
+
+	      if (listeners) {
+	        for (var i = 0; i < listeners.length; i++) {
+	          listeners[i](event)
+	        }
+	      }
+	    }
+	  }])
+
+	  return EventTarget
+	}()
+
+	exports.default = EventTarget
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports) {
+
+	"use strict"
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	exports.noop = noop
+	function noop() {}
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	exports.default = Canvas
+
+	var _constructor = __webpack_require__(3)
+
+	var _HTMLElement = __webpack_require__(4)
+
+	var _HTMLElement2 = _interopRequireDefault(_HTMLElement)
+
+	var _document = __webpack_require__(10)
+
+	var _document2 = _interopRequireDefault(_document)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	var hasModifiedCanvasPrototype = false
+	var hasInit2DContextConstructor = false
+	var hasInitWebGLContextConstructor = false
+
+	function Canvas() {
+	  var canvas = wx.createCanvas()
+
+	  canvas.type = 'canvas'
+
+	  canvas.__proto__.__proto__ = new _HTMLElement2.default('canvas')
+
+	  var _getContext = canvas.getContext
+
+	  canvas.getBoundingClientRect = function () {
+	    var ret = {
+	      top: 0,
+	      left: 0,
+	      width: window.innerWidth,
+	      height: window.innerHeight
+	    }
+	    return ret
+	  }
+
+	  return canvas
+	}
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _window = __webpack_require__(1)
+
+	var window = _interopRequireWildcard(_window)
+
+	var _HTMLElement = __webpack_require__(4)
+
+	var _HTMLElement2 = _interopRequireDefault(_HTMLElement)
+
+	var _Image = __webpack_require__(11)
+
+	var _Image2 = _interopRequireDefault(_Image)
+
+	var _Audio = __webpack_require__(12)
+
+	var _Audio2 = _interopRequireDefault(_Audio)
+
+	var _Canvas = __webpack_require__(9)
+
+	var _Canvas2 = _interopRequireDefault(_Canvas)
+
+	__webpack_require__(15)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key] } } newObj.default = obj; return newObj } }
+
+	var events = {}
+
+	var document = {
+	  readyState: 'complete',
+	  visibilityState: 'visible',
+	  documentElement: window,
+	  hidden: false,
+	  style: {},
+	  location: window.location,
+	  ontouchstart: null,
+	  ontouchmove: null,
+	  ontouchend: null,
+
+	  head: new _HTMLElement2.default('head'),
+	  body: new _HTMLElement2.default('body'),
+
+	  createElement: function createElement(tagName) {
+	    if (tagName === 'canvas') {
+	      return new _Canvas2.default()
+	    } else if (tagName === 'audio') {
+	      return new _Audio2.default()
+	    } else if (tagName === 'img') {
+	      return new _Image2.default()
+	    }
+
+	    return new _HTMLElement2.default(tagName)
+	  },
+	  getElementById: function getElementById(id) {
+	    if (id === window.canvas.id) {
+	      return window.canvas
+	    }
+	    return null
+	  },
+	  getElementsByTagName: function getElementsByTagName(tagName) {
+	    if (tagName === 'head') {
+	      return [document.head]
+	    } else if (tagName === 'body') {
+	      return [document.body]
+	    } else if (tagName === 'canvas') {
+	      return [window.canvas]
+	    }
+	    return []
+	  },
+	  querySelector: function querySelector(query) {
+	    if (query === 'head') {
+	      return document.head
+	    } else if (query === 'body') {
+	      return document.body
+	    } else if (query === 'canvas') {
+	      return window.canvas
+	    } else if (query === '#' + window.canvas.id) {
+	      return window.canvas
+	    }
+	    return null
+	  },
+	  querySelectorAll: function querySelectorAll(query) {
+	    if (query === 'head') {
+	      return [document.head]
+	    } else if (query === 'body') {
+	      return [document.body]
+	    } else if (query === 'canvas') {
+	      return [window.canvas]
+	    }
+	    return []
+	  },
+	  addEventListener: function addEventListener(type, listener) {
+	    if (!events[type]) {
+	      events[type] = []
+	    }
+	    events[type].push(listener)
+	  },
+	  removeEventListener: function removeEventListener(type, listener) {
+	    var listeners = events[type]
+
+	    if (listeners && listeners.length > 0) {
+	      for (var i = listeners.length; i--; i > 0) {
+	        if (listeners[i] === listener) {
+	          listeners.splice(i, 1)
+	          break
+	        }
+	      }
+	    }
+	  },
+	  dispatchEvent: function dispatchEvent(event) {
+	    var listeners = events[event.type]
+
+	    if (listeners) {
+	      for (var i = 0; i < listeners.length; i++) {
+	        listeners[i](event)
+	      }
+	    }
+	  }
+	}
+
+	exports.default = document
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports) {
+
+	"use strict"
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	exports.default = Image
+	function Image() {
+	  var image = wx.createImage()
+
+	  return image
+	}
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	var _HTMLAudioElement2 = __webpack_require__(13)
+
+	var _HTMLAudioElement3 = _interopRequireDefault(_HTMLAudioElement2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var HAVE_NOTHING = 0
+	var HAVE_METADATA = 1
+	var HAVE_CURRENT_DATA = 2
+	var HAVE_FUTURE_DATA = 3
+	var HAVE_ENOUGH_DATA = 4
+
+	var _innerAudioContext = new WeakMap()
+	var _src = new WeakMap()
+	var _loop = new WeakMap()
+	var _autoplay = new WeakMap()
+
+	var Audio = function (_HTMLAudioElement) {
+	  _inherits(Audio, _HTMLAudioElement)
+
+	  function Audio(url) {
+	    _classCallCheck(this, Audio)
+
+	    var _this = _possibleConstructorReturn(this, (Audio.__proto__ || Object.getPrototypeOf(Audio)).call(this))
+
+	    _this.HAVE_NOTHING = HAVE_NOTHING
+	    _this.HAVE_METADATA = HAVE_METADATA
+	    _this.HAVE_CURRENT_DATA = HAVE_CURRENT_DATA
+	    _this.HAVE_FUTURE_DATA = HAVE_FUTURE_DATA
+	    _this.HAVE_ENOUGH_DATA = HAVE_ENOUGH_DATA
+	    _this.readyState = HAVE_NOTHING
+
+
+	    _src.set(_this, '')
+
+	    var innerAudioContext = wx.createInnerAudioContext()
+
+	    _innerAudioContext.set(_this, innerAudioContext)
+
+	    innerAudioContext.onCanplay(function () {
+	      _this.dispatchEvent({ type: 'load' })
+	      _this.dispatchEvent({ type: 'loadend' })
+	      _this.dispatchEvent({ type: 'canplay' })
+	      _this.dispatchEvent({ type: 'canplaythrough' })
+	      _this.dispatchEvent({ type: 'loadedmetadata' })
+	      _this.readyState = HAVE_CURRENT_DATA
+	    })
+	    innerAudioContext.onPlay(function () {
+	      _this.dispatchEvent({ type: 'play' })
+	    })
+	    innerAudioContext.onPause(function () {
+	      _this.dispatchEvent({ type: 'pause' })
+	    })
+	    innerAudioContext.onEnded(function () {
+	      _this.dispatchEvent({ type: 'ended' })
+	      _this.readyState = HAVE_ENOUGH_DATA
+	    })
+	    innerAudioContext.onError(function () {
+	      _this.dispatchEvent({ type: 'error' })
+	    })
+
+	    if (url) {
+	      _innerAudioContext.get(_this).src = url
+	    }
+	    return _this
+	  }
+
+	  _createClass(Audio, [{
+	    key: 'load',
+	    value: function load() {
+	      console.warn('HTMLAudioElement.load() is not implemented.')
+	    }
+	  }, {
+	    key: 'play',
+	    value: function play() {
+	      _innerAudioContext.get(this).play()
+	    }
+	  }, {
+	    key: 'pause',
+	    value: function pause() {
+	      _innerAudioContext.get(this).pause()
+	    }
+	  }, {
+	    key: 'canPlayType',
+	    value: function canPlayType() {
+	      var mediaType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''
+
+	      if (typeof mediaType !== 'string') {
+	        return ''
+	      }
+
+	      if (mediaType.indexOf('audio/mpeg') > -1 || mediaType.indexOf('audio/mp4')) {
+	        return 'probably'
+	      }
+	      return ''
+	    }
+	  }, {
+	    key: 'cloneNode',
+	    value: function cloneNode() {
+	      var newAudio = new Audio()
+	      newAudio.loop = _innerAudioContext.get(this).loop
+	      newAudio.autoplay = _innerAudioContext.get(this).loop
+	      newAudio.src = this.src
+	      return newAudio
+	    }
+	  }, {
+	    key: 'currentTime',
+	    get: function get() {
+	      return _innerAudioContext.get(this).currentTime
+	    },
+	    set: function set(value) {
+	      _innerAudioContext.get(this).seek(value)
+	    }
+	  }, {
+	    key: 'src',
+	    get: function get() {
+	      return _src.get(this)
+	    },
+	    set: function set(value) {
+	      _src.set(this, value)
+	      _innerAudioContext.get(this).src = value
+	    }
+	  }, {
+	    key: 'loop',
+	    get: function get() {
+	      return _innerAudioContext.get(this).loop
+	    },
+	    set: function set(value) {
+	      _innerAudioContext.get(this).loop = value
+	    }
+	  }, {
+	    key: 'autoplay',
+	    get: function get() {
+	      return _innerAudioContext.get(this).autoplay
+	    },
+	    set: function set(value) {
+	      _innerAudioContext.get(this).autoplay = value
+	    }
+	  }, {
+	    key: 'paused',
+	    get: function get() {
+	      return _innerAudioContext.get(this).paused
+	    }
+	  }])
+
+	  return Audio
+	}(_HTMLAudioElement3.default)
+
+	exports.default = Audio
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _HTMLMediaElement2 = __webpack_require__(14)
+
+	var _HTMLMediaElement3 = _interopRequireDefault(_HTMLMediaElement2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var HTMLAudioElement = function (_HTMLMediaElement) {
+	  _inherits(HTMLAudioElement, _HTMLMediaElement)
+
+	  function HTMLAudioElement() {
+	    _classCallCheck(this, HTMLAudioElement)
+
+	    return _possibleConstructorReturn(this, (HTMLAudioElement.__proto__ || Object.getPrototypeOf(HTMLAudioElement)).call(this, 'audio'))
+	  }
+
+	  return HTMLAudioElement
+	}(_HTMLMediaElement3.default)
+
+	exports.default = HTMLAudioElement
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	var _HTMLElement2 = __webpack_require__(4)
+
+	var _HTMLElement3 = _interopRequireDefault(_HTMLElement2)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called") } return call && (typeof call === "object" || typeof call === "function") ? call : self }
+
+	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass) } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass }
+
+	var HTMLMediaElement = function (_HTMLElement) {
+	  _inherits(HTMLMediaElement, _HTMLElement)
+
+	  function HTMLMediaElement(type) {
+	    _classCallCheck(this, HTMLMediaElement)
+
+	    return _possibleConstructorReturn(this, (HTMLMediaElement.__proto__ || Object.getPrototypeOf(HTMLMediaElement)).call(this, type))
+	  }
+
+	  _createClass(HTMLMediaElement, [{
+	    key: 'addTextTrack',
+	    value: function addTextTrack() {}
+	  }, {
+	    key: 'captureStream',
+	    value: function captureStream() {}
+	  }, {
+	    key: 'fastSeek',
+	    value: function fastSeek() {}
+	  }, {
+	    key: 'load',
+	    value: function load() {}
+	  }, {
+	    key: 'pause',
+	    value: function pause() {}
+	  }, {
+	    key: 'play',
+	    value: function play() {}
+	  }])
+
+	  return HTMLMediaElement
+	}(_HTMLElement3.default)
+
+	exports.default = HTMLMediaElement
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	__webpack_require__(16)
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	var _window = __webpack_require__(1)
+
+	var window = _interopRequireWildcard(_window)
+
+	var _document = __webpack_require__(10)
+
+	var _document2 = _interopRequireDefault(_document)
+
+	var _util = __webpack_require__(8)
+
+	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj } }
+
+	function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key] } } newObj.default = obj; return newObj } }
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	var TouchEvent = function TouchEvent(type) {
+	  _classCallCheck(this, TouchEvent)
+
+	  this.target = window.canvas
+	  this.currentTarget = window.canvas
+	  this.touches = []
+	  this.targetTouches = []
+	  this.changedTouches = []
+	  this.preventDefault = _util.noop
+	  this.stopPropagation = _util.noop
+
+	  this.type = type
+	}
+
+	function touchEventHandlerFactory(type) {
+	  return function (event) {
+	    var touchEvent = new TouchEvent(type)
+
+	    touchEvent.touches = event.touches
+	    touchEvent.targetTouches = Array.prototype.slice.call(event.touches)
+	    touchEvent.changedTouches = event.changedTouches
+	    touchEvent.timeStamp = event.timeStamp
+	    _document2.default.dispatchEvent(touchEvent)
+	  }
+	}
+
+	wx.onTouchStart(touchEventHandlerFactory('touchstart'))
+	wx.onTouchMove(touchEventHandlerFactory('touchmove'))
+	wx.onTouchEnd(touchEventHandlerFactory('touchend'))
+	wx.onTouchCancel(touchEventHandlerFactory('touchcancel'))
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _util = __webpack_require__(8)
+
+	// TODO 需要 wx.getSystemInfo 获取更详细信息
+	var _wx$getSystemInfoSync = wx.getSystemInfoSync(),
+	    platform = _wx$getSystemInfoSync.platform
+
+	var navigator = {
+	  platform: platform,
+	  language: 'zh-cn',
+	  appVersion: '5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
+	  userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 MicroMessenger/6.6.0 MiniGame NetType/WIFI Language/zh_CN',
+	  onLine: true, // TODO 用 wx.getNetworkStateChange 和 wx.onNetworkStateChange 来返回真实的状态
+
+	  // TODO 用 wx.getLocation 来封装 geolocation
+	  geolocation: {
+	    getCurrentPosition: _util.noop,
+	    watchPosition: _util.noop,
+	    clearWatch: _util.noop
+	  }
+	}
+
+	exports.default = navigator
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	var _url = new WeakMap()
+	var _method = new WeakMap()
+	var _requestHeader = new WeakMap()
+	var _responseHeader = new WeakMap()
+	var _requestTask = new WeakMap()
+
+	function _triggerEvent(type) {
+	  if (typeof this['on' + type] === 'function') {
+	    for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+	      args[_key - 1] = arguments[_key]
+	    }
+
+	    this['on' + type].apply(this, args)
+	  }
+	}
+
+	function _changeReadyState(readyState) {
+	  this.readyState = readyState
+	  _triggerEvent.call(this, 'readystatechange')
+	}
+
+	var XMLHttpRequest = function () {
+	  // TODO 没法模拟 HEADERS_RECEIVED 和 LOADING 两个状态
+	  function XMLHttpRequest() {
+	    _classCallCheck(this, XMLHttpRequest)
+
+	    this.onabort = null
+	    this.onerror = null
+	    this.onload = null
+	    this.onloadstart = null
+	    this.onprogress = null
+	    this.ontimeout = null
+	    this.onloadend = null
+	    this.onreadystatechange = null
+	    this.readyState = 0
+	    this.response = null
+	    this.responseText = null
+	    this.responseType = ''
+	    this.responseXML = null
+	    this.status = 0
+	    this.statusText = ''
+	    this.upload = {}
+	    this.withCredentials = false
+
+	    _requestHeader.set(this, {
+	      'content-type': 'application/x-www-form-urlencoded'
+	    })
+	    _responseHeader.set(this, {})
+	  }
+
+	  /*
+	   * TODO 这一批事件应该是在 XMLHttpRequestEventTarget.prototype 上面的
+	   */
+
+
+	  _createClass(XMLHttpRequest, [{
+	    key: 'abort',
+	    value: function abort() {
+	      var myRequestTask = _requestTask.get(this)
+
+	      if (myRequestTask) {
+	        myRequestTask.abort()
+	      }
+	    }
+	  }, {
+	    key: 'getAllResponseHeaders',
+	    value: function getAllResponseHeaders() {
+	      var responseHeader = _responseHeader.get(this)
+
+	      return Object.keys(responseHeader).map(function (header) {
+	        return header + ': ' + responseHeader[header]
+	      }).join('\n')
+	    }
+	  }, {
+	    key: 'getResponseHeader',
+	    value: function getResponseHeader(header) {
+	      return _responseHeader.get(this)[header]
+	    }
+	  }, {
+	    key: 'open',
+	    value: function open(method, url /* async, user, password 这几个参数在小程序内不支持*/) {
+	      _method.set(this, method)
+	      _url.set(this, url)
+	      _changeReadyState.call(this, XMLHttpRequest.OPENED)
+	    }
+	  }, {
+	    key: 'overrideMimeType',
+	    value: function overrideMimeType() {}
+	  }, {
+	    key: 'send',
+	    value: function send() {
+	      var _this = this
+
+	      var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''
+
+	      if (this.readyState !== XMLHttpRequest.OPENED) {
+	        throw new Error("Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED.")
+	      } else {
+	        wx.request({
+	          data: data,
+	          url: _url.get(this),
+	          method: _method.get(this),
+	          header: _requestHeader.get(this),
+	          responseType: this.responseType,
+	          success: function success(_ref) {
+	            var data = _ref.data,
+	                statusCode = _ref.statusCode,
+	                header = _ref.header
+
+	            if (typeof data !== 'string' && !(data instanceof ArrayBuffer)) {
+	              try {
+	                data = JSON.stringify(data)
+	              } catch (e) {
+	                data = data
+	              }
+	            }
+
+	            _this.status = statusCode
+	            _responseHeader.set(_this, header)
+	            _triggerEvent.call(_this, 'loadstart')
+	            _changeReadyState.call(_this, XMLHttpRequest.HEADERS_RECEIVED)
+	            _changeReadyState.call(_this, XMLHttpRequest.LOADING)
+
+	            _this.response = data
+
+	            if (data instanceof ArrayBuffer) {
+	              _this.responseText = ''
+	              var bytes = new Uint8Array(data)
+	              var len = bytes.byteLength
+
+	              for (var i = 0; i < len; i++) {
+	                _this.responseText += String.fromCharCode(bytes[i])
+	              }
+	            } else {
+	              _this.responseText = data
+	            }
+	            _changeReadyState.call(_this, XMLHttpRequest.DONE)
+	            _triggerEvent.call(_this, 'load')
+	            _triggerEvent.call(_this, 'loadend')
+	          },
+	          fail: function fail(_ref2) {
+	            var errMsg = _ref2.errMsg
+
+	            // TODO 规范错误
+	            if (errMsg.indexOf('abort') !== -1) {
+	              _triggerEvent.call(_this, 'abort')
+	            } else {
+	              _triggerEvent.call(_this, 'error', errMsg)
+	            }
+	            _triggerEvent.call(_this, 'loadend')
+	          }
+	        })
+	      }
+	    }
+	  }, {
+	    key: 'setRequestHeader',
+	    value: function setRequestHeader(header, value) {
+	      var myHeader = _requestHeader.get(this)
+
+	      myHeader[header] = value
+	      _requestHeader.set(this, myHeader)
+	    }
+	  }])
+
+	  return XMLHttpRequest
+	}()
+
+	XMLHttpRequest.UNSEND = 0
+	XMLHttpRequest.OPENED = 1
+	XMLHttpRequest.HEADERS_RECEIVED = 2
+	XMLHttpRequest.LOADING = 3
+	XMLHttpRequest.DONE = 4
+	exports.default = XMLHttpRequest
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor) } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor } }()
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	var _socketTask = new WeakMap()
+
+	var WebSocket = function () {
+	  // TODO 更新 binaryType
+	  // The connection is in the process of closing.
+	  // The connection is not yet open.
+	  function WebSocket(url) {
+	    var _this = this
+
+	    var protocols = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []
+
+	    _classCallCheck(this, WebSocket)
+
+	    this.binaryType = ''
+	    this.bufferedAmount = 0
+	    this.extensions = ''
+	    this.onclose = null
+	    this.onerror = null
+	    this.onmessage = null
+	    this.onopen = null
+	    this.protocol = ''
+	    this.readyState = 3
+
+	    if (typeof url !== 'string' || !/(^ws:\/\/)|(^wss:\/\/)/.test(url)) {
+	      throw new TypeError('Failed to construct \'WebSocket\': The URL \'' + url + '\' is invalid')
+	    }
+
+	    this.url = url
+	    this.readyState = WebSocket.CONNECTING
+
+	    var socketTask = wx.connectSocket({
+	      url: url,
+	      protocols: Array.isArray(protocols) ? protocols : [protocols]
+	    })
+
+	    _socketTask.set(this, socketTask)
+
+	    socketTask.onClose(function (res) {
+	      _this.readyState = WebSocket.CLOSED
+	      if (typeof _this.onclose === 'function') {
+	        _this.onclose(res)
+	      }
+	    })
+
+	    socketTask.onMessage(function (res) {
+	      if (typeof _this.onmessage === 'function') {
+	        _this.onmessage(res)
+	      }
+	    })
+
+	    socketTask.onOpen(function () {
+	      _this.readyState = WebSocket.OPEN
+	      if (typeof _this.onopen === 'function') {
+	        _this.onopen()
+	      }
+	    })
+
+	    socketTask.onError(function (res) {
+	      if (typeof _this.onerror === 'function') {
+	        _this.onerror(new Error(res.errMsg))
+	      }
+	    })
+
+	    return this
+	  } // TODO 小程序内目前获取不到,实际上需要根据服务器选择的 sub-protocol 返回
+	  // TODO 更新 bufferedAmount
+	  // The connection is closed or couldn't be opened.
+
+	  // The connection is open and ready to communicate.
+
+
+	  _createClass(WebSocket, [{
+	    key: 'close',
+	    value: function close(code, reason) {
+	      this.readyState = WebSocket.CLOSING
+	      var socketTask = _socketTask.get(this)
+
+	      socketTask.close({
+	        code: code,
+	        reason: reason
+	      })
+	    }
+	  }, {
+	    key: 'send',
+	    value: function send(data) {
+	      if (typeof data !== 'string' && !(data instanceof ArrayBuffer)) {
+	        throw new TypeError('Failed to send message: The data ' + data + ' is invalid')
+	      }
+
+	      var socketTask = _socketTask.get(this)
+
+	      socketTask.send({
+	        data: data
+	      })
+	    }
+	  }])
+
+	  return WebSocket
+	}()
+
+	WebSocket.CONNECTING = 0
+	WebSocket.OPEN = 1
+	WebSocket.CLOSING = 2
+	WebSocket.CLOSED = 3
+	exports.default = WebSocket
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports) {
+
+	"use strict"
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+
+	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } }
+
+	/*
+	 * TODO 使用 wx.readFile 来封装 FileReader
+	 */
+	var FileReader = function FileReader() {
+	  _classCallCheck(this, FileReader)
+	}
+
+	exports.default = FileReader
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports) {
+
+	"use strict"
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	var localStorage = {
+	  get length() {
+	    var _wx$getStorageInfoSyn = wx.getStorageInfoSync(),
+	        keys = _wx$getStorageInfoSyn.keys
+
+	    return keys.length
+	  },
+
+	  key: function key(n) {
+	    var _wx$getStorageInfoSyn2 = wx.getStorageInfoSync(),
+	        keys = _wx$getStorageInfoSyn2.keys
+
+	    return keys[n]
+	  },
+	  getItem: function getItem(key) {
+	    return wx.getStorageSync(key)
+	  },
+	  setItem: function setItem(key, value) {
+	    return wx.setStorageSync(key, value)
+	  },
+	  removeItem: function removeItem(key) {
+	    wx.removeStorageSync(key)
+	  },
+	  clear: function clear() {
+	    wx.clearStorageSync()
+	  }
+	}
+
+	exports.default = localStorage
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports) {
+
+	'use strict'
+
+	Object.defineProperty(exports, "__esModule", {
+	  value: true
+	})
+	var location = {
+	  href: 'game.js',
+	  reload: function reload() {}
+	}
+
+	exports.default = location
+
+/***/ })
+/******/ ])

+ 132 - 0
Album/jss/main.js

xqd
@@ -0,0 +1,132 @@
+import EventUtil from './base/eventUtil'
+import BackGround from './runtime/background'
+import GameInfo from './runtime/gameinfo'
+import DataBus from './databus'
+
+let ctx = canvas.getContext('2d')
+let databus = new DataBus()
+
+/**
+ * 游戏主函数
+ */
+export default class Main {
+  constructor() {
+    this.bg = new BackGround(ctx)
+    this.gameInfo = new GameInfo()
+
+    let eventUtil = new EventUtil(((e) => {
+      this.gameInfo.tap(e)
+    }).bind(this), ((e) => {
+      this.movePieces(e.direction);
+    }).bind(this))
+
+    databus.reset()
+
+    window.requestAnimationFrame(
+      this.loop.bind(this),
+      databus.pieces.forEach((item, position) => {
+        item.render(ctx);
+      })
+    )
+  }
+
+  /**
+   * 移动方块的方法
+   * 
+   * @param {any} direction 移动方向
+   * @returns 
+   * @memberof Main
+   */
+  movePieces(direction) {
+    let targetPiece
+    switch (direction) {
+      case 'up':
+        targetPiece = databus.emptyPosition + databus.stage
+        break;
+      case 'down':
+        targetPiece = databus.emptyPosition - databus.stage
+        break;
+      case 'left':
+        targetPiece = databus.emptyPosition + 1
+        if (Math.floor(targetPiece / databus.stage) !== Math.floor(databus.emptyPosition / databus.stage)) {
+          // 如果两个商不相等,说明左右滑动出现了换行现象,不能执行
+          return;
+        }
+        break;
+      case 'right':
+        targetPiece = databus.emptyPosition - 1
+        if (Math.floor(targetPiece / databus.stage) !== Math.floor(databus.emptyPosition / databus.stage)) {
+          return;
+        }
+        break;
+      default:
+        break;
+    }
+    databus.pieces.forEach((item) => {
+      if (item.position === targetPiece) {
+        item.move(databus.emptyPosition)
+        databus.emptyPosition = targetPiece
+      }
+    })
+  }
+
+  checkGameOver() {
+    if (databus.gameOver || databus.pieces.length === 0) {
+      return
+    }
+    for (let i = 0; i < databus.pieces.length; i++) {
+      let piece = databus.pieces[i]
+      if (piece.index !== piece.position) {
+        return false
+      }
+    }
+    databus.gameOver = true
+    databus.finalTime = databus.getCurrentTime()
+  }
+  /**
+   * canvas重绘函数
+   * 每一帧重新绘制所有的需要展示的元素
+   */
+  render() {
+    ctx.clearRect(0, 0, canvas.width, canvas.height)
+
+    this.bg.render(ctx)
+    databus.pieces.forEach((item) => {
+      item.render(ctx);
+    })
+    this.gameInfo.render(ctx)
+  }
+
+  // 游戏逻辑更新主函数
+  update() {
+    // 统计是否有动画正在播放
+    let isAniPlaying = false
+    databus.pieces.forEach((item) => {
+      item.update();
+      if (item.ani !== 1) {
+        isAniPlaying = true
+      }
+    })
+
+    // 如果没有动画正在播放,查看游戏是否结束
+    if (!isAniPlaying) {
+      this.checkGameOver()
+    }
+  }
+
+  // 实现游戏帧循环
+  loop() {
+    this.update()
+    this.render()
+
+    window.requestAnimationFrame(
+      this.loop.bind(this),
+      canvas
+    )
+  }
+}
+// var s = new Main()
+// module.export = {
+//   start: s.constructor()
+// }
+

+ 119 - 0
Album/jss/models/piece.js

xqd
@@ -0,0 +1,119 @@
+import DataBus from '../databus'
+import Bezier from '../libs/bezier'
+
+const PIECE_WRAPPER_SRC = 'image/wrap.png'
+const PIECE_WRAPPER_WIDTH = 300
+const PIECE_WRAPPER_HEIGHT = 300
+
+const ANI_SPEED = 0.2
+
+let databus = new DataBus()
+let easeInOut = Bezier(0.42, 0, 0.58, 1)
+
+function getPositionXY(position) {
+  let width = databus.contentWidth / databus.stage
+  let result = {}
+  result.x = databus.contentPadding + (position % databus.stage) * width
+  result.y = databus.contentPaddingTop + Math.floor(position / databus.stage) * width
+  return result
+}
+
+export default class Piece {
+
+  /**
+   * Creates an instance of Piece.
+   * @param {number} [index=0] 该拼图的序数
+   * @param {number} [position=0] 该拼图当前的位置
+   * @memberof Piece
+   */
+  constructor(index = 0, position = 0) {
+    this.index = index
+    this.position = position
+    this.visible = true
+
+    // 根据contentWidth、index和stage来判断如何绘制图片
+    let cut = databus.puzzleImg.width / databus.stage
+    let width = databus.contentWidth / databus.stage
+
+    this.img = new Image()
+    this.img.src = databus.puzzleImg.src
+    this.sx = (index % databus.stage) * cut
+    this.sy = Math.floor(index / databus.stage) * cut
+    this.swidth = cut
+    this.sheight = cut
+
+    let positionXY = getPositionXY(position)
+    this.x = positionXY.x
+    this.y = positionXY.y
+    this.width = width
+    this.height = width
+
+    // old和new坐标用于动画效果
+    this.oldX = positionXY.x
+    this.oldY = positionXY.y
+    this.newX = positionXY.x
+    this.newY = positionXY.y
+    this.ani = 1 // ani为0的时候开始动画,ani为1的时候动画完成
+
+    this.wrapperImg = new Image()
+    this.wrapperImg.src = PIECE_WRAPPER_SRC
+  }
+
+  // 设定新的方块位置
+  move(position = 0) {
+    this.ani = 0
+    this.position = position
+    let positionXY = getPositionXY(position)
+    this.newX = positionXY.x
+    this.newY = positionXY.y
+    this.oldX = this.x
+    this.oldY = this.y
+  }
+
+  // 更新方块位置
+  update() {
+    if (this.ani >= 1) {
+      this.ani = 1
+      this.x = this.newX
+      this.y = this.newY
+      return
+    }
+    this.ani += ANI_SPEED
+    this.x = this.oldX + (this.newX - this.oldX) * easeInOut(this.ani)
+    this.y = this.oldY + (this.newY - this.oldY) * easeInOut(this.ani)
+  }
+
+  // 绘制方块
+  render(ctx) {
+    if (!this.visible)
+      return
+
+    ctx.drawImage(
+      this.img,
+      this.sx,
+      this.sy,
+      this.swidth,
+      this.sheight,
+      this.x,
+      this.y,
+      this.width,
+      this.height
+    )
+
+    ctx.drawImage(
+      this.wrapperImg,
+      this.x,
+      this.y,
+      this.width,
+      this.height
+    )
+  }
+  // 每一帧更新子弹位置
+  // update() {
+  //   this.y += this[__.speed]
+
+  //   // 对象回收
+  //   if (this.y > window.innerHeight + this.height)
+  //     databus.removeEnemey(this)
+  // }
+}

+ 69 - 0
Album/jss/runtime/background.js

xqd
@@ -0,0 +1,69 @@
+import DataBus from '../databus'
+
+const BG_IMG_SRC = 'image/bg.jpg'
+
+const BG_BORDER_SRC = 'image/border.png'
+const BG_BORDER_WIDTH = 1020
+const BG_BORDER_HEIGHT = 1020
+const BG_CONTENT_WIDTH = 1000
+const BG_CONTENT_HEIGHT = 1000
+
+const BG_PAPER_SRC = 'image/paper.png'
+let databus = new DataBus()
+
+
+/**
+ * 游戏背景类
+ * 提供update和render函数实现无限滚动的背景功能
+ */
+export default class BackGround {
+  constructor(ctx) {
+    // super(BG_IMG_SRC, BG_WIDTH, BG_HEIGHT)
+
+    this.img = new Image()
+    this.img.src = BG_IMG_SRC
+
+    this.borderImg = new Image()
+    this.borderImg.src = BG_BORDER_SRC
+
+    this.paperImg = new Image()
+    this.paperImg.src = BG_PAPER_SRC
+
+
+    // 因为puzzle多一个边框
+    // 所以根据contentWidth算出puzzleWidth
+    this.puzzleWidth = databus.contentWidth * (BG_BORDER_WIDTH / BG_CONTENT_WIDTH)
+    this.puzzlePadding = (databus.screenWidth - this.puzzleWidth) / 2
+    this.puzzlePaddingTop = databus.screenHeight - this.puzzleWidth - this.puzzlePadding;
+
+    this.render(ctx)
+  }
+
+  render(ctx) {
+    ctx.drawImage(
+      this.img,
+      0,
+      0,
+      databus.screenWidth,
+      databus.screenHeight
+    )
+
+    ctx.drawImage(
+      this.paperImg,
+      this.puzzlePadding,
+      this.puzzlePaddingTop,
+      this.puzzleWidth,
+      this.puzzleWidth
+    )
+    
+    ctx.drawImage(
+      this.borderImg,
+      this.puzzlePadding,
+      this.puzzlePaddingTop,
+      this.puzzleWidth,
+      this.puzzleWidth
+    )
+
+
+  }
+}

+ 432 - 0
Album/jss/runtime/gameMap.js

xqd
@@ -0,0 +1,432 @@
+const puzzleList3 = [
+    [5, 4, 7, 3, 1, 6, 2, 8],
+    [5, 3, 1, 7, 4, 8, 2, 6],
+    [6, 2, 1, 3, 5, 4, 8, 7],
+    [5, 8, 2, 7, 6, 3, 4, 1],
+    [6, 1, 4, 8, 7, 2, 3, 5],
+    [7, 2, 8, 1, 5, 3, 4, 6],
+    [8, 3, 2, 7, 6, 1, 5, 4],
+    [2, 7, 8, 3, 6, 1, 5, 4],
+    [7, 4, 3, 2, 5, 1, 8, 6],
+    [3, 4, 1, 7, 5, 6, 8, 2],
+    [6, 1, 3, 8, 5, 2, 4, 7],
+    [2, 1, 3, 5, 6, 8, 7, 4],
+    [2, 8, 1, 6, 3, 7, 4, 5],
+    [7, 6, 1, 5, 4, 8, 2, 3],
+    [8, 4, 7, 2, 6, 3, 1, 5],
+    [5, 7, 8, 6, 4, 3, 2, 1],
+    [6, 7, 4, 5, 1, 3, 8, 2],
+    [4, 1, 2, 3, 7, 5, 8, 6],
+    [8, 6, 2, 5, 1, 7, 3, 4],
+    [6, 8, 4, 2, 3, 7, 1, 5],
+    [1, 8, 7, 4, 6, 2, 3, 5],
+    [2, 6, 5, 3, 8, 1, 4, 7],
+    [7, 3, 8, 5, 6, 2, 1, 4],
+    [5, 7, 8, 1, 4, 3, 6, 2],
+    [5, 6, 8, 3, 1, 7, 4, 2],
+    [5, 7, 2, 6, 1, 3, 8, 4],
+    [4, 5, 3, 1, 8, 6, 2, 7],
+    [5, 8, 7, 2, 6, 4, 3, 1],
+    [8, 7, 5, 2, 3, 1, 6, 4],
+    [4, 8, 6, 2, 3, 7, 5, 1],
+    [4, 1, 2, 6, 7, 3, 8, 5],
+    [3, 6, 7, 5, 4, 1, 8, 2],
+    [7, 8, 6, 5, 2, 3, 4, 1],
+    [7, 5, 4, 3, 6, 1, 8, 2],
+    [5, 8, 4, 3, 6, 2, 1, 7],
+    [2, 7, 6, 5, 8, 1, 3, 4],
+    [4, 1, 5, 2, 6, 8, 3, 7],
+    [2, 1, 8, 7, 4, 3, 6, 5],
+    [5, 3, 2, 1, 8, 4, 6, 7],
+    [8, 2, 1, 4, 7, 3, 5, 6],
+    [1, 4, 6, 5, 8, 3, 7, 2],
+    [5, 8, 6, 3, 2, 4, 1, 7],
+    [6, 4, 8, 2, 7, 5, 3, 1],
+    [7, 1, 6, 4, 5, 3, 8, 2],
+    [2, 1, 4, 7, 5, 6, 8, 3],
+    [6, 7, 2, 4, 5, 8, 3, 1],
+    [6, 5, 8, 3, 7, 4, 2, 1],
+    [5, 1, 4, 6, 8, 3, 2, 7],
+    [8, 4, 5, 2, 1, 6, 7, 3],
+    [5, 2, 4, 6, 1, 7, 3, 8],
+    [3, 1, 6, 8, 7, 5, 2, 4],
+    [3, 7, 5, 8, 1, 4, 6, 2],
+    [3, 8, 6, 1, 2, 4, 5, 7],
+    [5, 1, 8, 2, 7, 3, 4, 6],
+    [7, 5, 4, 2, 3, 1, 8, 6],
+    [8, 3, 5, 1, 7, 4, 2, 6],
+    [6, 7, 4, 2, 8, 3, 1, 5],
+    [2, 1, 5, 7, 4, 3, 8, 6],
+    [1, 6, 2, 7, 5, 8, 4, 3],
+    [5, 6, 8, 7, 3, 1, 4, 2],
+    [8, 6, 3, 2, 5, 4, 1, 7],
+    [7, 6, 1, 8, 2, 3, 5, 4],
+    [3, 6, 5, 8, 4, 2, 1, 7],
+    [2, 4, 1, 3, 5, 7, 6, 8],
+    [3, 2, 1, 8, 5, 6, 7, 4],
+    [6, 7, 4, 8, 2, 3, 5, 1],
+    [3, 8, 5, 7, 6, 1, 2, 4],
+    [5, 6, 8, 3, 4, 7, 2, 1],
+    [1, 7, 5, 2, 8, 6, 4, 3],
+    [2, 4, 1, 3, 8, 7, 5, 6],
+    [6, 1, 5, 3, 8, 2, 4, 7],
+    [7, 3, 6, 1, 8, 2, 5, 4],
+    [6, 5, 1, 7, 2, 4, 8, 3],
+    [5, 1, 8, 6, 2, 7, 3, 4],
+    [4, 7, 5, 2, 8, 1, 6, 3],
+    [8, 7, 6, 1, 4, 3, 5, 2],
+    [5, 4, 2, 8, 6, 7, 1, 3],
+    [2, 4, 1, 5, 3, 8, 6, 7],
+    [5, 1, 2, 6, 8, 4, 3, 7],
+    [5, 7, 1, 2, 3, 6, 4, 8],
+    [7, 2, 4, 5, 3, 1, 6, 8],
+    [2, 4, 3, 1, 5, 7, 8, 6],
+    [4, 5, 1, 3, 8, 7, 2, 6],
+    [1, 4, 3, 6, 2, 5, 8, 7],
+    [8, 2, 3, 6, 4, 5, 1, 7],
+    [1, 5, 2, 6, 3, 7, 4, 8],
+    [3, 5, 8, 7, 1, 4, 6, 2],
+    [3, 8, 6, 5, 1, 7, 4, 2],
+    [8, 3, 4, 2, 5, 6, 1, 7],
+    [2, 5, 7, 8, 3, 4, 1, 6],
+    [2, 3, 6, 5, 8, 7, 1, 4],
+    [7, 6, 5, 3, 2, 8, 1, 4],
+    [3, 6, 1, 4, 7, 5, 2, 8],
+    [1, 4, 3, 5, 6, 2, 8, 7],
+    [8, 2, 6, 4, 3, 7, 5, 1],
+    [8, 7, 2, 5, 4, 1, 6, 3],
+    [8, 5, 7, 2, 4, 1, 6, 3],
+    [3, 1, 6, 8, 7, 2, 4, 5],
+    [4, 3, 6, 5, 8, 7, 2, 1]
+];
+const puzzleList4 = [
+    [12, 3, 5, 11, 15, 4, 8, 6, 2, 13, 7, 10, 9, 14, 1],
+    [1, 10, 3, 4, 13, 2, 12, 7, 6, 5, 8, 11, 15, 9, 14],
+    [3, 11, 14, 2, 13, 8, 15, 10, 12, 6, 5, 1, 4, 7, 9],
+    [8, 6, 10, 2, 12, 9, 11, 1, 14, 13, 3, 7, 5, 15, 4],
+    [15, 10, 6, 2, 4, 5, 3, 9, 8, 12, 11, 13, 14, 1, 7],
+    [14, 13, 1, 9, 12, 3, 8, 15, 11, 6, 4, 2, 10, 5, 7],
+    [11, 3, 6, 7, 14, 4, 10, 8, 2, 1, 13, 15, 5, 9, 12],
+    [3, 2, 11, 6, 5, 8, 7, 4, 1, 15, 9, 14, 13, 10, 12],
+    [7, 13, 8, 5, 12, 3, 6, 4, 10, 9, 15, 11, 2, 1, 14],
+    [1, 14, 5, 7, 15, 3, 11, 4, 12, 8, 10, 9, 13, 6, 2],
+    [14, 4, 15, 8, 2, 10, 1, 9, 12, 11, 5, 6, 3, 7, 13],
+    [2, 11, 1, 8, 5, 4, 12, 13, 14, 3, 10, 15, 9, 7, 6],
+    [5, 10, 11, 2, 15, 9, 4, 8, 13, 14, 12, 1, 7, 6, 3],
+    [4, 2, 15, 7, 9, 10, 14, 1, 6, 11, 5, 13, 8, 3, 12],
+    [1, 5, 15, 8, 11, 6, 10, 13, 2, 3, 9, 7, 4, 12, 14],
+    [3, 9, 13, 15, 8, 11, 10, 5, 7, 6, 4, 14, 12, 1, 2],
+    [13, 4, 15, 10, 1, 9, 8, 11, 7, 12, 2, 6, 5, 3, 14],
+    [4, 1, 12, 11, 7, 2, 9, 5, 8, 13, 15, 10, 14, 3, 6],
+    [10, 8, 1, 13, 12, 2, 6, 9, 3, 7, 4, 11, 5, 15, 14],
+    [6, 7, 13, 3, 9, 1, 2, 14, 12, 15, 11, 5, 8, 10, 4],
+    [5, 13, 8, 4, 14, 6, 15, 10, 3, 12, 7, 9, 1, 2, 11],
+    [3, 13, 15, 2, 9, 6, 8, 14, 4, 10, 12, 7, 11, 1, 5],
+    [10, 5, 4, 11, 9, 2, 6, 15, 1, 7, 8, 13, 3, 14, 12],
+    [6, 14, 3, 5, 13, 7, 11, 2, 4, 10, 1, 12, 8, 15, 9],
+    [9, 2, 14, 6, 12, 15, 1, 5, 4, 11, 7, 3, 10, 8, 13],
+    [5, 14, 9, 8, 15, 4, 3, 11, 13, 12, 6, 2, 1, 10, 7],
+    [7, 10, 4, 11, 8, 14, 13, 2, 3, 12, 9, 6, 5, 1, 15],
+    [14, 10, 6, 5, 11, 8, 1, 3, 4, 13, 7, 15, 2, 12, 9],
+    [14, 13, 15, 8, 2, 12, 5, 4, 1, 3, 6, 10, 11, 9, 7],
+    [11, 15, 6, 8, 14, 7, 9, 5, 2, 4, 13, 1, 10, 3, 12],
+    [7, 15, 14, 9, 2, 1, 3, 11, 10, 12, 8, 5, 4, 6, 13],
+    [5, 2, 15, 14, 7, 6, 4, 8, 1, 13, 9, 12, 10, 11, 3],
+    [8, 10, 11, 1, 14, 13, 5, 3, 9, 12, 15, 4, 2, 7, 6],
+    [8, 14, 7, 11, 6, 3, 12, 4, 10, 1, 15, 9, 2, 5, 13],
+    [15, 8, 9, 6, 2, 14, 12, 3, 5, 10, 1, 13, 7, 4, 11],
+    [6, 15, 7, 10, 1, 3, 12, 4, 8, 14, 5, 2, 9, 11, 13],
+    [12, 9, 2, 4, 3, 14, 7, 5, 1, 6, 13, 11, 15, 8, 10],
+    [13, 3, 15, 10, 2, 5, 9, 7, 6, 11, 1, 14, 8, 4, 12],
+    [13, 11, 2, 8, 15, 1, 9, 5, 6, 12, 4, 3, 14, 10, 7],
+    [7, 1, 5, 12, 15, 2, 8, 10, 3, 6, 9, 13, 11, 14, 4],
+    [14, 13, 12, 1, 2, 8, 6, 11, 7, 10, 15, 3, 4, 9, 5],
+    [3, 8, 13, 10, 12, 14, 5, 11, 1, 15, 9, 4, 7, 2, 6],
+    [11, 6, 10, 14, 8, 2, 13, 4, 12, 9, 3, 5, 1, 7, 15],
+    [7, 13, 3, 14, 9, 11, 12, 10, 2, 6, 1, 5, 4, 8, 15],
+    [2, 3, 6, 4, 14, 12, 13, 1, 5, 10, 8, 11, 9, 7, 15],
+    [11, 12, 9, 14, 8, 15, 10, 7, 1, 13, 5, 2, 3, 6, 4],
+    [5, 11, 4, 15, 12, 10, 2, 1, 8, 14, 9, 13, 7, 6, 3],
+    [14, 9, 13, 7, 1, 4, 2, 3, 8, 11, 15, 5, 10, 6, 12],
+    [15, 5, 13, 2, 14, 4, 1, 6, 12, 3, 9, 10, 8, 7, 11],
+    [10, 2, 15, 5, 12, 8, 7, 3, 6, 14, 11, 13, 4, 9, 1],
+    [11, 5, 4, 2, 7, 13, 3, 1, 12, 9, 14, 6, 10, 15, 8],
+    [13, 15, 4, 6, 1, 14, 11, 7, 10, 9, 8, 5, 3, 2, 12],
+    [12, 13, 14, 11, 3, 8, 7, 10, 2, 1, 6, 9, 5, 4, 15],
+    [12, 8, 15, 3, 9, 2, 5, 14, 4, 6, 11, 7, 1, 10, 13],
+    [1, 13, 9, 2, 12, 6, 8, 7, 4, 11, 14, 5, 10, 15, 3],
+    [9, 1, 15, 14, 5, 11, 2, 3, 12, 6, 10, 8, 7, 13, 4],
+    [13, 2, 11, 14, 15, 4, 9, 6, 1, 3, 7, 10, 5, 8, 12],
+    [12, 14, 6, 7, 4, 2, 3, 10, 15, 11, 1, 8, 9, 5, 13],
+    [8, 14, 1, 4, 3, 6, 15, 12, 11, 7, 5, 10, 2, 9, 13],
+    [8, 12, 9, 4, 3, 11, 15, 6, 5, 7, 2, 13, 14, 10, 1],
+    [3, 10, 14, 9, 15, 8, 2, 6, 5, 13, 7, 12, 4, 11, 1],
+    [7, 12, 5, 14, 2, 10, 11, 3, 13, 1, 4, 8, 15, 6, 9],
+    [4, 15, 5, 11, 9, 12, 14, 13, 6, 7, 10, 2, 1, 3, 8],
+    [10, 1, 3, 6, 11, 14, 5, 4, 15, 9, 13, 2, 12, 8, 7],
+    [11, 2, 3, 4, 7, 6, 12, 15, 5, 13, 14, 10, 9, 1, 8],
+    [11, 6, 5, 9, 15, 14, 4, 3, 1, 13, 12, 8, 10, 2, 7],
+    [11, 1, 2, 6, 8, 4, 10, 7, 5, 13, 12, 3, 9, 14, 15],
+    [4, 6, 2, 8, 12, 1, 5, 15, 9, 11, 7, 10, 13, 14, 3],
+    [9, 7, 2, 8, 11, 5, 4, 15, 12, 1, 6, 13, 14, 10, 3],
+    [12, 13, 15, 14, 6, 11, 7, 5, 1, 9, 4, 10, 3, 2, 8],
+    [1, 13, 3, 9, 6, 14, 5, 2, 11, 15, 10, 7, 12, 4, 8],
+    [13, 10, 11, 15, 2, 14, 7, 5, 6, 3, 9, 8, 4, 12, 1],
+    [8, 13, 11, 3, 6, 15, 1, 14, 4, 10, 9, 5, 2, 7, 12],
+    [11, 12, 4, 2, 9, 13, 10, 15, 3, 7, 8, 14, 6, 1, 5],
+    [3, 15, 2, 12, 9, 10, 13, 6, 5, 8, 14, 7, 4, 11, 1],
+    [8, 1, 6, 12, 14, 13, 11, 15, 10, 5, 2, 7, 3, 9, 4],
+    [12, 10, 4, 9, 7, 3, 14, 11, 8, 1, 15, 2, 6, 5, 13],
+    [3, 6, 15, 13, 2, 4, 9, 10, 7, 11, 8, 14, 1, 5, 12],
+    [12, 8, 10, 13, 2, 5, 11, 4, 7, 14, 3, 15, 9, 1, 6],
+    [13, 6, 7, 11, 12, 5, 4, 2, 1, 10, 9, 3, 8, 15, 14],
+    [1, 10, 12, 6, 7, 13, 3, 9, 2, 15, 8, 14, 5, 4, 11],
+    [11, 4, 13, 3, 1, 5, 6, 12, 2, 15, 14, 7, 9, 8, 10],
+    [7, 12, 14, 11, 2, 4, 10, 13, 6, 1, 15, 8, 3, 5, 9],
+    [15, 5, 9, 7, 4, 1, 6, 12, 14, 3, 2, 13, 11, 8, 10],
+    [12, 6, 13, 7, 15, 14, 9, 3, 1, 5, 8, 11, 4, 2, 10],
+    [6, 11, 15, 7, 12, 13, 8, 9, 14, 3, 1, 5, 2, 10, 4],
+    [14, 15, 2, 12, 11, 10, 13, 9, 1, 5, 4, 3, 7, 8, 6],
+    [2, 15, 6, 12, 11, 1, 10, 8, 3, 7, 9, 13, 4, 14, 5],
+    [6, 3, 9, 12, 14, 2, 11, 5, 10, 8, 4, 13, 1, 15, 7],
+    [4, 1, 7, 14, 9, 3, 6, 2, 12, 10, 15, 13, 11, 5, 8],
+    [4, 3, 2, 15, 9, 11, 8, 10, 1, 7, 12, 14, 5, 13, 6],
+    [1, 13, 11, 8, 10, 15, 3, 7, 14, 2, 6, 9, 5, 4, 12],
+    [3, 14, 15, 12, 7, 9, 11, 5, 10, 2, 6, 4, 1, 8, 13],
+    [14, 4, 7, 2, 11, 6, 3, 15, 5, 13, 8, 10, 12, 9, 1],
+    [7, 12, 5, 3, 13, 1, 6, 4, 10, 2, 11, 15, 14, 9, 8],
+    [3, 1, 7, 13, 6, 15, 12, 5, 11, 4, 9, 2, 14, 8, 10],
+    [4, 8, 6, 2, 7, 5, 1, 13, 10, 9, 12, 11, 14, 15, 3],
+    [13, 8, 9, 14, 2, 1, 7, 5, 10, 15, 12, 11, 3, 4, 6],
+    [15, 2, 5, 3, 9, 7, 4, 12, 1, 6, 11, 13, 10, 8, 14]
+];
+const puzzleList5 = [
+    [18, 12, 23, 5, 7, 11, 9, 2, 4, 20, 15, 13, 16, 10, 22, 21, 24, 19, 17, 3, 8, 6, 1, 14],
+    [14, 10, 9, 15, 2, 22, 1, 18, 16, 6, 8, 5, 24, 19, 23, 7, 21, 12, 20, 3, 4, 13, 11, 17],
+    [7, 12, 10, 8, 9, 19, 17, 6, 4, 16, 23, 3, 1, 20, 18, 24, 13, 14, 21, 2, 11, 22, 5, 15],
+    [20, 10, 5, 17, 15, 19, 2, 13, 3, 6, 21, 23, 9, 4, 24, 12, 22, 16, 7, 18, 14, 11, 1, 8],
+    [6, 8, 10, 18, 21, 9, 11, 1, 17, 14, 13, 19, 5, 15, 4, 20, 22, 2, 23, 16, 7, 24, 12, 3],
+    [5, 8, 22, 15, 19, 24, 13, 23, 18, 14, 16, 3, 17, 6, 2, 12, 7, 1, 4, 11, 9, 20, 21, 10],
+    [22, 1, 13, 14, 16, 11, 21, 9, 6, 24, 23, 5, 4, 18, 7, 2, 8, 19, 3, 15, 12, 20, 17, 10],
+    [6, 24, 11, 8, 15, 13, 12, 21, 16, 18, 14, 7, 22, 4, 5, 1, 10, 3, 2, 20, 9, 23, 19, 17],
+    [13, 2, 19, 1, 22, 16, 15, 10, 7, 20, 8, 12, 4, 21, 6, 23, 18, 5, 14, 17, 9, 3, 24, 11],
+    [3, 7, 13, 6, 16, 12, 19, 15, 20, 14, 8, 4, 1, 17, 11, 5, 22, 18, 24, 2, 23, 21, 9, 10],
+    [2, 14, 6, 3, 24, 23, 19, 8, 4, 7, 18, 16, 1, 11, 20, 17, 9, 15, 12, 5, 13, 22, 10, 21],
+    [18, 7, 12, 17, 22, 15, 20, 4, 24, 14, 23, 11, 3, 9, 13, 21, 5, 10, 19, 6, 2, 8, 16, 1],
+    [15, 21, 12, 11, 6, 9, 16, 8, 14, 20, 22, 10, 24, 4, 19, 2, 17, 18, 1, 13, 3, 23, 5, 7],
+    [17, 20, 6, 3, 5, 22, 24, 2, 12, 16, 4, 9, 13, 15, 1, 11, 14, 23, 21, 10, 18, 8, 7, 19],
+    [20, 22, 14, 15, 23, 7, 3, 17, 6, 13, 16, 5, 1, 11, 9, 12, 19, 4, 21, 2, 10, 24, 18, 8],
+    [8, 7, 16, 9, 2, 5, 20, 4, 19, 3, 13, 12, 17, 14, 18, 23, 10, 15, 22, 24, 1, 11, 6, 21],
+    [17, 7, 12, 3, 1, 10, 20, 19, 8, 22, 14, 21, 13, 11, 2, 16, 24, 4, 6, 5, 18, 23, 9, 15],
+    [5, 12, 9, 13, 3, 6, 17, 16, 21, 20, 24, 22, 2, 10, 11, 1, 18, 4, 14, 15, 19, 23, 8, 7],
+    [2, 24, 8, 21, 5, 6, 3, 14, 1, 15, 13, 11, 17, 23, 10, 7, 19, 18, 4, 22, 9, 20, 12, 16],
+    [9, 7, 22, 20, 18, 19, 24, 2, 4, 13, 17, 1, 12, 21, 10, 11, 14, 6, 5, 8, 16, 23, 3, 15],
+    [8, 7, 16, 23, 10, 6, 1, 17, 19, 14, 2, 12, 4, 9, 24, 13, 21, 22, 20, 5, 11, 18, 15, 3],
+    [22, 12, 7, 17, 6, 20, 1, 21, 11, 24, 16, 2, 18, 9, 5, 13, 4, 14, 8, 15, 23, 19, 3, 10],
+    [11, 2, 23, 16, 3, 20, 15, 1, 19, 5, 14, 8, 4, 7, 24, 17, 22, 21, 13, 9, 12, 6, 10, 18],
+    [2, 12, 10, 1, 18, 23, 6, 8, 24, 14, 17, 21, 16, 20, 4, 11, 13, 9, 7, 15, 19, 5, 3, 22],
+    [8, 19, 1, 24, 5, 18, 9, 14, 22, 13, 11, 4, 6, 17, 21, 20, 2, 3, 15, 10, 16, 7, 23, 12],
+    [21, 13, 17, 7, 11, 1, 3, 19, 22, 18, 20, 8, 10, 15, 16, 2, 24, 6, 12, 5, 14, 23, 4, 9],
+    [15, 8, 14, 23, 20, 21, 11, 1, 9, 22, 2, 13, 24, 3, 7, 19, 12, 4, 18, 5, 17, 10, 6, 16],
+    [11, 1, 7, 9, 23, 19, 2, 10, 5, 12, 22, 4, 6, 16, 13, 3, 17, 24, 8, 21, 20, 14, 18, 15],
+    [24, 12, 4, 19, 15, 13, 8, 10, 23, 1, 3, 5, 6, 9, 18, 20, 16, 21, 7, 17, 14, 22, 11, 2],
+    [1, 4, 11, 24, 19, 18, 16, 10, 22, 7, 23, 3, 17, 21, 5, 20, 9, 12, 2, 6, 8, 13, 14, 15],
+    [7, 23, 13, 9, 1, 4, 8, 24, 15, 20, 14, 16, 21, 6, 5, 12, 3, 10, 2, 18, 11, 19, 22, 17],
+    [23, 12, 9, 16, 14, 2, 22, 4, 7, 18, 24, 11, 17, 15, 19, 6, 3, 21, 8, 13, 5, 1, 20, 10],
+    [3, 14, 16, 17, 22, 19, 5, 21, 24, 7, 12, 13, 4, 6, 2, 8, 9, 10, 18, 15, 1, 23, 11, 20],
+    [18, 4, 22, 17, 8, 24, 1, 16, 7, 19, 21, 15, 13, 2, 23, 10, 5, 6, 20, 14, 9, 12, 3, 11],
+    [12, 18, 6, 5, 21, 2, 4, 14, 15, 22, 9, 10, 16, 1, 7, 3, 11, 23, 13, 19, 24, 17, 20, 8],
+    [2, 1, 9, 14, 15, 13, 20, 21, 11, 3, 4, 6, 18, 8, 19, 17, 5, 10, 24, 16, 23, 12, 7, 22],
+    [17, 10, 3, 22, 21, 12, 24, 23, 4, 8, 19, 5, 13, 11, 1, 9, 15, 18, 6, 14, 2, 7, 20, 16],
+    [1, 5, 19, 10, 21, 9, 14, 2, 13, 8, 3, 20, 15, 4, 11, 17, 18, 23, 16, 7, 12, 22, 24, 6],
+    [3, 24, 14, 5, 17, 22, 1, 15, 6, 8, 12, 20, 11, 10, 13, 4, 21, 9, 23, 2, 16, 19, 7, 18],
+    [6, 19, 12, 3, 20, 4, 21, 1, 2, 16, 9, 23, 22, 13, 24, 17, 15, 8, 7, 11, 14, 5, 10, 18],
+    [17, 19, 24, 2, 6, 12, 9, 20, 22, 10, 8, 15, 3, 18, 7, 23, 11, 21, 5, 16, 14, 4, 13, 1],
+    [2, 5, 24, 16, 18, 14, 12, 3, 7, 4, 15, 10, 13, 23, 9, 21, 20, 17, 1, 19, 8, 22, 11, 6],
+    [16, 22, 23, 24, 12, 18, 6, 20, 14, 7, 9, 19, 8, 17, 1, 21, 10, 5, 11, 15, 4, 3, 13, 2],
+    [19, 8, 10, 6, 21, 15, 2, 7, 24, 22, 16, 12, 17, 13, 23, 3, 11, 4, 14, 5, 9, 18, 1, 20],
+    [19, 11, 14, 20, 16, 10, 7, 2, 23, 8, 6, 22, 24, 4, 3, 15, 13, 1, 12, 17, 5, 9, 18, 21],
+    [18, 23, 20, 19, 5, 8, 22, 21, 14, 10, 1, 6, 12, 7, 16, 9, 3, 24, 13, 4, 11, 17, 2, 15],
+    [13, 16, 10, 24, 15, 11, 12, 23, 17, 6, 5, 8, 1, 2, 19, 7, 20, 22, 14, 4, 18, 21, 3, 9],
+    [4, 23, 3, 18, 16, 2, 20, 14, 15, 13, 8, 21, 9, 22, 7, 24, 5, 10, 6, 11, 17, 1, 19, 12],
+    [9, 1, 3, 17, 7, 20, 11, 22, 4, 5, 24, 10, 13, 23, 14, 18, 19, 8, 2, 12, 15, 21, 6, 16],
+    [18, 1, 23, 17, 24, 9, 13, 7, 2, 3, 15, 5, 19, 14, 6, 12, 8, 20, 4, 22, 21, 11, 10, 16],
+    [19, 24, 7, 11, 9, 22, 3, 10, 18, 23, 17, 2, 16, 15, 5, 4, 14, 21, 6, 20, 13, 1, 8, 12],
+    [6, 12, 11, 23, 15, 13, 20, 22, 10, 8, 17, 24, 18, 14, 3, 19, 21, 2, 1, 9, 16, 7, 4, 5],
+    [12, 17, 16, 8, 4, 15, 21, 18, 22, 14, 10, 3, 2, 24, 9, 13, 20, 23, 6, 1, 19, 7, 5, 11],
+    [16, 21, 7, 3, 22, 5, 1, 19, 17, 13, 12, 8, 24, 10, 2, 23, 4, 9, 20, 6, 11, 15, 14, 18],
+    [7, 19, 22, 12, 11, 3, 18, 8, 23, 13, 15, 5, 4, 2, 17, 9, 1, 6, 21, 16, 20, 14, 24, 10],
+    [14, 21, 3, 10, 22, 2, 18, 16, 20, 11, 19, 1, 15, 8, 9, 17, 12, 6, 24, 23, 4, 7, 13, 5],
+    [1, 8, 17, 5, 20, 11, 18, 6, 10, 24, 4, 3, 16, 12, 19, 23, 7, 2, 21, 9, 14, 22, 13, 15],
+    [7, 10, 4, 19, 12, 20, 14, 2, 5, 23, 21, 9, 18, 15, 16, 11, 22, 3, 17, 6, 24, 13, 1, 8],
+    [11, 6, 21, 24, 5, 19, 4, 16, 18, 12, 10, 13, 17, 9, 20, 23, 22, 14, 1, 3, 8, 7, 15, 2],
+    [3, 2, 10, 14, 9, 11, 7, 15, 18, 23, 12, 4, 16, 20, 24, 1, 6, 22, 8, 17, 19, 13, 21, 5],
+    [3, 24, 17, 11, 14, 9, 12, 7, 5, 16, 19, 10, 1, 4, 13, 21, 2, 8, 23, 22, 6, 18, 20, 15],
+    [3, 18, 17, 5, 22, 13, 24, 11, 23, 8, 10, 2, 1, 16, 20, 7, 6, 4, 21, 12, 19, 9, 14, 15],
+    [18, 5, 16, 22, 6, 21, 11, 1, 4, 8, 19, 23, 17, 2, 14, 3, 10, 20, 7, 9, 24, 15, 12, 13],
+    [17, 10, 9, 13, 8, 7, 19, 22, 5, 3, 21, 23, 18, 2, 15, 1, 14, 11, 24, 4, 16, 6, 20, 12],
+    [10, 24, 21, 19, 20, 23, 17, 4, 15, 16, 9, 8, 14, 2, 1, 7, 18, 5, 3, 12, 13, 22, 11, 6],
+    [3, 2, 18, 10, 19, 17, 22, 11, 9, 20, 6, 14, 24, 7, 16, 23, 5, 4, 12, 8, 1, 21, 13, 15],
+    [16, 11, 13, 20, 10, 15, 3, 24, 9, 23, 14, 6, 19, 5, 2, 18, 1, 4, 7, 17, 22, 21, 12, 8],
+    [3, 6, 15, 5, 18, 8, 13, 20, 11, 7, 19, 24, 1, 4, 17, 22, 23, 21, 10, 9, 16, 14, 12, 2],
+    [17, 10, 14, 19, 18, 22, 24, 8, 3, 23, 13, 11, 21, 6, 4, 15, 12, 1, 16, 7, 9, 2, 5, 20],
+    [8, 17, 24, 11, 5, 13, 16, 20, 12, 1, 7, 23, 6, 22, 19, 3, 18, 10, 2, 14, 4, 21, 9, 15],
+    [6, 8, 13, 18, 7, 9, 5, 4, 16, 17, 19, 2, 10, 14, 20, 22, 12, 24, 23, 1, 11, 3, 21, 15],
+    [24, 15, 2, 22, 18, 3, 19, 14, 13, 1, 5, 20, 7, 6, 12, 4, 8, 21, 23, 9, 17, 10, 11, 16],
+    [1, 9, 4, 23, 19, 15, 10, 5, 3, 24, 18, 21, 22, 13, 7, 8, 11, 16, 6, 14, 17, 12, 20, 2],
+    [3, 20, 22, 11, 14, 13, 5, 19, 1, 2, 8, 17, 10, 9, 7, 15, 23, 6, 4, 16, 18, 21, 12, 24],
+    [22, 6, 15, 20, 4, 23, 10, 8, 12, 13, 1, 5, 24, 21, 9, 7, 14, 3, 11, 17, 18, 2, 19, 16],
+    [16, 17, 6, 10, 13, 23, 24, 7, 12, 14, 22, 18, 20, 5, 15, 2, 9, 8, 3, 11, 4, 1, 21, 19],
+    [20, 21, 14, 11, 2, 16, 8, 22, 9, 4, 19, 12, 18, 3, 5, 15, 13, 23, 24, 6, 10, 7, 17, 1],
+    [20, 13, 16, 22, 2, 6, 14, 7, 10, 19, 17, 4, 9, 5, 12, 1, 11, 3, 23, 24, 21, 15, 8, 18],
+    [5, 22, 14, 23, 8, 15, 18, 1, 16, 20, 4, 12, 3, 19, 21, 7, 2, 6, 11, 10, 24, 9, 17, 13],
+    [14, 18, 23, 7, 6, 13, 5, 24, 8, 11, 17, 12, 10, 2, 9, 19, 4, 15, 16, 3, 20, 22, 21, 1],
+    [15, 8, 23, 24, 2, 12, 7, 19, 9, 18, 6, 14, 13, 4, 22, 11, 16, 3, 20, 10, 5, 1, 21, 17],
+    [10, 3, 24, 1, 19, 23, 4, 2, 12, 18, 5, 9, 8, 17, 15, 22, 7, 6, 14, 20, 11, 21, 13, 16],
+    [14, 9, 16, 23, 6, 2, 7, 15, 11, 8, 5, 21, 13, 4, 10, 18, 20, 24, 22, 17, 19, 1, 3, 12],
+    [2, 21, 15, 3, 8, 19, 11, 16, 24, 22, 17, 23, 9, 12, 6, 20, 5, 13, 7, 10, 4, 14, 1, 18],
+    [4, 13, 6, 2, 21, 14, 10, 1, 8, 5, 18, 3, 16, 23, 20, 22, 17, 19, 15, 12, 7, 11, 9, 24],
+    [21, 10, 3, 13, 20, 14, 23, 16, 24, 9, 7, 1, 11, 5, 22, 15, 4, 8, 2, 18, 6, 19, 12, 17],
+    [18, 7, 4, 14, 19, 13, 15, 10, 16, 22, 2, 23, 21, 1, 5, 9, 20, 11, 24, 3, 8, 12, 17, 6],
+    [22, 24, 10, 17, 1, 4, 12, 9, 21, 13, 3, 5, 8, 20, 11, 16, 15, 23, 14, 6, 19, 2, 18, 7],
+    [16, 10, 17, 14, 12, 15, 7, 9, 18, 24, 2, 11, 4, 1, 13, 5, 23, 21, 6, 8, 19, 3, 20, 22],
+    [11, 9, 20, 10, 22, 15, 13, 18, 6, 24, 1, 8, 7, 3, 5, 14, 16, 12, 19, 21, 23, 4, 17, 2],
+    [17, 19, 7, 15, 18, 20, 16, 9, 6, 14, 8, 5, 1, 3, 11, 12, 10, 21, 23, 24, 22, 13, 4, 2],
+    [5, 24, 22, 20, 12, 19, 14, 9, 15, 21, 13, 6, 4, 10, 18, 3, 8, 2, 11, 16, 7, 17, 1, 23],
+    [5, 24, 23, 15, 12, 8, 7, 17, 4, 11, 19, 13, 14, 6, 20, 10, 9, 2, 22, 1, 3, 21, 16, 18],
+    [16, 13, 5, 11, 1, 22, 21, 15, 18, 19, 12, 17, 10, 2, 24, 23, 6, 9, 7, 14, 8, 4, 3, 20],
+    [24, 1, 18, 8, 14, 3, 2, 15, 5, 9, 23, 4, 22, 12, 19, 10, 6, 20, 16, 13, 7, 17, 11, 21],
+    [19, 22, 23, 10, 7, 17, 14, 13, 21, 3, 4, 11, 24, 6, 12, 18, 15, 8, 1, 9, 20, 16, 5, 2],
+    [22, 16, 6, 12, 21, 17, 24, 4, 5, 7, 18, 10, 1, 19, 14, 23, 11, 3, 2, 20, 13, 15, 9, 8],
+    [18, 1, 2, 11, 15, 10, 22, 4, 12, 19, 21, 5, 23, 20, 6, 24, 7, 9, 14, 13, 8, 16, 17, 3],
+    [20, 9, 5, 19, 17, 13, 12, 2, 10, 16, 24, 4, 7, 6, 14, 8, 3, 11, 1, 22, 18, 21, 23, 15]
+];
+const puzzleMap3 = [
+    "ullurdruldrdluldrulurddr",
+    "llurdrulurdldluurrdlldrr",
+    "uulldrdlurrdllurrulldrrulddr",
+    "luurddluruldlurrddluldrr",
+    "luldrulurdldruruldrdllurrd",
+    "uulldrrdluurddluldrr",
+    "luruldrdlluurdldrurdllurdr",
+    "lulurdrulddrullurddlurdr",
+    "lulurdrulddluurrdd",
+    "uldluurrdllurdruldrd",
+    "ullurdldruurddluruldrd",
+    "ululdrdruulldrurdd",
+    "ullurrdldrullurdldrurd",
+    "uulddluurdrulddluurddr",
+    "luurddluulddruulddrurd",
+    "ulldruurddluulddruurdluldrrd",
+    "lluruldrruldrdllurrulddr",
+    "luldrrullurrddlurd",
+    "uuldldrulurdrulddrulldrurd",
+    "uuldrullddruulddrrulldrr",
+    "uulddlurdruulddruuldldrr",
+    "ulldrruulddlurrullddrr",
+    "lurulddrullurdldruulddrr",
+    "luuldrdlurruldrdluruldrd",
+    "uuldlurddruuldldrr",
+    "ulldrurdlluruldrdlururdd",
+    "ulurdlldrruulddrullurddr",
+    "uulddruuldldrulurddruuldldrr",
+    "lulurddluurdrdllurrulldrrd",
+    "uuldrullddrrulldruuldrdr",
+    "luldrulurrddlurd",
+    "uuldrdllurrdlluruldrrulddr",
+    "uldlurulddruurddluurdlldrr",
+    "luurddlulurrdldluurrdd",
+    "uullddrurulldrrdluruldrd",
+    "luuldrrdllurrulldrdrulurdd",
+    "ulldrulurddruuldrd",
+    "llururddllurulddrurd",
+    "ululddruldrruldlurdrulurdd",
+    "luulddrrulurddlulurrdd",
+    "luuldrrdlluurdruldldrr",
+    "uuldldrurdlurulldrrdluurdd",
+    "uullddruldrruuldrulldrdr",
+    "llurrdlluurddlurrulddr",
+    "uldrulurddlluruldrrd",
+    "ululddrurullddruuldrrulddr",
+    "uullddrruullddrurullddrr",
+    "ulldruuldrrdluurdluldrrd",
+    "uulldrdrulurddluuldrrd",
+    "llurrulldrrdllurrdluurdd",
+    "ulldruuldrrdlurullddrr",
+    "lluruldrrdllurruldrd",
+    "ululddruruldldrruldlurrd",
+    "luuldrurdlulddrurd",
+    "uuldrdluruldlurddlurrd",
+    "luruldlurdldrulurdrd",
+    "uullddrurdluurdlulddruldrr",
+    "llururddllurulddrr",
+    "uulldrdluurddlurrulddr",
+    "uulddlurdruulldrdlurulddrr",
+    "ululddruurddlurulldrrd",
+    "luurdldluurddruldlurrd",
+    "uuldldruuldrrdlurulddr",
+    "uldrulldrrullurrdllurddr",
+    "lulurrdllurdldrruulddlurdr",
+    "uldluurdlurrddluurddllurrd",
+    "uldrulldruulddrurulldrrd",
+    "uullddruulddrruullddrr",
+    "luurddluruldldrruuldrd",
+    "uldrulldrrullurrdllurdrd",
+    "ullurdldrurdluruldrd",
+    "uldruuldlurddluurddr",
+    "llururddluuldrurdluldrdr",
+    "ulldrulurdrulddrulldrr",
+    "llururddluurdlldrulurdrd",
+    "ululdrurddluruldrdllurrulddr",
+    "uldrulldruuldrurdd",
+    "ulldrulurrdllurddr",
+    "uldlurdrulldrulurrdlldrr",
+    "ulurddlulurdldrr",
+    "lluurrdldluurrdllurddr",
+    "luuldrdlurrdluldrr",
+    "uldrulldrrulurdllurdrd",
+    "uuldldrulurrddluuldrrd",
+    "uuldldruuldrurddlurd",
+    "ulurdldrulldrruldr",
+    "llurrulldrrdluruldrd",
+    "llurulddrurdluruldldrr",
+    "uuldlurdldrurulldrurdd",
+    "uuldrdluldrurulldrrd",
+    "ulldrruullddrr",
+    "uuldlurdldrurullddrr",
+    "lurullddruruldlurddr",
+    "uldlururddllurrulddr",
+    "uullddrrululddruuldrurdd",
+    "lluurdrdlluurddluurrdd",
+    "uulddluurdrdluldruruldlurdrd",
+    "lulurrdlldrrulurdldr",
+    "uldruuldldrulurddr"
+];
+
+const getRandom = function(list){
+    return list[Math.floor(Math.random() * list.length)]
+    // return [1, 2, 3, 4, 5, 6, 7, 8]
+}
+
+let instance
+
+export default class GameMap {
+    constructor(){
+        if (instance)
+            return instance
+
+        instance = this
+    }
+    getMap(stage = 3){
+        switch (stage) {
+            case 3:
+                return getRandom(puzzleList3);
+            case 4:
+                return getRandom(puzzleList4);            
+            case 5:
+                return getRandom(puzzleList5);                           
+            default:
+                return getRandom(puzzleList3);                
+        }
+    }
+}

+ 333 - 0
Album/jss/runtime/gameinfo.js

xqd
@@ -0,0 +1,333 @@
+import DataBus from '../databus'
+import Button from '../base/button'
+import Piece from '../models/piece'
+import GameMap from '../runtime/gameMap'
+
+let databus = new DataBus()
+let gameMap = new GameMap()
+
+const helpButtonPadding = 15
+
+
+// 拼图图片
+const PUZZLE_EASY_SRC = 'image/puzzle-easy.jpg'
+const PUZZLE_EASY_WIDTH = 1000
+const PUZZLE_EASY_HEIGHT = 1000
+
+const PUZZLE_MIDDLE_SRC = 'image/puzzle-middle.jpg'
+const PUZZLE_MIDDLE_WIDTH = 1000
+const PUZZLE_MIDDLE_HEIGHT = 1000
+
+const PUZZLE_HARD_SRC = 'image/puzzle-hard.jpg'
+const PUZZLE_HARD_WIDTH = 1000
+const PUZZLE_HARD_HEIGHT = 1000
+
+// 菜单图片
+const IMG_START_SRC = 'image/start.png'
+const IMG_START_WIDTH = 800
+const IMG_START_HEIGHT = 1000
+
+const IMG_EASY_SRC = 'image/easy.png'
+const IMG_EASY_WIDTH = 400
+const IMG_EASY_HEIGHT = 200
+
+const IMG_MIDDLE_SRC = 'image/middle.png'
+const IMG_MIDDLE_WIDTH = 400
+const IMG_MIDDLE_HEIGHT = 200
+
+const IMG_HARD_SRC = 'image/hard.png'
+const IMG_HARD_WIDTH = 400
+const IMG_HARD_HEIGHT = 200
+
+const IMG_TIME_SRC = 'image/time_bg.png'
+const IMG_TIME_WIDTH = 400
+const IMG_TIME_HEIGHT = 200
+
+const IMG_HELP_SRC = 'image/help.png'
+const IMG_HELP_WIDTH = 300
+const IMG_HELP_HEIGHT = 200
+
+const IMG_HELP_CONTENT_SRC = 'image/puzzle-help.png'
+const IMG_HELP_CONTENT_WIDTH = '640'
+const IMG_HELP_CONTENT_HEIGHT = '907'
+
+const IMG_HINT_SRC = 'image/hint.png'
+const IMG_HINT_WIDTH = 300
+const IMG_HINT_HEIGHT = 200
+
+const IMG_HINT_CONTENT_SRC = 'image/wrap.png'
+const IMG_HINT_CONTENT_WIDTH = 300
+const IMG_HINT_CONTENT_HEIGHT = 300
+
+const IMG_REPLAY_SRC = 'image/replay.png'
+const IMG_REPLAY_WIDTH = 300
+const IMG_REPLAY_HEIGHT = 200
+
+let instance
+
+export default class GameInfo {
+  constructor() {
+    if (instance)
+      return instance
+    instance = this
+
+    // 开始菜单背景
+    let imgStartRatio = (databus.screenWidth * 0.8) / IMG_START_WIDTH
+    this.imgStart = new Button(
+      IMG_START_SRC,
+      (databus.screenWidth - imgStartRatio * IMG_START_WIDTH) / 2,
+      (databus.screenHeight - imgStartRatio * IMG_START_HEIGHT) / 2,
+      imgStartRatio * IMG_START_WIDTH,
+      imgStartRatio * IMG_START_HEIGHT
+    )
+
+    //开始菜单按钮
+    let btnRatio = (databus.screenWidth * 0.4) / IMG_EASY_WIDTH
+    this.btnEasy = new Button(
+      IMG_EASY_SRC,
+      (databus.screenWidth - btnRatio * IMG_EASY_WIDTH) / 2,
+      (databus.screenHeight - btnRatio * IMG_EASY_HEIGHT) / 2 - btnRatio * IMG_EASY_HEIGHT * 1.5,
+      btnRatio * IMG_EASY_WIDTH,
+      btnRatio * IMG_EASY_HEIGHT
+    )
+
+    this.btnMiddle = new Button(
+      IMG_MIDDLE_SRC,
+      (databus.screenWidth - btnRatio * IMG_MIDDLE_WIDTH) / 2,
+      (databus.screenHeight - btnRatio * IMG_MIDDLE_HEIGHT) / 2,
+      btnRatio * IMG_MIDDLE_WIDTH,
+      btnRatio * IMG_MIDDLE_HEIGHT
+    )
+
+    this.btnHard = new Button(
+      IMG_HARD_SRC,
+      (databus.screenWidth - btnRatio * IMG_HARD_WIDTH) / 2,
+      (databus.screenHeight - btnRatio * IMG_HARD_HEIGHT) / 2 + btnRatio * IMG_HARD_HEIGHT * 1.5,
+      btnRatio * IMG_HARD_WIDTH,
+      btnRatio * IMG_HARD_HEIGHT
+    )
+
+    // 时间块
+    let timeRatio = (databus.screenWidth * 0.16) / IMG_TIME_WIDTH
+    this.timeBanner = new Button(
+      IMG_TIME_SRC,
+      databus.contentPadding,
+      databus.contentPaddingTop - (timeRatio * IMG_TIME_HEIGHT + helpButtonPadding),
+      timeRatio * IMG_TIME_WIDTH,
+      timeRatio * IMG_TIME_HEIGHT
+    )
+
+    // 重玩按钮
+    let replayRatio = (databus.screenWidth * 0.12) / IMG_REPLAY_WIDTH
+    this.btnReplay = new Button(
+      IMG_REPLAY_SRC,
+      (databus.contentPadding + databus.contentWidth) - replayRatio * IMG_REPLAY_WIDTH,
+      databus.contentPaddingTop - (replayRatio * IMG_REPLAY_HEIGHT + helpButtonPadding),
+      replayRatio * IMG_REPLAY_WIDTH,
+      replayRatio * IMG_REPLAY_HEIGHT
+    )
+
+    // 提示按钮
+    let hintRatio = (databus.screenWidth * 0.12) / IMG_HINT_WIDTH
+    this.btnHint = new Button(
+      IMG_HINT_SRC,
+      this.btnReplay.x - (hintRatio * IMG_HINT_WIDTH + 10),
+      databus.contentPaddingTop - (hintRatio * IMG_HINT_HEIGHT + helpButtonPadding),
+      hintRatio * IMG_HINT_WIDTH,
+      hintRatio * IMG_HINT_HEIGHT
+    )
+
+    let hintContentRatio = (databus.contentWidth * 0.6) / IMG_HINT_CONTENT_WIDTH
+    this.hintContent = new Button(
+      IMG_HINT_CONTENT_SRC,
+      (databus.contentPadding + databus.contentWidth) - hintContentRatio * IMG_HINT_CONTENT_WIDTH,
+      databus.contentPaddingTop - (hintContentRatio * IMG_HINT_CONTENT_HEIGHT + helpButtonPadding),
+      hintContentRatio * IMG_HINT_CONTENT_WIDTH,
+      hintContentRatio * IMG_HINT_CONTENT_HEIGHT
+    )
+    
+    // 帮助按钮
+    let helpRatio = (databus.screenWidth * 0.12) / IMG_HELP_WIDTH
+    this.btnHelp = new Button(
+      IMG_HELP_SRC,
+      this.btnHint.x - (helpRatio * IMG_HELP_WIDTH + 10),
+      databus.contentPaddingTop - (helpRatio * IMG_HELP_HEIGHT + helpButtonPadding),
+      helpRatio * IMG_HELP_WIDTH,
+      helpRatio * IMG_HELP_HEIGHT
+    )
+
+    // 帮助内容
+    let helpContentHeight = (databus.screenWidth / IMG_HELP_CONTENT_WIDTH) * IMG_HELP_CONTENT_HEIGHT
+    this.helpContent = new Button(
+      IMG_HELP_CONTENT_SRC,
+      0,
+      databus.screenHeight - helpContentHeight,
+      databus.screenWidth,
+      helpContentHeight
+    )
+  }
+
+  tap(event) {
+    if (!databus.gameStart) {
+      return this.tapGameStart(event)
+    }
+    if (!databus.gameOver) {
+      return this.tapGamePlaying(event)
+    }
+    return this.tapGameOver(event)
+  }
+
+  tapGameStart(event) {
+    if (this.btnEasy.isTapped(event.x, event.y)) {
+      databus.stage = 3
+      databus.gameStart = true
+      databus.puzzleImg = {
+        src: PUZZLE_EASY_SRC,
+        width: PUZZLE_EASY_WIDTH,
+        height: PUZZLE_EASY_HEIGHT
+      }
+    } else if (this.btnMiddle.isTapped(event.x, event.y)) {
+      databus.stage = 4
+      databus.gameStart = true
+      databus.puzzleImg = {
+        src: PUZZLE_MIDDLE_SRC,
+        width: PUZZLE_MIDDLE_WIDTH,
+        height: PUZZLE_MIDDLE_HEIGHT
+      }
+    } else if (this.btnHard.isTapped(event.x, event.y)) {
+      databus.stage = 5
+      databus.gameStart = true
+      databus.puzzleImg = {
+        src: PUZZLE_HARD_SRC,
+        width: PUZZLE_HARD_WIDTH,
+        height: PUZZLE_HARD_HEIGHT
+      }
+    } else {
+      return
+    }
+
+    // 设定初始的空位
+    databus.emptyPosition = (databus.stage * databus.stage) - 1
+
+    // 选择随机地图并将图块放进数列中
+    let randomMap = gameMap.getMap(databus.stage)
+    for (let i = 0; i < randomMap.length; i++) {
+      let position = randomMap[i] - 1;
+      databus.pieces.push(new Piece(i, position, databus.stage))
+    }
+
+    databus.startTime = Date.now()
+    this.puzzleImg = new Image()
+    this.puzzleImg.src = databus.puzzleImg.src
+  }
+
+  tapGamePlaying(event) {
+    if (databus.showHelp && this.helpContent.isTapped(event.x, event.y)) {
+      return databus.showHelp = false
+    }
+
+    if (databus.showHint && this.hintContent.isTapped(event.x, event.y)) {
+      return databus.showHint = false
+    }
+
+    if (this.btnReplay.isTapped(event.x, event.y)) {
+      databus.reset()
+    }
+
+    if (this.btnHelp.isTapped(event.x, event.y)) {
+      return databus.showHelp = true
+    }
+
+    if (this.btnHint.isTapped(event.x, event.y)) {
+      return databus.showHint = true
+    }
+  }
+
+  tapGameOver(event) {
+    if (this.btnReplay.isTapped(event.x, event.y)) {
+      databus.reset()
+    }
+  }
+
+  render(ctx) {
+    if (!databus.gameStart) {
+      return this.renderGameStart(ctx)
+    }
+    if (!databus.gameOver) {
+      return this.renderGamePlaying(ctx)
+    }
+    return this.renderGameOver(ctx)
+  }
+
+  renderGameStart(ctx) {
+    // 绘制半透明背景
+    ctx.fillStyle = "black";
+    ctx.globalAlpha = 0.6;
+    ctx.fillRect(0, 0, databus.screenWidth, databus.screenHeight);
+    ctx.globalAlpha = 1;
+
+    this.imgStart.render(ctx)
+    this.btnEasy.render(ctx)
+    this.btnMiddle.render(ctx)
+    this.btnHard.render(ctx)
+  }
+  renderGamePlaying(ctx) {
+    // 绘制时间
+    this.timeBanner.render(ctx)
+    ctx.fillStyle = "#ffffff"
+    ctx.font = "15px Arial"
+    ctx.fillText(
+      databus.getCurrentTime(),
+      this.timeBanner.x + (this.timeBanner.width / 2 - 18),
+      this.timeBanner.y + (this.timeBanner.height / 2 + 5)
+    )
+
+    this.btnHelp.render(ctx)
+    this.btnHint.render(ctx)
+    this.btnReplay.render(ctx)    
+    if (databus.showHelp) {
+      ctx.fillStyle = "black";
+      ctx.globalAlpha = 0.6;
+      ctx.fillRect(0, 0, databus.screenWidth, databus.screenHeight);
+      ctx.globalAlpha = 1;
+      this.helpContent.render(ctx)
+    }
+    if (databus.showHint) {
+      ctx.drawImage(
+        this.puzzleImg,
+        this.hintContent.x,
+        this.hintContent.y,
+        this.hintContent.width,
+        this.hintContent.height
+      )
+      this.hintContent.render(ctx)
+    }
+  }
+
+  renderGameOver(ctx, score) {
+
+    ctx.drawImage(
+      this.puzzleImg,
+      databus.contentPadding,
+      databus.contentPaddingTop,
+      databus.contentWidth,
+      databus.contentWidth
+    )
+
+    this.btnReplay.render(ctx)
+
+    // 绘制半透明背景
+    ctx.fillStyle = "black";
+    ctx.globalAlpha = 0.6;
+    ctx.fillRect(databus.contentPadding, databus.contentPaddingTop, databus.contentWidth, 50)
+    ctx.globalAlpha = 1;
+
+    ctx.fillStyle = "#ffffff"
+    ctx.font = "18px Arial"
+    ctx.fillText(
+      '恭喜!您用' + databus.finalTime + '完成了拼图!',
+      databus.contentPadding + 10,
+      databus.contentPaddingTop + 30,
+    )
+  }
+}

+ 39 - 0
Album/jss/runtime/music.js

xqd
@@ -0,0 +1,39 @@
+let instance
+
+/**
+ * 统一的音效管理器
+ */
+export default class Music {
+  constructor() {
+    if ( instance )
+      return instance
+
+    instance = this
+
+    this.bgmAudio = new Audio()
+    this.bgmAudio.loop = true
+    this.bgmAudio.src  = 'audio/bgm.mp3'
+
+    this.shootAudio     = new Audio()
+    this.shootAudio.src = 'audio/bullet.mp3'
+
+    this.boomAudio     = new Audio()
+    this.boomAudio.src = 'audio/boom.mp3'
+
+    this.playBgm()
+  }
+
+  playBgm() {
+    this.bgmAudio.play()
+  }
+
+  playShoot() {
+    this.shootAudio.currentTime = 0
+    this.shootAudio.play()
+  }
+
+  playExplosion() {
+    this.boomAudio.currentTime = 0
+    this.boomAudio.play()
+  }
+}