diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..c4b9996 --- /dev/null +++ b/.babelrc @@ -0,0 +1,15 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "browsers": [ + "ios >= 9", + "android >= 4" + ] + } + } + ] + ] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0b0739 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +.idea/ +npm-debug.log +yarn.lock +.DS_Store + diff --git a/LICENSE b/LICENSE index 2071b23..e31c337 100644 --- a/LICENSE +++ b/LICENSE @@ -1,9 +1,21 @@ MIT License -Copyright (c) +Copyright (c) 2018 BMQB, Inc -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 1ab045c..0a7e21d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,133 @@ -# towergame +[![](http://www.writebug.com/myres/static/uploads/2021/10/22/9c92c17a3018530ae6c17b70c748ed01.writebug)](LICENSE) -盖楼游戏 html5 canvas tower building game \ No newline at end of file +

盖楼游戏

+

+ +> 一个基于 Canvas 的盖楼游戏 + +> Tower Building Game (Tower Bloxx Deluxe Skyscraper) + +## Demo 预览 + +

+

在线预览地址 (Demo Link)

+

手机设备可以扫描下方二维码

+

+ +

+ +## Game Rule 游戏规则 + +以下为默认游戏规则,也可参照下节自定义游戏参数 + +- 每局游戏生命值为 3,掉落一块楼层生命值减 1,掉落 3 块后游戏结束,单局游戏无时间限制 +- 成功盖楼加 25 分,完美盖楼加 50 分,连续完美盖楼额外加 25 分,楼层掉落扣除生命值 1,单局游戏共有 3 次掉落机会 + +栗子:第一块完美盖楼加 50 分,第二块连续完美盖楼加 75 分,第三块连续完美盖楼加 100 分,依此类推…… + +

+ +

