├── game.json ├── res ├── launch.mp3 ├── background.png ├── startbutton.png └── xuemaojiao.mp3 ├── dist ├── res │ ├── launch.mp3 │ ├── background.png │ ├── startbutton.png │ └── xuemaojiao.mp3 ├── index.html └── game.5d4643f2.js ├── src ├── base │ ├── Body.js │ ├── Resource.js │ ├── DataStore.js │ ├── Sprite.js │ └── ResourceLoader.js ├── sprite │ ├── BackGround.js │ ├── StartButton.js │ └── Score.js ├── body │ ├── Border.js │ ├── Bridge.js │ ├── Block.js │ └── Aim.js └── Director.js ├── .babelrc ├── .gitignore ├── package.json ├── project.config.json ├── index.html ├── README.md ├── App.js └── game.js /game.json: -------------------------------------------------------------------------------- 1 | { 2 | "deviceOrientation": "portrait" 3 | } 4 | -------------------------------------------------------------------------------- /res/launch.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/res/launch.mp3 -------------------------------------------------------------------------------- /dist/res/launch.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/dist/res/launch.mp3 -------------------------------------------------------------------------------- /res/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/res/background.png -------------------------------------------------------------------------------- /res/startbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/res/startbutton.png -------------------------------------------------------------------------------- /res/xuemaojiao.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/res/xuemaojiao.mp3 -------------------------------------------------------------------------------- /dist/res/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/dist/res/background.png -------------------------------------------------------------------------------- /dist/res/startbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/dist/res/startbutton.png -------------------------------------------------------------------------------- /dist/res/xuemaojiao.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cheneyweb/wxgame-elastic/HEAD/dist/res/xuemaojiao.mp3 -------------------------------------------------------------------------------- /src/base/Body.js: -------------------------------------------------------------------------------- 1 | // 物体基类 2 | export class Body { 3 | constructor(physics) { 4 | this.physics = physics 5 | } 6 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env" 4 | ], 5 | "plugins": [ 6 | "transform-class-properties", 7 | "transform-object-rest-spread" 8 | ] 9 | } -------------------------------------------------------------------------------- /src/base/Resource.js: -------------------------------------------------------------------------------- 1 | export const Resources = [ 2 | ['background', 'res/background.png'], 3 | ['startButton', 'res/startbutton.png'], 4 | ['bgm', 'res/xuemaojiao.mp3'], 5 | ['launch', 'res/launch.mp3'] 6 | ] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | #/dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | package-lock.json 8 | vendor-manifest.json 9 | vendor.dll.js 10 | .cache 11 | 12 | # Editor directories and files 13 | .idea 14 | .vscode 15 | *.suo 16 | *.ntvs* 17 | *.njsproj 18 | *.sln 19 | -------------------------------------------------------------------------------- /src/sprite/BackGround.js: -------------------------------------------------------------------------------- 1 | import { Sprite } from '../base/Sprite.js' 2 | /** 3 | * 背景类 4 | */ 5 | export class BackGround extends Sprite { 6 | constructor(physics) { 7 | const image = Sprite.getImage('background') 8 | super( 9 | physics.ctx, image, 10 | (physics.canvas.width - image.width) / 2, 11 | (physics.canvas.height - image.height) / 2.5, 12 | image.width, image.height, 13 | 0, 14 | 0, 15 | image.width, image.height 16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /src/sprite/StartButton.js: -------------------------------------------------------------------------------- 1 | import { Sprite } from '../base/Sprite.js' 2 | /** 3 | * 开始按钮类 4 | */ 5 | export class StartButton extends Sprite { 6 | constructor(physics) { 7 | const image = Sprite.getImage('startButton') 8 | super( 9 | physics.ctx, image, 10 | (physics.canvas.width - image.width) / 2, 11 | (physics.canvas.height - image.height) / 2.5, 12 | image.width, image.height, 13 | 0, 14 | 0, 15 | image.width, image.height 16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /src/sprite/Score.js: -------------------------------------------------------------------------------- 1 | import { DataStore } from '../base/DataStore.js' 2 | /** 3 | * 计分器类 4 | */ 5 | export class Score { 6 | constructor(physics) { 7 | this.ctx = physics.ctx 8 | // 数据管理 9 | this.dataStore = DataStore.getInstance() 10 | this.dataStore.scoreCount = 0 11 | } 12 | 13 | // 绘制 14 | draw() { 15 | this.ctx.font = '25px Arial' 16 | this.ctx.fillStyle = '#464444' 17 | this.ctx.fillText(`分数 ${this.dataStore.scoreCount}`, 50, 20) 18 | } 19 | // 加分 20 | static increase() { 21 | DataStore.getInstance().scoreCount += 1 22 | } 23 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wxgame-elastic", 3 | "version": "1.0.0", 4 | "description": "微信小游戏-弹一弾", 5 | "main": "index.html", 6 | "scripts": { 7 | "dev": "parcel index.html", 8 | "build": "parcel build index.html --public-url / --no-source-maps", 9 | "build-github": "parcel build index.html --public-url /wxgame-elastic/dist/ --no-source-maps" 10 | }, 11 | "author": "cheneyxu", 12 | "license": "ISC", 13 | "dependencies": {}, 14 | "devDependencies": { 15 | "babel-plugin-transform-class-properties": "^6.24.1", 16 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 17 | "babel-preset-env": "^1.7.0", 18 | "parcel-bundler": "^1.9.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": false, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "game", 14 | "libVersion": "2.1.1", 15 | "appid": "touristappid", 16 | "projectname": "elastic", 17 | "isGameTourist": true, 18 | "condition": { 19 | "search": { 20 | "current": -1, 21 | "list": [] 22 | }, 23 | "conversation": { 24 | "current": -1, 25 | "list": [] 26 | }, 27 | "plugin": { 28 | "current": -1, 29 | "list": [] 30 | }, 31 | "game": { 32 | "list": [], 33 | "current": -1 34 | }, 35 | "miniprogram": { 36 | "current": -1, 37 | "list": [] 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/base/DataStore.js: -------------------------------------------------------------------------------- 1 | // 数据管理 2 | export class DataStore { 3 | // 单例 4 | static getInstance() { 5 | if (!DataStore.instance) { 6 | DataStore.instance = new DataStore() 7 | } 8 | return DataStore.instance 9 | } 10 | // 构造存储容器 11 | constructor() { 12 | this.map = new Map() 13 | this.res = null // 游戏资源 14 | this.isGameOver = false // 游戏进度标识 15 | this.scoreCount = 0 // 游戏分数 16 | } 17 | // 存入 18 | put(key, value) { 19 | // 如果传入的参数是函数,则new function 20 | if (typeof value === 'function') { 21 | value = new value() 22 | } 23 | this.map.set(key, value) 24 | // 可链式使用 25 | return this 26 | } 27 | // 取出 28 | get(key) { 29 | return this.map.get(key) 30 | } 31 | //销毁 32 | destroy() { 33 | for (let value of this.map.values()) { 34 | value = null 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/base/Sprite.js: -------------------------------------------------------------------------------- 1 | import { DataStore } from './DataStore.js' 2 | export class Sprite { 3 | constructor(ctx, img, x = 0, y = 0, w = 0, h = 0, srcX = 0, srcY = 0, srcW = 0, srcH = 0, ) { 4 | this.ctx = ctx 5 | this.img = img 6 | this.srcX = srcX 7 | this.srcY = srcY 8 | this.srcW = srcW 9 | this.srcH = srcH 10 | this.x = x 11 | this.y = y 12 | this.w = w 13 | this.h = h 14 | } 15 | 16 | /** 17 | * 绘制图片 18 | * img 传入Image对象 19 | * srcX 要剪裁的起始X坐标 20 | * srcY 要剪裁的起始Y坐标 21 | * srcW 剪裁的宽度 22 | * srcH 剪裁的高度 23 | * x 放置的x坐标 24 | * y 放置的y坐标 25 | * w 要使用的宽度 26 | * h 要使用的高度 27 | */ 28 | draw(img = this.img, 29 | x = this.x, y = this.y, w = this.w, h = this.h, 30 | srcX = this.srcX, srcY = this.srcY, srcW = this.srcW, srcH = this.srcH) { 31 | this.ctx.drawImage(img, srcX, srcY, srcW, srcH, x, y, w, h) 32 | } 33 | 34 | static getImage(key) { 35 | return DataStore.getInstance().res.get(key) 36 | } 37 | } -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | 微信小游戏-弹一弾 -------------------------------------------------------------------------------- /src/base/ResourceLoader.js: -------------------------------------------------------------------------------- 1 | //资源文件加载器,确保在图片资源加载完成后才渲染 2 | import { Resources } from './Resource.js' 3 | 4 | export class ResourceLoader { 5 | constructor() { 6 | this.imageCount = 0 7 | this.audioCount = 0 8 | //导入资源 9 | this.map = new Map(Resources) 10 | for (let [key, src] of this.map) { 11 | let res = null 12 | if (src.split('.')[1] == 'png' || src.split('.')[1] == 'jpg') { 13 | this.imageCount++ 14 | // H5创建image的API 15 | res = new Image() 16 | // 微信创建image的API 17 | // res = wx.createImage() 18 | res.src = src 19 | } else { 20 | this.audioCount++ 21 | // H5创建audio的API 22 | res = new Audio() 23 | // 微信创建audio的API 24 | // res = wx.createInnerAudioContext() 25 | res.src = src 26 | } 27 | this.map.set(key, res) 28 | } 29 | } 30 | 31 | // 加载完成回调 32 | onload(cb) { 33 | let loadCount = 0 34 | for (let res of this.map.values()) { 35 | // 使this指向当前的ResourceLoader 36 | res.onload = () => { 37 | loadCount++ 38 | if (loadCount >= this.imageCount) { 39 | cb(this.map) 40 | } 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/body/Border.js: -------------------------------------------------------------------------------- 1 | // 边界 2 | import { Body } from '../base/Body.js' 3 | 4 | export class Border extends Body { 5 | constructor(physics) { 6 | super(physics) 7 | } 8 | 9 | draw() { 10 | const physics = this.physics 11 | let bottomHeight = 10 12 | let leftWidth = 10 13 | const borderBottom = physics.Matter.Bodies.rectangle( 14 | physics.canvas.width / 2, physics.canvas.height - bottomHeight / 2, 15 | physics.canvas.width - leftWidth * 2, bottomHeight, { 16 | isStatic: true, 17 | render: { 18 | visible: true 19 | } 20 | }) 21 | const borderLeft = physics.Matter.Bodies.rectangle( 22 | leftWidth / 2, physics.canvas.height / 2, 23 | leftWidth, physics.canvas.height, { 24 | isStatic: true, 25 | render: { 26 | visible: true 27 | } 28 | }) 29 | const borderRight = physics.Matter.Bodies.rectangle( 30 | physics.canvas.width - leftWidth / 2, physics.canvas.height / 2, 31 | leftWidth, physics.canvas.height, { 32 | isStatic: true, 33 | render: { 34 | visible: true 35 | } 36 | }) 37 | physics.Matter.World.add(physics.engine.world, [borderBottom, borderLeft, borderRight]) 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 微信小游戏-弹一弾 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 41 | 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wxgame-elastic 2 | **微信小游戏-弹一弾,纯Canvas原生实现,同时兼容微信小游戏和H5网页模式,引用Matter物理引擎,精简小巧,体积不超过1MB** 3 | 4 | ## 演示 5 | ![elastic-demo.gif](https://upload-images.jianshu.io/upload_images/5173617-bfdc01eefe371fa3.gif?imageMogr2/auto-orient/strip) 6 | 7 | >H5模式演示版本:[https://cheneyweb.github.io/wxgame-elastic/dist/index.html](https://cheneyweb.github.io/wxgame-elastic/dist/index.html) 8 | 9 | >H5模式二维码,手机扫码体验(微信扫码,浏览器扫码等都可以) 10 | 11 | ![elastic-qrcode.png](https://upload-images.jianshu.io/upload_images/5173617-ceda6855b90f3b5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 12 | 13 | >微信小游戏模式演示版本:需要打开微信开发者工具导入工程目录 14 | 15 | ## 工程结构 16 | 17 | ```js 18 | ├── App.js 弹一弾游戏入口 19 | ├── game.js 微信小游戏入口 20 | ├── game.json 21 | ├── project.config.json 22 | ├── res 资源集合 23 | │   ├── background.png 24 | │   ├── launch.mp3 25 | │   ├── startbutton.png 26 | │   └── xuemaojiao.mp3 27 | └── src 28 | ├── Director.js 导演 29 | ├── base 精简版游戏引擎 30 | │   ├── Body.js 物理物体元素基类 31 | │   ├── DataStore.js 全局状态管理类 32 | │   ├── Resource.js 统一资源定义类 33 | │   ├── ResourceLoader.js 统一资源加载类 34 | │   ├── Sprite.js 普通物体渲染画笔类 35 | │   └── matter.js 物理引擎 36 | ├── body 物理物体元素 37 | │   ├── Aim.js 准星瞄准 38 | │   ├── Block.js 障碍方块 39 | │   ├── Border.js 边界墙体 40 | └── sprite 普通物体元素 41 | ├── BackGround.js 游戏背景 42 | ├── Score.js 游戏分数 43 | └── StartButton.js 开始按钮 44 | ``` 45 | 46 | ## 构建 47 | 48 | >微信小游戏模式 49 | 50 | *说明:使用微信开发者工具打开wxgame-elastic目录即可,以下9个文件/目录可移除以减小体积* 51 | 52 | ```sh 53 | .cache 54 | dist 55 | node_modules 56 | .babelrc 57 | .gitignore 58 | index.html 59 | package.json 60 | package-lock.json 61 | README.md 62 | ``` 63 | 64 | >H5网页游戏模式 65 | 66 | *说明:执行以下构建命令后,启动 Chrome 访问 localhost:1234 即可进行游戏* 67 | 68 | ```sh 69 | cd wxgame-elastic 70 | npm run build 71 | cp -r res dist 72 | npm run dev 73 | ``` 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import { ResourceLoader } from './src/base/ResourceLoader.js' 2 | import { DataStore } from './src/base/DataStore.js' 3 | import { Director } from './src/Director.js' 4 | 5 | /** 6 | * 游戏入口 7 | */ 8 | export class App { 9 | constructor(canvas, options) { 10 | this.canvas = canvas // 画布 11 | this.physics = { ...options, ctx: this.canvas.getContext('2d') } // 物理引擎 12 | this.director = new Director(this.physics) // 导演 13 | this.dataStore = DataStore.getInstance() 14 | // 资源加载 15 | new ResourceLoader().onload(res => { 16 | // 持久化资源 17 | this.dataStore.res = res 18 | // 加载精灵 19 | this.director.spriteLoad(res) 20 | // 运行游戏 21 | this.run() 22 | }) 23 | } 24 | 25 | /** 26 | * 运行游戏 27 | */ 28 | run() { 29 | // 注册事件 30 | this.registerEvent() 31 | // 物理渲染 32 | this.director.physicsDirect() 33 | // 精灵渲染 34 | this.director.spriteDirect() 35 | // 音乐播放 36 | this.dataStore.res.get('bgm').autoplay = true 37 | } 38 | 39 | /** 40 | * 重新加载游戏 41 | */ 42 | reload() { 43 | // 物理渲染 44 | this.director.physicsDirect(true) 45 | // 精灵渲染 46 | this.director.spriteDirect(true) 47 | } 48 | 49 | /** 50 | * 注册事件 51 | */ 52 | registerEvent() { 53 | // 移动设备触摸事件,使用=>使this指向Main类 54 | this.canvas.addEventListener('touchstart', e => { 55 | // 屏蔽事件冒泡 56 | e.preventDefault() 57 | // 如果游戏是结束状态,则重新开始 58 | if (this.dataStore.isGameOver) { 59 | // 重新初始化 60 | this.dataStore.isGameOver = false 61 | this.reload() 62 | } 63 | }) 64 | // PC设备点击事件 65 | this.canvas.addEventListener('mousedown', e => { 66 | // 屏蔽事件冒泡 67 | e.preventDefault() 68 | // 如果游戏是结束状态,则重新开始 69 | if (this.dataStore.isGameOver) { 70 | // 重新初始化 71 | this.dataStore.isGameOver = false 72 | this.reload() 73 | } 74 | }) 75 | } 76 | } -------------------------------------------------------------------------------- /src/body/Bridge.js: -------------------------------------------------------------------------------- 1 | import { Body } from '../base/Body.js' 2 | 3 | /** 4 | * 桥梁 5 | */ 6 | export class Bridge extends Body { 7 | constructor(physics) { 8 | super(physics) 9 | } 10 | 11 | draw() { 12 | const physics = this.physics 13 | // add bodies 14 | var group = physics.Matter.Body.nextGroup(true); 15 | // 桥梁主体 16 | var bridge = physics.Matter.Composites.stack(160, 290, 12, 1, 0, 0, function (x, y) { 17 | return physics.Matter.Bodies.rectangle(x - 20, y, 53, 20, { 18 | collisionFilter: { group: group }, 19 | chamfer: 5, 20 | density: 0.005, 21 | frictionAir: 0.05, 22 | render: { 23 | fillStyle: '#575375' 24 | } 25 | }); 26 | }); 27 | 28 | physics.Matter.Composites.chain(bridge, 0.3, 0, -0.3, 0, { 29 | stiffness: 1, 30 | length: 0, 31 | render: { 32 | visible: false 33 | } 34 | }); 35 | 36 | // var stack = physics.Matter.Composites.stack(250, 50, 6, 3, 0, 0, function (x, y) { 37 | // return physics.Matter.Bodies.rectangle(x, y, 50, 50, physics.Matter.Common.random(20, 40)); 38 | // }); 39 | 40 | physics.Matter.World.add(physics.engine.world, [ 41 | bridge, 42 | // stack, 43 | // physics.Matter.Bodies.rectangle(30, 490, 220, 380, { 44 | // isStatic: true, 45 | // chamfer: { radius: 20 } 46 | // }), 47 | // physics.Matter.Bodies.rectangle(770, 490, 220, 380, { 48 | // isStatic: true, 49 | // chamfer: { radius: 20 } 50 | // }), 51 | physics.Matter.Constraint.create({ 52 | pointA: { x: 0, y: 400 }, 53 | bodyB: bridge.bodies[0], 54 | pointB: { x: -25, y: 0 }, 55 | length: 2, 56 | stiffness: 0.9 57 | }), 58 | physics.Matter.Constraint.create({ 59 | pointA: { x: this.physics.canvas.width, y: 400 }, 60 | bodyB: bridge.bodies[bridge.bodies.length - 1], 61 | pointB: { x: 25, y: 0 }, 62 | length: 2, 63 | stiffness: 0.9 64 | }) 65 | ]); 66 | } 67 | } -------------------------------------------------------------------------------- /src/Director.js: -------------------------------------------------------------------------------- 1 | // 精灵对象 2 | import { BackGround } from './sprite/BackGround.js' 3 | import { StartButton } from './sprite/StartButton.js' 4 | import { Score } from './sprite/Score.js' 5 | // 物理引擎绘制对象 6 | import { Block } from './body/Block.js' 7 | import { Border } from './body/Border.js' 8 | import { Bridge } from './body/Bridge.js' 9 | import { Aim } from './body/Aim.js' 10 | // 数据管理 11 | import { DataStore } from './base/DataStore.js' 12 | 13 | /** 14 | * 导演类,控制游戏的逻辑 15 | */ 16 | export class Director { 17 | constructor(physics) { 18 | this.physics = physics 19 | this.dataStore = DataStore.getInstance() 20 | } 21 | // 加载精灵对象 22 | spriteLoad() { 23 | this.sprite = new Map() 24 | this.sprite['score'] = new Score(this.physics) 25 | this.sprite['startButton'] = new StartButton(this.physics) 26 | this.sprite['background'] = new BackGround(this.physics) 27 | } 28 | // 逐帧绘制 29 | spriteDirect(isReload) { 30 | if(isReload){ 31 | this.dataStore.scoreCount = 0 32 | } 33 | // 绘制前先判断是否碰撞 34 | // this.check() 35 | // 游戏未结束 36 | if (!this.dataStore.isGameOver) { 37 | // 绘制游戏内容 38 | this.sprite['score'].draw() 39 | // this.sprite['background'].draw() 40 | // 自适应浏览器的帧率,提高性能 41 | this.animationHandle = requestAnimationFrame(() => this.spriteDirect()) 42 | } 43 | // 游戏结束 44 | else { 45 | // 停止物理引擎 46 | this.physics.Matter.Engine.clear(this.physics.engine) 47 | this.physics.Matter.World.clear(this.physics.engine.world) 48 | this.physics.Matter.Render.stop(this.physics.render) 49 | // 停止绘制 50 | cancelAnimationFrame(this.animationHandle) 51 | // 结束界面 52 | this.sprite['score'].draw() 53 | this.sprite['startButton'].draw() 54 | } 55 | } 56 | // 物理绘制 57 | physicsDirect(isReload) { 58 | this.physics.Matter.Render.run(this.physics.render) 59 | if (!isReload) { 60 | new Aim(this.physics).draw().event() 61 | // new Bridge(this.physics).draw() 62 | } 63 | new Block(this.physics).draw().event().upMove() 64 | new Border(this.physics).draw() 65 | } 66 | } -------------------------------------------------------------------------------- /game.js: -------------------------------------------------------------------------------- 1 | // require('./src/base/weapp-adapter.js') 2 | const Matter = require('./src/base/matter.js') 3 | import { App } from './App.js' 4 | 5 | // 同时兼容H5模式和微信小游戏模式 6 | const canvas = typeof wx == 'undefined' ? document.getElementById('app') : wx.createCanvas() 7 | // H5网页游戏模式 8 | if (typeof wx == 'undefined') { 9 | canvas.width = 375 10 | canvas.height = 667 11 | } 12 | // 微信小游戏模式 13 | else { 14 | window.Image = () => wx.createImage() 15 | window.Audio = () => wx.createInnerAudioContext() 16 | } 17 | // 初始化物理引擎 18 | const engine = Matter.Engine.create({ 19 | enableSleeping: true 20 | }) 21 | const render = Matter.Render.create({ 22 | canvas: canvas, 23 | engine: engine, 24 | options: { 25 | width: canvas.width, 26 | height: canvas.height, 27 | background: './res/background.png', // transparent 28 | wireframes: false, 29 | showAngleIndicator: false 30 | } 31 | }) 32 | Matter.Engine.run(engine) 33 | // Matter.Render.run(render) 34 | 35 | // 初始化游戏 36 | const physics = { Matter, engine, canvas, render } 37 | new App(canvas, physics) 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | // const A = { 48 | // x: 0, 49 | // y: 0 50 | // } 51 | 52 | // const B = { 53 | // x: 150, 54 | // y: 0 55 | // } 56 | 57 | // var context = canvas.getContext('2d') 58 | // context.fillStyle = 'red' 59 | 60 | // var engine = Matter.Engine.create(); 61 | 62 | // var boxA = Matter.Bodies.rectangle(A.x, A.y, 30, 30); 63 | // var boxB = Matter.Bodies.rectangle(B.x, B.y, 60, 60); 64 | // var ground = Matter.Bodies.rectangle(0, canvas.height - 60, canvas.width, 10, { isStatic: true }); 65 | 66 | // Matter.World.add(engine.world, [boxA, boxB, ground]); 67 | // setInterval(function () { 68 | // context.clearRect(0, 0, canvas.width, canvas.height) 69 | // Matter.Events.trigger(engine, 'tick', { timestamp: engine.timing.timestamp }) 70 | // Matter.Engine.update(engine, engine.timing.delta) 71 | // Matter.Events.trigger(engine, 'afterTick', { timestamp: engine.timing.timestamp }) 72 | // console.info(boxA) 73 | // context.fillRect(boxA.position.x, boxA.position.y, 30, 30) 74 | // context.fillRect(boxB.position.x, boxB.position.y, 60, 60) 75 | // context.fillRect(0, canvas.height - 60, canvas.width, 10) 76 | // // console.log('boxA', boxA.position); 77 | // // console.log('boxB', boxB.position); 78 | // }, 50) -------------------------------------------------------------------------------- /src/body/Block.js: -------------------------------------------------------------------------------- 1 | import { Body } from '../base/Body.js' 2 | import { Score } from '../sprite/Score.js' 3 | import { DataStore } from '../base/DataStore.js' 4 | /** 5 | * 方块 6 | */ 7 | export class Block extends Body { 8 | constructor(physics) { 9 | super(physics) 10 | this.blockCount = 5 11 | this.blockMap = {} 12 | this.blockHPMax = 10 13 | this.dataStore = DataStore.getInstance() 14 | } 15 | 16 | draw() { 17 | let physics = this.physics 18 | let lastBlockPositionX = 15 19 | let lastBlockPositionY = 20 20 | let blockArr = [] 21 | // 生成随机数量方块 22 | for (let i = 0; i < this.blockCount; i++) { 23 | let hp = Math.floor(Math.random() * this.blockHPMax) + 1 24 | const block = physics.Matter.Bodies.rectangle( 25 | lastBlockPositionX + Math.floor(Math.random() * 20) + 15, 26 | physics.canvas.height - lastBlockPositionY - Math.floor(Math.random() * 50), 27 | 30, 30, { 28 | isStatic: true, 29 | render: { 30 | visible: true, 31 | text: { 32 | content: hp, 33 | color: "white", 34 | size: 16, 35 | family: "Arial", 36 | } 37 | // sprite: { 38 | // texture: 'res/ball.png', 39 | // xScale: 0.1, 40 | // yScale: 0.1 41 | // } 42 | }, 43 | }) 44 | block.hp = hp 45 | lastBlockPositionX += 50 46 | blockArr.push(block) 47 | this.blockMap[block.id] = block 48 | } 49 | // 将方块集合添加进入世界 50 | physics.Matter.World.add(physics.engine.world, blockArr) 51 | return this 52 | } 53 | 54 | // 方块被碰撞 55 | event() { 56 | let physics = this.physics 57 | // 方块被碰撞时事件 58 | physics.Matter.Events.on(physics.engine, 'collisionStart', (event) => { 59 | var pairs = event.pairs 60 | for (let pair of pairs) { 61 | // 被碰撞的方块生命减到0时,销毁 62 | if (this.blockMap[pair.bodyA.id]) { 63 | this.blockMap[pair.bodyA.id].hp-- 64 | // 恢复重力 65 | this.physics.engine.world.gravity.y = 1 66 | Score.increase() 67 | pair.bodyA.render.text.content = this.blockMap[pair.bodyA.id].hp 68 | if (this.blockMap[pair.bodyA.id].hp <= 0) { 69 | physics.Matter.World.remove(physics.engine.world, this.blockMap[pair.bodyA.id]) 70 | delete this.blockMap[pair.bodyA.id] 71 | // 所有方块打完判断游戏结束 72 | // if (Object.keys(this.blockMap).length == 0) { 73 | // this.dataStore.isGameOver = true 74 | // } 75 | } 76 | } 77 | // pair.bodyB.render.fillStyle = '#333' 78 | } 79 | }) 80 | return this 81 | } 82 | 83 | // 方块向上移动 84 | upMove() { 85 | let physics = this.physics 86 | let i = 0 87 | physics.Matter.Events.on(physics.engine, 'beforeUpdate', (event) => { 88 | for (let id in this.blockMap) { 89 | // body is static so must manually update velocity for friction to work 90 | // physics.Body.setVelocity(body, { x: px - this.blockMap[id].position.x, y: 0 }) 91 | physics.Matter.Body.setPosition(this.blockMap[id], { x: this.blockMap[id].position.x, y: this.blockMap[id].position.y - 0.2 }) 92 | if (this.blockMap[id].position.y < 30) { 93 | this.dataStore.isGameOver = true 94 | this.blockMap = {} 95 | physics.Matter.Events.off(physics.engine, 'beforeUpdate') 96 | break 97 | } 98 | } 99 | // 绘制新一行方块,且方块生命值上条 100 | if (i > 0 && i % 1000 == 0) { 101 | this.blockHPMax += 10 102 | this.draw() 103 | } 104 | i++ 105 | }) 106 | } 107 | } -------------------------------------------------------------------------------- /src/body/Aim.js: -------------------------------------------------------------------------------- 1 | // 瞄准类 2 | import { Body } from '../base/Body.js' 3 | import { DataStore } from '../base/DataStore.js' 4 | 5 | export class Aim extends Body { 6 | constructor(physics) { 7 | super(physics) 8 | this.dataStore = DataStore.getInstance() 9 | 10 | this.ballRadius = 10 11 | this.baseBallX = this.physics.canvas.width / 2 12 | this.baseBallY = this.ballRadius * 2 13 | 14 | this.x = physics.canvas.width / 2 15 | this.y = physics.canvas.height / 2 16 | this.balls = [] 17 | this.ballAppends = [] 18 | this.ballCount = 7 19 | this.ballAppendCount = 20 20 | this.isRending = false 21 | this.isForce = false 22 | this.inervalMax = 100 23 | } 24 | 25 | // 覆写绘制 26 | draw() { 27 | // if (this.isRending) { 28 | // return 29 | // } 30 | // 清空场景 31 | this.physics.Matter.World.remove(this.physics.engine.world, this.balls) 32 | this.balls = [] 33 | this.physics.Matter.World.remove(this.physics.engine.world, this.ballAppends) 34 | this.ballAppends = [] 35 | // 重绘弹球 36 | this.drawBall() 37 | // 重绘制瞄准 38 | this.drawAim() 39 | return this 40 | } 41 | 42 | // 绘制瞄准 43 | drawAim() { 44 | if (this.isRending) { 45 | return 46 | } 47 | for (let i = 0; i < this.ballCount; i++) { 48 | const ball = this.physics.Matter.Bodies.circle( 49 | this.baseBallX + (this.x - this.baseBallX) * i / (this.ballCount - 1), 50 | this.baseBallY + (this.y - this.baseBallY) * i / (this.ballCount - 1), 51 | this.ballRadius, { 52 | isStatic: true, 53 | density: 0.04, 54 | friction: 0.01, 55 | frictionAir: 0.00001, 56 | restitution: 0.9, 57 | render: { 58 | visible: true, 59 | fillStyle: '#F35e66', 60 | strokeStyle: 'black' 61 | } 62 | }) 63 | this.balls.push(ball) 64 | } 65 | this.physics.Matter.World.add(this.physics.engine.world, this.balls) 66 | } 67 | 68 | drawBall() { 69 | if (!this.isForce) { 70 | return 71 | } 72 | // 设定正在绘制弹球 73 | this.isRending = true 74 | this.ballAppends = [] 75 | this.intervalCount = 0 76 | // 定时弹出球,且设定定时结束条件 77 | const interval = setInterval(() => { 78 | // 绘制弹球 79 | if (this.ballAppends.length < this.ballAppendCount) { 80 | const ballAppend = this.physics.Matter.Bodies.circle( 81 | this.baseBallX, 82 | this.baseBallY, 83 | this.ballRadius, { 84 | isStatic: false, 85 | density: 0.04, 86 | friction: 0.01, 87 | frictionAir: 0.00001, 88 | restitution: 0.9, 89 | render: { 90 | visible: true, 91 | fillStyle: '#F35e66', 92 | strokeStyle: 'black' 93 | } 94 | }) 95 | ballAppend.isBall = true 96 | this.physics.Matter.World.add(this.physics.engine.world, ballAppend) 97 | const speed = { 98 | x: (this.x - this.baseBallX) / (this.y - this.baseBallY), 99 | y: 1 100 | } 101 | // 修正速度,确保从各个角度射出小球的速度差不多,原理是根据勾股定理计算出每个小球的斜边,以全屏斜边作为比对 102 | const fixRate = Math.sqrt(Math.pow(speed.x, 2) + Math.pow(speed.y, 2)) / Math.sqrt(Math.pow(this.physics.canvas.width, 2) + Math.pow(this.physics.canvas.height, 2)) * 1000 103 | // 给小球赋予推力 104 | this.physics.Matter.Body.applyForce(ballAppend, ballAppend.position, { 105 | x: speed.x / fixRate * 0.7, 106 | y: speed.y / fixRate * 0.7 107 | }) 108 | this.ballAppends.push(ballAppend) 109 | } 110 | // 超过60%的球休眠则可以重新发射 111 | let bodies = this.physics.Matter.Composite.allBodies(this.physics.engine.world) 112 | let sleeping = bodies.filter((body) => body.isSleeping && body.isBall) 113 | // let isWorldSleeping = bodies.length === sleeping.length 114 | let isWorldSleeping = sleeping.length / this.ballAppends.length > 0.6 || this.intervalCount > this.inervalMax 115 | if (isWorldSleeping) { 116 | this.isRending = false 117 | this.isForce = false 118 | this.draw() 119 | clearInterval(interval) 120 | } 121 | this.intervalCount++ 122 | }, 100) 123 | } 124 | 125 | // 事件触发 126 | event() { 127 | let physics = this.physics 128 | // 移动设备触摸事件 129 | physics.canvas.addEventListener('touchmove', e => { 130 | this.eventHandler(e, { isForce: false }) 131 | }) 132 | physics.canvas.addEventListener('touchstart', e => { 133 | this.eventHandler(e, { isForce: false }) 134 | }) 135 | physics.canvas.addEventListener('touchend', e => { 136 | this.eventHandler(e, { isForce: true }) 137 | }) 138 | // PC设备鼠标事件 139 | physics.canvas.addEventListener('mousemove', e => { 140 | this.eventHandler(e, { isForce: false }) 141 | }) 142 | physics.canvas.addEventListener('mousedown', e => { 143 | this.eventHandler(e, { isForce: false }) 144 | }) 145 | physics.canvas.addEventListener('mouseup', e => { 146 | this.eventHandler(e, { isForce: true }) 147 | }) 148 | return this 149 | } 150 | 151 | // 事件处理 152 | eventHandler(e, options) { 153 | e.preventDefault() 154 | this.isForce = options.isForce 155 | // 刚触发弹射 156 | if (this.isForce && !this.isRending) { 157 | // 弹射一瞬间关闭重力 158 | this.physics.engine.world.gravity.y = 0 159 | this.dataStore.res.get('launch').play() 160 | } 161 | // 非弹射静止 162 | if (!this.isForce && !this.isRending) { 163 | // 移动设备触摸事件 164 | if (e.touches) { 165 | this.x = e.touches[0].clientX 166 | this.y = Math.max(50, e.touches[0].clientY) 167 | } 168 | // PC设备鼠标事件 169 | else { 170 | this.x = e.offsetX 171 | this.y = Math.max(50, e.offsetY) 172 | } 173 | } 174 | // 非动态渲染 175 | if (!this.isRending) { 176 | this.draw() 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /dist/game.5d4643f2.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,n,t){var i="function"==typeof parcelRequire&&parcelRequire,o="function"==typeof require&&require;function u(n,t){if(!r[n]){if(!e[n]){var f="function"==typeof parcelRequire&&parcelRequire;if(!t&&f)return f(n,!0);if(i)return i(n,!0);if(o&&"string"==typeof n)return o(n);var c=new Error("Cannot find module '"+n+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[n][1][r]||r};var l=r[n]=new u.Module(n);e[n][0].call(l.exports,p,l,l.exports,this)}return r[n].exports;function p(e){return u(p.resolve(e))}}u.isParcelRequire=!0,u.Module=function(e){this.id=e,this.bundle=u,this.exports={}},u.modules=e,u.cache=r,u.parent=i,u.register=function(r,n){e[r]=[function(e,r){r.exports=n},{}]};for(var f=0;f0&&r.rotateAbout(s.position,n,e.position,s.position)}},o.setVelocity=function(e,t){e.positionPrev.x=e.position.x-t.x,e.positionPrev.y=e.position.y-t.y,e.velocity.x=t.x,e.velocity.y=t.y,e.speed=r.magnitude(e.velocity)},o.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},o.translate=function(e,t){o.setPosition(e,r.add(e.position,t))},o.rotate=function(e,t,n){if(n){var i=Math.cos(t),r=Math.sin(t),s=e.position.x-n.x,a=e.position.y-n.y;o.setPosition(e,{x:n.x+(s*i-a*r),y:n.y+(s*r+a*i)}),o.setAngle(e,e.angle+t)}else o.setAngle(e,e.angle+t)},o.scale=function(e,t,n,r){var s=0,a=0;r=r||e.position;for(var d=0;d0&&(s+=u.area,a+=u.inertia),u.position.x=r.x+(u.position.x-r.x)*t,u.position.y=r.y+(u.position.y-r.y)*n,l.update(u.bounds,u.vertices,e.velocity)}e.parts.length>1&&(e.area=s,e.isStatic||(o.setMass(e,e.density*s),o.setInertia(e,a))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},o.update=function(e,t,n,o){var s=Math.pow(t*n*e.timeScale,2),a=1-e.frictionAir*n*e.timeScale,d=e.position.x-e.positionPrev.x,u=e.position.y-e.positionPrev.y;e.velocity.x=d*a*o+e.force.x/e.mass*s,e.velocity.y=u*a*o+e.force.y/e.mass*s,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.position.x+=e.velocity.x,e.position.y+=e.velocity.y,e.angularVelocity=(e.angle-e.anglePrev)*a*o+e.torque/e.inertia*s,e.anglePrev=e.angle,e.angle+=e.angularVelocity,e.speed=r.magnitude(e.velocity),e.angularSpeed=Math.abs(e.angularVelocity);for(var p=0;p0&&(m.position.x+=e.velocity.x,m.position.y+=e.velocity.y),0!==e.angularVelocity&&(i.rotate(m.vertices,e.angularVelocity,e.position),c.rotate(m.axes,e.angularVelocity),p>0&&r.rotateAbout(m.position,e.angularVelocity,e.position,m.position)),l.update(m.bounds,m.vertices,e.velocity)}},o.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var o=t.x-e.position.x,i=t.y-e.position.y;e.torque+=o*n.y-i*n.x},o._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n1?1:0;u1?1:0;m0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)}},{"../geometry/Bounds":26,"./Pair":7,"./SAT":11}],6:[function(e,t,n){var o={};t.exports=o;var i=e("./Pair"),r=e("./Detector"),s=e("../core/Common");o.create=function(e){var t={controller:o,detector:r.collisions,buckets:{},pairs:{},pairsList:[],bucketWidth:48,bucketHeight:48};return s.extend(t,e)},o.update=function(e,t,n,i){var r,s,a,l,c,d=n.world,u=e.buckets,p=!1;for(r=0;rd.bounds.max.x||m.bounds.max.yd.bounds.max.y)){var f=o._getRegion(e,m);if(!m.region||f.id!==m.region.id||i){m.region&&!i||(m.region=f);var v=o._regionUnion(f,m.region);for(s=v.startCol;s<=v.endCol;s++)for(a=v.startRow;a<=v.endRow;a++){l=u[c=o._getBucketId(s,a)];var y=s>=f.startCol&&s<=f.endCol&&a>=f.startRow&&a<=f.endRow,g=s>=m.region.startCol&&s<=m.region.endCol&&a>=m.region.startRow&&a<=m.region.endRow;!y&&g&&g&&l&&o._bucketRemoveBody(e,l,m),(m.region===f||y&&!g||i)&&(l||(l=o._createBucket(u,c)),o._bucketAddBody(e,l,m))}m.region=f,p=!0}}}p&&(e.pairsList=o._createActivePairsList(e))},o.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},o._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),i=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),s=Math.max(e.endRow,t.endRow);return o._createRegion(n,i,r,s)},o._getRegion=function(e,t){var n=t.bounds,i=Math.floor(n.min.x/e.bucketWidth),r=Math.floor(n.max.x/e.bucketWidth),s=Math.floor(n.min.y/e.bucketHeight),a=Math.floor(n.max.y/e.bucketHeight);return o._createRegion(i,r,s,a)},o._createRegion=function(e,t,n,o){return{id:e+","+t+","+n+","+o,startCol:e,endCol:t,startRow:n,endRow:o}},o._getBucketId=function(e,t){return"C"+e+"R"+t},o._createBucket=function(e,t){return e[t]=[]},o._bucketAddBody=function(e,t,n){for(var o=0;o0?o.push(n):delete e.pairs[t[i]];return o}},{"../core/Common":14,"./Detector":5,"./Pair":7}],7:[function(e,t,n){var o={};t.exports=o;var i=e("./Contact");o.create=function(e,t){var n=e.bodyA,i=e.bodyB,r=e.parentA,s=e.parentB,a={id:o.id(n,i),bodyA:n,bodyB:i,contacts:{},activeContacts:[],separation:0,isActive:!0,isSensor:n.isSensor||i.isSensor,timeCreated:t,timeUpdated:t,inverseMass:r.inverseMass+s.inverseMass,friction:Math.min(r.friction,s.friction),frictionStatic:Math.max(r.frictionStatic,s.frictionStatic),restitution:Math.max(r.restitution,s.restitution),slop:Math.max(r.slop,s.slop)};return o.update(a,e,t),a},o.update=function(e,t,n){var r=e.contacts,s=t.supports,a=e.activeContacts,l=t.parentA,c=t.parentB;if(e.collision=t,e.inverseMass=l.inverseMass+c.inverseMass,e.friction=Math.min(l.friction,c.friction),e.frictionStatic=Math.max(l.frictionStatic,c.frictionStatic),e.restitution=Math.max(l.restitution,c.restitution),e.slop=Math.max(l.slop,c.slop),a.length=0,t.collided){for(var d=0;do._pairMaxIdleLife&&c.push(s);for(s=0;sm.friction*m.frictionStatic*E*n&&(L=T,F=s.clamp(m.friction*R*n,-L,L));var O=r.cross(A,g),q=r.cross(P,g),W=b/(v.inverseMass+y.inverseMass+v.inverseInertia*O*O+y.inverseInertia*q*q);if(V*=W,F*=W,I<0&&I*I>o._restingThresh*n)S.normalImpulse=0;else{var D=S.normalImpulse;S.normalImpulse=Math.min(S.normalImpulse+V,0),V=S.normalImpulse-D}if(_*_>o._restingThreshTangent*n)S.tangentImpulse=0;else{var N=S.tangentImpulse;S.tangentImpulse=s.clamp(S.tangentImpulse+F,-L,L),F=S.tangentImpulse-N}i.x=g.x*V+x.x*F,i.y=g.y*V+x.y*F,v.isStatic||v.isSleeping||(v.positionPrev.x+=i.x*v.inverseMass,v.positionPrev.y+=i.y*v.inverseMass,v.anglePrev+=r.cross(A,i)*v.inverseInertia),y.isStatic||y.isSleeping||(y.positionPrev.x-=i.x*y.inverseMass,y.positionPrev.y-=i.y*y.inverseMass,y.anglePrev-=r.cross(P,i)*y.inverseInertia)}}}}},{"../core/Common":14,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],11:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../geometry/Vector");o.collides=function(e,t,n){var s,a,l,c,d=!1;if(n){var u=e.parent,p=t.parent,m=u.speed*u.speed+u.angularSpeed*u.angularSpeed+p.speed*p.speed+p.angularSpeed*p.angularSpeed;d=n&&n.collided&&m<.2,c=n}else c={collided:!1,bodyA:e,bodyB:t};if(n&&d){var f=c.axisBody,v=f===e?t:e,y=[f.axes[n.axisNumber]];if(l=o._overlapAxes(f.vertices,v.vertices,y),c.reused=!0,l.overlap<=0)return c.collided=!1,c}else{if((s=o._overlapAxes(e.vertices,t.vertices,e.axes)).overlap<=0)return c.collided=!1,c;if((a=o._overlapAxes(t.vertices,e.vertices,t.axes)).overlap<=0)return c.collided=!1,c;s.overlapi?i=a:a=0?s.index-1:d.length-1],c.x=i.x-u.x,c.y=i.y-u.y,l=-r.dot(n,c),a=i,i=d[(s.index+1)%d.length],c.x=i.x-u.x,c.y=i.y-u.y,(o=-r.dot(n,c))0?1:.7),t.damping=t.damping||0,t.angularStiffness=t.angularStiffness||0,t.angleA=t.bodyA?t.bodyA.angle:t.angleA,t.angleB=t.bodyB?t.bodyB.angle:t.angleB,t.plugin={};var s={visible:!0,lineWidth:2,strokeStyle:"#ffffff",type:"line",anchors:!0};return 0===t.length&&t.stiffness>.1?(s.type="pin",s.anchors=!1):t.stiffness<.9&&(s.type="spring"),t.render=c.extend(s,t.render),t},o.preSolveAll=function(e){for(var t=0;t0&&(u.position.x+=c.x,u.position.y+=c.y),0!==c.angle&&(i.rotate(u.vertices,c.angle,n.position),l.rotate(u.axes,c.angle),d>0&&r.rotateAbout(u.position,c.angle,n.position,u.position)),a.update(u.bounds,u.vertices,n.velocity)}c.angle*=o._warming,c.x*=o._warming,c.y*=o._warming}}}},{"../core/Common":14,"../core/Sleeping":22,"../geometry/Axes":25,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],13:[function(e,t,n){var o={};t.exports=o;var i=e("../geometry/Vertices"),r=e("../core/Sleeping"),s=e("../core/Mouse"),a=e("../core/Events"),l=e("../collision/Detector"),c=e("./Constraint"),d=e("../body/Composite"),u=e("../core/Common"),p=e("../geometry/Bounds");o.create=function(e,t){var n=(e?e.mouse:null)||(t?t.mouse:null);n||(e&&e.render&&e.render.canvas?n=s.create(e.render.canvas):t&&t.element?n=s.create(t.element):(n=s.create(),u.warn("MouseConstraint.create: options.mouse was undefined, options.element was undefined, may not function as expected")));var i={type:"mouseConstraint",mouse:n,element:null,body:null,constraint:c.create({label:"Mouse Constraint",pointA:n.position,pointB:{x:0,y:0},length:.01,stiffness:.1,angularStiffness:1,render:{strokeStyle:"#90EE90",lineWidth:3}}),collisionFilter:{category:1,mask:4294967295,group:0}},r=u.extend(i,t);return a.on(e,"beforeUpdate",function(){var t=d.allBodies(e.world);o.update(r,t),o._triggerEvents(r)}),r},o.update=function(e,t){var n=e.mouse,o=e.constraint,s=e.body;if(0===n.button){if(o.bodyB)r.set(o.bodyB,!1),o.pointA=n.position;else for(var c=0;c1?1:0;d0;t--){var n=Math.floor(i.random()*(t+1)),o=e[t];e[t]=e[n],e[n]=o}return e},i.choose=function(e){return e[Math.floor(i.random()*e.length)]},i.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},i.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},i.isFunction=function(e){return"function"==typeof e},i.isPlainObject=function(e){return"object"===(void 0===e?"undefined":n(e))&&e.constructor===Object},i.isString=function(e){return"[object String]"===toString.call(e)},i.clamp=function(e,t,n){return en?n:e},i.sign=function(e){return e<0?-1:1},i.now=function(){if(window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return new Date-i._nowStartTime},i.random=function(e,t){return t=void 0!==t?t:1,(e=void 0!==e?e:0)+o()*(t-e)};var o=function(){return i._seed=(9301*i._seed+49297)%233280,i._seed/233280};i.colorToNumber=function(e){return 3==(e=e.replace("#","")).length&&(e=e.charAt(0)+e.charAt(0)+e.charAt(1)+e.charAt(1)+e.charAt(2)+e.charAt(2)),parseInt(e,16)},i.logLevel=1,i.log=function(){console&&i.logLevel>0&&i.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},i.info=function(){console&&i.logLevel>0&&i.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},i.warn=function(){console&&i.logLevel>0&&i.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},i.nextId=function(){return i._nextId++},i.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;n0&&d.trigger(e,"collisionStart",{pairs:h.collisionStart}),s.preSolvePosition(h.list),i=0;i0&&d.trigger(e,"collisionActive",{pairs:h.collisionActive}),h.collisionEnd.length>0&&d.trigger(e,"collisionEnd",{pairs:h.collisionEnd}),o._bodiesClearForces(y),d.trigger(e,"afterUpdate",v),e},o.merge=function(e,t){if(m.extend(e,t),t.world){e.world=t.world,o.clear(e);for(var n=u.allBodies(e.world),i=0;ir?(i.warn("Plugin.register:",o.toString(t),"was upgraded to",o.toString(e)),o._registry[e.name]=e):n-1},o.isFor=function(e,t){var n=e.for&&o.dependencyParse(e.for);return!e.for||t.name===n.name&&o.versionSatisfies(t.version,n.range)},o.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=o.dependencies(e),r=i.topologicalSort(n),s=[],a=0;a0&&i.info(s.join(" "))}else i.warn("Plugin.use:",o.toString(e),"does not specify any dependencies to install.")},o.dependencies=function(e,t){var n=o.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=o.resolve(e)||e,t[r]=i.map(e.uses||[],function(t){o.isPlugin(t)&&o.register(t);var r=o.dependencyParse(t),s=o.resolve(t);return s&&!o.versionSatisfies(s.version,r.range)?(i.warn("Plugin.dependencies:",o.toString(s),"does not satisfy",o.toString(r),"used by",o.toString(n)+"."),s._warned=!0,e._warned=!0):s||(i.warn("Plugin.dependencies:",o.toString(t),"used by",o.toString(n),"could not be resolved."),e._warned=!0),r.name});for(var s=0;s=i[2];if("^"===n.operator)return i[0]>0?s[0]===i[0]&&r.number>=n.number:i[1]>0?s[1]===i[1]&&s[2]>=i[2]:s[2]===i[2]}return e===t||"*"===e}},{"./Common":14}],21:[function(e,t,n){var o={};t.exports=o;var i=e("./Events"),r=e("./Engine"),s=e("./Common");!function(){var e,t,n;("undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame,t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),e)||(e=function(e){n=setTimeout(function(){e(s.now())},1e3/60)},t=function(){clearTimeout(n)});o.create=function(e){var t=s.extend({fps:60,correction:1,deltaSampleSize:60,counterTimestamp:0,frameCounter:0,deltaHistory:[],timePrev:null,timeScalePrev:1,frameRequestId:null,isFixed:!1,enabled:!0},e);return t.delta=t.delta||1e3/t.fps,t.deltaMin=t.deltaMin||1e3/t.fps,t.deltaMax=t.deltaMax||1e3/(.5*t.fps),t.fps=1e3/t.delta,t},o.run=function(t,n){return void 0!==t.positionIterations&&(n=t,t=o.create()),function i(r){t.frameRequestId=e(i),r&&t.enabled&&o.tick(t,n,r)}(),t},o.tick=function(e,t,n){var o,s=t.timing,a=1,l={timestamp:s.timestamp};i.trigger(e,"beforeTick",l),i.trigger(t,"beforeTick",l),e.isFixed?o=e.delta:(o=n-e.timePrev||e.delta,e.timePrev=n,e.deltaHistory.push(o),e.deltaHistory=e.deltaHistory.slice(-e.deltaSampleSize),a=(o=(o=(o=Math.min.apply(null,e.deltaHistory))e.deltaMax?e.deltaMax:o)/e.delta,e.delta=o),0!==e.timeScalePrev&&(a*=s.timeScale/e.timeScalePrev),0===s.timeScale&&(a=0),e.timeScalePrev=s.timeScale,e.correction=a,e.frameCounter+=1,n-e.counterTimestamp>=1e3&&(e.fps=e.frameCounter*((n-e.counterTimestamp)/1e3),e.counterTimestamp=n,e.frameCounter=0),i.trigger(e,"tick",l),i.trigger(t,"tick",l),t.world.isModified&&t.render&&t.render.controller&&t.render.controller.clear&&t.render.controller.clear(t.render),i.trigger(e,"beforeUpdate",l),r.update(t,o,a),i.trigger(e,"afterUpdate",l),t.render&&t.render.controller&&(i.trigger(e,"beforeRender",l),i.trigger(t,"beforeRender",l),t.render.controller.world(t.render),i.trigger(e,"afterRender",l),i.trigger(t,"afterRender",l)),i.trigger(e,"afterTick",l),i.trigger(t,"afterTick",l)},o.stop=function(e){t(e.frameRequestId)},o.start=function(e,t){o.run(e,t)}}()},{"./Common":14,"./Engine":15,"./Events":16}],22:[function(e,t,n){var o={};t.exports=o;var i=e("./Events");o._motionWakeThreshold=.18,o._motionSleepThreshold=.08,o._minBias=.9,o.update=function(e,t){for(var n=t*t*t,i=0;i0&&r.motion=r.sleepThreshold&&o.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else o.set(r,!1)}},o.afterCollisions=function(e,t){for(var n=t*t*t,i=0;io._motionWakeThreshold*n&&o.set(c,!1)}}}},o.set=function(e,t){var n=e.isSleeping;t?(e.isSleeping=!0,e.sleepCounter=e.sleepThreshold,e.positionImpulse.x=0,e.positionImpulse.y=0,e.positionPrev.x=e.position.x,e.positionPrev.y=e.position.y,e.anglePrev=e.angle,e.speed=0,e.angularSpeed=0,e.motion=0,n||i.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&i.trigger(e,"sleepEnd"))}},{"./Events":16}],23:[function(e,t,n){var o={};t.exports=o;var i,r=e("../geometry/Vertices"),s=e("../core/Common"),a=e("../body/Body"),l=e("../geometry/Bounds"),c=e("../geometry/Vector");o.rectangle=function(e,t,n,o,i){i=i||{};var l={label:"Rectangle Body",position:{x:e,y:t},vertices:r.fromPath("L 0 0 L "+n+" 0 L "+n+" "+o+" L 0 "+o)};if(i.chamfer){var c=i.chamfer;l.vertices=r.chamfer(l.vertices,c.radius,c.quality,c.qualityMin,c.qualityMax),delete i.chamfer}return a.create(s.extend({},l,i))},o.trapezoid=function(e,t,n,o,i,l){l=l||{};var c,d=n*(i*=.5),u=d+(1-2*i)*n,p=u+d;c=i<.5?"L 0 0 L "+d+" "+-o+" L "+u+" "+-o+" L "+p+" 0":"L 0 0 L "+u+" "+-o+" L "+p+" 0";var m={label:"Trapezoid Body",position:{x:e,y:t},vertices:r.fromPath(c)};if(l.chamfer){var f=l.chamfer;m.vertices=r.chamfer(m.vertices,f.radius,f.quality,f.qualityMin,f.qualityMax),delete l.chamfer}return a.create(s.extend({},m,l))},o.circle=function(e,t,n,i,r){i=i||{};var a={label:"Circle Body",circleRadius:n};r=r||25;var l=Math.ceil(Math.max(10,Math.min(r,n)));return l%2==1&&(l+=1),o.polygon(e,t,l,n,s.extend({},a,i))},o.polygon=function(e,t,n,i,l){if(l=l||{},n<3)return o.circle(e,t,i,l);for(var c=2*Math.PI/n,d="",u=.5*c,p=0;p0&&r.area(A)1?(m=a.create(s.extend({parts:f.slice(0)},o)),a.setPosition(m,{x:e,y:t}),m):f[0]}},{"../body/Body":1,"../core/Common":14,"../geometry/Bounds":26,"../geometry/Vector":28,"../geometry/Vertices":29}],24:[function(e,t,n){var o={};t.exports=o;var i=e("../body/Composite"),r=e("../constraint/Constraint"),s=e("../core/Common"),a=e("../body/Body"),l=e("./Bodies");o.stack=function(e,t,n,o,r,s,l){for(var c,d=i.create({label:"Stack"}),u=e,p=t,m=0,f=0;fv&&(v=x),a.translate(g,{x:.5*h,y:.5*x}),u=g.bounds.max.x+r,i.addBody(d,g),c=g,m+=1}else u+=r}p+=v+s,u=e}return d},o.chain=function(e,t,n,o,a,l){for(var c=e.bodies,d=1;d0)for(c=0;c0&&(p=m[c-1+(l-1)*t],i.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:u},a)))),o&&cp||s<(c=p-c)||s>n-1-c))return 1===u&&a.translate(d,{x:(s+(n%2==1?1:-1))*m,y:0}),l(e+(d?s*m:0)+s*r,o,s,c,d,u)})},o.newtonsCradle=function(e,t,n,o,s){for(var a=i.create({label:"Newtons Cradle"}),c=0;ce.max.x&&(e.max.x=i.x),i.xe.max.y&&(e.max.y=i.y),i.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},o.contains=function(e,t){return t.x>=e.min.x&&t.x<=e.max.x&&t.y>=e.min.y&&t.y<=e.max.y},o.overlaps=function(e,t){return e.min.x<=t.max.x&&e.max.x>=t.min.x&&e.max.y>=t.min.y&&e.min.y<=t.max.y},o.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},o.shift=function(e,t){var n=e.max.x-e.min.x,o=e.max.y-e.min.y;e.min.x=t.x,e.max.x=t.x+n,e.min.y=t.y,e.max.y=t.y+o}},{}],27:[function(e,t,n){var o={};t.exports=o;e("../geometry/Bounds");var i=e("../core/Common");o.pathToVertices=function(e,t){"undefined"==typeof window||"SVGPathSeg"in window||i.warn("Svg.pathToVertices: SVGPathSeg not defined, a polyfill is required.");var n,r,s,a,l,c,d,u,p,m,f,v=[],y=0,g=0,x=0;t=t||15;var h=function(e,t,n){var o=n%2==1&&n>1;if(!p||e!=p.x||t!=p.y){p&&o?(m=p.x,f=p.y):(m=0,f=0);var i={x:m+e,y:f+t};!o&&p||(p=i),v.push(i),g=m+e,x=f+t}},b=function(e){var t=e.pathSegTypeAsLetter.toUpperCase();if("Z"!==t){switch(t){case"M":case"L":case"T":case"C":case"S":case"Q":g=e.x,x=e.y;break;case"H":g=e.x;break;case"V":x=e.y}h(g,x,e.pathSegType)}};for(o._svgPathToAbsolute(e),s=e.getTotalLength(),c=[],n=0;n0)return!1}return!0},o.scale=function(e,t,n,r){if(1===t&&1===n)return e;var s,a;r=r||o.centre(e);for(var l=0;l=0?l-1:e.length-1],d=e[l],u=e[(l+1)%e.length],p=t[l0&&(r|=2),3===r)return!1;return 0!==r||null},o.hull=function(e){var t,n,o=[],r=[];for((e=e.slice(0)).sort(function(e,t){var n=e.x-t.x;return 0!==n?n:e.y-t.y}),n=0;n=2&&i.cross3(r[r.length-2],r[r.length-1],t)<=0;)r.pop();r.push(t)}for(n=e.length-1;n>=0;n-=1){for(t=e[n];o.length>=2&&i.cross3(o[o.length-2],o[o.length-1],t)<=0;)o.pop();o.push(t)}return o.pop(),r.pop(),o.concat(r)}},{"../core/Common":14,"../geometry/Vector":28}],30:[function(e,t,n){var o=t.exports=e("../core/Matter");o.Body=e("../body/Body"),o.Composite=e("../body/Composite"),o.World=e("../body/World"),o.Contact=e("../collision/Contact"),o.Detector=e("../collision/Detector"),o.Grid=e("../collision/Grid"),o.Pairs=e("../collision/Pairs"),o.Pair=e("../collision/Pair"),o.Query=e("../collision/Query"),o.Resolver=e("../collision/Resolver"),o.SAT=e("../collision/SAT"),o.Constraint=e("../constraint/Constraint"),o.MouseConstraint=e("../constraint/MouseConstraint"),o.Common=e("../core/Common"),o.Engine=e("../core/Engine"),o.Events=e("../core/Events"),o.Mouse=e("../core/Mouse"),o.Runner=e("../core/Runner"),o.Sleeping=e("../core/Sleeping"),o.Plugin=e("../core/Plugin"),o.Bodies=e("../factory/Bodies"),o.Composites=e("../factory/Composites"),o.Axes=e("../geometry/Axes"),o.Bounds=e("../geometry/Bounds"),o.Svg=e("../geometry/Svg"),o.Vector=e("../geometry/Vector"),o.Vertices=e("../geometry/Vertices"),o.Render=e("../render/Render"),o.RenderPixi=e("../render/RenderPixi"),o.World.add=o.Composite.add,o.World.remove=o.Composite.remove,o.World.addComposite=o.Composite.addComposite,o.World.addBody=o.Composite.addBody,o.World.addConstraint=o.Composite.addConstraint,o.World.clear=o.Composite.clear,o.Engine.run=o.Runner.run},{"../body/Body":1,"../body/Composite":2,"../body/World":3,"../collision/Contact":4,"../collision/Detector":5,"../collision/Grid":6,"../collision/Pair":7,"../collision/Pairs":8,"../collision/Query":9,"../collision/Resolver":10,"../collision/SAT":11,"../constraint/Constraint":12,"../constraint/MouseConstraint":13,"../core/Common":14,"../core/Engine":15,"../core/Events":16,"../core/Matter":17,"../core/Metrics":18,"../core/Mouse":19,"../core/Plugin":20,"../core/Runner":21,"../core/Sleeping":22,"../factory/Bodies":23,"../factory/Composites":24,"../geometry/Axes":25,"../geometry/Bounds":26,"../geometry/Svg":27,"../geometry/Vector":28,"../geometry/Vertices":29,"../render/Render":31,"../render/RenderPixi":32}],31:[function(e,t,n){var o={};t.exports=o;var i=e("../core/Common"),r=e("../body/Composite"),s=e("../geometry/Bounds"),a=e("../core/Events"),l=e("../collision/Grid"),c=e("../geometry/Vector"),d=e("../core/Mouse");!function(){var e,t;"undefined"!=typeof window&&(e=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){window.setTimeout(function(){e(i.now())},1e3/60)},t=window.cancelAnimationFrame||window.mozCancelAnimationFrame||window.webkitCancelAnimationFrame||window.msCancelAnimationFrame),o.create=function(e){var t={controller:o,engine:null,element:null,canvas:null,mouse:null,frameRequestId:null,options:{width:800,height:600,pixelRatio:1,background:"#18181d",wireframeBackground:"#0f0f13",hasBounds:!!e.bounds,enabled:!0,wireframes:!0,showSleeping:!0,showDebug:!1,showBroadphase:!1,showBounds:!1,showVelocity:!1,showCollisions:!1,showSeparations:!1,showAxes:!1,showPositions:!1,showAngleIndicator:!1,showIds:!1,showShadows:!1,showVertexNumbers:!1,showConvexHulls:!1,showInternalEdges:!1,showMousePosition:!1}},r=i.extend(t,e);return r.canvas&&(r.canvas.width=r.options.width||r.canvas.width,r.canvas.height=r.options.height||r.canvas.height),r.mouse=e.mouse,r.engine=e.engine,r.canvas=r.canvas||n(r.options.width,r.options.height),r.context=r.canvas.getContext("2d"),r.textures={},r.bounds=r.bounds||{min:{x:0,y:0},max:{x:r.canvas.width,y:r.canvas.height}},1!==r.options.pixelRatio&&o.setPixelRatio(r,r.options.pixelRatio),i.isElement(r.element)?r.element.appendChild(r.canvas):r.canvas.parentNode||i.log("Render.create: options.element was undefined, render.canvas was created but not appended","warn"),r},o.run=function(t){!function n(i){t.frameRequestId=e(n),o.world(t)}()},o.stop=function(e){t(e.frameRequestId)},o.setPixelRatio=function(e,t){var n=e.options,o=e.canvas;"auto"===t&&(t=u(o)),n.pixelRatio=t,o.setAttribute("data-pixel-ratio",t),o.width=n.width*t,o.height=n.height*t,o.style.width=n.width+"px",o.style.height=n.height+"px",e.context.scale(t,t)},o.lookAt=function(e,t,n,o){o=void 0===o||o,t=i.isArray(t)?t:[t],n=n||{x:0,y:0};for(var r={min:{x:1/0,y:1/0},max:{x:-1/0,y:-1/0}},s=0;sr.max.x&&(r.max.x=c.x),l.yr.max.y&&(r.max.y=c.y))}var u=r.max.x-r.min.x+2*n.x,p=r.max.y-r.min.y+2*n.y,m=e.canvas.height,f=e.canvas.width/m,v=u/p,y=1,g=1;v>f?g=v/f:y=f/v,e.options.hasBounds=!0,e.bounds.min.x=r.min.x,e.bounds.max.x=r.min.x+u*y,e.bounds.min.y=r.min.y,e.bounds.max.y=r.min.y+p*g,o&&(e.bounds.min.x+=.5*u-u*y*.5,e.bounds.max.x+=.5*u-u*y*.5,e.bounds.min.y+=.5*p-p*g*.5,e.bounds.max.y+=.5*p-p*g*.5),e.bounds.min.x-=n.x,e.bounds.max.x-=n.x,e.bounds.min.y-=n.y,e.bounds.max.y-=n.y,e.mouse&&(d.setScale(e.mouse,{x:(e.bounds.max.x-e.bounds.min.x)/e.canvas.width,y:(e.bounds.max.y-e.bounds.min.y)/e.canvas.height}),d.setOffset(e.mouse,e.bounds.min))},o.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,o=t/e.options.width,i=n/e.options.height;e.context.scale(1/o,1/i),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},o.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},o.world=function(e){var t,n=e.engine,i=n.world,u=e.canvas,p=e.context,f=e.options,v=r.allBodies(i),y=r.allConstraints(i),g=f.wireframes?f.wireframeBackground:f.background,x=[],h=[],b={timestamp:n.timing.timestamp};if(a.trigger(e,"beforeRender",b),e.currentBackground!==g&&m(e,g),p.globalCompositeOperation="source-in",p.fillStyle="transparent",p.fillRect(0,0,u.width,u.height),p.globalCompositeOperation="source-over",f.hasBounds){for(t=0;t=500){var l="";s.timing&&(l+="fps: "+Math.round(s.timing.fps)+" "),e.debugString=l,e.debugTimestamp=o.timing.timestamp}if(e.debugString){n.font="12px Arial",a.wireframes?n.fillStyle="rgba(255,255,255,0.5)":n.fillStyle="rgba(0,0,0,0.5)";for(var c=e.debugString.split("\n"),d=0;d1?1:0;s1?1:0;a1?1:0;r1?1:0;a1?1:0;r1?1:0;r1?1:0;i0)){var d=o.activeContacts[0].vertex.x,u=o.activeContacts[0].vertex.y;2===o.activeContacts.length&&(d=(o.activeContacts[0].vertex.x+o.activeContacts[1].vertex.x)/2,u=(o.activeContacts[0].vertex.y+o.activeContacts[1].vertex.y)/2),i.bodyB===i.supports[0].body||!0===i.bodyA.isStatic?a.moveTo(d-8*i.normal.x,u-8*i.normal.y):a.moveTo(d+8*i.normal.x,u+8*i.normal.y),a.lineTo(d,u)}l.wireframes?a.strokeStyle="rgba(255,165,0,0.7)":a.strokeStyle="orange",a.lineWidth=1,a.stroke()},o.separations=function(e,t,n){var o,i,r,s,a,l=n,c=e.options;for(l.beginPath(),a=0;a1?1:0;p=t.imageCount&&r(t.map)}}}catch(r){o=!0,a=r}finally{try{!n&&u.return&&u.return()}finally{if(o)throw a}}}}]),o}(); 9 | },{"./Resource.js":16}],12:[function(require,module,exports) { 10 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:0,h=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,s=arguments.length>5&&void 0!==arguments[5]?arguments[5]:0,a=arguments.length>6&&void 0!==arguments[6]?arguments[6]:0,l=arguments.length>7&&void 0!==arguments[7]?arguments[7]:0,v=arguments.length>8&&void 0!==arguments[8]?arguments[8]:0,c=arguments.length>9&&void 0!==arguments[9]?arguments[9]:0;i(this,n),this.ctx=t,this.img=e,this.srcX=a,this.srcY=l,this.srcW=v,this.srcH=c,this.x=r,this.y=o,this.w=h,this.h=s}return t(n,[{key:"draw",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.img,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.x,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:this.y,n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:this.w,r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:this.h,o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:this.srcX,h=arguments.length>6&&void 0!==arguments[6]?arguments[6]:this.srcY,s=arguments.length>7&&void 0!==arguments[7]?arguments[7]:this.srcW,a=arguments.length>8&&void 0!==arguments[8]?arguments[8]:this.srcH;this.ctx.drawImage(t,o,h,s,a,e,i,n,r)}}],[{key:"getImage",value:function(t){return e.DataStore.getInstance().res.get(t)}}]),n}(); 13 | },{"./DataStore.js":12}],17:[function(require,module,exports) { 14 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.BackGround=void 0;var t=require("../base/Sprite.js");function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function r(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var n=exports.BackGround=function(n){function i(o){e(this,i);var n=t.Sprite.getImage("background");return r(this,(i.__proto__||Object.getPrototypeOf(i)).call(this,o.ctx,n,(o.canvas.width-n.width)/2,(o.canvas.height-n.height)/2.5,n.width,n.height,0,0,n.width,n.height))}return o(i,t.Sprite),i}(); 15 | },{"../base/Sprite.js":24}],18:[function(require,module,exports) { 16 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.StartButton=void 0;var t=require("../base/Sprite.js");function e(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function r(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var n=exports.StartButton=function(n){function i(o){e(this,i);var n=t.Sprite.getImage("startButton");return r(this,(i.__proto__||Object.getPrototypeOf(i)).call(this,o.ctx,n,(o.canvas.width-n.width)/2,(o.canvas.height-n.height)/2.5,n.width,n.height,0,0,n.width,n.height))}return o(i,t.Sprite),i}(); 17 | },{"../base/Sprite.js":24}],19:[function(require,module,exports) { 18 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Score=void 0;var t=function(){function t(t,e){for(var r=0;r0&&o%1e3==0&&(e.blockHPMax+=10,e.draw()),o++})}}]),l}(); 23 | },{"../base/Body.js":25,"../sprite/Score.js":19,"../base/DataStore.js":12}],21:[function(require,module,exports) { 24 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Border=void 0;var e=function(){function e(e,t){for(var r=0;r.6||e.intervalCount>e.inervalMax)&&(e.isRending=!1,e.isForce=!1,e.draw(),clearInterval(t)),e.intervalCount++},100)}}},{key:"event",value:function(){var e=this,t=this.physics;return t.canvas.addEventListener("touchmove",function(t){e.eventHandler(t,{isForce:!1})}),t.canvas.addEventListener("touchstart",function(t){e.eventHandler(t,{isForce:!1})}),t.canvas.addEventListener("touchend",function(t){e.eventHandler(t,{isForce:!0})}),t.canvas.addEventListener("mousemove",function(t){e.eventHandler(t,{isForce:!1})}),t.canvas.addEventListener("mousedown",function(t){e.eventHandler(t,{isForce:!1})}),t.canvas.addEventListener("mouseup",function(t){e.eventHandler(t,{isForce:!0})}),this}},{key:"eventHandler",value:function(e,t){e.preventDefault(),this.isForce=t.isForce,this.isForce&&!this.isRending&&(this.physics.engine.world.gravity.y=0,this.dataStore.res.get("launch").play()),this.isForce||this.isRending||(e.touches?(this.x=e.touches[0].clientX,this.y=Math.max(50,e.touches[0].clientY)):(this.x=e.offsetX,this.y=Math.max(50,e.offsetY))),this.isRending||this.draw()}}]),l}(); 29 | },{"../base/Body.js":25,"../base/DataStore.js":12}],10:[function(require,module,exports) { 30 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Director=void 0;var e=function(){function e(e,t){for(var r=0;r