+ +## Customise 自定义 + +``` +git http://git.writebug.com/NGQwMzBkYmY3/towergame.git +cd tower_game +npm install +npm start +``` + +打开 `http://localhost:8082` + +- 图片、音频资源可以直接替换 `assets` 目录下对应的资源文件 +- 游戏规则可以修改 `index.html` 文件 `L480` 的 `option` 对象 + +## Option 自定义选项 + +可以使用以下 `option` 表格里的参数,完成游戏自定义,**所有参数都是非必填项** + +| Option | Type | Description | +| -------------------------------------------- | -------- | --------------------- | +| width | number | 游戏主画面宽度 | +| height | number | 游戏主画面高度 | +| canvasId | string | Canvas 的 DOM ID | +| soundOn | boolean | 是否开启声音 | +| successScore | number | 成功盖楼分数 | +| perfectScore | number | 完美盖楼额外奖励分数 | +| hookSpeed | function | 钩子平移速度 | +| hookAngle | function | 钩子摆动角度 | +| landBlockSpeed | function | 下方楼房横向速度 | +| setGameScore | function | 当前游戏分数 hook | +| setGameSuccess | function | 当前游戏成功次数 hook | +| setGameFailed | function | 当前游戏失败次数 hook | + +#### hookSpeed + +钩子平移速度 +函数接收两个参数,当前成功楼层和当前分数,返回速度数值 + +``` +function(currentFloor, currentScore) { + return number +} +``` + +#### hookAngle + +钩子摆动角度 +函数接收两个参数,当前成功楼层和当前分数,返回角度数值 + +``` +function(currentFloor, currentScore) { + return number +} +``` + +#### landBlockSpeed + +下方楼房平移速度 +函数接收两个参数,当前成功楼层和当前分数,返回速度数值 + +``` +function(currentFloor, currentScore) { + return number +} +``` + +#### setGameScore + +当前游戏分数 hook +函数接收一个参数,当前游戏分数 + +``` +function(score) { + // your logic +} +``` + +#### setGameSuccess + +当前游戏成功次数 hook +函数接收一个参数,当前游戏成功次数 + +``` +function(successCount) { + // your logic +} +``` + +#### setGameFailed + +当前游戏失败次数 hook +函数接收一个参数,当前游戏失败次数 + +``` +function(failedCount) { + // your logic +} +``` + +## License + +MIT license. diff --git a/assets/background.png b/assets/background.png new file mode 100644 index 0000000..9b6b056 Binary files /dev/null and b/assets/background.png differ diff --git a/assets/bgm.mp3 b/assets/bgm.mp3 new file mode 100644 index 0000000..3eb966d Binary files /dev/null and b/assets/bgm.mp3 differ diff --git a/assets/bgm.ogg b/assets/bgm.ogg new file mode 100644 index 0000000..5f7c2bf Binary files /dev/null and b/assets/bgm.ogg differ diff --git a/assets/block-perfect.png b/assets/block-perfect.png new file mode 100644 index 0000000..8f2ac0a Binary files /dev/null and b/assets/block-perfect.png differ diff --git a/assets/block-rope.png b/assets/block-rope.png new file mode 100644 index 0000000..54e39ea Binary files /dev/null and b/assets/block-rope.png differ diff --git a/assets/block.png b/assets/block.png new file mode 100644 index 0000000..edc5b12 Binary files /dev/null and b/assets/block.png differ diff --git a/assets/c1.png b/assets/c1.png new file mode 100644 index 0000000..e592dd6 Binary files /dev/null and b/assets/c1.png differ diff --git a/assets/c2.png b/assets/c2.png new file mode 100644 index 0000000..2689a4a Binary files /dev/null and b/assets/c2.png differ diff --git a/assets/c3.png b/assets/c3.png new file mode 100644 index 0000000..4ba68c9 Binary files /dev/null and b/assets/c3.png differ diff --git a/assets/c4.png b/assets/c4.png new file mode 100644 index 0000000..861fbff Binary files /dev/null and b/assets/c4.png differ diff --git a/assets/c5.png b/assets/c5.png new file mode 100644 index 0000000..e15e790 Binary files /dev/null and b/assets/c5.png differ diff --git a/assets/c6.png b/assets/c6.png new file mode 100644 index 0000000..7f1bdcb Binary files /dev/null and b/assets/c6.png differ diff --git a/assets/c7.png b/assets/c7.png new file mode 100644 index 0000000..721cd11 Binary files /dev/null and b/assets/c7.png differ diff --git a/assets/c8.png b/assets/c8.png new file mode 100644 index 0000000..91a974c Binary files /dev/null and b/assets/c8.png differ diff --git a/assets/drop-perfect.mp3 b/assets/drop-perfect.mp3 new file mode 100644 index 0000000..01bf0f6 Binary files /dev/null and b/assets/drop-perfect.mp3 differ diff --git a/assets/drop-perfect.ogg b/assets/drop-perfect.ogg new file mode 100644 index 0000000..08a218e Binary files /dev/null and b/assets/drop-perfect.ogg differ diff --git a/assets/drop.mp3 b/assets/drop.mp3 new file mode 100644 index 0000000..e78b20b Binary files /dev/null and b/assets/drop.mp3 differ diff --git a/assets/drop.ogg b/assets/drop.ogg new file mode 100644 index 0000000..d1fd7f5 Binary files /dev/null and b/assets/drop.ogg differ diff --git a/assets/f1.png b/assets/f1.png new file mode 100644 index 0000000..55d8899 Binary files /dev/null and b/assets/f1.png differ diff --git a/assets/f2.png b/assets/f2.png new file mode 100644 index 0000000..c69d89c Binary files /dev/null and b/assets/f2.png differ diff --git a/assets/f3.png b/assets/f3.png new file mode 100644 index 0000000..98c9a0f Binary files /dev/null and b/assets/f3.png differ diff --git a/assets/f4.png b/assets/f4.png new file mode 100644 index 0000000..86800bf Binary files /dev/null and b/assets/f4.png differ diff --git a/assets/f5.png b/assets/f5.png new file mode 100644 index 0000000..86800bf Binary files /dev/null and b/assets/f5.png differ diff --git a/assets/f6.png b/assets/f6.png new file mode 100644 index 0000000..cc5200b Binary files /dev/null and b/assets/f6.png differ diff --git a/assets/f7.png b/assets/f7.png new file mode 100644 index 0000000..bf999c2 Binary files /dev/null and b/assets/f7.png differ diff --git a/assets/game-over.mp3 b/assets/game-over.mp3 new file mode 100644 index 0000000..563e9f1 Binary files /dev/null and b/assets/game-over.mp3 differ diff --git a/assets/game-over.ogg b/assets/game-over.ogg new file mode 100644 index 0000000..2243012 Binary files /dev/null and b/assets/game-over.ogg differ diff --git a/assets/heart.png b/assets/heart.png new file mode 100644 index 0000000..80c435b Binary files /dev/null and b/assets/heart.png differ diff --git a/assets/hook.png b/assets/hook.png new file mode 100644 index 0000000..fa9506d Binary files /dev/null and b/assets/hook.png differ diff --git a/assets/main-bg.png b/assets/main-bg.png new file mode 100644 index 0000000..c9faf14 Binary files /dev/null and b/assets/main-bg.png differ diff --git a/assets/main-index-logo.png b/assets/main-index-logo.png new file mode 100644 index 0000000..5464788 Binary files /dev/null and b/assets/main-index-logo.png differ diff --git a/assets/main-index-start.png b/assets/main-index-start.png new file mode 100644 index 0000000..20f26cc Binary files /dev/null and b/assets/main-index-start.png differ diff --git a/assets/main-index-title.png b/assets/main-index-title.png new file mode 100644 index 0000000..118332c Binary files /dev/null and b/assets/main-index-title.png differ diff --git a/assets/main-loading-logo.png b/assets/main-loading-logo.png new file mode 100644 index 0000000..5f45f7d Binary files /dev/null and b/assets/main-loading-logo.png differ diff --git a/assets/main-loading.gif b/assets/main-loading.gif new file mode 100644 index 0000000..283c16a Binary files /dev/null and b/assets/main-loading.gif differ diff --git a/assets/main-modal-again-b.png b/assets/main-modal-again-b.png new file mode 100644 index 0000000..e5eccda Binary files /dev/null and b/assets/main-modal-again-b.png differ diff --git a/assets/main-modal-bg.png b/assets/main-modal-bg.png new file mode 100644 index 0000000..0caf110 Binary files /dev/null and b/assets/main-modal-bg.png differ diff --git a/assets/main-modal-invite-b.png b/assets/main-modal-invite-b.png new file mode 100644 index 0000000..c879200 Binary files /dev/null and b/assets/main-modal-invite-b.png differ diff --git a/assets/main-modal-over.png b/assets/main-modal-over.png new file mode 100644 index 0000000..b748e31 Binary files /dev/null and b/assets/main-modal-over.png differ diff --git a/assets/main-share-icon.png b/assets/main-share-icon.png new file mode 100644 index 0000000..e03f6b6 Binary files /dev/null and b/assets/main-share-icon.png differ diff --git a/assets/rope.png b/assets/rope.png new file mode 100644 index 0000000..657d463 Binary files /dev/null and b/assets/rope.png differ diff --git a/assets/rotate.mp3 b/assets/rotate.mp3 new file mode 100644 index 0000000..0b9495d Binary files /dev/null and b/assets/rotate.mp3 differ diff --git a/assets/rotate.ogg b/assets/rotate.ogg new file mode 100644 index 0000000..d2d72c8 Binary files /dev/null and b/assets/rotate.ogg differ diff --git a/assets/score.png b/assets/score.png new file mode 100644 index 0000000..b63a409 Binary files /dev/null and b/assets/score.png differ diff --git a/assets/tutorial-arrow.png b/assets/tutorial-arrow.png new file mode 100644 index 0000000..a74a237 Binary files /dev/null and b/assets/tutorial-arrow.png differ diff --git a/assets/tutorial.png b/assets/tutorial.png new file mode 100644 index 0000000..1cb5bc4 Binary files /dev/null and b/assets/tutorial.png differ diff --git a/assets/wenxue.eot b/assets/wenxue.eot new file mode 100644 index 0000000..e66f998 Binary files /dev/null and b/assets/wenxue.eot differ diff --git a/assets/wenxue.svg b/assets/wenxue.svg new file mode 100644 index 0000000..74fc086 --- /dev/null +++ b/assets/wenxue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/wenxue.ttf b/assets/wenxue.ttf new file mode 100644 index 0000000..1220965 Binary files /dev/null and b/assets/wenxue.ttf differ diff --git a/assets/wenxue.woff b/assets/wenxue.woff new file mode 100644 index 0000000..7a0de0b Binary files /dev/null and b/assets/wenxue.woff differ diff --git a/assets/zepto-1.1.6.min.js b/assets/zepto-1.1.6.min.js new file mode 100644 index 0000000..c73d81c --- /dev/null +++ b/assets/zepto-1.1.6.min.js @@ -0,0 +1,2 @@ +/* Zepto v1.1.6 - zepto event ajax form ie - zeptojs.com/license */ +var Zepto=function(){function L(t){return null==t?String(t):j[S.call(t)]||"object"}function Z(t){return"function"==L(t)}function _(t){return null!=t&&t==t.window}function $(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function D(t){return"object"==L(t)}function M(t){return D(t)&&!_(t)&&Object.getPrototypeOf(t)==Object.prototype}function R(t){return"number"==typeof t.length}function k(t){return s.call(t,function(t){return null!=t})}function z(t){return t.length>0?n.fn.concat.apply([],t):t}function F(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function q(t){return t in f?f[t]:f[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function H(t,e){return"number"!=typeof e||c[F(t)]?e:e+"px"}function I(t){var e,n;return u[t]||(e=a.createElement(t),a.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),u[t]=n),u[t]}function V(t){return"children"in t?o.call(t.children):n.map(t.childNodes,function(t){return 1==t.nodeType?t:void 0})}function B(n,i,r){for(e in i)r&&(M(i[e])||A(i[e]))?(M(i[e])&&!M(n[e])&&(n[e]={}),A(i[e])&&!A(n[e])&&(n[e]=[]),B(n[e],i[e],r)):i[e]!==t&&(n[e]=i[e])}function U(t,e){return null==e?n(t):n(t).filter(e)}function J(t,e,n,i){return Z(e)?e.call(t,n,i):e}function X(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function W(e,n){var i=e.className||"",r=i&&i.baseVal!==t;return n===t?r?i.baseVal:i:void(r?i.baseVal=n:e.className=n)}function Y(t){try{return t?"true"==t||("false"==t?!1:"null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?n.parseJSON(t):t):t}catch(e){return t}}function G(t,e){e(t);for(var n=0,i=t.childNodes.length;i>n;n++)G(t.childNodes[n],e)}var t,e,n,i,C,N,r=[],o=r.slice,s=r.filter,a=window.document,u={},f={},c={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,h=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,p=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,d=/^(?:body|html)$/i,m=/([A-Z])/g,g=["val","css","html","text","data","width","height","offset"],v=["after","prepend","before","append"],y=a.createElement("table"),x=a.createElement("tr"),b={tr:a.createElement("tbody"),tbody:y,thead:y,tfoot:y,td:x,th:x,"*":a.createElement("div")},w=/complete|loaded|interactive/,E=/^[\w-]*$/,j={},S=j.toString,T={},O=a.createElement("div"),P={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},A=Array.isArray||function(t){return t instanceof Array};return T.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var i,r=t.parentNode,o=!r;return o&&(r=O).appendChild(t),i=~T.qsa(r,e).indexOf(t),o&&O.removeChild(t),i},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return s.call(t,function(e,n){return t.indexOf(e)==n})},T.fragment=function(e,i,r){var s,u,f;return h.test(e)&&(s=n(a.createElement(RegExp.$1))),s||(e.replace&&(e=e.replace(p,"<$1>")),i===t&&(i=l.test(e)&&RegExp.$1),i in b||(i="*"),f=b[i],f.innerHTML=""+e,s=n.each(o.call(f.childNodes),function(){f.removeChild(this)})),M(r)&&(u=n(s),n.each(r,function(t,e){g.indexOf(t)>-1?u[t](e):u.attr(t,e)})),s},T.Z=function(t,e){return t=t||[],t.__proto__=n.fn,t.selector=e||"",t},T.isZ=function(t){return t instanceof T.Z},T.init=function(e,i){var r;if(!e)return T.Z();if("string"==typeof e)if(e=e.trim(),"<"==e[0]&&l.test(e))r=T.fragment(e,RegExp.$1,i),e=null;else{if(i!==t)return n(i).find(e);r=T.qsa(a,e)}else{if(Z(e))return n(a).ready(e);if(T.isZ(e))return e;if(A(e))r=k(e);else if(D(e))r=[e],e=null;else if(l.test(e))r=T.fragment(e.trim(),RegExp.$1,i),e=null;else{if(i!==t)return n(i).find(e);r=T.qsa(a,e)}}return T.Z(r,e)},n=function(t,e){return T.init(t,e)},n.extend=function(t){var e,n=o.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){B(t,n,e)}),t},T.qsa=function(t,e){var n,i="#"==e[0],r=!i&&"."==e[0],s=i||r?e.slice(1):e,a=E.test(s);return $(t)&&a&&i?(n=t.getElementById(s))?[n]:[]:1!==t.nodeType&&9!==t.nodeType?[]:o.call(a&&!i?r?t.getElementsByClassName(s):t.getElementsByTagName(e):t.querySelectorAll(e))},n.contains=a.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},n.type=L,n.isFunction=Z,n.isWindow=_,n.isArray=A,n.isPlainObject=M,n.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},n.inArray=function(t,e,n){return r.indexOf.call(e,t,n)},n.camelCase=C,n.trim=function(t){return null==t?"":String.prototype.trim.call(t)},n.uuid=0,n.support={},n.expr={},n.map=function(t,e){var n,r,o,i=[];if(R(t))for(r=0;r=0?e:e+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return r.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return Z(t)?this.not(this.not(t)):n(s.call(this,function(e){return T.matches(e,t)}))},add:function(t,e){return n(N(this.concat(n(t,e))))},is:function(t){return this.length>0&&T.matches(this[0],t)},not:function(e){var i=[];if(Z(e)&&e.call!==t)this.each(function(t){e.call(this,t)||i.push(this)});else{var r="string"==typeof e?this.filter(e):R(e)&&Z(e.item)?o.call(e):n(e);this.forEach(function(t){r.indexOf(t)<0&&i.push(t)})}return n(i)},has:function(t){return this.filter(function(){return D(t)?n.contains(this,t):n(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!D(t)?t:n(t)},last:function(){var t=this[this.length-1];return t&&!D(t)?t:n(t)},find:function(t){var e,i=this;return e=t?"object"==typeof t?n(t).filter(function(){var t=this;return r.some.call(i,function(e){return n.contains(e,t)})}):1==this.length?n(T.qsa(this[0],t)):this.map(function(){return T.qsa(this,t)}):n()},closest:function(t,e){var i=this[0],r=!1;for("object"==typeof t&&(r=n(t));i&&!(r?r.indexOf(i)>=0:T.matches(i,t));)i=i!==e&&!$(i)&&i.parentNode;return n(i)},parents:function(t){for(var e=[],i=this;i.length>0;)i=n.map(i,function(t){return(t=t.parentNode)&&!$(t)&&e.indexOf(t)<0?(e.push(t),t):void 0});return U(e,t)},parent:function(t){return U(N(this.pluck("parentNode")),t)},children:function(t){return U(this.map(function(){return V(this)}),t)},contents:function(){return this.map(function(){return o.call(this.childNodes)})},siblings:function(t){return U(this.map(function(t,e){return s.call(V(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return n.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=I(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=Z(t);if(this[0]&&!e)var i=n(t).get(0),r=i.parentNode||this.length>1;return this.each(function(o){n(this).wrapAll(e?t.call(this,o):r?i.cloneNode(!0):i)})},wrapAll:function(t){if(this[0]){n(this[0]).before(t=n(t));for(var e;(e=t.children()).length;)t=e.first();n(t).append(this)}return this},wrapInner:function(t){var e=Z(t);return this.each(function(i){var r=n(this),o=r.contents(),s=e?t.call(this,i):t;o.length?o.wrapAll(s):r.append(s)})},unwrap:function(){return this.parent().each(function(){n(this).replaceWith(n(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(e){return this.each(function(){var i=n(this);(e===t?"none"==i.css("display"):e)?i.show():i.hide()})},prev:function(t){return n(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return n(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var i=this.innerHTML;n(this).empty().append(J(this,t,e,i))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=J(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this[0].textContent:null},attr:function(n,i){var r;return"string"!=typeof n||1 in arguments?this.each(function(t){if(1===this.nodeType)if(D(n))for(e in n)X(this,e,n[e]);else X(this,n,J(this,i,t,this.getAttribute(n)))}):this.length&&1===this[0].nodeType?!(r=this[0].getAttribute(n))&&n in this[0]?this[0][n]:r:t},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){X(this,t)},this)})},prop:function(t,e){return t=P[t]||t,1 in arguments?this.each(function(n){this[t]=J(this,e,n,this[t])}):this[0]&&this[0][t]},data:function(e,n){var i="data-"+e.replace(m,"-$1").toLowerCase(),r=1 in arguments?this.attr(i,n):this.attr(i);return null!==r?Y(r):t},val:function(t){return 0 in arguments?this.each(function(e){this.value=J(this,t,e,this.value)}):this[0]&&(this[0].multiple?n(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var i=n(this),r=J(this,t,e,i.offset()),o=i.offsetParent().offset(),s={top:r.top-o.top,left:r.left-o.left};"static"==i.css("position")&&(s.position="relative"),i.css(s)});if(!this.length)return null;var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(t,i){if(arguments.length<2){var r,o=this[0];if(!o)return;if(r=getComputedStyle(o,""),"string"==typeof t)return o.style[C(t)]||r.getPropertyValue(t);if(A(t)){var s={};return n.each(t,function(t,e){s[e]=o.style[C(e)]||r.getPropertyValue(e)}),s}}var a="";if("string"==L(t))i||0===i?a=F(t)+":"+H(t,i):this.each(function(){this.style.removeProperty(F(t))});else for(e in t)t[e]||0===t[e]?a+=F(e)+":"+H(e,t[e])+";":this.each(function(){this.style.removeProperty(F(e))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(n(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return t?r.some.call(this,function(t){return this.test(W(t))},q(t)):!1},addClass:function(t){return t?this.each(function(e){if("className"in this){i=[];var r=W(this),o=J(this,t,e,r);o.split(/\s+/g).forEach(function(t){n(this).hasClass(t)||i.push(t)},this),i.length&&W(this,r+(r?" ":"")+i.join(" "))}}):this},removeClass:function(e){return this.each(function(n){if("className"in this){if(e===t)return W(this,"");i=W(this),J(this,e,n,i).split(/\s+/g).forEach(function(t){i=i.replace(q(t)," ")}),W(this,i.trim())}})},toggleClass:function(e,i){return e?this.each(function(r){var o=n(this),s=J(this,e,r,W(this));s.split(/\s+/g).forEach(function(e){(i===t?!o.hasClass(e):i)?o.addClass(e):o.removeClass(e)})}):this},scrollTop:function(e){if(this.length){var n="scrollTop"in this[0];return e===t?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=e}:function(){this.scrollTo(this.scrollX,e)})}},scrollLeft:function(e){if(this.length){var n="scrollLeft"in this[0];return e===t?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=e}:function(){this.scrollTo(e,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),i=this.offset(),r=d.test(e[0].nodeName)?{top:0,left:0}:e.offset();return i.top-=parseFloat(n(t).css("margin-top"))||0,i.left-=parseFloat(n(t).css("margin-left"))||0,r.top+=parseFloat(n(e[0]).css("border-top-width"))||0,r.left+=parseFloat(n(e[0]).css("border-left-width"))||0,{top:i.top-r.top,left:i.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||a.body;t&&!d.test(t.nodeName)&&"static"==n(t).css("position");)t=t.offsetParent;return t})}},n.fn.detach=n.fn.remove,["width","height"].forEach(function(e){var i=e.replace(/./,function(t){return t[0].toUpperCase()});n.fn[e]=function(r){var o,s=this[0];return r===t?_(s)?s["inner"+i]:$(s)?s.documentElement["scroll"+i]:(o=this.offset())&&o[e]:this.each(function(t){s=n(this),s.css(e,J(this,r,t,s[e]()))})}}),v.forEach(function(t,e){var i=e%2;n.fn[t]=function(){var t,o,r=n.map(arguments,function(e){return t=L(e),"object"==t||"array"==t||null==e?e:T.fragment(e)}),s=this.length>1;return r.length<1?this:this.each(function(t,u){o=i?u:u.parentNode,u=0==e?u.nextSibling:1==e?u.firstChild:2==e?u:null;var f=n.contains(a.documentElement,o);r.forEach(function(t){if(s)t=t.cloneNode(!0);else if(!o)return n(t).remove();o.insertBefore(t,u),f&&G(t,function(t){null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src||window.eval.call(window,t.innerHTML)})})})},n.fn[i?t+"To":"insert"+(e?"Before":"After")]=function(e){return n(e)[t](this),this}}),T.Z.prototype=n.fn,T.uniq=N,T.deserializeValue=Y,n.zepto=T,n}();window.Zepto=Zepto,void 0===window.$&&(window.$=Zepto),function(t){function l(t){return t._zid||(t._zid=e++)}function h(t,e,n,i){if(e=p(e),e.ns)var r=d(e.ns);return(s[l(t)]||[]).filter(function(t){return!(!t||e.e&&t.e!=e.e||e.ns&&!r.test(t.ns)||n&&l(t.fn)!==l(n)||i&&t.sel!=i)})}function p(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function d(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function m(t,e){return t.del&&!u&&t.e in f||!!e}function g(t){return c[t]||u&&f[t]||t}function v(e,i,r,o,a,u,f){var h=l(e),d=s[h]||(s[h]=[]);i.split(/\s/).forEach(function(i){if("ready"==i)return t(document).ready(r);var s=p(i);s.fn=r,s.sel=a,s.e in c&&(r=function(e){var n=e.relatedTarget;return!n||n!==this&&!t.contains(this,n)?s.fn.apply(this,arguments):void 0}),s.del=u;var l=u||r;s.proxy=function(t){if(t=j(t),!t.isImmediatePropagationStopped()){t.data=o;var i=l.apply(e,t._args==n?[t]:[t].concat(t._args));return i===!1&&(t.preventDefault(),t.stopPropagation()),i}},s.i=d.length,d.push(s),"addEventListener"in e&&e.addEventListener(g(s.e),s.proxy,m(s,f))})}function y(t,e,n,i,r){var o=l(t);(e||"").split(/\s/).forEach(function(e){h(t,e,n,i).forEach(function(e){delete s[o][e.i],"removeEventListener"in t&&t.removeEventListener(g(e.e),e.proxy,m(e,r))})})}function j(e,i){return(i||!e.isDefaultPrevented)&&(i||(i=e),t.each(E,function(t,n){var r=i[t];e[t]=function(){return this[n]=x,r&&r.apply(i,arguments)},e[n]=b}),(i.defaultPrevented!==n?i.defaultPrevented:"returnValue"in i?i.returnValue===!1:i.getPreventDefault&&i.getPreventDefault())&&(e.isDefaultPrevented=x)),e}function S(t){var e,i={originalEvent:t};for(e in t)w.test(e)||t[e]===n||(i[e]=t[e]);return j(i,t)}var n,e=1,i=Array.prototype.slice,r=t.isFunction,o=function(t){return"string"==typeof t},s={},a={},u="onfocusin"in window,f={focus:"focusin",blur:"focusout"},c={mouseenter:"mouseover",mouseleave:"mouseout"};a.click=a.mousedown=a.mouseup=a.mousemove="MouseEvents",t.event={add:v,remove:y},t.proxy=function(e,n){var s=2 in arguments&&i.call(arguments,2);if(r(e)){var a=function(){return e.apply(n,s?s.concat(i.call(arguments)):arguments)};return a._zid=l(e),a}if(o(n))return s?(s.unshift(e[n],e),t.proxy.apply(null,s)):t.proxy(e[n],e);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,i){return this.on(t,e,n,i,1)};var x=function(){return!0},b=function(){return!1},w=/^([A-Z]|returnValue$|layer[XY]$)/,E={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,s,a,u,f){var c,l,h=this;return e&&!o(e)?(t.each(e,function(t,e){h.on(t,s,a,e,f)}),h):(o(s)||r(u)||u===!1||(u=a,a=s,s=n),(r(a)||a===!1)&&(u=a,a=n),u===!1&&(u=b),h.each(function(n,r){f&&(c=function(t){return y(r,t.type,u),u.apply(this,arguments)}),s&&(l=function(e){var n,o=t(e.target).closest(s,r).get(0);return o&&o!==r?(n=t.extend(S(e),{currentTarget:o,liveFired:r}),(c||u).apply(o,[n].concat(i.call(arguments,1)))):void 0}),v(r,e,u,a,s,l||c)}))},t.fn.off=function(e,i,s){var a=this;return e&&!o(e)?(t.each(e,function(t,e){a.off(t,i,e)}),a):(o(i)||r(s)||s===!1||(s=i,i=n),s===!1&&(s=b),a.each(function(){y(this,e,s,i)}))},t.fn.trigger=function(e,n){return e=o(e)||t.isPlainObject(e)?t.Event(e):j(e),e._args=n,this.each(function(){e.type in f&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,n){var i,r;return this.each(function(s,a){i=S(o(e)?t.Event(e):e),i._args=n,i.target=a,t.each(h(a,e.type||e),function(t,e){return r=e.proxy(i),i.isImmediatePropagationStopped()?!1:void 0})}),r},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){o(t)||(e=t,t=e.type);var n=document.createEvent(a[t]||"Events"),i=!0;if(e)for(var r in e)"bubbles"==r?i=!!e[r]:n[r]=e[r];return n.initEvent(t,i,!0),j(n)}}(Zepto),function(t){function h(e,n,i){var r=t.Event(n);return t(e).trigger(r,i),!r.isDefaultPrevented()}function p(t,e,i,r){return t.global?h(e||n,i,r):void 0}function d(e){e.global&&0===t.active++&&p(e,null,"ajaxStart")}function m(e){e.global&&!--t.active&&p(e,null,"ajaxStop")}function g(t,e){var n=e.context;return e.beforeSend.call(n,t,e)===!1||p(e,n,"ajaxBeforeSend",[t,e])===!1?!1:void p(e,n,"ajaxSend",[t,e])}function v(t,e,n,i){var r=n.context,o="success";n.success.call(r,t,o,e),i&&i.resolveWith(r,[t,o,e]),p(n,r,"ajaxSuccess",[e,n,t]),x(o,e,n)}function y(t,e,n,i,r){var o=i.context;i.error.call(o,n,e,t),r&&r.rejectWith(o,[n,e,t]),p(i,o,"ajaxError",[n,i,t||e]),x(e,n,i)}function x(t,e,n){var i=n.context;n.complete.call(i,e,t),p(n,i,"ajaxComplete",[e,n]),m(n)}function b(){}function w(t){return t&&(t=t.split(";",2)[0]),t&&(t==f?"html":t==u?"json":s.test(t)?"script":a.test(t)&&"xml")||"text"}function E(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function j(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()||(e.url=E(e.url,e.data),e.data=void 0)}function S(e,n,i,r){return t.isFunction(n)&&(r=i,i=n,n=void 0),t.isFunction(i)||(r=i,i=void 0),{url:e,data:n,success:i,dataType:r}}function C(e,n,i,r){var o,s=t.isArray(n),a=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),r&&(n=i?r:r+"["+(a||"object"==o||"array"==o?n:"")+"]"),!r&&s?e.add(u.name,u.value):"array"==o||!i&&"object"==o?C(e,u,i,n):e.add(n,u)})}var i,r,e=0,n=window.document,o=/)<[^<]*)*<\/script>/gi,s=/^(?:text|application)\/javascript/i,a=/^(?:text|application)\/xml/i,u="application/json",f="text/html",c=/^\s*$/,l=n.createElement("a");l.href=window.location.href,t.active=0,t.ajaxJSONP=function(i,r){if(!("type"in i))return t.ajax(i);var f,h,o=i.jsonpCallback,s=(t.isFunction(o)?o():o)||"jsonp"+ ++e,a=n.createElement("script"),u=window[s],c=function(e){t(a).triggerHandler("error",e||"abort")},l={abort:c};return r&&r.promise(l),t(a).on("load error",function(e,n){clearTimeout(h),t(a).off().remove(),"error"!=e.type&&f?v(f[0],l,i,r):y(null,n||"error",l,i,r),window[s]=u,f&&t.isFunction(u)&&u(f[0]),u=f=void 0}),g(l,i)===!1?(c("abort"),l):(window[s]=function(){f=arguments},a.src=i.url.replace(/\?(.+)=\?/,"?$1="+s),n.head.appendChild(a),i.timeout>0&&(h=setTimeout(function(){c("timeout")},i.timeout)),l)},t.ajaxSettings={type:"GET",beforeSend:b,success:b,error:b,complete:b,context:null,global:!0,xhr:function(){return new window.XMLHttpRequest},accepts:{script:"text/javascript, application/javascript, application/x-javascript",json:u,xml:"application/xml, text/xml",html:f,text:"text/plain"},crossDomain:!1,timeout:0,processData:!0,cache:!0},t.ajax=function(e){var a,o=t.extend({},e||{}),s=t.Deferred&&t.Deferred();for(i in t.ajaxSettings)void 0===o[i]&&(o[i]=t.ajaxSettings[i]);d(o),o.crossDomain||(a=n.createElement("a"),a.href=o.url,a.href=a.href,o.crossDomain=l.protocol+"//"+l.host!=a.protocol+"//"+a.host),o.url||(o.url=window.location.toString()),j(o);var u=o.dataType,f=/\?.+=\?/.test(o.url);if(f&&(u="jsonp"),o.cache!==!1&&(e&&e.cache===!0||"script"!=u&&"jsonp"!=u)||(o.url=E(o.url,"_="+Date.now())),"jsonp"==u)return f||(o.url=E(o.url,o.jsonp?o.jsonp+"=?":o.jsonp===!1?"":"callback=?")),t.ajaxJSONP(o,s);var C,h=o.accepts[u],p={},m=function(t,e){p[t.toLowerCase()]=[t,e]},x=/^([\w-]+:)\/\//.test(o.url)?RegExp.$1:window.location.protocol,S=o.xhr(),T=S.setRequestHeader;if(s&&s.promise(S),o.crossDomain||m("X-Requested-With","XMLHttpRequest"),m("Accept",h||"*/*"),(h=o.mimeType||h)&&(h.indexOf(",")>-1&&(h=h.split(",",2)[0]),S.overrideMimeType&&S.overrideMimeType(h)),(o.contentType||o.contentType!==!1&&o.data&&"GET"!=o.type.toUpperCase())&&m("Content-Type",o.contentType||"application/x-www-form-urlencoded"),o.headers)for(r in o.headers)m(r,o.headers[r]);if(S.setRequestHeader=m,S.onreadystatechange=function(){if(4==S.readyState){S.onreadystatechange=b,clearTimeout(C);var e,n=!1;if(S.status>=200&&S.status<300||304==S.status||0==S.status&&"file:"==x){u=u||w(o.mimeType||S.getResponseHeader("content-type")),e=S.responseText;try{"script"==u?(1,eval)(e):"xml"==u?e=S.responseXML:"json"==u&&(e=c.test(e)?null:t.parseJSON(e))}catch(i){n=i}n?y(n,"parsererror",S,o,s):v(e,S,o,s)}else y(S.statusText||null,S.status?"error":"abort",S,o,s)}},g(S,o)===!1)return S.abort(),y(null,"abort",S,o,s),S;if(o.xhrFields)for(r in o.xhrFields)S[r]=o.xhrFields[r];var N="async"in o?o.async:!0;S.open(o.type,o.url,N,o.username,o.password);for(r in p)T.apply(S,p[r]);return o.timeout>0&&(C=setTimeout(function(){S.onreadystatechange=b,S.abort(),y(null,"timeout",S,o,s)},o.timeout)),S.send(o.data?o.data:null),S},t.get=function(){return t.ajax(S.apply(null,arguments))},t.post=function(){var e=S.apply(null,arguments);return e.type="POST",t.ajax(e)},t.getJSON=function(){var e=S.apply(null,arguments);return e.dataType="json",t.ajax(e)},t.fn.load=function(e,n,i){if(!this.length)return this;var a,r=this,s=e.split(/\s/),u=S(e,n,i),f=u.success;return s.length>1&&(u.url=s[0],a=s[1]),u.success=function(e){r.html(a?t("
").html(e.replace(o,"")).find(a):e),f&&f.apply(r,arguments)},t.ajax(u),this};var T=encodeURIComponent;t.param=function(e,n){var i=[];return i.add=function(e,n){t.isFunction(n)&&(n=n()),null==n&&(n=""),this.push(T(e)+"="+T(n))},C(i,e,n),i.join("&").replace(/%20/g,"+")}}(Zepto),function(t){t.fn.serializeArray=function(){var e,n,i=[],r=function(t){return t.forEach?t.forEach(r):void i.push({name:e,value:t})};return this[0]&&t.each(this[0].elements,function(i,o){n=o.type,e=o.name,e&&"fieldset"!=o.nodeName.toLowerCase()&&!o.disabled&&"submit"!=n&&"reset"!=n&&"button"!=n&&"file"!=n&&("radio"!=n&&"checkbox"!=n||o.checked)&&r(t(o).val())}),i},t.fn.serialize=function(){var t=[];return this.serializeArray().forEach(function(e){t.push(encodeURIComponent(e.name)+"="+encodeURIComponent(e.value))}),t.join("&")},t.fn.submit=function(e){if(0 in arguments)this.bind("submit",e);else if(this.length){var n=t.Event("submit");this.eq(0).trigger(n),n.isDefaultPrevented()||this.get(0).submit()}return this}}(Zepto),function(t){"__proto__"in{}||t.extend(t.zepto,{Z:function(e,n){return e=e||[],t.extend(e,t.fn),e.selector=n||"",e.__Z=!0,e},isZ:function(e){return"array"===t.type(e)&&"__Z"in e}});try{getComputedStyle(void 0)}catch(e){var n=getComputedStyle;window.getComputedStyle=function(t){try{return n(t)}catch(e){return null}}}}(Zepto);window.jQuery = window.$ = Zepto; diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..a089346 --- /dev/null +++ b/dist/main.js @@ -0,0 +1 @@ +!function(e){var t={};function i(n){if(t[n])return t[n].exports;var a=t[n]={i:n,l:!1,exports:{}};return e[n].call(a.exports,a,a.exports,i),a.l=!0,a.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:n})},i.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=15)}([function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.moveDownMovement=t.tutorialMovement=t.lightningMovement=t.hookUpMovement=t.hookDownMovement=t.bgInitMovement=t.initialAngle=t.out=t.land=t.drop=t.beforeDrop=t.swing=t.rotateLeft=t.rotateRight=t.flightLayer=t.flightCount=t.ropeHeight=t.cloudSize=t.blockHeight=t.blockWidth=t.blockCount=t.bgLinearGradientOffset=t.lineInitialOffset=t.bgImgOffset=t.hookNormal=t.hookUp=t.hookDown=t.gameScore=t.perfectCount=t.failedCount=t.successCount=t.hardMode=t.gameUserOption=t.gameStartNow=void 0;t.gameStartNow="GAME_START_NOW";t.gameUserOption="GAME_USER_OPTION";t.hardMode="HARD_MODE";t.successCount="SUCCESS_COUNT";t.failedCount="FAILED_COUNT";t.perfectCount="PERFECT_COUNT";t.gameScore="GAME_SCORE";t.hookDown="HOOK_DOWN";t.hookUp="HOOK_UP";t.hookNormal="HOOK_NORMAL";t.bgImgOffset="BACKGROUND_IMG_OFFSET_HEIGHT";t.lineInitialOffset="LINE_INITIAL_OFFSET";t.bgLinearGradientOffset="BACKGROUND_LINEAR_GRADIENT_OFFSET_HEIGHT";t.blockCount="BLOCK_COUNT";t.blockWidth="BLOCK_WIDTH";t.blockHeight="BLOCK_HEIGHT";t.cloudSize="CLOUD_SIZE";t.ropeHeight="ROPE_HEIGHT";t.flightCount="FLIGHT_COUNT";t.flightLayer="FLIGHT_LAYER";t.rotateRight="ROTATE_RIGHT";t.rotateLeft="ROTATE_LEFT";t.swing="SWING";t.beforeDrop="BEFORE_DROP";t.drop="DROP";t.land="LAND";t.out="OUT";t.initialAngle="INITIAL_ANGLE";t.bgInitMovement="BG_INIT_MOVEMENT";t.hookDownMovement="HOOK_DOWN_MOVEMENT";t.hookUpMovement="HOOK_UP_MOVEMENT";t.lightningMovement="LIGHTNING_MOVEMENT";t.tutorialMovement="TUTORIAL_MOVEMENT";t.moveDownMovement="MOVE_DOWN_MOVEMENT"},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.drawYellowString=t.addScore=t.addFailedCount=t.addSuccessCount=t.touchEventHandler=t.getHookStatus=t.getLandBlockVelocity=t.getSwingBlockVelocity=t.getAngleBase=t.getMoveDownValue=t.checkMoveDown=void 0;var n=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));t.checkMoveDown=function(e){return e.checkTimeMovement(n.moveDownMovement)};t.getMoveDownValue=function(e,t){var i=t?t.pixelsPerFrame:e.pixelsPerFrame.bind(e),a=e.getVariable(n.successCount),r=2*e.getVariable(n.blockHeight);return i(a<=4?1.25*r:r)};t.getAngleBase=function(e){var t=e.getVariable(n.successCount),i=e.getVariable(n.gameScore),a=e.getVariable(n.gameUserOption).hookAngle;if(a)return a(t,i);if(e.getVariable(n.hardMode))return 90;switch(!0){case t<10:return 30;case t<20:return 60;default:return 80}};t.getSwingBlockVelocity=function(e,t){var i,a=e.getVariable(n.successCount),r=e.getVariable(n.gameScore),o=e.getVariable(n.gameUserOption).hookSpeed;if(o)return o(a,r);switch(!0){case a<1:i=0;break;case a<10:i=1;break;case a<20:i=.8;break;case a<30:i=.7;break;default:i=.74}return e.getVariable(n.hardMode)&&(i=1.1),Math.sin(t/(200/i))};t.getLandBlockVelocity=function(e,t){var i=e.getVariable(n.successCount),a=e.getVariable(n.gameScore),r=e.getVariable(n.gameUserOption).landBlockSpeed;if(r)return r(i,a);var o,s=e.width;switch(!0){case i<5:o=0;break;case i<13:o=.001;break;case i<23:o=.002;break;default:o=.003}return Math.cos(t/200)*o*s};var a=function(e){return e.checkTimeMovement(n.hookDownMovement)?n.hookDown:e.checkTimeMovement(n.hookUpMovement)?n.hookUp:n.hookNormal};t.getHookStatus=a;t.touchEventHandler=function(e){if(e.getVariable(n.gameStartNow)&&!(e.debug&&e.paused||a(e)!==n.hookNormal)){e.removeInstance("tutorial"),e.removeInstance("tutorial-arrow");var t=e.getInstance("block_".concat(e.getVariable(n.blockCount)));t&&t.status===n.swing&&(e.setTimeMovement(n.hookUpMovement,500),t.status=n.beforeDrop)}};t.addSuccessCount=function(e){var t=e.getVariable(n.gameUserOption).setGameSuccess,i=e.getVariable(n.successCount)+1;e.setVariable(n.successCount,i),e.getVariable(n.hardMode)&&e.setVariable(n.ropeHeight,e.height*e.utils.random(.35,.55)),t&&t(i)};t.addFailedCount=function(e){var t=e.getVariable(n.gameUserOption).setGameFailed,i=e.getVariable(n.failedCount)+1;e.setVariable(n.failedCount,i),e.setVariable(n.perfectCount,0),t&&t(i),i>=3&&(e.pauseAudio("bgm"),e.playAudio("game-over"),e.setVariable(n.gameStartNow,!1))};t.addScore=function(e,t){var i=e.getVariable(n.gameUserOption),a=i.setGameScore,r=i.successScore,o=i.perfectScore,s=e.getVariable(n.perfectCount,0),c=e.getVariable(n.gameScore),u=t?s+1:0,l=c+(r||25)+(o||25)*u;e.setVariable(n.gameScore,l),e.setVariable(n.perfectCount,u),a&&a(l)};t.drawYellowString=function(e,t){var i=t.string,n=t.size,a=t.x,r=t.y,o=t.textAlign,s=e.ctx,c=n,u=.1*c;s.save(),s.beginPath();var l=s.createLinearGradient(0,0,0,r);l.addColorStop(0,"#FAD961"),l.addColorStop(1,"#F76B1C"),s.fillStyle=l,s.lineWidth=u,s.strokeStyle="#FFF",s.textAlign=o||"center",s.font="".concat(c,"px ").concat("wenxue"),s.strokeText(i,a,r),s.fillText(i,a,r),s.restore()}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"Engine",{enumerable:!0,get:function(){return n.default}}),Object.defineProperty(t,"Instance",{enumerable:!0,get:function(){return a.default}});var n=r(i(14)),a=r(i(11));function r(e){return e&&e.__esModule?e:{default:e}}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addFlight=t.flightPainter=t.flightAction=void 0;var n=i(2),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));var r=function(e,t){var i=e.visible,n=e.ready,r=e.type;if(i){var o=t.getVariable(a.cloudSize);if(!n){var s=function(e,t){var i=e.width,n=e.height,r=e.utils.random,o=e.getVariable(a.cloudSize);return{bottomToTop:{x:i*r(.3,.7),y:n,vx:0,vy:.7*e.pixelsPerFrame(n)*-1},leftToRight:{x:-1*o,y:n*r(.3,.6),vx:.4*e.pixelsPerFrame(i),vy:.1*e.pixelsPerFrame(n)*-1},rightToLeft:{x:i,y:n*r(.2,.5),vx:.4*e.pixelsPerFrame(i)*-1,vy:.1*e.pixelsPerFrame(n)},rightTopToLeft:{x:i,y:0,vx:.6*e.pixelsPerFrame(i)*-1,vy:.5*e.pixelsPerFrame(n)}}[t]}(t,r);e.ready=!0,e.width=o,e.height=o,e.x=s.x,e.y=s.y,e.vx=s.vx,e.vy=s.vy}e.x+=e.vx,e.y+=e.vy,(e.y+o<0||e.y>t.height||e.x+o<0||e.x>t.width)&&(e.visible=!1)}};t.flightAction=r;var o=function(e,t){var i=t.ctx,n=t.getImg(e.imgName);i.drawImage(n,e.x,e.y,e.width,e.height)};t.flightPainter=o;t.addFlight=function(e,t,i){if(e.getVariable(a.flightCount)!==t){var s=new n.Instance({name:"flight_".concat(t),action:r,painter:o});s.imgName="f".concat(t),s.type=i,e.addInstance(s,a.flightLayer),e.setVariable(a.flightCount,t)}}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.blockPainter=t.blockAction=void 0;var n=i(1),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));var r=function(e,t){e.status===a.rotateLeft?e.y-e.width>=t.height&&(e.visible=!1,e.status=a.out,(0,n.addFailedCount)(t)):e.y>=t.height&&(e.visible=!1,e.status=a.out,(0,n.addFailedCount)(t))};t.blockAction=function(e,t,i){var o=e,s=t.getVariable(a.ropeHeight);if(o.visible){o.ready||(o.ready=!0,o.status=a.swing,e.updateWidth(t.getVariable(a.blockWidth)),e.updateHeight(t.getVariable(a.blockHeight)),e.x=t.width/2,e.y=-1.5*s);var c=t.getInstance("line");switch(o.status){case a.swing:t.getTimeMovement(a.hookDownMovement,[[e.y,e.y+s]],function(t){e.y=t},{name:"block"}),function(e,t,i){var r=t.getVariable(a.ropeHeight);if(e.status===a.swing){var o=e,s=t.getVariable(a.initialAngle);o.angle=s*(0,n.getSwingBlockVelocity)(t,i),o.weightX=o.x+Math.sin(o.angle)*r,o.weightY=o.y+Math.cos(o.angle)*r}}(e,t,i);break;case a.beforeDrop:o.x=e.weightX-e.calWidth,o.y=e.weightY+.3*e.height,o.rotate=0,o.ay=t.pixelsPerFrame(3e-4*t.height),o.startDropTime=i,o.status=a.drop;break;case a.drop:var u=i-o.startDropTime;o.startDropTime=i,o.vy+=o.ay*u,o.y+=o.vy*u+.5*o.ay*Math.pow(u,2);var l=function(e,t){return e.y+e.height>=t.y?e.xt.collisionX+e.calWidth?1:e.xt.collisionX?3:e.x>t.x+.8*e.calWidth&&e.xt.width-2*f||o.x<-f)&&t.setVariable(a.hardMode,!0),5===l?(e.perfect=!0,(0,n.addScore)(t,!0),t.playAudio("drop-perfect")):((0,n.addScore)(t),t.playAudio("drop"))}break;case a.land:t.getTimeMovement(a.moveDownMovement,[[e.y,e.y+(0,n.getMoveDownValue)(t,{pixelsPerFrame:function(e){return e/2}})]],function(i){e.visible&&(e.y=i,e.y>t.height&&(e.visible=!1))},{name:e.name}),e.x+=(0,n.getLandBlockVelocity)(t,i);break;case a.rotateLeft:case a.rotateRight:var v=o.status===a.rotateRight,m=t.pixelsPerFrame(4*Math.PI),p=v?e.rotate>1.3:e.rotate<-1.3,y=v?1:-1;if(p)e.rotate+=m/8*y,e.y+=t.pixelsPerFrame(.7*t.height),e.x+=t.pixelsPerFrame(.3*t.width)*y;else{var b=(e.calWidth-e.outwardOffset)/e.calWidth;b=b>.5?b:.5,e.rotate+=m*b*y;var w=e.originOutwardAngle+e.rotate,k=v?c.collisionX+e.calWidth:c.x+e.calWidth,O=c.y;e.x=k-Math.cos(w)*e.originHypotenuse,e.y=O-Math.sin(w)*e.originHypotenuse}r(e,t)}}};var o=function(e,t){var i=e.perfect,n=t.getImg(i?"block-perfect":"block");t.ctx.drawImage(n,e.x,e.y,e.width,e.height)};t.blockPainter=function(e,t){switch(e.status){case a.swing:!function(e,t){var i=t.getImg("blockRope");t.ctx.drawImage(i,e.weightX-e.calWidth,e.weightY,e.width,1.3*e.height);var n=e.weightX-e.calWidth;t.debugLineY(n)}(e,t);break;case a.drop:case a.land:o(e,t);break;case a.rotateLeft:case a.rotateRight:!function(e,t){var i=t.ctx;i.save(),i.translate(e.x,e.y),i.rotate(e.rotate),i.translate(-e.x,-e.y),o(e,t),i.restore()}(e,t)}}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.startAnimate=t.endAnimate=void 0;var n=i(2),a=i(4),r=i(1),o=i(3),s=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));t.endAnimate=function(e){if(e.getVariable(s.gameStartNow)){var t=e.getVariable(s.successCount,0),i=e.getVariable(s.failedCount),n=e.getVariable(s.gameScore,0),a=Number(t)>99?.1*e.width:0;(0,r.drawYellowString)(e,{string:"层",size:.06*e.width,x:.24*e.width+a,y:.12*e.width,textAlign:"left"}),(0,r.drawYellowString)(e,{string:t,size:.17*e.width,x:.22*e.width+a,y:.2*e.width,textAlign:"right"});var o=e.getImg("score"),c=o.width,u=o.height,l=.35*e.width,d=u*l/c;e.ctx.drawImage(o,.61*e.width,.038*e.width,l,d),(0,r.drawYellowString)(e,{string:n,size:.06*e.width,x:.9*e.width,y:.11*e.width,textAlign:"right"});for(var h=e.ctx,g=e.getImg("heart"),f=g.width,v=g.height,m=.08*e.width,p=v*m/f,y=1;y<=3;y+=1)h.save(),y<=i&&(h.globalAlpha=.2),h.drawImage(g,.66*e.width+(y-1)*m,.16*e.width,m,p),h.restore()}};t.startAnimate=function(e){if(e.getVariable(s.gameStartNow)){var t=e.getInstance("block_".concat(e.getVariable(s.blockCount)));if(!t||[s.land,s.out].indexOf(t.status)>-1){if((0,r.checkMoveDown)(e)&&(0,r.getMoveDownValue)(e))return;if(e.checkTimeMovement(s.hookUpMovement))return;var i=(0,r.getAngleBase)(e),c=Math.PI*e.utils.random(i,i+5)*e.utils.randomPositiveNegative()/180;e.setVariable(s.blockCount,e.getVariable(s.blockCount)+1),e.setVariable(s.initialAngle,c),e.setTimeMovement(s.hookDownMovement,500);var u=new n.Instance({name:"block_".concat(e.getVariable(s.blockCount)),action:a.blockAction,painter:a.blockPainter});e.addInstance(u)}switch(Number(e.getVariable(s.successCount,0))){case 2:(0,o.addFlight)(e,1,"leftToRight");break;case 6:(0,o.addFlight)(e,2,"rightToLeft");break;case 8:(0,o.addFlight)(e,3,"leftToRight");break;case 14:(0,o.addFlight)(e,4,"bottomToTop");break;case 18:(0,o.addFlight)(e,5,"bottomToTop");break;case 22:(0,o.addFlight)(e,6,"bottomToTop");break;case 25:(0,o.addFlight)(e,7,"rightTopToLeft")}}}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.tutorialPainter=t.tutorialAction=void 0;var n=i(1),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));t.tutorialAction=function(e,t,i){var n=t.width,a=t.height,r=e.name;if(!e.ready){e.ready=!0;var o=.2*n;e.updateWidth(o),e.height=.46*o,e.x=t.calWidth-e.calWidth,e.y=.45*a,"tutorial"!==r&&(e.y+=1.2*e.height)}"tutorial"!==r&&(e.y+=Math.cos(i/200)*e.height*.01)};t.tutorialPainter=function(e,t){if(!t.checkTimeMovement(a.tutorialMovement)&&(0,n.getHookStatus)(t)===a.hookNormal){var i=t.ctx,r=e.name,o=t.getImg(r);i.drawImage(o,e.x,e.y,e.width,e.height)}}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.hookPainter=t.hookAction=void 0;var n=i(1),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));t.hookAction=function(e,t,i){var r=t.getVariable(a.ropeHeight);e.ready||(e.x=t.width/2,e.y=-1.5*r,e.ready=!0),t.getTimeMovement(a.hookUpMovement,[[e.y,e.y-r]],function(t){e.y=t},{after:function(){e.y=-1.5*r}}),t.getTimeMovement(a.hookDownMovement,[[e.y,e.y+r]],function(t){e.y=t},{name:"hook"});var o=t.getVariable(a.initialAngle);e.angle=o*(0,n.getSwingBlockVelocity)(t,i),e.weightX=e.x+Math.sin(e.angle)*r,e.weightY=e.y+Math.cos(e.angle)*r};t.hookPainter=function(e,t){var i=t.ctx,n=t.getVariable(a.ropeHeight),r=.1*n,o=t.getImg("hook");i.save(),i.translate(e.x,e.y),i.rotate(2*Math.PI-e.angle),i.translate(-e.x,-e.y),t.ctx.drawImage(o,e.x-r/2,e.y,r,n+5),i.restore()}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.cloudPainter=t.cloudAction=void 0;var n=i(1),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));var r=function(e){var t=e.count,i=function(e){return e[Math.floor(Math.random()*e.length)]};e.imgName=i(t>6?["c4","c5","c6","c7","c8"]:["c1","c2","c3"])};t.cloudAction=function(e,t){if(!e.ready){e.ready=!0,r(e),e.width=t.getVariable(a.cloudSize),e.height=t.getVariable(a.cloudSize);var i=t.width,o=t.height,s=[{x:.1*i,y:.66*-o},{x:.65*i,y:.33*-o},{x:.1*i,y:0},{x:.65*i,y:.33*o}][e.index-1];e.x=t.utils.random(s.x,1.2*s.x),e.originX=e.x,e.ax=t.pixelsPerFrame(e.width*t.utils.random(.05,.08)*t.utils.randomPositiveNegative()),e.y=t.utils.random(s.y,1.2*s.y)}e.x+=e.ax,(e.x>=e.originX+e.width||e.x<=e.originX-e.width)&&(e.ax*=-1),(0,n.checkMoveDown)(t)&&(e.y+=1.2*(0,n.getMoveDownValue)(t)),e.y>=t.height&&(e.y=.66*-t.height,e.count+=4,r(e))};t.cloudPainter=function(e,t){var i=t.ctx,n=t.getImg(e.imgName);i.drawImage(n,e.x,e.y,e.width,e.height)}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.linePainter=t.lineAction=void 0;var n=i(1),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));t.lineAction=function(e,t,i){var r=e;r.ready||(r.y=t.getVariable(a.lineInitialOffset),r.ready=!0,r.collisionX=t.width-t.getVariable(a.blockWidth)),t.getTimeMovement(a.moveDownMovement,[[e.y,e.y+(0,n.getMoveDownValue)(t,{pixelsPerFrame:function(e){return e/2}})]],function(t){e.y=t},{name:"line"});var o=(0,n.getLandBlockVelocity)(t,i);e.x+=o,e.collisionX+=o};t.linePainter=function(e,t){var i=t.ctx;t.debug&&(i.save(),i.beginPath(),i.strokeStyle="red",i.moveTo(e.x,e.y),i.lineTo(e.collisionX,e.y),i.lineWidth=1,i.stroke(),i.restore())}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.background=t.backgroundLinearGradient=t.backgroundImg=void 0;var n=i(1),a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0));var r=function(e){var t=e.getImg("background"),i=t.width,r=t.height*e.width/i,o=e.getVariable(a.bgImgOffset,e.height-r);o>e.height||(e.getTimeMovement(a.moveDownMovement,[[o,o+(0,n.getMoveDownValue)(e,{pixelsPerFrame:function(e){return e/2}})]],function(e){o=e},{name:"background"}),e.getTimeMovement(a.bgInitMovement,[[o,o+r/4]],function(e){o=e}),e.setVariable(a.bgImgOffset,o),e.setVariable(a.lineInitialOffset,e.height-.394*r),e.ctx.drawImage(t,0,o,e.width,r))};t.backgroundImg=r;var o=function(e,t,i){var n=t+1>=e.length?e.length-1:t,a=e[n],r=e[n+1>=e.length-1?n:n+1],o=function(e){var t=a[e],n=r[e];return Math.round(t+(n-t)*i)};return"rgb(".concat(o(0),", ").concat(o(1),", ").concat(o(2),")")},s=function(e){var t=e.ctx.createLinearGradient(0,0,0,e.height),i=[[200,255,150],[105,230,240],[90,190,240],[85,100,190],[55,20,35],[75,25,35],[25,0,10]],r=e.getVariable(a.bgLinearGradientOffset,0);(0,n.checkMoveDown)(e)&&e.setVariable(a.bgLinearGradientOffset,r+1.5*(0,n.getMoveDownValue)(e));var s=parseInt(r/e.height,10),c=r%e.height/e.height,u=o(i,s,c),l=o(i,s+1,c);t.addColorStop(0,l),t.addColorStop(1,u),e.ctx.fillStyle=t,e.ctx.beginPath(),e.ctx.rect(0,0,e.width,e.height),e.ctx.fill();var d=function(){e.ctx.fillStyle="rgba(255, 255, 255, 0.7)",e.ctx.fillRect(0,0,e.width,e.height)};e.getTimeMovement(a.lightningMovement,[],function(){},{before:d,after:d})};t.backgroundLinearGradient=s;t.background=function(e){s(e),r(e)}},function(e,t,i){"use strict";function n(e,t){for(var i=0;i0&&void 0!==arguments[0]?arguments[0]:{};!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e);var i=t.name,n=t.painter,a=t.action;this.name=i,this.x=0,this.y=0,this.width=0,this.height=0,this.ax=0,this.ay=0,this.vx=0,this.vy=0,this.visible=!0,this.painter=n||null,this.action=a||null,this.ready=!1}var t,i,a;return t=e,(i=[{key:"paint",value:function(e){null!==this.painter&&this.visible&&this.painter(this,e)}},{key:"update",value:function(e,t){null!==this.action&&this.action(this,e,t)}},{key:"updateWidth",value:function(e){this.width=e,this.calWidth=e/2}},{key:"updateHeight",value:function(e){this.height=e,this.calHeight=e/2}}])&&n(t.prototype,i),a&&n(t,a),e}();t.default=a},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n={linear:function(e,t,i,n){return i*e/n+t},easeIn:function(e,t,i,n){return i*(e/=n)*e+t},easeOut:function(e,t,i,n){return-i*(e/=n)*(e-2)+t},easeInOut:function(e,t,i,n){return(e/=n/2)<1?i/2*e*e+t:-i/2*(--e*(e-2)-1)+t}};t.default=n},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.arraySwap=t.requestAnimationFrameTool=t.isTouchDevice=t.isFunction=t.randomPositiveNegative=t.random=t.getCurrentTime=void 0;var n=function(){return+new Date};t.getCurrentTime=n;t.random=function(e,t){return Math.random()*(t-e)+e};t.randomPositiveNegative=function(){return Math.random()<.5?-1:1};t.isFunction=function(e){return"function"==typeof e};t.isTouchDevice=function(){return"ontouchstart"in window||window.navigator.msMaxTouchPoints};var a,r=(a=1e3/60,window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(function(){var t=n();e(t);var i=n();a=1e3/60-(i-t)},a)});t.requestAnimationFrameTool=r;t.arraySwap=function(e,t,i){var n=e[i];e[i]=e[t],e[t]=n}},function(e,t,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,a=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(13)),r=(n=i(12))&&n.__esModule?n:{default:n};function o(e){return function(e){if(Array.isArray(e)){for(var t=0,i=new Array(e.length);t0&&void 0!==arguments[0]?arguments[0]:{};if(function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),document.createElement("canvas").getContext){var i=t.canvasId,n=t.debug,r=t.width,o=t.height,s=t.highResolution,c=t.loadLimit,u=t.soundOn,d=r||window.innerWidth,h=o||window.innerHeight;this.canvas=document.getElementById(i),s&&(this.canvas.style.width="".concat(d,"px"),this.canvas.style.height="".concat(h,"px"),d*=2,h*=2),this.highResolution=s,this.canvas.width=d,this.canvas.height=h,this.width=this.canvas.width,this.height=this.canvas.height,this.calWidth=.5*this.width,this.calHeight=.5*this.height,this.debug=!!n,this.ctx=this.canvas.getContext("2d"),this.defaultLayer="default",this.layerArr=[this.defaultLayer],this.instancesObj={},this.instancesObj[this.defaultLayer]=[],this.utils=a,this.customVariable={};var g=this;this.isTouchDevice=l(),this.debugArr=[],this.assetsObj={image:{},audio:{}},this.assetsCount={image:0,audio:0},this.assetsErrorQueue=[],this.assetsErrorCount=0,this.loadLimit=c||3,this.soundOn=!!u,this.fps=0,this.lastTime=0,this.lastPausedAt=0,this.pausedTime=0,this.paused=!1,this.timeMovement={},this.timeMovementStartArr=[],this.timeMovementFinishArr=[],this.keyUpListeners={},this.keyDownListeners={},this.keyPressListeners={},this.startAnimate=function(){},this.paintUnderInstance=function(){},this.paintAboveInstance=function(){},this.endAnimate=function(){},this.touchStartListener=function(){},this.touchEndListener=function(){},this.touchMoveListener=function(){},document.addEventListener("keyup",function(e){g.keyListener(e,"keyup")},!1),document.addEventListener("keydown",function(e){g.keyListener(e,"keydown")},!1),document.addEventListener("keypress",function(e){g.keyListener(e,"keypress")},!1),this.isTouchDevice?(document.addEventListener("touchstart",function(e){g.touchStartListener(e)},!1),document.addEventListener("touchend",function(e){g.touchEndListener(e)},!1),document.addEventListener("touchmove",function(e){g.touchMoveListener(e)},!1)):(document.addEventListener("mousedown",function(e){g.touchStartListener(e)},!1),document.addEventListener("mouseup",function(e){g.touchEndListener(e)},!1),document.addEventListener("mousemove",function(e){g.touchMoveListener(e)},!1))}else window.alert("HTML5 Canvas is not supported in your browser.")}var t,i,n;return t=e,(i=[{key:"addAudio",value:function(e,t){var i=this,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;if(this.soundOn){n||(this.assetsCount.audio+=1);var a=new window.Audio;a.src=t,this.assetsObj.audio[e]=a,a.addEventListener("error",function(){i.assetsErrorQueue.push({name:e,src:t,retry:n+1,type:"audio"})},!1),a.load()}}},{key:"getAudio",value:function(e){return this.assetsObj.audio[e]}},{key:"playAudio",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(this.soundOn){var i=this.getAudio(e);if(i){if(i.play(),!t)return;i.addEventListener("ended",function(){i.currentTime=0,i.play()},!1)}}}},{key:"pauseAudio",value:function(e){var t=this.getAudio(e);t&&t.pause()}},{key:"setVariable",value:function(e,t){this.customVariable[e]=t}},{key:"getVariable",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,i=this.customVariable[e];return i||(null!==t?(this.setVariable(e,t),t):null)}},{key:"addImg",value:function(e,t){var i=this,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;n||(this.assetsCount.image+=1);var a=new window.Image;a.src=t,a.onload=function(){i.assetsObj.image[e]=a},a.onerror=function(){i.assetsErrorQueue.push({name:e,src:t,retry:n+1,type:"image"})}}},{key:"getImg",value:function(e){return this.assetsObj.image[e]}},{key:"animate",value:function(e){var t=this,i=e-this.pausedTime,n=this;this.paused?setTimeout(function(){t.animate.call(n,i)},100):(this.tick(i),this.clean(),this.startAnimate(this,i),this.paintUnderInstance(this),this.updateInstances(i),this.paintInstances(),this.paintAboveInstance(),this.endAnimate(this,i),this.tickTimeMovement(),this.debug&&this.showFps(),this.debug&&this.drawDebug(),c(function(e){t.animate.call(n,e)}))}},{key:"showFps",value:function(){this.ctx.save(),this.ctx.fillStyle="red",this.ctx.font="".concat(this.highResolution?32:16,"px Arial"),this.ctx.fillText("FPS: ".concat(this.fps.toFixed()),5,this.highResolution?40:20),this.ctx.restore()}},{key:"debugLineX",value:function(e){this.debugArr.push({type:"lineX",y:e})}},{key:"debugLineY",value:function(e){this.debugArr.push({type:"lineY",x:e})}},{key:"debugDot",value:function(e,t){this.debugArr.push({type:"dot",x:e,y:t})}},{key:"drawDebug",value:function(){var e=this;this.debugArr.forEach(function(t){var i=t.type,n=t.x,a=t.y;switch(i){case"dot":e.drawDebugDot(n,a);break;case"lineX":e.drawDebugLine(null,a);break;case"lineY":e.drawDebugLine(n,null)}})}},{key:"drawDebugLine",value:function(e,t){var i,n,a=[0,t],r=[this.width,t];e&&(a=[e,0],r=[e,this.height]),this.ctx.save(),this.ctx.strokeStyle="red",this.ctx.beginPath(),(i=this.ctx).moveTo.apply(i,o(a)),(n=this.ctx).lineTo.apply(n,o(r)),this.ctx.stroke(),this.ctx.restore()}},{key:"drawDebugDot",value:function(e,t){this.ctx.save(),this.ctx.fillStyle="red",this.ctx.beginPath(),this.ctx.arc(e,t,2,0,2*Math.PI,!0),this.ctx.fill(),this.ctx.fillStyle="white",this.ctx.beginPath(),this.ctx.arc(e,t,1,0,2*Math.PI,!0),this.ctx.fill(),this.ctx.restore()}},{key:"tick",value:function(e){this.updateFps(e),this.lastTime=e}},{key:"updateFps",value:function(e){0===this.lastTime?this.fps=60:this.fps=1e3/(e-this.lastTime)}},{key:"pixelsPerFrame",value:function(e){return e/this.fps}},{key:"tickTimeMovement",value:function(){var e=this;this.timeMovementStartArr.forEach(function(t){e.timeMovement[t].processing=!0}),this.timeMovementStartArr=[],this.timeMovementFinishArr.forEach(function(t){delete e.timeMovement[t]}),this.timeMovementFinishArr=[]}},{key:"getTimeMovement",value:function(e,t,i){var n=this,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=a.before,s=a.after,c=r.default[a.easing||"linear"],u=a.name||"default",l=this.timeMovement[e];if(l){l.processing||("hook"===a.name&&console.log(t),this.timeMovementStartArr.push(e),l.store[u]=[],t.forEach(function(e){l.store[u].push({start:parseFloat(e[0]),end:parseFloat(e[1])})}),o&&o());var d=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=l.duration,a=t;if(!e){var r=n.utils.getCurrentTime(),o=l.startTime;a=r-o}var s=l.store[u].map(function(e){return c(a,e.start,e.end-e.start,t)});i.apply(n,s)};this.checkTimeMovement(e)?d():(this.timeMovementFinishArr.push(e),d(!0),s&&s())}}},{key:"checkTimeMovement",value:function(e){var t=this.timeMovement[e]||{};return this.utils.getCurrentTime()<=t.endTime}},{key:"setTimeMovement",value:function(e,t){var i=this.utils.getCurrentTime();this.timeMovement[e]={startTime:i,endTime:i+t,duration:t,store:{}}}},{key:"clean",value:function(){this.ctx.clearRect(0,0,this.width,this.height),this.debugArr=[]}},{key:"addLayer",value:function(e){this.layerArr.push(e),this.instancesObj[e]=[]}},{key:"removeLayer",value:function(e){this.layerArr=this.layerArr.filter(function(t){return t!==e}),delete this.instancesObj[e]}},{key:"swapLayer",value:function(e,t){this.utils.arraySwap(this.layerArr,e,t)}},{key:"addInstance",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.defaultLayer;this.instancesObj[t].push(e)}},{key:"getInstance",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.defaultLayer;return this.instancesObj[t].filter(function(t){return t.name===e})[0]}},{key:"removeInstance",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.defaultLayer;this.getInstance(e,t)&&(this.instancesObj[t]=this.instancesObj[t].filter(function(t){return t.name!==e}))}},{key:"updateInstances",value:function(e){var t=this;this.layerArr.forEach(function(i){t.instancesObj[i].forEach(function(i){i.update&&i.update(t,e)})})}},{key:"paintInstances",value:function(){var e=this;this.layerArr.forEach(function(t){e.instancesObj[t].forEach(function(t){t.paint&&t.paint(e)})})}},{key:"togglePaused",value:function(){var e=this.utils.getCurrentTime();this.paused=!this.paused,this.paused?this.lastPausedAt=e:this.pausedTime+=e-this.lastPausedAt}},{key:"addKeyUpListener",value:function(e,t){this.keyUpListeners[e]=t}},{key:"addKeyDownListener",value:function(e,t){this.keyDownListeners[e]=t}},{key:"addKeyPressListener",value:function(e,t){this.keyPressListeners[e]=t}},{key:"findKeyListener",value:function(e,t){return"keyup"===t?this.keyUpListeners[e]:"keydown"===t?this.keyDownListeners[e]:this.keyPressListeners[e]}},{key:"keyListener",value:function(e,t){var i;switch(e.keyCode){case 13:i="enter";break;case 32:i="space";break;case 37:i="leftArrow";break;case 39:i="rightArrow";break;case 38:i="upArrow";break;case 40:i="downArrow";break;default:i=e.keyCode}var n=this.findKeyListener(i,t);n&&n()}},{key:"load",value:function(e,t){var i=this,n=setInterval(function(){var a=i.assetsCount.image+i.assetsCount.audio,r=Object.keys(i.assetsObj.image).length+Object.keys(i.assetsObj.audio).length;t&&u(t)&&t({success:r,failed:i.assetsErrorCount,total:a}),i.assetsErrorQueue.length>0&&(i.assetsErrorQueue.forEach(function(e){var t=e.retry,n=e.name,a=e.src,r=e.type;t>=i.loadLimit?i.assetsErrorCount+=1:"image"===r?i.addImg(n,a,t):i.addAudio(n,a,t)}),i.assetsErrorQueue=[]),r===a&&(e&&u(e)?e():i.init(),clearInterval(n))},200)}},{key:"init",value:function(){var e=this,t=this;c(function(i){e.animate.call(t,i)})}}])&&s(t.prototype,i),n&&s(t,n),e}();t.default=d},function(e,t,i){"use strict";var n=i(2),a=i(1),r=i(10),o=i(9),s=i(8),c=i(7),u=i(6),l=function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var n=Object.defineProperty&&Object.getOwnPropertyDescriptor?Object.getOwnPropertyDescriptor(e,i):{};n.get||n.set?Object.defineProperty(t,i,n):t[i]=e[i]}return t.default=e,t}(i(0)),d=i(5);window.TowerGame=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.width,i=e.height,h=e.canvasId,g=e.soundOn,f=new n.Engine({canvasId:h,highResolution:!0,width:t,height:i,soundOn:g}),v=function(e){return"./assets/".concat(e)};f.addImg("background",v("background.png")),f.addImg("hook",v("hook.png")),f.addImg("blockRope",v("block-rope.png")),f.addImg("block",v("block.png")),f.addImg("block-perfect",v("block-perfect.png"));for(var m=1;m<=8;m+=1)f.addImg("c".concat(m),v("c".concat(m,".png")));f.addLayer(l.flightLayer);for(var p=1;p<=7;p+=1)f.addImg("f".concat(p),v("f".concat(p,".png")));f.swapLayer(0,1),f.addImg("tutorial",v("tutorial.png")),f.addImg("tutorial-arrow",v("tutorial-arrow.png")),f.addImg("heart",v("heart.png")),f.addImg("score",v("score.png")),f.addAudio("drop-perfect",v("drop-perfect.mp3")),f.addAudio("drop",v("drop.mp3")),f.addAudio("game-over",v("game-over.mp3")),f.addAudio("rotate",v("rotate.mp3")),f.addAudio("bgm",v("bgm.mp3")),f.setVariable(l.blockWidth,.25*f.width),f.setVariable(l.blockHeight,.71*f.getVariable(l.blockWidth)),f.setVariable(l.cloudSize,.3*f.width),f.setVariable(l.ropeHeight,.4*f.height),f.setVariable(l.blockCount,0),f.setVariable(l.successCount,0),f.setVariable(l.failedCount,0),f.setVariable(l.gameScore,0),f.setVariable(l.hardMode,!1),f.setVariable(l.gameUserOption,e);for(var y=1;y<=4;y+=1){var b=new n.Instance({name:"cloud_".concat(y),action:s.cloudAction,painter:s.cloudPainter});b.index=y,b.count=5-y,f.addInstance(b)}var w=new n.Instance({name:"line",action:o.lineAction,painter:o.linePainter});f.addInstance(w);var k=new n.Instance({name:"hook",action:c.hookAction,painter:c.hookPainter});return f.addInstance(k),f.startAnimate=d.startAnimate,f.endAnimate=d.endAnimate,f.paintUnderInstance=r.background,f.addKeyDownListener("enter",function(){f.debug&&f.togglePaused()}),f.touchStartListener=function(){(0,a.touchEventHandler)(f)},f.playBgm=function(){f.playAudio("bgm",!0)},f.pauseBgm=function(){f.pauseAudio("bgm")},f.start=function(){var e=new n.Instance({name:"tutorial",action:u.tutorialAction,painter:u.tutorialPainter});f.addInstance(e);var t=new n.Instance({name:"tutorial-arrow",action:u.tutorialAction,painter:u.tutorialPainter});f.addInstance(t),f.setTimeMovement(l.bgInitMovement,500),f.setTimeMovement(l.tutorialMovement,500),f.setVariable(l.gameStartNow,!0)},f}}]); \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..0bdc43e --- /dev/null +++ b/index.html @@ -0,0 +1,571 @@ + + + + + + Tower + + + + +
+
+
+
+
0%
+
+
+
+
+
+
加载中
+
+
+ +
+
+
+ +
+
+
+ +
+ +
+
+ + + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..280f173 --- /dev/null +++ b/index.js @@ -0,0 +1,17 @@ +const express = require('express') +const path = require('path') +const opn = require('opn') + +const server = express() +const host = 'http://localhost:8082' +server.use('/assets', express.static(path.resolve(__dirname, './assets'))) +server.use('/dist', express.static(path.resolve(__dirname, './dist'))) + +server.get('*', (req, res) => { + res.sendFile(path.resolve(__dirname, './index.html')); +}) + +server.listen(8082, () => { + console.log(`server started at ${host}`) + opn(host) +}) diff --git a/package.json b/package.json new file mode 100644 index 0000000..ebec5c2 --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "tower_game", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "npm run build && node index.js", + "build": "webpack --mode production --module-bind js=babel-loader" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bmqb/tower_game.git" + }, + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/bmqb/tower_game/issues" + }, + "homepage": "https://github.com/bmqb/tower_game#readme", + "devDependencies": { + "@babel/core": "^7.0.0-beta.42", + "@babel/preset-env": "^7.0.0-beta.42", + "babel-loader": "^8.0.0-beta", + "webpack": "^4.0.1", + "webpack-cli": "^2.0.9" + }, + "dependencies": { + "cooljs": "^1.0.2", + "express": "^4.16.3", + "opn": "^5.3.0" + } +} diff --git a/src/animateFuncs.js b/src/animateFuncs.js new file mode 100644 index 0000000..6c072ee --- /dev/null +++ b/src/animateFuncs.js @@ -0,0 +1,124 @@ +import { Instance } from 'cooljs' +import { blockAction, blockPainter } from './block' +import { + checkMoveDown, + getMoveDownValue, + drawYellowString, + getAngleBase +} from './utils' +import { addFlight } from './flight' +import * as constant from './constant' + +export const endAnimate = (engine) => { + const gameStartNow = engine.getVariable(constant.gameStartNow) + if (!gameStartNow) return + const successCount = engine.getVariable(constant.successCount, 0) + const failedCount = engine.getVariable(constant.failedCount) + const gameScore = engine.getVariable(constant.gameScore, 0) + const threeFiguresOffset = Number(successCount) > 99 ? engine.width * 0.1 : 0 + + drawYellowString(engine, { + string: '层', + size: engine.width * 0.06, + x: (engine.width * 0.24) + threeFiguresOffset, + y: engine.width * 0.12, + textAlign: 'left' + }) + drawYellowString(engine, { + string: successCount, + size: engine.width * 0.17, + x: (engine.width * 0.22) + threeFiguresOffset, + y: engine.width * 0.2, + textAlign: 'right' + }) + const score = engine.getImg('score') + const scoreWidth = score.width + const scoreHeight = score.height + const zoomedWidth = engine.width * 0.35 + const zoomedHeight = (scoreHeight * zoomedWidth) / scoreWidth + engine.ctx.drawImage( + score, + engine.width * 0.61, + engine.width * 0.038, + zoomedWidth, + zoomedHeight + ) + drawYellowString(engine, { + string: gameScore, + size: engine.width * 0.06, + x: engine.width * 0.9, + y: engine.width * 0.11, + textAlign: 'right' + }) + const { ctx } = engine + const heart = engine.getImg('heart') + const heartWidth = heart.width + const heartHeight = heart.height + const zoomedHeartWidth = engine.width * 0.08 + const zoomedHeartHeight = (heartHeight * zoomedHeartWidth) / heartWidth + for (let i = 1; i <= 3; i += 1) { + ctx.save() + if (i <= failedCount) { + ctx.globalAlpha = 0.2 + } + ctx.drawImage( + heart, + (engine.width * 0.66) + ((i - 1) * zoomedHeartWidth), + engine.width * 0.16, + zoomedHeartWidth, + zoomedHeartHeight + ) + ctx.restore() + } +} + +export const startAnimate = (engine) => { + const gameStartNow = engine.getVariable(constant.gameStartNow) + if (!gameStartNow) return + const lastBlock = engine.getInstance(`block_${engine.getVariable(constant.blockCount)}`) + if (!lastBlock || [constant.land, constant.out].indexOf(lastBlock.status) > -1) { + if (checkMoveDown(engine) && getMoveDownValue(engine)) return + if (engine.checkTimeMovement(constant.hookUpMovement)) return + const angleBase = getAngleBase(engine) + const initialAngle = (Math.PI + * engine.utils.random(angleBase, angleBase + 5) + * engine.utils.randomPositiveNegative() + ) / 180 + engine.setVariable(constant.blockCount, engine.getVariable(constant.blockCount) + 1) + engine.setVariable(constant.initialAngle, initialAngle) + engine.setTimeMovement(constant.hookDownMovement, 500) + const block = new Instance({ + name: `block_${engine.getVariable(constant.blockCount)}`, + action: blockAction, + painter: blockPainter + }) + engine.addInstance(block) + } + const successCount = Number(engine.getVariable(constant.successCount, 0)) + switch (successCount) { + case 2: + addFlight(engine, 1, 'leftToRight') + break + case 6: + addFlight(engine, 2, 'rightToLeft') + break + case 8: + addFlight(engine, 3, 'leftToRight') + break + case 14: + addFlight(engine, 4, 'bottomToTop') + break + case 18: + addFlight(engine, 5, 'bottomToTop') + break + case 22: + addFlight(engine, 6, 'bottomToTop') + break + case 25: + addFlight(engine, 7, 'rightTopToLeft') + break + default: + break + } +} + diff --git a/src/background.js b/src/background.js new file mode 100644 index 0000000..419ec78 --- /dev/null +++ b/src/background.js @@ -0,0 +1,100 @@ +import { checkMoveDown, getMoveDownValue } from './utils' +import * as constant from './constant' + +export const backgroundImg = (engine) => { + const bg = engine.getImg('background') + const bgWidth = bg.width + const bgHeight = bg.height + const zoomedHeight = (bgHeight * engine.width) / bgWidth + let offsetHeight = engine.getVariable(constant.bgImgOffset, engine.height - zoomedHeight) + if (offsetHeight > engine.height) { + return + } + engine.getTimeMovement( + constant.moveDownMovement, + [[offsetHeight, offsetHeight + (getMoveDownValue(engine, { pixelsPerFrame: s => s / 2 }))]], + (value) => { + offsetHeight = value + }, + { + name: 'background' + } + ) + engine.getTimeMovement( + constant.bgInitMovement, + [[offsetHeight, offsetHeight + (zoomedHeight / 4)]], + (value) => { + offsetHeight = value + } + ) + engine.setVariable(constant.bgImgOffset, offsetHeight) + engine.setVariable(constant.lineInitialOffset, engine.height - (zoomedHeight * 0.394)) + engine.ctx.drawImage( + bg, + 0, offsetHeight, + engine.width, zoomedHeight + ) +} + +const getLinearGradientColorRgb = (colorArr, colorIndex, proportion) => { + const currentIndex = colorIndex + 1 >= colorArr.length ? colorArr.length - 1 : colorIndex + const colorCurrent = colorArr[currentIndex] + const nextIndex = currentIndex + 1 >= colorArr.length - 1 ? currentIndex : currentIndex + 1 + const colorNext = colorArr[nextIndex] + const calRgbValue = (index) => { + const current = colorCurrent[index] + const next = colorNext[index] + return Math.round(current + ((next - current) * proportion)) + } + return `rgb(${calRgbValue(0)}, ${calRgbValue(1)}, ${calRgbValue(2)})` +} + +export const backgroundLinearGradient = (engine) => { + const grad = engine.ctx.createLinearGradient(0, 0, 0, engine.height) + const colorArr = [ + [200, 255, 150], + [105, 230, 240], + [90, 190, 240], + [85, 100, 190], + [55, 20, 35], + [75, 25, 35], + [25, 0, 10] + ] + const offsetHeight = engine.getVariable(constant.bgLinearGradientOffset, 0) + if (checkMoveDown(engine)) { + engine.setVariable( + constant.bgLinearGradientOffset + , offsetHeight + (getMoveDownValue(engine) * 1.5) + ) + } + const colorIndex = parseInt(offsetHeight / engine.height, 10) + const calOffsetHeight = offsetHeight % engine.height + const proportion = calOffsetHeight / engine.height + const colorBase = getLinearGradientColorRgb(colorArr, colorIndex, proportion) + const colorTop = getLinearGradientColorRgb(colorArr, colorIndex + 1, proportion) + grad.addColorStop(0, colorTop) + grad.addColorStop(1, colorBase) + engine.ctx.fillStyle = grad + engine.ctx.beginPath() + engine.ctx.rect(0, 0, engine.width, engine.height) + engine.ctx.fill() + + // lightning + const lightning = () => { + engine.ctx.fillStyle = 'rgba(255, 255, 255, 0.7)' + engine.ctx.fillRect(0, 0, engine.width, engine.height) + } + engine.getTimeMovement( + constant.lightningMovement, [], () => {}, + { + before: lightning, + after: lightning + } + ) +} + +export const background = (engine) => { + backgroundLinearGradient(engine) + backgroundImg(engine) +} + diff --git a/src/block.js b/src/block.js new file mode 100644 index 0000000..103be85 --- /dev/null +++ b/src/block.js @@ -0,0 +1,250 @@ +import { + getMoveDownValue, + getLandBlockVelocity, + getSwingBlockVelocity, + touchEventHandler, + addSuccessCount, + addFailedCount, + addScore +} from './utils' +import * as constant from './constant' + +const checkCollision = (block, line) => { + // 0 goon 1 drop 2 rotate left 3 rotate right 4 ok 5 perfect + if (block.y + block.height >= line.y) { + if (block.x < line.x - block.calWidth || block.x > line.collisionX + block.calWidth) { + return 1 + } + if (block.x < line.x) { + return 2 + } + if (block.x > line.collisionX) { + return 3 + } + if (block.x > line.x + (block.calWidth * 0.8) && block.x < line.x + (block.calWidth * 1.2)) { + // -10% +10% + return 5 + } + return 4 + } + return 0 +} +const swing = (instance, engine, time) => { + const ropeHeight = engine.getVariable(constant.ropeHeight) + if (instance.status !== constant.swing) return + const i = instance + const initialAngle = engine.getVariable(constant.initialAngle) + i.angle = initialAngle * + getSwingBlockVelocity(engine, time) + i.weightX = i.x + + (Math.sin(i.angle) * ropeHeight) + i.weightY = i.y + + (Math.cos(i.angle) * ropeHeight) +} + +const checkBlockOut = (instance, engine) => { + if (instance.status === constant.rotateLeft) { + // 左转 要等右上角消失才算消失 + if (instance.y - instance.width >= engine.height) { + instance.visible = false + instance.status = constant.out + addFailedCount(engine) + } + } else if (instance.y >= engine.height) { + instance.visible = false + instance.status = constant.out + addFailedCount(engine) + } +} + +export const blockAction = (instance, engine, time) => { + const i = instance + const ropeHeight = engine.getVariable(constant.ropeHeight) + if (!i.visible) { + return + } + if (!i.ready) { + i.ready = true + i.status = constant.swing + instance.updateWidth(engine.getVariable(constant.blockWidth)) + instance.updateHeight(engine.getVariable(constant.blockHeight)) + instance.x = engine.width / 2 + instance.y = ropeHeight * -1.5 + } + const line = engine.getInstance('line') + switch (i.status) { + case constant.swing: + engine.getTimeMovement( + constant.hookDownMovement, + [[instance.y, instance.y + ropeHeight]], + (value) => { + instance.y = value + }, + { + name: 'block' + } + ) + swing(instance, engine, time) + break + case constant.beforeDrop: + i.x = instance.weightX - instance.calWidth + i.y = instance.weightY + (0.3 * instance.height) // add rope height + i.rotate = 0 + i.ay = engine.pixelsPerFrame(0.0003 * engine.height) // acceleration of gravity + i.startDropTime = time + i.status = constant.drop + break + case constant.drop: + const deltaTime = time - i.startDropTime + i.startDropTime = time + i.vy += i.ay * deltaTime + i.y += (i.vy * deltaTime) + (0.5 * i.ay * (deltaTime ** 2)) + const collision = checkCollision(instance, line) + const blockY = line.y - instance.height + const calRotate = (ins) => { + ins.originOutwardAngle = Math.atan(ins.height / ins.outwardOffset) + ins.originHypotenuse = Math.sqrt((ins.height ** 2) + + (ins.outwardOffset ** 2)) + engine.playAudio('rotate') + } + switch (collision) { + case 1: + checkBlockOut(instance, engine) + break + case 2: + i.status = constant.rotateLeft + instance.y = blockY + instance.outwardOffset = (line.x + instance.calWidth) - instance.x + calRotate(instance) + break + case 3: + i.status = constant.rotateRight + instance.y = blockY + instance.outwardOffset = (line.collisionX + instance.calWidth) - instance.x + calRotate(instance) + break + case 4: + case 5: + i.status = constant.land + const lastSuccessCount = engine.getVariable(constant.successCount) + addSuccessCount(engine) + engine.setTimeMovement(constant.moveDownMovement, 500) + if (lastSuccessCount === 10 || lastSuccessCount === 15) { + engine.setTimeMovement(constant.lightningMovement, 150) + } + instance.y = blockY + line.y = blockY + line.x = i.x - i.calWidth + line.collisionX = line.x + i.width + // 作弊检测 超出左边或右边1/3 + const cheatWidth = i.width * 0.3 + if (i.x > engine.width - (cheatWidth * 2) + || i.x < -cheatWidth) { + engine.setVariable(constant.hardMode, true) + } + if (collision === 5) { + instance.perfect = true + addScore(engine, true) + engine.playAudio('drop-perfect') + } else { + addScore(engine) + engine.playAudio('drop') + } + break + default: + break + } + break + case constant.land: + engine.getTimeMovement( + constant.moveDownMovement, + [[instance.y, instance.y + (getMoveDownValue(engine, { pixelsPerFrame: s => s / 2 }))]], + (value) => { + if (!instance.visible) return + instance.y = value + if (instance.y > engine.height) { + instance.visible = false + } + }, + { + name: instance.name + } + ) + instance.x += getLandBlockVelocity(engine, time) + break + case constant.rotateLeft: + case constant.rotateRight: + const isRight = i.status === constant.rotateRight + const rotateSpeed = engine.pixelsPerFrame(Math.PI * 4) + const isShouldFall = isRight ? instance.rotate > 1.3 : instance.rotate < -1.3// 75度 + const leftFix = isRight ? 1 : -1 + if (isShouldFall) { + instance.rotate += (rotateSpeed / 8) * leftFix + instance.y += engine.pixelsPerFrame(engine.height * 0.7) + instance.x += engine.pixelsPerFrame(engine.width * 0.3) * leftFix + } else { + let rotateRatio = (instance.calWidth - instance.outwardOffset) + / instance.calWidth + rotateRatio = rotateRatio > 0.5 ? rotateRatio : 0.5 + instance.rotate += rotateSpeed * rotateRatio * leftFix + const angle = instance.originOutwardAngle + instance.rotate + const rotateAxisX = isRight ? line.collisionX + instance.calWidth + : line.x + instance.calWidth + const rotateAxisY = line.y + instance.x = rotateAxisX - + (Math.cos(angle) * instance.originHypotenuse) + instance.y = rotateAxisY - + (Math.sin(angle) * instance.originHypotenuse) + } + checkBlockOut(instance, engine) + break + default: + break + } +} + +const drawSwingBlock = (instance, engine) => { + const bl = engine.getImg('blockRope') + engine.ctx.drawImage( + bl, instance.weightX - instance.calWidth + , instance.weightY + , instance.width, instance.height * 1.3 + ) + const leftX = instance.weightX - instance.calWidth + engine.debugLineY(leftX) +} + +const drawBlock = (instance, engine) => { + const { perfect } = instance + const bl = engine.getImg(perfect ? 'block-perfect' : 'block') + engine.ctx.drawImage(bl, instance.x, instance.y, instance.width, instance.height) +} + +const drawRotatedBlock = (instance, engine) => { + const { ctx } = engine + ctx.save() + ctx.translate(instance.x, instance.y) + ctx.rotate(instance.rotate) + ctx.translate(-instance.x, -instance.y) + drawBlock(instance, engine) + ctx.restore() +} + +export const blockPainter = (instance, engine) => { + const { status } = instance + switch (status) { + case constant.swing: + drawSwingBlock(instance, engine) + break + case constant.drop: + case constant.land: + drawBlock(instance, engine) + break + case constant.rotateLeft: + case constant.rotateRight: + drawRotatedBlock(instance, engine) + break + default: + break + } +} diff --git a/src/cloud.js b/src/cloud.js new file mode 100644 index 0000000..1f4c1c9 --- /dev/null +++ b/src/cloud.js @@ -0,0 +1,53 @@ +import { checkMoveDown, getMoveDownValue } from './utils' +import * as constant from './constant' + +const randomCloudImg = (instance) => { + const { count } = instance + const clouds = ['c1', 'c2', 'c3'] + const stones = ['c4', 'c5', 'c6', 'c7', 'c8'] + const randomImg = array => (array[Math.floor(Math.random() * array.length)]) + instance.imgName = count > 6 ? randomImg(stones) : randomImg(clouds) +} + +export const cloudAction = (instance, engine) => { + if (!instance.ready) { + instance.ready = true + randomCloudImg(instance) + instance.width = engine.getVariable(constant.cloudSize) + instance.height = engine.getVariable(constant.cloudSize) + const engineW = engine.width + const engineH = engine.height + const positionArr = [ + { x: engineW * 0.1, y: -engineH * 0.66 }, + { x: engineW * 0.65, y: -engineH * 0.33 }, + { x: engineW * 0.1, y: 0 }, + { x: engineW * 0.65, y: engineH * 0.33 } + ] + const position = positionArr[instance.index - 1] + instance.x = engine.utils.random(position.x, (position.x * 1.2)) + instance.originX = instance.x + instance.ax = engine.pixelsPerFrame(instance.width * engine.utils.random(0.05, 0.08) + * engine.utils.randomPositiveNegative()) + instance.y = engine.utils.random(position.y, (position.y * 1.2)) + } + instance.x += instance.ax + if (instance.x >= instance.originX + instance.width + || instance.x <= instance.originX - instance.width) { + instance.ax *= -1 + } + if (checkMoveDown(engine)) { + instance.y += getMoveDownValue(engine) * 1.2 + } + if (instance.y >= engine.height) { + instance.y = -engine.height * 0.66 + instance.count += 4 + randomCloudImg(instance) + } +} + +export const cloudPainter = (instance, engine) => { + const { ctx } = engine + const cloud = engine.getImg(instance.imgName) + ctx.drawImage(cloud, instance.x, instance.y, instance.width, instance.height) +} + diff --git a/src/constant.js b/src/constant.js new file mode 100644 index 0000000..2b5ebf5 --- /dev/null +++ b/src/constant.js @@ -0,0 +1,42 @@ +export const gameStartNow = 'GAME_START_NOW' +export const gameUserOption = 'GAME_USER_OPTION' +export const hardMode = 'HARD_MODE' + +export const successCount = 'SUCCESS_COUNT' +export const failedCount = 'FAILED_COUNT' +export const perfectCount = 'PERFECT_COUNT' +export const gameScore = 'GAME_SCORE' + +export const hookDown = 'HOOK_DOWN' +export const hookUp = 'HOOK_UP' +export const hookNormal = 'HOOK_NORMAL' + +export const bgImgOffset = 'BACKGROUND_IMG_OFFSET_HEIGHT' +export const lineInitialOffset = 'LINE_INITIAL_OFFSET' +export const bgLinearGradientOffset = 'BACKGROUND_LINEAR_GRADIENT_OFFSET_HEIGHT' + + +export const blockCount = 'BLOCK_COUNT' +export const blockWidth = 'BLOCK_WIDTH' +export const blockHeight = 'BLOCK_HEIGHT' +export const cloudSize = 'CLOUD_SIZE' +export const ropeHeight = 'ROPE_HEIGHT' +export const flightCount = 'FLIGHT_COUNT' +export const flightLayer = 'FLIGHT_LAYER' + +export const rotateRight = 'ROTATE_RIGHT' +export const rotateLeft = 'ROTATE_LEFT' +export const swing = 'SWING' +export const beforeDrop = 'BEFORE_DROP' +export const drop = 'DROP' +export const land = 'LAND' +export const out = 'OUT' + +export const initialAngle = 'INITIAL_ANGLE' + +export const bgInitMovement = 'BG_INIT_MOVEMENT' +export const hookDownMovement = 'HOOK_DOWN_MOVEMENT' +export const hookUpMovement = 'HOOK_UP_MOVEMENT' +export const lightningMovement = 'LIGHTNING_MOVEMENT' +export const tutorialMovement = 'TUTORIAL_MOVEMENT' +export const moveDownMovement = 'MOVE_DOWN_MOVEMENT' diff --git a/src/flight.js b/src/flight.js new file mode 100644 index 0000000..9205e47 --- /dev/null +++ b/src/flight.js @@ -0,0 +1,82 @@ +import { Instance } from 'cooljs' +import * as constant from './constant' + +const getActionConfig = (engine, type) => { + const { + width, height, utils + } = engine + const { random } = utils + const size = engine.getVariable(constant.cloudSize) + const actionTypes = { + bottomToTop: { + x: width * random(0.3, 0.7), + y: height, + vx: 0, + vy: engine.pixelsPerFrame(height) * 0.7 * -1 + }, + leftToRight: { + x: size * -1, + y: height * random(0.3, 0.6), + vx: engine.pixelsPerFrame(width) * 0.4, + vy: engine.pixelsPerFrame(height) * 0.1 * -1 + }, + rightToLeft: { + x: width, + y: height * random(0.2, 0.5), + vx: engine.pixelsPerFrame(width) * 0.4 * -1, + vy: engine.pixelsPerFrame(height) * 0.1 + }, + rightTopToLeft: { + x: width, + y: 0, + vx: engine.pixelsPerFrame(width) * 0.6 * -1, + vy: engine.pixelsPerFrame(height) * 0.5 + } + } + return actionTypes[type] +} + + +export const flightAction = (instance, engine) => { + const { visible, ready, type } = instance + if (!visible) return + const size = engine.getVariable(constant.cloudSize) + if (!ready) { + const action = getActionConfig(engine, type) + instance.ready = true + instance.width = size + instance.height = size + instance.x = action.x + instance.y = action.y + instance.vx = action.vx + instance.vy = action.vy + } + instance.x += instance.vx + instance.y += instance.vy + if (instance.y + size < 0 + || instance.y > engine.height + || instance.x + size < 0 + || instance.x > engine.width) { + instance.visible = false + } +} + +export const flightPainter = (instance, engine) => { + const { ctx } = engine + const flight = engine.getImg(instance.imgName) + ctx.drawImage(flight, instance.x, instance.y, instance.width, instance.height) +} + +export const addFlight = (engine, number, type) => { + const flightCount = engine.getVariable(constant.flightCount) + if (flightCount === number) return + const flight = new Instance({ + name: `flight_${number}`, + action: flightAction, + painter: flightPainter + }) + flight.imgName = `f${number}` + flight.type = type + engine.addInstance(flight, constant.flightLayer) + engine.setVariable(constant.flightCount, number) +} diff --git a/src/hook.js b/src/hook.js new file mode 100644 index 0000000..a182cf3 --- /dev/null +++ b/src/hook.js @@ -0,0 +1,54 @@ +import { getSwingBlockVelocity } from './utils' +import * as constant from './constant' + +export const hookAction = (instance, engine, time) => { + const ropeHeight = engine.getVariable(constant.ropeHeight) + if (!instance.ready) { + instance.x = engine.width / 2 + instance.y = ropeHeight * -1.5 + instance.ready = true + } + engine.getTimeMovement( + constant.hookUpMovement, + [[instance.y, instance.y - ropeHeight]], + (value) => { + instance.y = value + }, + { + after: () => { + instance.y = ropeHeight * -1.5 + } + } + ) + engine.getTimeMovement( + constant.hookDownMovement, + [[instance.y, instance.y + ropeHeight]], + (value) => { + instance.y = value + }, + { + name: 'hook' + } + ) + const initialAngle = engine.getVariable(constant.initialAngle) + instance.angle = initialAngle * + getSwingBlockVelocity(engine, time) + instance.weightX = instance.x + + (Math.sin(instance.angle) * ropeHeight) + instance.weightY = instance.y + + (Math.cos(instance.angle) * ropeHeight) +} + +export const hookPainter = (instance, engine) => { + const { ctx } = engine + const ropeHeight = engine.getVariable(constant.ropeHeight) + const ropeWidth = ropeHeight * 0.1 + const hook = engine.getImg('hook') + ctx.save() + ctx.translate(instance.x, instance.y) + ctx.rotate((Math.PI * 2) - instance.angle) + ctx.translate(-instance.x, -instance.y) + engine.ctx.drawImage(hook, instance.x - (ropeWidth / 2), instance.y, ropeWidth, ropeHeight + 5) + ctx.restore() +} + diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..7f49cb4 --- /dev/null +++ b/src/index.js @@ -0,0 +1,119 @@ +import { Engine, Instance } from 'cooljs' +import { touchEventHandler } from './utils' +import { background } from './background' +import { lineAction, linePainter } from './line' +import { cloudAction, cloudPainter } from './cloud' +import { hookAction, hookPainter } from './hook' +import { tutorialAction, tutorialPainter } from './tutorial' +import * as constant from './constant' +import { startAnimate, endAnimate } from './animateFuncs' + +window.TowerGame = (option = {}) => { + const { + width, + height, + canvasId, + soundOn + } = option + const game = new Engine({ + canvasId, + highResolution: true, + width, + height, + soundOn + }) + const pathGenerator = (path) => `./assets/${path}` + + game.addImg('background', pathGenerator('background.png')) + game.addImg('hook', pathGenerator('hook.png')) + game.addImg('blockRope', pathGenerator('block-rope.png')) + game.addImg('block', pathGenerator('block.png')) + game.addImg('block-perfect', pathGenerator('block-perfect.png')) + for (let i = 1; i <= 8; i += 1) { + game.addImg(`c${i}`, pathGenerator(`c${i}.png`)) + } + game.addLayer(constant.flightLayer) + for (let i = 1; i <= 7; i += 1) { + game.addImg(`f${i}`, pathGenerator(`f${i}.png`)) + } + game.swapLayer(0, 1) + game.addImg('tutorial', pathGenerator('tutorial.png')) + game.addImg('tutorial-arrow', pathGenerator('tutorial-arrow.png')) + game.addImg('heart', pathGenerator('heart.png')) + game.addImg('score', pathGenerator('score.png')) + game.addAudio('drop-perfect', pathGenerator('drop-perfect.mp3')) + game.addAudio('drop', pathGenerator('drop.mp3')) + game.addAudio('game-over', pathGenerator('game-over.mp3')) + game.addAudio('rotate', pathGenerator('rotate.mp3')) + game.addAudio('bgm', pathGenerator('bgm.mp3')) + game.setVariable(constant.blockWidth, game.width * 0.25) + game.setVariable(constant.blockHeight, game.getVariable(constant.blockWidth) * 0.71) + game.setVariable(constant.cloudSize, game.width * 0.3) + game.setVariable(constant.ropeHeight, game.height * 0.4) + game.setVariable(constant.blockCount, 0) + game.setVariable(constant.successCount, 0) + game.setVariable(constant.failedCount, 0) + game.setVariable(constant.gameScore, 0) + game.setVariable(constant.hardMode, false) + game.setVariable(constant.gameUserOption, option) + for (let i = 1; i <= 4; i += 1) { + const cloud = new Instance({ + name: `cloud_${i}`, + action: cloudAction, + painter: cloudPainter + }) + cloud.index = i + cloud.count = 5 - i + game.addInstance(cloud) + } + const line = new Instance({ + name: 'line', + action: lineAction, + painter: linePainter + }) + game.addInstance(line) + const hook = new Instance({ + name: 'hook', + action: hookAction, + painter: hookPainter + }) + game.addInstance(hook) + + game.startAnimate = startAnimate + game.endAnimate = endAnimate + game.paintUnderInstance = background + game.addKeyDownListener('enter', () => { + if (game.debug) game.togglePaused() + }) + game.touchStartListener = () => { + touchEventHandler(game) + } + + game.playBgm = () => { + game.playAudio('bgm', true) + } + + game.pauseBgm = () => { + game.pauseAudio('bgm') + } + + game.start = () => { + const tutorial = new Instance({ + name: 'tutorial', + action: tutorialAction, + painter: tutorialPainter + }) + game.addInstance(tutorial) + const tutorialArrow = new Instance({ + name: 'tutorial-arrow', + action: tutorialAction, + painter: tutorialPainter + }) + game.addInstance(tutorialArrow) + game.setTimeMovement(constant.bgInitMovement, 500) + game.setTimeMovement(constant.tutorialMovement, 500) + game.setVariable(constant.gameStartNow, true) + } + + return game +} diff --git a/src/line.js b/src/line.js new file mode 100644 index 0000000..7ca1faf --- /dev/null +++ b/src/line.js @@ -0,0 +1,40 @@ +import { getMoveDownValue, getLandBlockVelocity } from './utils' +import * as constant from './constant' + +export const lineAction = (instance, engine, time) => { + const i = instance + if (!i.ready) { + i.y = engine.getVariable(constant.lineInitialOffset) + i.ready = true + i.collisionX = engine.width - engine.getVariable(constant.blockWidth) + } + engine.getTimeMovement( + constant.moveDownMovement, + [[instance.y, instance.y + (getMoveDownValue(engine, { pixelsPerFrame: s => s / 2 }))]], + (value) => { + instance.y = value + }, + { + name: 'line' + } + ) + const landBlockVelocity = getLandBlockVelocity(engine, time) + instance.x += landBlockVelocity + instance.collisionX += landBlockVelocity +} + +export const linePainter = (instance, engine) => { + const { ctx, debug } = engine + if (!debug) { + return + } + ctx.save() + ctx.beginPath() + ctx.strokeStyle = 'red' + ctx.moveTo(instance.x, instance.y) + ctx.lineTo(instance.collisionX, instance.y) + ctx.lineWidth = 1 + ctx.stroke() + ctx.restore() +} + diff --git a/src/tutorial.js b/src/tutorial.js new file mode 100644 index 0000000..ad59398 --- /dev/null +++ b/src/tutorial.js @@ -0,0 +1,35 @@ +import { getHookStatus } from './utils' +import * as constant from './constant' + +export const tutorialAction = (instance, engine, time) => { + const { width, height } = engine + const { name } = instance + if (!instance.ready) { + instance.ready = true + const tutorialWidth = width * 0.2 + instance.updateWidth(tutorialWidth) + instance.height = tutorialWidth * 0.46 + instance.x = engine.calWidth - instance.calWidth + instance.y = height * 0.45 + if (name !== 'tutorial') { + instance.y += instance.height * 1.2 + } + } + if (name !== 'tutorial') { + instance.y += Math.cos(time / 200) * instance.height * 0.01 + } +} + +export const tutorialPainter = (instance, engine) => { + if (engine.checkTimeMovement(constant.tutorialMovement)) { + return + } + if (getHookStatus(engine) !== constant.hookNormal) { + return + } + const { ctx } = engine + const { name } = instance + const t = engine.getImg(name) + ctx.drawImage(t, instance.x, instance.y, instance.width, instance.height) +} + diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..f17a7f4 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,177 @@ +import * as constant from './constant' + +export const checkMoveDown = engine => + (engine.checkTimeMovement(constant.moveDownMovement)) + +export const getMoveDownValue = (engine, store) => { + const pixelsPerFrame = store ? store.pixelsPerFrame : engine.pixelsPerFrame.bind(engine) + const successCount = engine.getVariable(constant.successCount) + const calHeight = engine.getVariable(constant.blockHeight) * 2 + if (successCount <= 4) { + return pixelsPerFrame(calHeight * 1.25) + } + return pixelsPerFrame(calHeight) +} + +export const getAngleBase = (engine) => { + const successCount = engine.getVariable(constant.successCount) + const gameScore = engine.getVariable(constant.gameScore) + const { hookAngle } = engine.getVariable(constant.gameUserOption) + if (hookAngle) { + return hookAngle(successCount, gameScore) + } + if (engine.getVariable(constant.hardMode)) { + return 90 + } + switch (true) { + case successCount < 10: + return 30 + case successCount < 20: + return 60 + default: + return 80 + } +} + +export const getSwingBlockVelocity = (engine, time) => { + const successCount = engine.getVariable(constant.successCount) + const gameScore = engine.getVariable(constant.gameScore) + const { hookSpeed } = engine.getVariable(constant.gameUserOption) + if (hookSpeed) { + return hookSpeed(successCount, gameScore) + } + let hard + switch (true) { + case successCount < 1: + hard = 0 + break + case successCount < 10: + hard = 1 + break + case successCount < 20: + hard = 0.8 + break + case successCount < 30: + hard = 0.7 + break + default: + hard = 0.74 + break + } + if (engine.getVariable(constant.hardMode)) { + hard = 1.1 + } + return Math.sin(time / (200 / hard)) +} + +export const getLandBlockVelocity = (engine, time) => { + const successCount = engine.getVariable(constant.successCount) + const gameScore = engine.getVariable(constant.gameScore) + const { landBlockSpeed } = engine.getVariable(constant.gameUserOption) + if (landBlockSpeed) { + return landBlockSpeed(successCount, gameScore) + } + const { width } = engine + let hard + switch (true) { + case successCount < 5: + hard = 0 + break + case successCount < 13: + hard = 0.001 + break + case successCount < 23: + hard = 0.002 + break + default: + hard = 0.003 + break + } + return Math.cos(time / 200) * hard * width +} + +export const getHookStatus = (engine) => { + if (engine.checkTimeMovement(constant.hookDownMovement)) { + return constant.hookDown + } + if (engine.checkTimeMovement(constant.hookUpMovement)) { + return constant.hookUp + } + return constant.hookNormal +} + +export const touchEventHandler = (engine) => { + if (!engine.getVariable(constant.gameStartNow)) return + if (engine.debug && engine.paused) { + return + } + if (getHookStatus(engine) !== constant.hookNormal) { + return + } + engine.removeInstance('tutorial') + engine.removeInstance('tutorial-arrow') + const b = engine.getInstance(`block_${engine.getVariable(constant.blockCount)}`) + if (b && b.status === constant.swing) { + engine.setTimeMovement(constant.hookUpMovement, 500) + b.status = constant.beforeDrop + } +} + +export const addSuccessCount = (engine) => { + const { setGameSuccess } = engine.getVariable(constant.gameUserOption) + const lastSuccessCount = engine.getVariable(constant.successCount) + const success = lastSuccessCount + 1 + engine.setVariable(constant.successCount, success) + if (engine.getVariable(constant.hardMode)) { + engine.setVariable(constant.ropeHeight, engine.height * engine.utils.random(0.35, 0.55)) + } + if (setGameSuccess) setGameSuccess(success) +} + +export const addFailedCount = (engine) => { + const { setGameFailed } = engine.getVariable(constant.gameUserOption) + const lastFailedCount = engine.getVariable(constant.failedCount) + const failed = lastFailedCount + 1 + engine.setVariable(constant.failedCount, failed) + engine.setVariable(constant.perfectCount, 0) + if (setGameFailed) setGameFailed(failed) + if (failed >= 3) { + engine.pauseAudio('bgm') + engine.playAudio('game-over') + engine.setVariable(constant.gameStartNow, false) + } +} + +export const addScore = (engine, isPerfect) => { + const { setGameScore, successScore, perfectScore } = engine.getVariable(constant.gameUserOption) + const lastPerfectCount = engine.getVariable(constant.perfectCount, 0) + const lastGameScore = engine.getVariable(constant.gameScore) + const perfect = isPerfect ? lastPerfectCount + 1 : 0 + const score = lastGameScore + (successScore || 25) + ((perfectScore || 25) * perfect) + engine.setVariable(constant.gameScore, score) + engine.setVariable(constant.perfectCount, perfect) + if (setGameScore) setGameScore(score) +} + +export const drawYellowString = (engine, option) => { + const { + string, size, x, y, textAlign + } = option + const { ctx } = engine + const fontName = 'wenxue' + const fontSize = size + const lineSize = fontSize * 0.1 + ctx.save() + ctx.beginPath() + const gradient = ctx.createLinearGradient(0, 0, 0, y) + gradient.addColorStop(0, '#FAD961') + gradient.addColorStop(1, '#F76B1C') + ctx.fillStyle = gradient + ctx.lineWidth = lineSize + ctx.strokeStyle = '#FFF' + ctx.textAlign = textAlign || 'center' + ctx.font = `${fontSize}px ${fontName}` + ctx.strokeText(string, x, y) + ctx.fillText(string, x, y) + ctx.restore() +}