diff --git a/app/data/ct.libs/matter/.eslintrc.js b/app/data/ct.libs/matter/.eslintrc.js new file mode 100644 index 000000000..c4a68dad9 --- /dev/null +++ b/app/data/ct.libs/matter/.eslintrc.js @@ -0,0 +1,15 @@ +module.exports = { + "env": { + "browser": true, + "es6": true + }, + "extends": "eslint:recommended", + "globals": { + "Matter": "readonly" + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "rules": { + } +}; diff --git a/app/data/ct.libs/matter/docs/Additional utility functions.md b/app/data/ct.libs/matter/docs/Additional utility functions.md new file mode 100644 index 000000000..f36f7bd85 --- /dev/null +++ b/app/data/ct.libs/matter/docs/Additional utility functions.md @@ -0,0 +1,5 @@ +# Additional functions + +## `ct.matter.getImpact(pair)` + +Calculates a good approximation of an impact two colliding copies caused to each other. The impact is calculated based on copies' velocity relative to each other and their mass. It does not account for impulse transferred through several copies. diff --git a/app/data/ct.libs/matter/docs/Advanced usage.md b/app/data/ct.libs/matter/docs/Advanced usage.md new file mode 100644 index 000000000..fe5a9a378 --- /dev/null +++ b/app/data/ct.libs/matter/docs/Advanced usage.md @@ -0,0 +1,12 @@ +# Advanced usage + +This module bundles the whole Matter.js library. Though it is possible to make an entire game not using Matter.js methods, there are tons of advanced APIs that allow creating soft bodies, 2D cars, ragdolls, complex compound shapes, collision filtering, and other things. + +First of all, you can get the physical bodies that are used by copies with `this.matterBody`. Each of these bodies have a backwards reference to ct.js copies at `body.copy`, where `body` is a Matter.js physical body. + +All the Matter.js methods are available under the `Matter` object. For example, you can call `Matter.Body.setMass(this.matterBody, 100)` to dynamically change the mass of a copy. + +## Further reading + +* [Matter.js docs](https://brm.io/matter-js/docs/index.html) +* [Demos](https://brm.io/matter-js/demo/#wreckingBall). You can see their source code by clicking the `{}` icon at the top of each demo. diff --git a/app/data/ct.libs/matter/docs/Creating constraints.md b/app/data/ct.libs/matter/docs/Creating constraints.md new file mode 100644 index 000000000..d572113ea --- /dev/null +++ b/app/data/ct.libs/matter/docs/Creating constraints.md @@ -0,0 +1,19 @@ +# Creating physical constraints + +This module has a couple of methods that simplify the creation of constraints between two copies, or a copy and a position in space. These constraints create a spring, or a rope, that limits a copy's movement. + +## `ct.matter.pin(copy)` + +Pins a copy in place, making it spin around its center of mass but preventing any other movement. + +## `ct.matter.tie(copy, position, stiffness = 0.05, damping = 0.05)` + +Ties a copy to a specific position in space, making it swing around it. + +## `ct.matter.rope(copy, length, stiffness = 0.05, damping = 0.05)` + +Puts a copy on a rope. It is similar to `ct.matter.tie`, but the length of a rope is defined explicitly, and starts from the copy's current position. + +## `ct.matter.tieTogether(copy1, copy2, stiffness, damping)` + +Ties two copies together with a rope. \ No newline at end of file diff --git a/app/data/ct.libs/matter/docs/Listening to collision events.md b/app/data/ct.libs/matter/docs/Listening to collision events.md new file mode 100644 index 000000000..fba3a5acf --- /dev/null +++ b/app/data/ct.libs/matter/docs/Listening to collision events.md @@ -0,0 +1,38 @@ +# Listening to collision events + +You can listen to collision events with `ct.matter.on(eventName, callback)`. The callback is passed an object that has `pairs` property, which has all the collisions that happened in one frame. Long story short, see this example: + +```js +// Room's OnCreate code +// Listen for collisions in the world +ct.matter.on('collisionStart', e => { + // Loop over every collision in a frame + for (var pair of e.pairs) { + // Get how strong the impact was + // We will use it for damage calculation to aliens + var impact = ct.matter.getImpact(pair); + + // Each pair has bodyA and bodyB — two objects that has collided. + // This little loop applies checks for both bodies + var bodies = [pair.bodyA, pair.bodyB]; + for (var body of bodies) { + // Here, body.copy is the ct.js copy that owns this physical body. + // Does a body belong to a copy of type "Alien"? + if (body.copy.type === 'Alien') { + // If the impact was too strong, destroy the alien. + if (impact > 75) { + body.copy.kill = true; + } + } + } + } +}); +``` + +> **Warning**: DO NOT write `ct.matter.on` inside copies' code. This will apply large amounts of listeners that do the same thing, which will degrade performance and break your gameplay logic. Instead, write `ct.matter.on` once in room's On Create code. + +There are three collision events you can listen to: + +* `collisionStart` — objects has struck each other, or an object entered a sensor's area. +* `collisionActive` — called on each frame for all the current collisions. +* `collisionEnd` — objects stopped colliding, or an object has left sensor's area. diff --git a/app/data/ct.libs/matter/docs/Manipulating copies.md b/app/data/ct.libs/matter/docs/Manipulating copies.md new file mode 100644 index 000000000..9e00a74b9 --- /dev/null +++ b/app/data/ct.libs/matter/docs/Manipulating copies.md @@ -0,0 +1,73 @@ +# Manipulating copies. + +`ct.matter` requires you to use specific methods to move and transform your copies. Usual parameter-based manipulations won't work. + +## `ct.matter.teleport(copy, x, y);` + +Moves a copy to a new position without changing its velocity. + +| Argument | Type | Description | +| -------- | -------- | --------------------------- | +| `copy` | `Copy` | The ct.js copy to teleport. | +| `x` | `number` | The new X coordinate. | +| `y` | `number` | The new Y coordinate. | + +## `ct.matter.push(copy, forceX, forceY, fromX, fromY);` + +Applies a force onto a copy. The resulting velocity depends on object's mass and friction. +You can optionally define a point from which the force is applied to make the copy spin. + +| Argument | Type | Description | +| ------------------ | -------- | ------------------------------------------------------- | +| `copy` | `Copy` | The copy that should be pushed. | +| `forceX` | `number` | The force applied along the horizontal axis. | +| `forceY` | `number` | The force applied along the vertical axis. | +| `fromX` (optional) | `number` | An optional X coordinate from which to apply the force. | +| `fromY` (optional) | `number` | An optional Y coordinate from which to apply the force. | + +## `ct.matter.spin(copy, speed);` + +Sets copy's angular velocity. + +| Argument | Type | Description | +| -------- | -------- | -------------------------------- | +| `copy` | `Copy` | The copy that should be spinned. | +| `speed` | `number` | New angular velocity | + +## `ct.matter.rotate(copy, angle);` + +Rotates copy to the defined angle. + +| Argument | Type | Description | +| -------- | -------- | -------------------------------- | +| `copy` | `Copy` | The copy that should be rotated. | +| `angle` | `number` | New angle. | + +## `ct.matter.rotateBy(copy, angle);` + +Rotates copy by the defined angle. + +| Argument | Type | Description | +| -------- | -------- | -------------------------------- | +| `copy` | `Copy` | The copy that should be rotated. | +| `angle` | `number` | How much to turn the copy. | + +## `ct.matter.scale(copy, x, y);` + +Scales the copy and its physical object. + +| Argument | Type | Description | +| -------- | -------- | ------------------------------------ | +| `copy` | `Copy` | The copy that should be scaled | +| `x` | `number` | New scale value, by horizontal axis. | +| `y` | `number` | New scale value, by vertical axis. | + +## `ct.matter.launch(copy, hspeed, vspeed);` + +Sets the copy's velocity, instantly and magically. + +| Argument | Type | Description | +| -------- | -------- | --------------------------------------- | +| `copy` | `Copy` | The copy which speed should be changed. | +| `hspeed` | `number` | New horizontal speed. | +| `vspeed` | `number` | New vertical speed. | diff --git a/app/data/ct.libs/matter/docs/Read this or you will create a black hole.md b/app/data/ct.libs/matter/docs/Read this or you will create a black hole.md new file mode 100644 index 000000000..cc70ce4cb --- /dev/null +++ b/app/data/ct.libs/matter/docs/Read this or you will create a black hole.md @@ -0,0 +1,32 @@ +# Read this or you will create a black hole + +Working with copies when `ct.matter` is enabled is drastically different from the regular workflow. + +## `vspeed`, `hspeed`, `scale`, `x`, `y` and many others are read-only + +Changing any of these values will have no effect as Matter.js provides properties a bit more complex than these. Instead of that, use these methods: + +* `ct.matter.teleport(copy, x, y)` to move a copy in an arbitrary place; +* `ct.matter.push(copy, forceX, forceY)` to apply a force so that a copy gradually accelerates where you want; +* `ct.matter.launch(copy, hspeed, vspeed)` to set copy's velocity. Use it for actions like jumpts, or for explosion impacts. +* `ct.matter.spin(copy, speed)` to set angular velocity. +* `ct.matter.rotate(copy, amgle)` to set copy's orientation. +* `ct.matter.scale(copy, x, y)` to resize a copy. + +You can still read `x`, `y`, `hspeed`, `vspeed`, `speed`, `direction`, but these are to be considered read-only. + +See "Manipulating copies" page for more information. + +## Remove `this.move();` + +`this.move();` will conflict with the physics system and cause jittering and other unpleasanties. + +## Texture's axis is the center of mass + +This affects how a copy rotates when in contact with other copies. The axis must be inside the collision shape. + +## Collision logic is defined differently + +Instead of testing for collisions from behalf of a particular copy like it happens in `ct.place`, you will define a rulebook that will listen to all the collisions in a room, and you will filter out these collisions according to your gameplay logic. Due to that, **never** listen to these events in copies, as each your copy will have to loop over all the collision events, hindering performance badly. Instead, set up a listener once in your room's OnCreate code. + +See "Listening to collision events" for more information. diff --git a/app/data/ct.libs/matter/includes/matter.min.js b/app/data/ct.libs/matter/includes/matter.min.js new file mode 100644 index 000000000..996575636 --- /dev/null +++ b/app/data/ct.libs/matter/includes/matter.min.js @@ -0,0 +1,6 @@ +/*! + * matter-js 0.16.1 by @liabru 2021-01-31 + * http://brm.io/matter-js/ + * License MIT + */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(function(){try{return require("poly-decomp")}catch(e){}}()):"function"==typeof define&&define.amd?define("Matter",["poly-decomp"],t):"object"==typeof exports?exports.Matter=t(function(){try{return require("poly-decomp")}catch(e){}}()):e.Matter=t(e.decomp)}(this,(function(e){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=24)}([function(e,t){var n={};e.exports=n,function(){n._nextId=0,n._seed=0,n._nowStartTime=+new Date,n.extend=function(e,t){var i,o;"boolean"==typeof t?(i=2,o=t):(i=1,o=!0);for(var r=i;r0;t--){var i=Math.floor(n.random()*(t+1)),o=e[t];e[t]=e[i],e[i]=o}return e},n.choose=function(e){return e[Math.floor(n.random()*e.length)]},n.isElement=function(e){return"undefined"!=typeof HTMLElement?e instanceof HTMLElement:!!(e&&e.nodeType&&e.nodeName)},n.isArray=function(e){return"[object Array]"===Object.prototype.toString.call(e)},n.isFunction=function(e){return"function"==typeof e},n.isPlainObject=function(e){return"object"==typeof e&&e.constructor===Object},n.isString=function(e){return"[object String]"===toString.call(e)},n.clamp=function(e,t,n){return en?n:e},n.sign=function(e){return e<0?-1:1},n.now=function(){if("undefined"!=typeof window&&window.performance){if(window.performance.now)return window.performance.now();if(window.performance.webkitNow)return window.performance.webkitNow()}return new Date-n._nowStartTime},n.random=function(t,n){return n=void 0!==n?n:1,(t=void 0!==t?t:0)+e()*(n-t)};var e=function(){return n._seed=(9301*n._seed+49297)%233280,n._seed/233280};n.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)},n.logLevel=1,n.log=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.log.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.info=function(){console&&n.logLevel>0&&n.logLevel<=2&&console.info.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.warn=function(){console&&n.logLevel>0&&n.logLevel<=3&&console.warn.apply(console,["matter-js:"].concat(Array.prototype.slice.call(arguments)))},n.nextId=function(){return n._nextId++},n.indexOf=function(e,t){if(e.indexOf)return e.indexOf(t);for(var n=0;ne.max.x&&(e.max.x=o.x),o.xe.max.y&&(e.max.y=o.y),o.y0?e.max.x+=n.x:e.min.x+=n.x,n.y>0?e.max.y+=n.y:e.min.y+=n.y)},n.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},n.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},n.translate=function(e,t){e.min.x+=t.x,e.max.x+=t.x,e.min.y+=t.y,e.max.y+=t.y},n.shift=function(e,t){var n=e.max.x-e.min.x,i=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+i}},function(e,t){var n={};e.exports=n,n.create=function(e,t){return{x:e||0,y:t||0}},n.clone=function(e){return{x:e.x,y:e.y}},n.magnitude=function(e){return Math.sqrt(e.x*e.x+e.y*e.y)},n.magnitudeSquared=function(e){return e.x*e.x+e.y*e.y},n.rotate=function(e,t,n){var i=Math.cos(t),o=Math.sin(t);n||(n={});var r=e.x*i-e.y*o;return n.y=e.x*o+e.y*i,n.x=r,n},n.rotateAbout=function(e,t,n,i){var o=Math.cos(t),r=Math.sin(t);i||(i={});var s=n.x+((e.x-n.x)*o-(e.y-n.y)*r);return i.y=n.y+((e.x-n.x)*r+(e.y-n.y)*o),i.x=s,i},n.normalise=function(e){var t=n.magnitude(e);return 0===t?{x:0,y:0}:{x:e.x/t,y:e.y/t}},n.dot=function(e,t){return e.x*t.x+e.y*t.y},n.cross=function(e,t){return e.x*t.y-e.y*t.x},n.cross3=function(e,t,n){return(t.x-e.x)*(n.y-e.y)-(t.y-e.y)*(n.x-e.x)},n.add=function(e,t,n){return n||(n={}),n.x=e.x+t.x,n.y=e.y+t.y,n},n.sub=function(e,t,n){return n||(n={}),n.x=e.x-t.x,n.y=e.y-t.y,n},n.mult=function(e,t){return{x:e.x*t,y:e.y*t}},n.div=function(e,t){return{x:e.x/t,y:e.y/t}},n.perp=function(e,t){return{x:(t=!0===t?-1:1)*-e.y,y:t*e.x}},n.neg=function(e){return{x:-e.x,y:-e.y}},n.angle=function(e,t){return Math.atan2(t.y-e.y,t.x-e.x)},n._temp=[n.create(),n.create(),n.create(),n.create(),n.create(),n.create()]},function(e,t,n){var i={};e.exports=i;var o=n(2),r=n(0);i.create=function(e,t){for(var n=[],i=0;i0)return!1}return!0},i.scale=function(e,t,n,r){if(1===t&&1===n)return e;var s,a;r=r||i.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},i.hull=function(e){var t,n,i=[],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&&o.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];i.length>=2&&o.cross3(i[i.length-2],i[i.length-1],t)<=0;)i.pop();i.push(t)}return i.pop(),r.pop(),i.concat(r)}},function(e,t,n){var i={};e.exports=i;var o=n(0);i.on=function(e,t,n){for(var i,o=t.split(" "),r=0;r0){n||(n={}),i=t.split(" ");for(var c=0;c0&&r.rotateAbout(s.position,n,e.position,s.position)}},i.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)},i.setAngularVelocity=function(e,t){e.anglePrev=e.angle-t,e.angularVelocity=t,e.angularSpeed=Math.abs(e.angularVelocity)},i.translate=function(e,t){i.setPosition(e,r.add(e.position,t))},i.rotate=function(e,t,n){if(n){var o=Math.cos(t),r=Math.sin(t),s=e.position.x-n.x,a=e.position.y-n.y;i.setPosition(e,{x:n.x+(s*o-a*r),y:n.y+(s*r+a*o)}),i.setAngle(e,e.angle+t)}else i.setAngle(e,e.angle+t)},i.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||(i.setMass(e,e.density*s),i.setInertia(e,a))),e.circleRadius&&(t===n?e.circleRadius*=t:e.circleRadius=null)},i.update=function(e,t,n,i){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*i+e.force.x/e.mass*s,e.velocity.y=u*a*i+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*i+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&&(f.position.x+=e.velocity.x,f.position.y+=e.velocity.y),0!==e.angularVelocity&&(o.rotate(f.vertices,e.angularVelocity,e.position),c.rotate(f.axes,e.angularVelocity),p>0&&r.rotateAbout(f.position,e.angularVelocity,e.position,f.position)),l.update(f.bounds,f.vertices,e.velocity)}},i.applyForce=function(e,t,n){e.force.x+=n.x,e.force.y+=n.y;var i=t.x-e.position.x,o=t.y-e.position.y;e.torque+=i*n.y-o*n.x},i._totalProperties=function(e){for(var t={mass:0,area:0,inertia:0,centre:{x:0,y:0}},n=1===e.parts.length?0:1;n0&&r.motion=r.sleepThreshold&&i.set(r,!0)):r.sleepCounter>0&&(r.sleepCounter-=1)}else i.set(r,!1)}},i.afterCollisions=function(e,t){for(var n=t*t*t,o=0;oi._motionWakeThreshold*n&&i.set(c,!1)}}}},i.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||o.trigger(e,"sleepStart")):(e.isSleeping=!1,e.sleepCounter=0,n&&o.trigger(e,"sleepEnd"))}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2),s=n(7),a=n(1),l=n(15),c=n(0);i._warming=.4,i._torqueDampen=1,i._minLength=1e-6,i.create=function(e){var t=e;t.bodyA&&!t.pointA&&(t.pointA={x:0,y:0}),t.bodyB&&!t.pointB&&(t.pointB={x:0,y:0});var n=t.bodyA?r.add(t.bodyA.position,t.pointA):t.pointA,i=t.bodyB?r.add(t.bodyB.position,t.pointB):t.pointB,o=r.magnitude(r.sub(n,i));t.length=void 0!==t.length?t.length:o,t.id=t.id||c.nextId(),t.label=t.label||"Constraint",t.type="constraint",t.stiffness=t.stiffness||(t.length>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},i.preSolveAll=function(e){for(var t=0;t0&&(u.position.x+=c.x,u.position.y+=c.y),0!==c.angle&&(o.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*=i._warming,c.x*=i._warming,c.y*=i._warming}}},i.pointAWorld=function(e){return{x:(e.bodyA?e.bodyA.position.x:0)+e.pointA.x,y:(e.bodyA?e.bodyA.position.y:0)+e.pointA.y}},i.pointBWorld=function(e){return{x:(e.bodyB?e.bodyB.position.x:0)+e.pointB.x,y:(e.bodyB?e.bodyB.position.y:0)+e.pointB.y}}},function(e,t,n){var i={};e.exports=i;var o=n(18);i.create=function(e,t){var n=e.bodyA,o=e.bodyB,r=e.parentA,s=e.parentB,a={id:i.id(n,o),bodyA:n,bodyB:o,contacts:{},activeContacts:[],separation:0,isActive:!0,confirmedActive:!0,isSensor:n.isSensor||o.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 i.update(a,e,t),a},i.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;dr.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,f=e.canvas.height,v=e.canvas.width/f,m=u/p,y=1,g=1;m>v?g=m/v:y=v/m,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,i&&(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))},i.startViewTransform=function(e){var t=e.bounds.max.x-e.bounds.min.x,n=e.bounds.max.y-e.bounds.min.y,i=t/e.options.width,o=n/e.options.height;e.context.setTransform(e.options.pixelRatio/i,0,0,e.options.pixelRatio/o,0,0),e.context.translate(-e.bounds.min.x,-e.bounds.min.y)},i.endViewTransform=function(e){e.context.setTransform(e.options.pixelRatio,0,0,e.options.pixelRatio,0,0)},i.world=function(e){var t,n=e.engine,o=n.world,u=e.canvas,p=e.context,v=e.options,m=r.allBodies(o),y=r.allConstraints(o),g=v.wireframes?v.wireframeBackground:v.background,x=[],h=[],b={timestamp:n.timing.timestamp};if(a.trigger(e,"beforeRender",b),e.currentBackground!==g&&f(e,g),p.globalCompositeOperation="source-in",p.fillStyle="transparent",p.fillRect(0,0,u.width,u.height),p.globalCompositeOperation="source-over",v.hasBounds){for(t=0;t=500){var d="";s.timing&&(d+="fps: "+Math.round(s.timing.fps)+" "),s.extended&&(s.timing&&(d+="delta: "+s.timing.delta.toFixed(3)+" ",d+="correction: "+s.timing.correction.toFixed(3)+" "),d+="bodies: "+c.length+" ",i.broadphase.controller===l&&(d+="buckets: "+s.buckets+" "),d+="\n",d+="collisions: "+s.collisions+" ",d+="pairs: "+i.pairs.list.length+" ",d+="broad: "+s.broadEff+" ",d+="mid: "+s.midEff+" ",d+="narrow: "+s.narrowEff+" "),e.debugString=d,e.debugTimestamp=i.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 u=e.debugString.split("\n"),p=0;p1?1:0;s1?1:0;a1?1:0;r1?1:0;a1?1:0;r1?1:0;r1?1:0;o0)){var d=i.activeContacts[0].vertex.x,u=i.activeContacts[0].vertex.y;2===i.activeContacts.length&&(d=(i.activeContacts[0].vertex.x+i.activeContacts[1].vertex.x)/2,u=(i.activeContacts[0].vertex.y+i.activeContacts[1].vertex.y)/2),o.bodyB===o.supports[0].body||!0===o.bodyA.isStatic?a.moveTo(d-8*o.normal.x,u-8*o.normal.y):a.moveTo(d+8*o.normal.x,u+8*o.normal.y),a.lineTo(d,u)}l.wireframes?a.strokeStyle="rgba(255,165,0,0.7)":a.strokeStyle="orange",a.lineWidth=1,a.stroke()},i.separations=function(e,t,n){var i,o,r,s,a,l=n,c=e.options;for(l.beginPath(),a=0;ad.bounds.max.x||v.bounds.max.yd.bounds.max.y)){var m=i._getRegion(e,v);if(!v.region||m.id!==v.region.id||o){f.broadphaseTests+=1,v.region&&!o||(v.region=m);var y=i._regionUnion(m,v.region);for(s=y.startCol;s<=y.endCol;s++)for(a=y.startRow;a<=y.endRow;a++){l=u[c=i._getBucketId(s,a)];var g=s>=m.startCol&&s<=m.endCol&&a>=m.startRow&&a<=m.endRow,x=s>=v.region.startCol&&s<=v.region.endCol&&a>=v.region.startRow&&a<=v.region.endRow;!g&&x&&x&&l&&i._bucketRemoveBody(e,l,v),(v.region===m||g&&!x||o)&&(l||(l=i._createBucket(u,c)),i._bucketAddBody(e,l,v))}v.region=m,p=!0}}}p&&(e.pairsList=i._createActivePairsList(e))},i.clear=function(e){e.buckets={},e.pairs={},e.pairsList=[]},i._regionUnion=function(e,t){var n=Math.min(e.startCol,t.startCol),o=Math.max(e.endCol,t.endCol),r=Math.min(e.startRow,t.startRow),s=Math.max(e.endRow,t.endRow);return i._createRegion(n,o,r,s)},i._getRegion=function(e,t){var n=t.bounds,o=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 i._createRegion(o,r,s,a)},i._createRegion=function(e,t,n,i){return{id:e+","+t+","+n+","+i,startCol:e,endCol:t,startRow:n,endRow:i}},i._getBucketId=function(e,t){return"C"+e+"R"+t},i._createBucket=function(e,t){return e[t]=[]},i._bucketAddBody=function(e,t,n){for(var i=0;i0?i.push(n):delete e.pairs[t[o]];return i}},function(e,t,n){var i={};e.exports=i;var o=n(13),r=n(9),s=n(1);i.collisions=function(e,t){for(var n=[],a=t.pairs.table,l=t.metrics,c=0;c1?1:0;p1?1:0;v0:0!=(e.mask&t.category)&&0!=(t.mask&e.category)}},function(e,t,n){var i={};e.exports=i;var o=n(3),r=n(2);i.collides=function(e,t,n){var s,a,l,c,d=!1;if(n){var u=e.parent,p=t.parent,f=u.speed*u.speed+u.angularSpeed*u.angularSpeed+p.speed*p.speed+p.angularSpeed*p.angularSpeed;d=n&&n.collided&&f<.2,c=n}else c={collided:!1,bodyA:e,bodyB:t};if(n&&d){var v=c.axisBody,m=v===e?t:e,y=[v.axes[n.axisNumber]];if(l=i._overlapAxes(v.vertices,m.vertices,y),c.reused=!0,l.overlap<=0)return c.collided=!1,c}else{if((s=i._overlapAxes(e.vertices,t.vertices,e.axes)).overlap<=0)return c.collided=!1,c;if((a=i._overlapAxes(t.vertices,e.vertices,t.axes)).overlap<=0)return c.collided=!1,c;s.overlapo?o=a:a=0?s.index-1:d.length-1],c.x=o.x-u.x,c.y=o.y-u.y,l=-r.dot(n,c),a=o,o=d[(s.index+1)%d.length],c.x=o.x-u.x,c.y=o.y-u.y,(i=-r.dot(n,c))0&&o.area(B)1?(g=s.create(r.extend({parts:x.slice(0)},d)),s.setPosition(g,{x:e,y:t}),g):x[0]}},function(e,t,n){var i={};e.exports=i;var o=n(0);i._registry={},i.register=function(e){if(i.isPlugin(e)||o.warn("Plugin.register:",i.toString(e),"does not implement all required fields."),e.name in i._registry){var t=i._registry[e.name],n=i.versionParse(e.version).number,r=i.versionParse(t.version).number;n>r?(o.warn("Plugin.register:",i.toString(t),"was upgraded to",i.toString(e)),i._registry[e.name]=e):n-1},i.isFor=function(e,t){var n=e.for&&i.dependencyParse(e.for);return!e.for||t.name===n.name&&i.versionSatisfies(t.version,n.range)},i.use=function(e,t){if(e.uses=(e.uses||[]).concat(t||[]),0!==e.uses.length){for(var n=i.dependencies(e),r=o.topologicalSort(n),s=[],a=0;a0&&o.info(s.join(" "))}else o.warn("Plugin.use:",i.toString(e),"does not specify any dependencies to install.")},i.dependencies=function(e,t){var n=i.dependencyParse(e),r=n.name;if(!(r in(t=t||{}))){e=i.resolve(e)||e,t[r]=o.map(e.uses||[],(function(t){i.isPlugin(t)&&i.register(t);var r=i.dependencyParse(t),s=i.resolve(t);return s&&!i.versionSatisfies(s.version,r.range)?(o.warn("Plugin.dependencies:",i.toString(s),"does not satisfy",i.toString(r),"used by",i.toString(n)+"."),s._warned=!0,e._warned=!0):s||(o.warn("Plugin.dependencies:",i.toString(t),"used by",i.toString(n),"could not be resolved."),e._warned=!0),r.name}));for(var s=0;s=|>)?\s*((\d+)\.(\d+)\.(\d+))(-[0-9A-Za-z-]+)?$/;t.test(e)||o.warn("Plugin.versionParse:",e,"is not a valid version or range.");var n=t.exec(e),i=Number(n[4]),r=Number(n[5]),s=Number(n[6]);return{isRange:Boolean(n[1]||n[2]),version:n[3],range:e,operator:n[1]||n[2]||"",major:i,minor:r,patch:s,parts:[i,r,s],prerelease:n[7],number:1e8*i+1e4*r+s}},i.versionSatisfies=function(e,t){t=t||"*";var n=i.versionParse(t),o=i.versionParse(e);if(n.isRange){if("*"===n.operator||"*"===e)return!0;if(">"===n.operator)return o.number>n.number;if(">="===n.operator)return o.number>=n.number;if("~"===n.operator)return o.major===n.major&&o.minor===n.minor&&o.patch>=n.patch;if("^"===n.operator)return n.major>0?o.major===n.major&&o.number>=n.number:n.minor>0?o.minor===n.minor&&o.patch>=n.patch:o.patch===n.patch}return e===t||"*"===e}},function(e,t){var n={};e.exports=n,n.create=function(e){return{id:n.id(e),vertex:e,normalImpulse:0,tangentImpulse:0}},n.id=function(e){return e.body.id+"_"+e.index}},function(e,t,n){var i={};e.exports=i;var o=n(5),r=(n(8),n(0));i.create=function(e){var t=o.create(),n={label:"World",gravity:{x:0,y:1,scale:.001},bounds:{min:{x:-1/0,y:-1/0},max:{x:1/0,y:1/0}}};return r.extend(t,n,e)}},function(e,t,n){var i={};e.exports=i;var o=n(9),r=n(0);i._pairMaxIdleLife=1e3,i.create=function(e){return r.extend({table:{},list:[],collisionStart:[],collisionActive:[],collisionEnd:[]},e)},i.update=function(e,t,n){var i,r,s,a,l=e.list,c=e.table,d=e.collisionStart,u=e.collisionEnd,p=e.collisionActive;for(d.length=0,u.length=0,p.length=0,a=0;ai._pairMaxIdleLife&&c.push(s);for(s=0;sf.friction*f.frictionStatic*O*n&&(V=T,E=s.clamp(f.friction*R*n,-V,V));var F=r.cross(P,g),W=r.cross(C,g),q=b/(m.inverseMass+y.inverseMass+m.inverseInertia*F*F+y.inverseInertia*W*W);if(L*=q,E*=q,I<0&&I*I>i._restingThresh*n)S.normalImpulse=0;else{var j=S.normalImpulse;S.normalImpulse=Math.min(S.normalImpulse+L,0),L=S.normalImpulse-j}if(_*_>i._restingThreshTangent*n)S.tangentImpulse=0;else{var D=S.tangentImpulse;S.tangentImpulse=s.clamp(S.tangentImpulse+E,-V,V),E=S.tangentImpulse-D}o.x=g.x*L+x.x*E,o.y=g.y*L+x.y*E,m.isStatic||m.isSleeping||(m.positionPrev.x+=o.x*m.inverseMass,m.positionPrev.y+=o.y*m.inverseMass,m.anglePrev+=r.cross(P,o)*m.inverseInertia),y.isStatic||y.isSleeping||(y.positionPrev.x-=o.x*y.inverseMass,y.positionPrev.y-=o.y*y.inverseMass,y.anglePrev-=r.cross(C,o)*y.inverseInertia)}}}}},function(e,t,n){var i={};e.exports=i;var o=n(19),r=n(7),s=n(21),a=n(10),l=n(20),c=n(23),d=n(11),u=n(4),p=n(5),f=n(8),v=n(0),m=n(6);i.create=function(e,t){t=(t=v.isElement(e)?t:e)||{},((e=v.isElement(e)?e:null)||t.render)&&v.warn("Engine.create: engine.render is deprecated (see docs)");var n={positionIterations:6,velocityIterations:4,constraintIterations:2,enableSleeping:!1,events:[],plugin:{},timing:{timestamp:0,timeScale:1},broadphase:{controller:d}},i=v.extend(n,t);if(e||i.render){var r={element:e,controller:a};i.render=v.extend(r,i.render)}return i.render&&i.render.controller&&(i.render=i.render.controller.create(i.render)),i.render&&(i.render.engine=i),i.world=t.world||o.create(i.world),i.pairs=l.create(),i.broadphase=i.broadphase.controller.create(i.broadphase),i.metrics=i.metrics||{extended:!1},i.metrics=c.create(i.metrics),i},i.update=function(e,t,n){t=t||1e3/60,n=n||1;var o,a=e.world,d=e.timing,v=e.broadphase,m=[];d.timestamp+=t*d.timeScale;var y={timestamp:d.timestamp};u.trigger(e,"beforeUpdate",y);var g=p.allBodies(a),x=p.allConstraints(a);for(c.reset(e.metrics),e.enableSleeping&&r.update(g,d.timeScale),i._bodiesApplyGravity(g,a.gravity),i._bodiesUpdate(g,t,d.timeScale,n,a.bounds),f.preSolveAll(g),o=0;o0&&u.trigger(e,"collisionStart",{pairs:b.collisionStart}),s.preSolvePosition(b.list),o=0;o0&&u.trigger(e,"collisionActive",{pairs:b.collisionActive}),b.collisionEnd.length>0&&u.trigger(e,"collisionEnd",{pairs:b.collisionEnd}),c.update(e.metrics,e),i._bodiesClearForces(g),u.trigger(e,"afterUpdate",y),e},i.merge=function(e,t){if(v.extend(e,t),t.world){e.world=t.world,i.clear(e);for(var n=p.allBodies(e.world),o=0;o1?1:0;de.deltaMax?e.deltaMax:i)/e.delta,e.delta=i),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),o.trigger(e,"tick",l),o.trigger(t,"tick",l),t.world.isModified&&t.render&&t.render.controller&&t.render.controller.clear&&t.render.controller.clear(t.render),o.trigger(e,"beforeUpdate",l),r.update(t,i,a),o.trigger(e,"afterUpdate",l),t.render&&t.render.controller&&(o.trigger(e,"beforeRender",l),o.trigger(t,"beforeRender",l),t.render.controller.world(t.render),o.trigger(e,"afterRender",l),o.trigger(t,"afterRender",l)),o.trigger(e,"afterTick",l),o.trigger(t,"afterTick",l)},i.stop=function(e){t(e.frameRequestId)},i.start=function(e,t){i.run(e,t)}}()},function(e,t,n){var i={};e.exports=i;var o=n(5),r=n(8),s=n(0),a=n(6),l=n(16);i.stack=function(e,t,n,i,r,s,l){for(var c,d=o.create({label:"Stack"}),u=e,p=t,f=0,v=0;vm&&(m=x),a.translate(g,{x:.5*h,y:.5*x}),u=g.bounds.max.x+r,o.addBody(d,g),c=g,f+=1}else u+=r}p+=m+s,u=e}return d},i.chain=function(e,t,n,i,a,l){for(var c=e.bodies,d=1;d0)for(c=0;c0&&(p=f[c-1+(l-1)*t],o.addConstraint(e,r.create(s.extend({bodyA:p,bodyB:u},a)))),i&&cp||s<(c=p-c)||s>n-1-c))return 1===u&&a.translate(d,{x:(s+(n%2==1?1:-1))*f,y:0}),l(e+(d?s*f:0)+s*r,i,s,c,d,u)}))},i.newtonsCradle=function(e,t,n,i,s){for(var a=o.create({label:"Newtons Cradle"}),c=0;c1;if(!p||e!=p.x||t!=p.y){p&&i?(f=p.x,v=p.y):(f=0,v=0);var o={x:f+e,y:v+t};!i&&p||(p=o),m.push(o),g=f+e,x=v+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(i._svgPathToAbsolute(e),s=e.getTotalLength(),c=[],n=0;n1?1:0;p diff --git a/app/data/ct.libs/matter/injects/onbeforecreate.js b/app/data/ct.libs/matter/injects/onbeforecreate.js new file mode 100644 index 000000000..67cfe1e84 --- /dev/null +++ b/app/data/ct.libs/matter/injects/onbeforecreate.js @@ -0,0 +1,3 @@ +if (this.matterEnable) { + ct.matter.onCreate(this); +} diff --git a/app/data/ct.libs/matter/injects/ondestroy.js b/app/data/ct.libs/matter/injects/ondestroy.js new file mode 100644 index 000000000..6d50de952 --- /dev/null +++ b/app/data/ct.libs/matter/injects/ondestroy.js @@ -0,0 +1,3 @@ +if (this.matterEnable) { + Matter.World.remove(ct.room.matterWorld, this.matterBody); +} diff --git a/app/data/ct.libs/matter/module.json b/app/data/ct.libs/matter/module.json new file mode 100644 index 000000000..0384ed5ed --- /dev/null +++ b/app/data/ct.libs/matter/module.json @@ -0,0 +1,127 @@ +{ + "main": { + "name": "Matter.js physics library", + "tagline": "Add realtime 2D physics engine to your project.", + "version": "0.0.0", + "authors": [{ + "name": "Cosmo Myzrail Gorynych", + "mail": "admin@nersta.ru" + }], + "categories": [ + "motionPlanning" + ] + }, + + "fields": [{ + "name": "Use static delta time", + "type": "checkbox", + "default": true, + "help": "Uses a constant frame time instead of ct.delta to make world updates more deterministic and stable. Disabling this option may result in an unstable, jiggly physics behavior.", + "key": "matterUseStaticDeltaTime" + }], + + "typeExtends": [{ + "type": "group", + "name": "Physics", + "openedByDefault": false, + "lsKey": "physics.general", + "items": [{ + "name": "Enable", + "type": "checkbox", + "default": false, + "key": "matterEnable" + }, { + "name": "Is static", + "type": "checkbox", + "key": "matterStatic", + "default": false + }, { + "name": "Is a sensor", + "type": "checkbox", + "key": "matterSensor", + "default": false, + "help": "When turned on, the copy won't prevent others' movement but will be able to trigger collisions" + }, { + "name": "Density", + "type": "number", + "key": "matterDensity", + "hint": "How each pixel of this object contributes to its mass. The larger and more dense an object, the more heavy it is.", + "default": 0.001 + }, { + "name": "Bounciness", + "type": "number", + "key": "matterRestitution", + "default": 0.1, + "min": 0, + "max": 1, + "step": 0.1 + }, { + "name": "Friction", + "type": "number", + "key": "matterFriction", + "default": 1 + }, { + "name": "Static friction", + "type": "number", + "key": "matterFrictionStatic", + "default": 0.1 + }, { + "name": "Air friction", + "type": "number", + "key": "matterFrictionAir", + "default": 0.01 + }, { + "name": "Fix pivot", + "type": "point2D", + "key": "matterFixPivot", + "help": "Shifts the texture. Helps with polygonal shapes where the module cannot align center of mass and texture automatically.", + "step": 1, + "default": [0, 0] + }] + }, { + "type": "group", + "name": "Physics constraints", + "openedByDefault": false, + "lsKey": "physics.constraints", + "items": [{ + "name": "Type", + "type": "radio", + "options": [{ + "value": "none", + "name": "None" + }, { + "value": "pinpoint", + "name": "Pin in place", + "help": "Keeps position but allows rotation" + }, { + "value": "rope", + "name": "Rope", + "help": "Creates a rope with a defined length" + }], + "default": "none", + "key": "matterConstraint" + }, { + "name": "Rope length", + "type": "number", + "default": 64, + "key": "matterRopeLength" + }, { + "name": "Rope stiffness", + "type": "number", + "default": 0.05, + "key": "matterRopeStiffness" + }, { + "name": "Rope damping", + "type": "number", + "default": 0.05, + "key": "matterRopeDamping" + }] + }], + "roomExtends": [{ + "name": "Gravity", + "type": "point2D", + "key": "matterGravity", + "step": 0.1, + "default": [0, 9.8] + }] +} diff --git a/app/data/ct.libs/matter/types.d.ts b/app/data/ct.libs/matter/types.d.ts new file mode 100644 index 000000000..14bd69e1a --- /dev/null +++ b/app/data/ct.libs/matter/types.d.ts @@ -0,0 +1,3963 @@ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-empty-interface */ +/* eslint-disable no-dupe-class-members */ +/* eslint-disable @typescript-eslint/ban-types */ +/* eslint-disable id-blacklist */ +/* eslint-disable no-use-before-define */ +/* eslint-disable max-len */ + +declare namespace Matter { + /** + * Installs the given plugins on the `Matter` namespace. + * This is a short-hand for `Plugin.use`, see it for more information. + * Call this function once at the start of your code, with all of the plugins you wish to install as arguments. + * Avoid calling this function multiple times unless you intend to manually control installation order. + * @method use + * @param ...plugin {Function} The plugin(s) to install on `base` (multi-argument). + */ + export function use(...plugins: (Plugin | string)[]): void; + + /** + * The `Matter.Axes` module contains methods for creating and manipulating sets of axes. + * + * @class Axes + */ + export class Axes { + /** + * Creates a new set of axes from the given vertices. + * @method fromVertices + * @param {vertices} vertices + * @return {axes} A new axes from the given vertices + */ + static fromVertices(vertices: Array): Array; + /** + * Rotates a set of axes by the given angle. + * @method rotate + * @param {axes} axes + * @param {number} angle + */ + static rotate(axes: Array, angle: number): void; + } + + interface IChamfer { + radius?: number | Array; + quality?: number; + qualityMin?: number; + qualityMax?: number; + } + + interface IChamferableBodyDefinition extends IBodyDefinition { + chamfer?: IChamfer; + } + + /** + * The `Matter.Bodies` module contains factory methods for creating rigid body models + * with commonly used body configurations (such as rectangles, circles and other polygons). + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Bodies + */ + export class Bodies { + /** + * Creates a new rigid body model with a circle hull. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method circle + * @param {number} x + * @param {number} y + * @param {number} radius + * @param {object} [options] + * @param {number} [maxSides] + * @return {body} A new circle body + */ + static circle(x: number, y: number, radius: number, options?: IBodyDefinition, maxSides?: number): Body; + + /** + * Creates a new rigid body model with a regular polygon hull with the given number of sides. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method polygon + * @param {number} x + * @param {number} y + * @param {number} sides + * @param {number} radius + * @param {object} [options] + * @return {body} A new regular polygon body + */ + static polygon(x: number, y: number, sides: number, radius: number, options?: IChamferableBodyDefinition): Body; + + /** + * Creates a new rigid body model with a rectangle hull. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method rectangle + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + * @param {object} [options] + * @return {body} A new rectangle body + */ + static rectangle(x: number, y: number, width: number, height: number, options?: IChamferableBodyDefinition): Body; + + /** + * Creates a new rigid body model with a trapezoid hull. + * The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method trapezoid + * @param {number} x + * @param {number} y + * @param {number} width + * @param {number} height + * @param {number} slope + * @param {object} [options] + * @return {body} A new trapezoid body + */ + static trapezoid(x: number, y: number, width: number, height: number, slope: number, options?: IChamferableBodyDefinition): Body; + /** + * Creates a body using the supplied vertices (or an array containing multiple sets of vertices). + * If the vertices are convex, they will pass through as supplied. + * Otherwise if the vertices are concave, they will be decomposed if [poly-decomp.js](https://github.com/schteppe/poly-decomp.js) is available. + * Note that this process is not guaranteed to support complex sets of vertices (e.g. those with holes may fail). + * By default the decomposition will discard collinear edges (to improve performance). + * It can also optionally discard any parts that have an area less than `minimumArea`. + * If the vertices can not be decomposed, the result will fall back to using the convex hull. + * The options parameter is an object that specifies any `Matter.Body` properties you wish to override the defaults. + * See the properties section of the `Matter.Body` module for detailed information on what you can pass via the `options` object. + * @method fromVertices + * @param {number} x + * @param {number} y + * @param [[vector]] vertexSets + * @param {object} [options] + * @param {bool} [flagInternal=false] + * @param {number} [removeCollinear=0.01] + * @param {number} [minimumArea=10] + * @return {body} + */ + static fromVertices(x: number, y: number, vertexSets: Array>, options?: IBodyDefinition, flagInternal?: boolean, removeCollinear?: number, minimumArea?: number): Body; + } + + export interface IBodyDefinition { + /** + * A `Number` specifying the angle of the body, in radians. + * + * @property angle + * @type number + * @default 0 + */ + angle?: number; + /** + * A `Number` that _measures_ the current angular speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.angularVelocity`). + * + * @readOnly + * @property angularSpeed + * @type number + * @default 0 + */ + angularSpeed?: number; + /** + * A `Number` that _measures_ the current angular velocity of the body after the last `Body.update`. It is read-only. + * If you need to modify a body's angular velocity directly, you should apply a torque or simply change the body's `angle` (as the engine uses position-Verlet integration). + * + * @readOnly + * @property angularVelocity + * @type number + * @default 0 + */ + angularVelocity?: number; + /** + * A `Number` that _measures_ the area of the body's convex hull, calculated at creation by `Body.create`. + * + * @property area + * @type string + * @default + */ + area?: number; + /** + * An array of unique axis vectors (edge normals) used for collision detection. + * These are automatically calculated from the given convex hull (`vertices` array) in `Body.create`. + * They are constantly updated by `Body.update` during the simulation. + * + * @property axes + * @type vector[] + */ + axes?: Array; + /** + * A `Bounds` object that defines the AABB region for the body. + * It is automatically calculated from the given convex hull (`vertices` array) in `Body.create` and constantly updated by `Body.update` during simulation. + * + * @property bounds + * @type bounds + */ + bounds?: Bounds; + /** + * A `Number` that defines the density of the body, that is its mass per unit area. + * If you pass the density via `Body.create` the `mass` property is automatically calculated for you based on the size (area) of the object. + * This is generally preferable to simply setting mass and allows for more intuitive definition of materials (e.g. rock has a higher density than wood). + * + * @property density + * @type number + * @default 0.001 + */ + density?: number; + /** + * A `Vector` that specifies the force to apply in the current step. It is zeroed after every `Body.update`. See also `Body.applyForce`. + * + * @property force + * @type vector + * @default { x: 0, y: 0 } + */ + force?: Vector; + /** + * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`. + * A value of `0` means that the body may slide indefinitely. + * A value of `1` means the body may come to a stop almost instantly after a force is applied. + * + * The effects of the value may be non-linear. + * High values may be unstable depending on the body. + * The engine uses a Coulomb friction model including static and kinetic friction. + * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula: + * + * Math.min(bodyA.friction, bodyB.friction) + * + * @property friction + * @type number + * @default 0.1 + */ + friction?: number; + /** + * A `Number` that defines the air friction of the body (air resistance). + * A value of `0` means the body will never slow as it moves through space. + * The higher the value, the faster a body slows when moving through space. + * The effects of the value are non-linear. + * + * @property frictionAir + * @type number + * @default 0.01 + */ + frictionAir?: number; + /** + * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`. + * + * @property id + * @type number + */ + id?: number; + /** + * A `Number` that defines the moment of inertia (i.e. second moment of area) of the body. + * It is automatically calculated from the given convex hull (`vertices` array) and density in `Body.create`. + * If you modify this value, you must also modify the `body.inverseInertia` property (`1 / inertia`). + * + * @property inertia + * @type number + */ + inertia?: number; + /** + * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`). + * If you modify this value, you must also modify the `body.inertia` property. + * + * @property inverseInertia + * @type number + */ + inverseInertia?: number; + /** + * A `Number` that defines the inverse mass of the body (`1 / mass`). + * If you modify this value, you must also modify the `body.mass` property. + * + * @property inverseMass + * @type number + */ + inverseMass?: number; + /** + * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically. + * + * @property isSensor + * @type boolean + * @default false + */ + isSensor?: boolean; + /** + * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken. + * If you need to set a body as sleeping, you should use `Sleeping.set` as this requires more than just setting this flag. + * + * @property isSleeping + * @type boolean + * @default false + */ + isSleeping?: boolean; + /** + * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed. + * If you need to set a body as static after its creation, you should use `Body.setStatic` as this requires more than just setting this flag. + * + * @property isStatic + * @type boolean + * @default false + */ + isStatic?: boolean; + /** + * An arbitrary `String` name to help the user identify and manage bodies. + * + * @property label + * @type string + * @default "Body" + */ + + label?: string; + /** + * A `Number` that defines the mass of the body, although it may be more appropriate to specify the `density` property instead. + * If you modify this value, you must also modify the `body.inverseMass` property (`1 / mass`). + * + * @property mass + * @type number + */ + mass?: number; + /** + * A `Number` that _measures_ the amount of movement a body currently has (a combination of `speed` and `angularSpeed`). It is read-only and always positive. + * It is used and updated by the `Matter.Sleeping` module during simulation to decide if a body has come to rest. + * + * @readOnly + * @property motion + * @type number + * @default 0 + */ + motion?: number; + /** + * An object reserved for storing plugin-specific properties. + * + * @property plugin + * @type {} + */ + plugin?: any; + /** + * A `Vector` that specifies the current world-space position of the body. + * + * @property position + * @type vector + * @default { x: 0, y: */ + position?: Vector; + /** + * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. + * + * @property render + * @type object + */ + render?: IBodyRenderOptions; + /** + * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`. + * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. + * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy. + * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula: + * + * Math.max(bodyA.restitution, bodyB.restitution) + * + * @property restitution + * @type number + * @default 0 + */ + restitution?: number; + /** + * A `Number` that defines the number of updates in which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine). + * + * @property sleepThreshold + * @type number + * @default 60 + */ + sleepThreshold?: number; + /** + * A `Number` that specifies a tolerance on how far a body is allowed to 'sink' or rotate into other bodies. + * Avoid changing this value unless you understand the purpose of `slop` in physics engines. + * The default should generally suffice, although very large bodies may require larger values for stable stacking. + * + * @property slop + * @type number + * @default 0.05 + */ + slop?: number; + /** + * A `Number` that _measures_ the current speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.velocity`). + * + * @readOnly + * @property speed + * @type number + * @default 0 + */ + speed?: number; + /** + * A `Number` that allows per-body time scaling, e.g. a force-field where bodies inside are in slow-motion, while others are at full speed. + * + * @property timeScale + * @type number + * @default 1 + */ + timeScale?: number; + /** + * A `Number` that specifies the torque (turning force) to apply in the current step. It is zeroed after every `Body.update`. + * + * @property torque + * @type number + * @default 0 + */ + torque?: number; + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "body" + */ + type?: string; + /** + * A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only. + * If you need to modify a body's velocity directly, you should either apply a force or simply change the body's `position` (as the engine uses position-Verlet integration). + * + * @readOnly + * @property velocity + * @type vector + * @default { x: 0, y: 0 } + */ + velocity?: Vector; + /** + * An array of `Vector` objects that specify the convex hull of the rigid body. + * These should be provided about the origin `(0, 0)`. E.g. + * + * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }] + * + * When passed via `Body.create`, the vertices are translated relative to `body.position` (i.e. world-space, and constantly updated by `Body.update` during simulation). + * The `Vector` objects are also augmented with additional properties required for efficient collision detection. + * + * Other properties such as `inertia` and `bounds` are automatically calculated from the passed vertices (unless provided via `options`). + * Concave hulls are not currently supported. The module `Matter.Vertices` contains useful methods for working with vertices. + * + * @property vertices + * @type vector[] + */ + vertices?: Array; + /** + * An array of bodies that make up this body. + * The first body in the array must always be a self reference to the current body instance. + * All bodies in the `parts` array together form a single rigid compound body. + * Parts are allowed to overlap, have gaps or holes or even form concave bodies. + * Parts themselves should never be added to a `World`, only the parent body should be. + * Use `Body.setParts` when setting parts to ensure correct updates of all properties. + * + * @property parts + * @type body[] + */ + parts?: Array; + /** + * A self reference if the body is _not_ a part of another body. + * Otherwise this is a reference to the body that this is a part of. + * See `body.parts`. + * + * @property parent + * @type body + */ + parent?: Body; + /** + * A `Number` that defines the static friction of the body (in the Coulomb friction model). + * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used. + * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary. + * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction. + * + * @property frictionStatic + * @type number + * @default 0.5 + */ + frictionStatic?: number; + /** + * An `Object` that specifies the collision filtering properties of this body. + * + * Collisions between two bodies will obey the following rules: + * - If the two bodies have the same non-zero value of `collisionFilter.group`, + * they will always collide if the value is positive, and they will never collide + * if the value is negative. + * - If the two bodies have different values of `collisionFilter.group` or if one + * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows: + * + * Each body belongs to a collision category, given by `collisionFilter.category`. This + * value is used as a bit field and the category should have only one bit set, meaning that + * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32 + * different collision categories available. + * + * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies + * the categories it collides with (the value is the bitwise AND value of all these categories). + * + * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's + * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0` + * are both true. + * + * @property collisionFilter + * @type object + */ + collisionFilter?: ICollisionFilter; + + } + + export interface IBodyRenderOptions { + + /** + * A flag that indicates if the body should be rendered. + * + * @property render.visible + * @type boolean + * @default true + */ + visible?: boolean; + + /** + * An `Object` that defines the sprite properties to use when rendering, if any. + * + * @property render.sprite + * @type object + */ + sprite?: IBodyRenderOptionsSprite; + + /** + * A String that defines the fill style to use when rendering the body (if a sprite is not defined). It is the same as when using a canvas, so it accepts CSS style property values. + Default: a random colour + */ + fillStyle?: string; + + /** + * A Number that defines the line width to use when rendering the body outline (if a sprite is not defined). A value of 0 means no outline will be rendered. + Default: 1.5 + */ + lineWidth?: number; + + /** + * A String that defines the stroke style to use when rendering the body outline (if a sprite is not defined). It is the same as when using a canvas, so it accepts CSS style property values. + Default: a random colour + */ + strokeStyle?: string; + + + /* + * Sets the opacity. 1.0 is fully opaque. 0.0 is fully translucent + */ + opacity?: number; + } + + export interface IBodyRenderOptionsSprite { + /** + * An `String` that defines the path to the image to use as the sprite texture, if any. + * + * @property render.sprite.texture + * @type string + */ + texture: string; + + /** + * A `Number` that defines the scaling in the x-axis for the sprite, if any. + * + * @property render.sprite.xScale + * @type number + * @default 1 + */ + xScale: number; + + /** + * A `Number` that defines the scaling in the y-axis for the sprite, if any. + * + * @property render.sprite.yScale + * @type number + * @default 1 + */ + yScale: number; + } + + /** + * The `Matter.Body` module contains methods for creating and manipulating body models. + * A `Matter.Body` is a rigid body that can be simulated by a `Matter.Engine`. + * Factories for commonly used body configurations (such as rectangles, circles and other polygons) can be found in the module `Matter.Bodies`. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + + * @class Body + */ + export class Body { + /** + * Applies a force to a body from a given world-space position, including resulting torque. + * @method applyForce + * @param {body} body + * @param {vector} position + * @param {vector} force + */ + static applyForce(body: Body, position: Vector, force: Vector): void; + + /** + * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {} options + * @return {body} body + */ + static create(options: IBodyDefinition): Body; + /** + * Rotates a body by a given angle relative to its current angle, without imparting any angular velocity. + * @method rotate + * @param {body} body + * @param {number} rotation + */ + static rotate(body: Body, rotation: number): void; + /** + * Returns the next unique group index for which bodies will collide. + * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide. + * See `body.collisionFilter` for more information. + * @method nextGroup + * @param {bool} [isNonColliding=false] + * @return {Number} Unique group index + */ + static nextGroup(isNonColliding: boolean): number; + /** + * Returns the next unique category bitfield (starting after the initial default category `0x0001`). + * There are 32 available. See `body.collisionFilter` for more information. + * @method nextCategory + * @return {Number} Unique category bitfield + */ + static nextCategory(): number; + /** + * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist. + * Prefer to use the actual setter functions in performance critical situations. + * @method set + * @param {body} body + * @param {} settings A property name (or map of properties and values) to set on the body. + * @param {} value The value to set if `settings` is a single property name. + */ + static set(body: Body, settings: any, value?: any): void; + /** + * Sets the mass of the body. Inverse mass and density are automatically updated to reflect the change. + * @method setMass + * @param {body} body + * @param {number} mass + */ + static setMass(body: Body, mass: number): void; + /** + * Sets the density of the body. Mass is automatically updated to reflect the change. + * @method setDensity + * @param {body} body + * @param {number} density + */ + static setDensity(body: Body, density: number): void; + /** + * Sets the moment of inertia (i.e. second moment of area) of the body of the body. + * Inverse inertia is automatically updated to reflect the change. Mass is not changed. + * @method setInertia + * @param {body} body + * @param {number} inertia + */ + static setInertia(body: Body, interna: number): void; + /** + * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`). + * Vertices will be automatically transformed to be orientated around their centre of mass as the origin. + * They are then automatically translated to world space based on `body.position`. + * + * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array). + * Vertices must form a convex hull, concave hulls are not supported. + * + * @method setVertices + * @param {body} body + * @param {vector[]} vertices + */ + static setVertices(body: Body, vertices: Array): void; + /** + * Sets the parts of the `body` and updates mass, inertia and centroid. + * Each part will have its parent set to `body`. + * By default the convex hull will be automatically computed and set on `body`, unless `autoHull` is set to `false.` + * Note that this method will ensure that the first part in `body.parts` will always be the `body`. + * @method setParts + * @param {body} body + * @param [body] parts + * @param {bool} [autoHull=true] + */ + static setParts(body: Body, parts: Body[], autoHull?: boolean): void; + /** + * Set the centre of mass of the body. + * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation. + * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density. + * This is equal to moving `body.position` but not the `body.vertices`. + * Invalid if the `centre` falls outside the body's convex hull. + * @method setCentre + * @param body + * @param centre + * @param relative + */ + static setCentre(body: Body, centre: Vector, relative?: boolean): void; + /** + * Sets the position of the body instantly. Velocity, angle, force etc. are unchanged. + * @method setPosition + * @param {body} body + * @param {vector} position + */ + static setPosition(body: Body, position: Vector): void; + /** + * Sets the angle of the body instantly. Angular velocity, position, force etc. are unchanged. + * @method setAngle + * @param {body} body + * @param {number} angle + */ + static setAngle(body: Body, angle: number): void; + /** + * Sets the linear velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`. + * @method setVelocity + * @param {body} body + * @param {vector} velocity + */ + static setVelocity(body: Body, velocity: Vector): void; + /** + * Sets the angular velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`. + * @method setAngularVelocity + * @param {body} body + * @param {number} velocity + */ + static setAngularVelocity(body: Body, velocity: number): void; + + + /** + * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity. + * @method setStatic + * @param {body} body + * @param {bool} isStatic + */ + static setStatic(body: Body, isStatic: boolean): void; + + /** + * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre). + * @method scale + * @param {body} body + * @param {number} scaleX + * @param {number} scaleY + * @param {vector} [point] + */ + static scale(body: Body, scaleX: number, scaleY: number, point?: Vector): void; + + /** + * Moves a body by a given vector relative to its current position, without imparting any velocity. + * @method translate + * @param {body} body + * @param {vector} translation + */ + static translate(body: Body, translation: Vector): void; + + /** + * Performs a simulation step for the given `body`, including updating position and angle using Verlet integration. + * @method update + * @param {body} body + * @param {number} deltaTime + * @param {number} timeScale + * @param {number} correction + */ + static update(body: Body, deltaTime: number, timeScale: number, correction: number): void; + + /** + * A `Number` specifying the angle of the body, in radians. + * + * @property angle + * @type number + * @default 0 + */ + angle: number; + /** + * A `Number` that _measures_ the current angular speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.angularVelocity`). + * + * @readOnly + * @property angularSpeed + * @type number + * @default 0 + */ + angularSpeed: number; + /** + * A `Number` that _measures_ the current angular velocity of the body after the last `Body.update`. It is read-only. + * If you need to modify a body's angular velocity directly, you should apply a torque or simply change the body's `angle` (as the engine uses position-Verlet integration). + * + * @readOnly + * @property angularVelocity + * @type number + * @default 0 + */ + angularVelocity: number; + /** + * A `Number` that _measures_ the area of the body's convex hull, calculated at creation by `Body.create`. + * + * @property area + * @type string + * @default + */ + area: number; + /** + * An array of unique axis vectors (edge normals) used for collision detection. + * These are automatically calculated from the given convex hull (`vertices` array) in `Body.create`. + * They are constantly updated by `Body.update` during the simulation. + * + * @property axes + * @type vector[] + */ + axes: Array; + /** + * A `Bounds` object that defines the AABB region for the body. + * It is automatically calculated from the given convex hull (`vertices` array) in `Body.create` and constantly updated by `Body.update` during simulation. + * + * @property bounds + * @type bounds + */ + bounds: Bounds; + /** + * A `Number` that is set to the radius of the object if the body was constructed using `Bodies.circle`. + * May have a value of `null` if the body is no longer a circle (i.e. was scaled with a scaleX != scaleY). + * + * @property circleRadius + * @default 0 + */ + circleRadius?: number; + /** + * A `Number` that defines the density of the body, that is its mass per unit area. + * If you pass the density via `Body.create` the `mass` property is automatically calculated for you based on the size (area) of the object. + * This is generally preferable to simply setting mass and allows for more intuitive definition of materials (e.g. rock has a higher density than wood). + * + * @property density + * @type number + * @default 0.001 + */ + density: number; + /** + * A `Vector` that specifies the force to apply in the current step. It is zeroed after every `Body.update`. See also `Body.applyForce`. + * + * @property force + * @type vector + * @default { x: 0, y: 0 } + */ + force: Vector; + /** + * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`. + * A value of `0` means that the body may slide indefinitely. + * A value of `1` means the body may come to a stop almost instantly after a force is applied. + * + * The effects of the value may be non-linear. + * High values may be unstable depending on the body. + * The engine uses a Coulomb friction model including static and kinetic friction. + * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula: + * + * Math.min(bodyA.friction, bodyB.friction) + * + * @property friction + * @type number + * @default 0.1 + */ + friction: number; + /** + * A `Number` that defines the air friction of the body (air resistance). + * A value of `0` means the body will never slow as it moves through space. + * The higher the value, the faster a body slows when moving through space. + * The effects of the value are non-linear. + * + * @property frictionAir + * @type number + * @default 0.01 + */ + frictionAir: number; + /** + * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`. + * + * @property id + * @type number + */ + id: number; + /** + * A `Number` that defines the moment of inertia (i.e. second moment of area) of the body. + * It is automatically calculated from the given convex hull (`vertices` array) and density in `Body.create`. + * If you modify this value, you must also modify the `body.inverseInertia` property (`1 / inertia`). + * + * @property inertia + * @type number + */ + inertia: number; + /** + * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`). + * If you modify this value, you must also modify the `body.inertia` property. + * + * @property inverseInertia + * @type number + */ + inverseInertia: number; + /** + * A `Number` that defines the inverse mass of the body (`1 / mass`). + * If you modify this value, you must also modify the `body.mass` property. + * + * @property inverseMass + * @type number + */ + inverseMass: number; + /** + * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken. + * If you need to set a body as sleeping, you should use `Sleeping.set` as this requires more than just setting this flag. + * + * @property isSleeping + * @type boolean + * @default false + */ + isSleeping: boolean; + /** + * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed. + * If you need to set a body as static after its creation, you should use `Body.setStatic` as this requires more than just setting this flag. + * + * @property isStatic + * @type boolean + * @default false + */ + isStatic: boolean; + /** + * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically. + * + * @property isSensor + * @type boolean + * @default false + */ + isSensor: boolean; + /** + * An arbitrary `String` name to help the user identify and manage bodies. + * + * @property label + * @type string + * @default "Body" + */ + + label: string; + /** + * A `Number` that defines the mass of the body, although it may be more appropriate to specify the `density` property instead. + * If you modify this value, you must also modify the `body.inverseMass` property (`1 / mass`). + * + * @property mass + * @type number + */ + mass: number; + /** + * A `Number` that _measures_ the amount of movement a body currently has (a combination of `speed` and `angularSpeed`). It is read-only and always positive. + * It is used and updated by the `Matter.Sleeping` module during simulation to decide if a body has come to rest. + * + * @readOnly + * @property motion + * @type number + * @default 0 + */ + motion: number; + /** + * A `Vector` that specifies the current world-space position of the body. + * + * @property position + * @type vector + * @default { x: 0, y: */ + position: Vector; + /** + * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. + * + * @property render + * @type object + */ + render: IBodyRenderOptions; + /** + * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`. + * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. + * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy. + * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula: + * + * Math.max(bodyA.restitution, bodyB.restitution) + * + * @property restitution + * @type number + * @default 0 + */ + restitution: number; + /** + * A `Number` that defines the number of updates in which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine). + * + * @property sleepThreshold + * @type number + * @default 60 + */ + sleepThreshold: number; + /** + * A `Number` that specifies a tolerance on how far a body is allowed to 'sink' or rotate into other bodies. + * Avoid changing this value unless you understand the purpose of `slop` in physics engines. + * The default should generally suffice, although very large bodies may require larger values for stable stacking. + * + * @property slop + * @type number + * @default 0.05 + */ + slop: number; + /** + * A `Number` that _measures_ the current speed of the body after the last `Body.update`. It is read-only and always positive (it's the magnitude of `body.velocity`). + * + * @readOnly + * @property speed + * @type number + * @default 0 + */ + speed: number; + /** + * A `Number` that allows per-body time scaling, e.g. a force-field where bodies inside are in slow-motion, while others are at full speed. + * + * @property timeScale + * @type number + * @default 1 + */ + timeScale: number; + /** + * A `Number` that specifies the torque (turning force) to apply in the current step. It is zeroed after every `Body.update`. + * + * @property torque + * @type number + * @default 0 + */ + torque: number; + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "body" + */ + type: string; + /** + * A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only. + * If you need to modify a body's velocity directly, you should either apply a force or simply change the body's `position` (as the engine uses position-Verlet integration). + * + * @readOnly + * @property velocity + * @type vector + * @default { x: 0, y: 0 } + */ + velocity: Vector; + /** + * An array of `Vector` objects that specify the convex hull of the rigid body. + * These should be provided about the origin `(0, 0)`. E.g. + * + * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }] + * + * When passed via `Body.create`, the vertices are translated relative to `body.position` (i.e. world-space, and constantly updated by `Body.update` during simulation). + * The `Vector` objects are also augmented with additional properties required for efficient collision detection. + * + * Other properties such as `inertia` and `bounds` are automatically calculated from the passed vertices (unless provided via `options`). + * Concave hulls are not currently supported. The module `Matter.Vertices` contains useful methods for working with vertices. + * + * @property vertices + * @type vector[] + */ + vertices: Array; + /** + * An array of bodies that make up this body. + * The first body in the array must always be a self reference to the current body instance. + * All bodies in the `parts` array together form a single rigid compound body. + * Parts are allowed to overlap, have gaps or holes or even form concave bodies. + * Parts themselves should never be added to a `World`, only the parent body should be. + * Use `Body.setParts` when setting parts to ensure correct updates of all properties. + * + * @property parts + * @type body[] + */ + parts: Array; + /** + * A self reference if the body is _not_ a part of another body. + * Otherwise this is a reference to the body that this is a part of. + * See `body.parts`. + * + * @property parent + * @type body + */ + parent: Body; + /** + * An object reserved for storing plugin-specific properties. + * + * @property plugin + */ + plugin: any; + /** + * A `Number` that defines the static friction of the body (in the Coulomb friction model). + * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used. + * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary. + * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction. + * + * @property frictionStatic + * @type number + * @default 0.5 + */ + frictionStatic: number; + /** + * An `Object` that specifies the collision filtering properties of this body. + * + * Collisions between two bodies will obey the following rules: + * - If the two bodies have the same non-zero value of `collisionFilter.group`, + * they will always collide if the value is positive, and they will never collide + * if the value is negative. + * - If the two bodies have different values of `collisionFilter.group` or if one + * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows: + * + * Each body belongs to a collision category, given by `collisionFilter.category`. This + * value is used as a bit field and the category should have only one bit set, meaning that + * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32 + * different collision categories available. + * + * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies + * the categories it collides with (the value is the bitwise AND value of all these categories). + * + * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's + * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0` + * are both true. + * + * @property collisionFilter + * @type object + */ + collisionFilter: ICollisionFilter; + + /** + * A ct.js copy that owns this Body object. + */ + copy: Copy + } + + /** + * The `Matter.Bounds` module contains methods for creating and manipulating axis-aligned bounding boxes (AABB). + * + * @class Bounds + */ + export class Bounds { + min: Vector; + max: Vector; + + /** + * Creates a new axis-aligned bounding box (AABB) for the given vertices. + * @method create + * @param {vertices} vertices + * @return {bounds} A new bounds object + */ + static create (vertices: Vertices): Bounds; + /** + * Updates bounds using the given vertices and extends the bounds given a velocity. + * @method update + * @param {bounds} bounds + * @param {vertices} vertices + * @param {vector} velocity + */ + static update(bounds: Bounds, vertices: Vertices, velocity: Vector): void; + /** + * Returns true if the bounds contains the given point. + * @method contains + * @param {bounds} bounds + * @param {vector} point + * @return {boolean} True if the bounds contain the point, otherwise false + */ + static contains(bounds: Bounds, point: Vector): boolean; + /** + * Returns true if the two bounds intersect. + * @method overlaps + * @param {bounds} boundsA + * @param {bounds} boundsB + * @return {boolean} True if the bounds overlap, otherwise false + */ + static overlaps(boundsA: Bounds, boundsB: Bounds): boolean; + /** + * Translates the bounds by the given vector. + * @method translate + * @param {bounds} bounds + * @param {vector} vector + */ + static translate(bounds: Bounds, vector: Vector): void; + /** + * Shifts the bounds to the given position. + * @method shift + * @param {bounds} bounds + * @param {vector} position + */ + static shift(bounds: Bounds, position: Vector): void; + } + + export interface ICompositeDefinition { + /** + * An array of `Body` that are _direct_ children of this composite. + * To add or remove bodies you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allBodies` method. + * + * @property bodies + * @type body[] + * @default [] + */ + bodies?: Array; + + /** + * An array of `Composite` that are _direct_ children of this composite. + * To add or remove composites you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allComposites` method. + * + * @property composites + * @type composite[] + * @default [] + */ + composites?: Array; + + /** + * An array of `Constraint` that are _direct_ children of this composite. + * To add or remove constraints you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allConstraints` method. + * + * @property constraints + * @type constraint[] + * @default [] + */ + constraints?: Array; + + /** + * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. + * + * @property id + * @type number + */ + id?: number; + + /** + * A flag that specifies whether the composite has been modified during the current step. + * Most `Matter.Composite` methods will automatically set this flag to `true` to inform the engine of changes to be handled. + * If you need to change it manually, you should use the `Composite.setModified` method. + * + * @property isModified + * @type boolean + * @default false + */ + isModified?: boolean; + + /** + * An arbitrary `String` name to help the user identify and manage composites. + * + * @property label + * @type string + * @default "Composite" + */ + label?: string; + + /** + * The `Composite` that is the parent of this composite. It is automatically managed by the `Matter.Composite` methods. + * + * @property parent + * @type composite + * @default null + */ + parent?: Composite; + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "composite" + */ + type?: string; + } + + /** + * The `Matter.Composite` module contains methods for creating and manipulating composite bodies. + * A composite body is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`, therefore composites form a tree structure. + * It is important to use the functions in this module to modify composites, rather than directly modifying their properties. + * Note that the `Matter.World` object is also a type of `Matter.Composite` and as such all composite methods here can also operate on a `Matter.World`. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Composite + */ + export class Composite { + /** + * Generic add function. Adds one or many body(s), constraint(s) or a composite(s) to the given composite. + * Triggers `beforeAdd` and `afterAdd` events on the `composite`. + * @method add + * @param {composite} composite + * @param {} object + * @return {composite} The original composite with the objects added + */ + static add(composite: Composite, object: Body | Composite | Constraint): Composite; + + /** + * Returns all bodies in the given composite, including all bodies in its children, recursively. + * @method allBodies + * @param {composite} composite + * @return {body[]} All the bodies + */ + static allBodies(composite: Composite): Array; + + /** + * Returns all composites in the given composite, including all composites in its children, recursively. + * @method allComposites + * @param {composite} composite + * @return {composite[]} All the composites + */ + static allComposites(composite: Composite): Array; + + /** + * Returns all constraints in the given composite, including all constraints in its children, recursively. + * @method allConstraints + * @param {composite} composite + * @return {constraint[]} All the constraints + */ + static allConstraints(composite: Composite): Array; + + /** + * Removes all bodies, constraints and composites from the given composite. + * Optionally clearing its children recursively. + * @method clear + * @param {composite} composite + * @param {boolean} keepStatic + * @param {boolean} [deep=false] + */ + static clear(composite: Composite, keepStatic: boolean, deep?: boolean): void; + + /** + * Creates a new composite. The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properites section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {} [options] + * @return {composite} A new composite + */ + static create(options?: ICompositeDefinition): Composite; + + /** + * Searches the composite recursively for an object matching the type and id supplied, null if not found. + * @method get + * @param {composite} composite + * @param {number} id + * @param {string} type + * @return {object} The requested object, if found + */ + static get(composite: Composite, id: number, type: string): Body | Composite | Constraint; + + /** + * Moves the given object(s) from compositeA to compositeB (equal to a remove followed by an add). + * @method move + * @param {compositeA} compositeA + * @param {object[]} objects + * @param {compositeB} compositeB + * @return {composite} Returns compositeA + */ + static move(compositeA: Composite, objects: Array, compositeB: Composite): Composite; + + /** + * Assigns new ids for all objects in the composite, recursively. + * @method rebase + * @param {composite} composite + * @return {composite} Returns composite + */ + static rebase(composite: Composite): Composite; + + /** + * Generic remove function. Removes one or many body(s), constraint(s) or a composite(s) to the given composite. + * Optionally searching its children recursively. + * Triggers `beforeRemove` and `afterRemove` events on the `composite`. + * @method remove + * @param {composite} composite + * @param {} object + * @param {boolean} [deep=false] + * @return {composite} The original composite with the objects removed + */ + static remove(composite: Composite, object: Body | Composite | Constraint, deep?: boolean): Composite; + + + /** + * Sets the composite's `isModified` flag. + * If `updateParents` is true, all parents will be set (default: false). + * If `updateChildren` is true, all children will be set (default: false). + * @method setModified + * @param {composite} composite + * @param {boolean} isModified + * @param {boolean} [updateParents=false] + * @param {boolean} [updateChildren=false] + */ + static setModified(composite: Composite, isModified: boolean, updateParents?: boolean, updateChildren?: boolean): void; + /** + * Translates all children in the composite by a given vector relative to their current positions, + * without imparting any velocity. + * @method translate + * @param {composite} composite + * @param {vector} translation + * @param {bool} [recursive=true] + */ + static translate(composite: Composite, translation: Vector, recursive?: boolean): void; + /** + * Rotates all children in the composite by a given angle about the given point, without imparting any angular velocity. + * @method rotate + * @param {composite} composite + * @param {number} rotation + * @param {vector} point + * @param {bool} [recursive=true] + */ + static rotate(composite: Composite, rotation: number, point: Vector, recursive?: boolean): void; + /** + * Scales all children in the composite, including updating physical properties (mass, area, axes, inertia), from a world-space point. + * @method scale + * @param {composite} composite + * @param {number} scaleX + * @param {number} scaleY + * @param {vector} point + * @param {bool} [recursive=true] + */ + static scale(composite: Composite, scaleX: number, scaleY: number, point: Vector, recursive?: boolean): void; + + + /** + * An array of `Body` that are _direct_ children of this composite. + * To add or remove bodies you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allBodies` method. + * + * @property bodies + * @type body[] + * @default [] + */ + bodies: Array; + + /** + * An array of `Composite` that are _direct_ children of this composite. + * To add or remove composites you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allComposites` method. + * + * @property composites + * @type composite[] + * @default [] + */ + composites: Array; + + /** + * An array of `Constraint` that are _direct_ children of this composite. + * To add or remove constraints you should use `Composite.add` and `Composite.remove` methods rather than directly modifying this property. + * If you wish to recursively find all descendants, you should use the `Composite.allConstraints` method. + * + * @property constraints + * @type constraint[] + * @default [] + */ + constraints: Array; + + /** + * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. + * + * @property id + * @type number + */ + id: number; + + /** + * A flag that specifies whether the composite has been modified during the current step. + * Most `Matter.Composite` methods will automatically set this flag to `true` to inform the engine of changes to be handled. + * If you need to change it manually, you should use the `Composite.setModified` method. + * + * @property isModified + * @type boolean + * @default false + */ + isModified: boolean; + + /** + * An arbitrary `String` name to help the user identify and manage composites. + * + * @property label + * @type string + * @default "Composite" + */ + label: string; + + /** + * The `Composite` that is the parent of this composite. It is automatically managed by the `Matter.Composite` methods. + * + * @property parent + * @type composite + * @default null + */ + parent: Composite; + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "composite" + */ + type: string; + } + + /** + * The `Matter.Composites` module contains factory methods for creating composite bodies + * with commonly used configurations (such as stacks and chains). + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Composites + */ + export class Composites { + /** + * Creates a composite with simple car setup of bodies and constraints. + * @method car + * @param {number} xx + * @param {number} yy + * @param {number} width + * @param {number} height + * @param {number} wheelSize + * @return {composite} A new composite car body + */ + static car(xx: number, yy: number, width: number, height: number, wheelSize: number): Composite; + + /** + * Chains all bodies in the given composite together using constraints. + * @method chain + * @param {composite} composite + * @param {number} xOffsetA + * @param {number} yOffsetA + * @param {number} xOffsetB + * @param {number} yOffsetB + * @param {object} options + * @return {composite} A new composite containing objects chained together with constraints + */ + static chain(composite: Composite, xOffsetA: number, yOffsetA: number, xOffsetB: number, yOffsetB: number, options: any): Composite; + + /** + * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces. + * @method mesh + * @param {composite} composite + * @param {number} columns + * @param {number} rows + * @param {boolean} crossBrace + * @param {object} options + * @return {composite} The composite containing objects meshed together with constraints + */ + static mesh(composite: Composite, columns: number, rows: number, crossBrace: boolean, options: any): Composite; + + /** + * Creates a composite with a Newton's Cradle setup of bodies and constraints. + * @method newtonsCradle + * @param {number} xx + * @param {number} yy + * @param {number} number + * @param {number} size + * @param {number} length + * @return {composite} A new composite newtonsCradle body + */ + static newtonsCradle(xx: number, yy: number, _number: number, size: number, length: number): Composite; + + /** + * Create a new composite containing bodies created in the callback in a pyramid arrangement. + * This function uses the body's bounds to prevent overlaps. + * @method pyramid + * @param {number} xx + * @param {number} yy + * @param {number} columns + * @param {number} rows + * @param {number} columnGap + * @param {number} rowGap + * @param {function} callback + * @return {composite} A new composite containing objects created in the callback + */ + static pyramid(xx: number, yy: number, columns: number, rows: number, columnGap: number, rowGap: number, callback: Function): Composite; + + /** + * Creates a simple soft body like object. + * @method softBody + * @param {number} xx + * @param {number} yy + * @param {number} columns + * @param {number} rows + * @param {number} columnGap + * @param {number} rowGap + * @param {boolean} crossBrace + * @param {number} particleRadius + * @param {} particleOptions + * @param {} constraintOptions + * @return {composite} A new composite softBody + */ + static softBody(xx: number, yy: number, columns: number, rows: number, columnGap: number, rowGap: number, crossBrace: boolean, particleRadius: number, particleOptions: any, constraintOptions: any): Composite; + + /** + * Create a new composite containing bodies created in the callback in a grid arrangement. + * This function uses the body's bounds to prevent overlaps. + * @method stack + * @param {number} xx + * @param {number} yy + * @param {number} columns + * @param {number} rows + * @param {number} columnGap + * @param {number} rowGap + * @param {function} callback + * @return {composite} A new composite containing objects created in the callback + */ + static stack(xx: number, yy: number, columns: number, rows: number, columnGap: number, rowGap: number, callback: Function): Composite; + } + + export interface IConstraintDefinition { + /** + * The first possible `Body` that this constraint is attached to. + * + * @property bodyA + * @type body + * @default null + */ + bodyA?: Body; + + /** + * The second possible `Body` that this constraint is attached to. + * + * @property bodyB + * @type body + * @default null + */ + bodyB?: Body; + + /** + * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. + * + * @property id + * @type number + */ + id?: number; + + /** + * An arbitrary `String` name to help the user identify and manage bodies. + * + * @property label + * @type string + * @default "Constraint" + */ + label?: string; + + /** + * A `Number` that specifies the target resting length of the constraint. + * It is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * + * @property length + * @type number + */ + length?: number; + + /** + * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position. + * + * @property pointA + * @type vector + * @default { x: 0, y: 0 } + */ + pointA?: Vector; + + /** + * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position. + * + * @property pointB + * @type vector + * @default { x: 0, y: 0 } + */ + pointB?: Vector; + + /** + * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. + * + * @property render + * @type object + */ + render?: IConstraintRenderDefinition; + + /** + * A `Number` that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. + * A value of `1` means the constraint should be very stiff. + * A value of `0.2` means the constraint acts like a soft spring. + * + * @property stiffness + * @type number + * @default 1 + */ + stiffness?: number; + + /** + * A `Number` that specifies the damping of the constraint, + * i.e. the amount of resistance applied to each body based on their velocities to limit the amount of oscillation. + * Damping will only be apparent when the constraint also has a very low `stiffness`. + * A value of `0.1` means the constraint will apply heavy damping, resulting in little to no oscillation. + * A value of `0` means the constraint will apply no damping. + * + * @property damping + * @type number + * @default 0 + */ + damping?: number; + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "constraint" + */ + type?: string; + } + + export interface IConstraintRenderDefinition { + /** + * A `Number` that defines the line width to use when rendering the constraint outline. + * A value of `0` means no outline will be rendered. + * + * @property render.lineWidth + * @type number + * @default 2 + */ + lineWidth?: number; + + /** + * A `String` that defines the stroke style to use when rendering the constraint outline. + * It is the same as when using a canvas, so it accepts CSS style property values. + * + * @property render.strokeStyle + * @type string + * @default a random colour + */ + strokeStyle?: string; + + /** + * A flag that indicates if the constraint should be rendered. + * + * @property render.visible + * @type boolean + * @default true + */ + visible?: boolean; + + /** + * A `Boolean` that defines if the constraint's anchor points should be rendered. + * + * @property render.anchors + * @type boolean + * @default true + */ + anchors?: boolean; + + /** + * A String that defines the constraint rendering type. The possible values are + * 'line', 'pin', 'spring'. An appropriate render type will be automatically + * chosen unless one is given in options. + * + * @property render.type + * @type string + * @default 'line' + */ + type?: 'line' | 'pin' | 'spring'; + } + + + /** + * The `Matter.Constraint` module contains methods for creating and manipulating constraints. + * Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position). + * The stiffness of constraints can be modified to create springs or elastic. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Constraint + */ + export class Constraint { + /** + * Creates a new constraint. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {} options + * @return {constraint} constraint + */ + static create(options: IConstraintDefinition): Constraint; + + /** + * The first possible `Body` that this constraint is attached to. + * + * @property bodyA + * @type body + * @default null + */ + bodyA: Body; + + /** + * The second possible `Body` that this constraint is attached to. + * + * @property bodyB + * @type body + * @default null + */ + bodyB: Body; + + /** + * An integer `Number` uniquely identifying number generated in `Composite.create` by `Common.nextId`. + * + * @property id + * @type number + */ + id: number; + + /** + * An arbitrary `String` name to help the user identify and manage bodies. + * + * @property label + * @type string + * @default "Constraint" + */ + label: string; + + /** + * A `Number` that specifies the target resting length of the constraint. + * It is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`. + * + * @property length + * @type number + */ + length: number; + + /** + * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position. + * + * @property pointA + * @type vector + * @default { x: 0, y: 0 } + */ + pointA: Vector; + + /** + * A `Vector` that specifies the offset of the constraint from center of the `constraint.bodyA` if defined, otherwise a world-space position. + * + * @property pointB + * @type vector + * @default { x: 0, y: 0 } + */ + pointB: Vector; + + /** + * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`. + * + * @property render + * @type object + */ + render: IConstraintRenderDefinition; + + /** + * A `Number` that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. + * A value of `1` means the constraint should be very stiff. + * A value of `0.2` means the constraint acts like a soft spring. + * + * @property stiffness + * @type number + * @default 1 + */ + stiffness: number; + + /** + * A `Number` that specifies the damping of the constraint, + * i.e. the amount of resistance applied to each body based on their velocities to limit the amount of oscillation. + * Damping will only be apparent when the constraint also has a very low `stiffness`. + * A value of `0.1` means the constraint will apply heavy damping, resulting in little to no oscillation. + * A value of `0` means the constraint will apply no damping. + * + * @property damping + * @type number + * @default 0 + */ + damping: number; + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "constraint" + */ + type: string; + } + + + export interface IEngineDefinition { + /** + * An integer `Number` that specifies the number of position iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * + * @property positionIterations + * @type number + * @default 6 + */ + positionIterations?: number; + /** + * An integer `Number` that specifies the number of velocity iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * + * @property velocityIterations + * @type number + * @default 4 + */ + velocityIterations?: number; + /** + * An integer `Number` that specifies the number of constraint iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * The default value of `2` is usually very adequate. + * + * @property constraintIterations + * @type number + * @default 2 + */ + constraintIterations?: number; + + /** + * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module. + * Sleeping can improve stability and performance, but often at the expense of accuracy. + * + * @property enableSleeping + * @type boolean + * @default false + */ + enableSleeping?: boolean; + /** + * An `Object` containing properties regarding the timing systems of the engine. + * + * @property timing + * @type object + */ + timing?: IEngineTimingOptions; + /** + * An instance of a broadphase controller. The default value is a `Matter.Grid` instance created by `Engine.create`. + * + * @property broadphase + * @type grid + * @default a Matter.Grid instance + */ + grid?: Grid; + /** + * A `World` composite object that will contain all simulated bodies and constraints. + * + * @property world + * @type world + * @default a Matter.World instance + */ + world?: World; + + } + + export interface IEngineTimingOptions { + /** + * A `Number` that specifies the global scaling factor of time for all bodies. + * A value of `0` freezes the simulation. + * A value of `0.1` gives a slow-motion effect. + * A value of `1.2` gives a speed-up effect. + * + * @property timing.timeScale + * @type number + * @default 1 + */ + timeScale: number; + + /** + * A `Number` that specifies the current simulation-time in milliseconds starting from `0`. + * It is incremented on every `Engine.update` by the given `delta` argument. + * + * @property timing.timestamp + * @type number + * @default 0 + */ + timestamp: number; + } + + /** + * The `Matter.Engine` module contains methods for creating and manipulating engines. + * An engine is a controller that manages updating the simulation of the world. + * See `Matter.Runner` for an optional game loop utility. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Engine + */ + export class Engine { + /** + * Clears the engine including the world, pairs and broadphase. + * @method clear + * @param {engine} engine + */ + static clear(engine: Engine): void; + + /** + * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {HTMLElement} element + * @param {object} [options] + * @return {engine} engine + */ + static create(element?: HTMLElement | IEngineDefinition, options?: IEngineDefinition): Engine; + + /** + * Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {object} [options] + * @return {engine} engine + * @deprecated + */ + static create(options?: IEngineDefinition): Engine; + + /** + * Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`. + * @method merge + * @param {engine} engineA + * @param {engine} engineB + */ + static merge(engineA: Engine, engineB: Engine): void; + + + /** + * Moves the simulation forward in time by `delta` ms. + * The `correction` argument is an optional `Number` that specifies the time correction factor to apply to the update. + * This can help improve the accuracy of the simulation in cases where `delta` is changing between updates. + * The value of `correction` is defined as `delta / lastDelta`, i.e. the percentage change of `delta` over the last step. + * Therefore the value is always `1` (no correction) when `delta` constant (or when no correction is desired, which is the default). + * See the paper on Time Corrected Verlet for more information. + * + * Triggers `beforeUpdate` and `afterUpdate` events. + * Triggers `collisionStart`, `collisionActive` and `collisionEnd` events. + * @method update + * @param {engine} engine + * @param {number} [delta=16.666] + * @param {number} [correction=1] + */ + static update(engine: Engine, delta?: number, correction?: number): Engine; + + /** + * An alias for `Runner.run`, see `Matter.Runner` for more information. + * @method run + * @param {engine} engine + */ + static run(enige: Engine): void; + + /** + * An instance of a broadphase controller. The default value is a `Matter.Grid` instance created by `Engine.create`. + * + * @property broadphase + * @type grid + * @default a Matter.Grid instance + */ + broadphase: Grid; + /** + * An integer `Number` that specifies the number of constraint iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * The default value of `2` is usually very adequate. + * + * @property constraintIterations + * @type number + * @default 2 + */ + constraintIterations: number; + + /** + * A flag that specifies whether the engine is running or not. + */ + enabled: boolean; + + /** + * A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module. + * Sleeping can improve stability and performance, but often at the expense of accuracy. + * + * @property enableSleeping + * @type boolean + * @default false + */ + enableSleeping: boolean; + + /** + * Collision pair set for this `Engine`. + */ + pairs: any; + + /** + * An integer `Number` that specifies the number of position iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * + * @property positionIterations + * @type number + * @default 6 + */ + positionIterations: number; + + /** + * An instance of a `Render` controller. The default value is a `Matter.Render` instance created by `Engine.create`. + * One may also develop a custom renderer module based on `Matter.Render` and pass an instance of it to `Engine.create` via `options.render`. + * + * A minimal custom renderer object must define at least three functions: `create`, `clear` and `world` (see `Matter.Render`). + * It is also possible to instead pass the _module_ reference via `options.render.controller` and `Engine.create` will instantiate one for you. + * + * @property render + * @type render + * @default a Matter.Render instance + */ + render: Render; + + /** + * An `Object` containing properties regarding the timing systems of the engine. + * + * @property timing + * @type object + */ + timing: IEngineTimingOptions; + + /** + * An integer `Number` that specifies the number of velocity iterations to perform each update. + * The higher the value, the higher quality the simulation will be at the expense of performance. + * + * @property velocityIterations + * @type number + * @default 4 + */ + velocityIterations: number; + + /** + * A `World` composite object that will contain all simulated bodies and constraints. + * + * @property world + * @type world + * @default a Matter.World instance + */ + world: World; + } + + + export interface IGridDefinition { + + } + + /** + * The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures. + * + * @class Grid + */ + export class Grid { + /** + * Creates a new grid. + * @method create + * @param {} options + * @return {grid} A new grid + */ + static create(options?: IGridDefinition): Grid; + + /** + * Updates the grid. + * @method update + * @param {grid} grid + * @param {body[]} bodies + * @param {engine} engine + * @param {boolean} forceUpdate + */ + static update(grid: Grid, bodies: Array, engine: Engine, forceUpdate: boolean): void; + + /** + * Clears the grid. + * @method clear + * @param {grid} grid + */ + static clear(grid: Grid): void; + + + /** + * The width of a single grid bucket. + * + * @property type + * @type number + */ + bucketWidth: number; + + /** + * The height of a single grid bucket. + * + * @property type + * @type number + */ + bucketHeight: number; + } + + export interface IMouseConstraintDefinition { + /** + * The `Constraint` object that is used to move the body during interaction. + * + * @property constraint + * @type constraint + */ + constraint?: Constraint; + + /** + * An `Object` that specifies the collision filter properties. + * The collision filter allows the user to define which types of body this mouse constraint can interact with. + * See `body.collisionFilter` for more information. + * + * @property collisionFilter + * @type object + */ + collisionFilter?: ICollisionFilter; + + /** + * The `Body` that is currently being moved by the user, or `null` if no body. + * + * @property body + * @type body + * @default null + */ + body?: Body; + + /** + * The `Mouse` instance in use. If not supplied in `MouseConstraint.create`, one will be created. + * + * @property mouse + * @type mouse + * @default mouse + */ + mouse?: Mouse; + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "constraint" + */ + + type?: string; + } + + /** + * The `Matter.MouseConstraint` module contains methods for creating mouse constraints. + * Mouse constraints are used for allowing user interaction, providing the ability to move bodies via the mouse or touch. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class MouseConstraint + */ + export class MouseConstraint { + /** + * Creates a new mouse constraint. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {engine} engine + * @param {} options + * @return {MouseConstraint} A new MouseConstraint + */ + static create(engine: Engine, options?: IMouseConstraintDefinition): MouseConstraint; + + /** + * The `Constraint` object that is used to move the body during interaction. + * + * @property constraint + * @type constraint + */ + constraint: Constraint; + + /** + * An `Object` that specifies the collision filter properties. + * The collision filter allows the user to define which types of body this mouse constraint can interact with. + * See `body.collisionFilter` for more information. + * + * @property collisionFilter + * @type object + */ + collisionFilter: ICollisionFilter; + + /** + * The `Body` that is currently being moved by the user, or `null` if no body. + * + * @property body + * @type body + * @default null + */ + body: Body; + + /** + * The `Mouse` instance in use. If not supplied in `MouseConstraint.create`, one will be created. + * + * @property mouse + * @type mouse + * @default mouse + */ + mouse: Mouse; + + /** + * A `String` denoting the type of object. + * + * @property type + * @type string + * @default "constraint" + */ + + type: string; + } + + /** + * The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets. + * + * @class Pairs + */ + export class Pairs { + /** + * Clears the given pairs structure. + * @method clear + * @param {pairs} pairs + * @return {pairs} pairs + */ + static clear(pairs: any): any; + } + + export interface IPair { + id: number; + bodyA: Body; + bodyB: Body; + contacts: any; + activeContacts: any; + separation: number; + isActive: boolean; + timeCreated: number; + timeUpdated: number, + inverseMass: number; + friction: number; + frictionStatic: number; + restitution: number; + slop: number; + } + + /** + * The `Matter.Query` module contains methods for performing collision queries. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Query + */ + export class Query { + /** + * Finds a list of collisions between body and bodies. + * @method collides + * @param {body} body + * @param {body[]} bodies + * @return {object[]} Collisions + */ + static collides(body: Body, bodies: Array): Array; + + /** + * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided. + * @method ray + * @param {body[]} bodies + * @param {vector} startPoint + * @param {vector} endPoint + * @param {number} [rayWidth] + * @return {object[]} Collisions + */ + static ray(bodies: Array, startPoint: Vector, endPoint: Vector, rayWidth?: number): Array; + + /** + * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies. + * @method region + * @param {body[]} bodies + * @param {bounds} bounds + * @param {bool} [outside=false] + * @return {body[]} The bodies matching the query + */ + static region(bodies: Array, bounds: Bounds, outside?: boolean): Array; + + /** + * Returns all bodies whose vertices contain the given point, from the given set of bodies. + * @method point + * @param {body[]} bodies + * @param {vector} point + * @return {body[]} The bodies matching the query + */ + static point(bodies: Array, point: Vector): Array; + } + + export interface IRenderDefinition { + /** + * A back-reference to the `Matter.Render` module. + * + * @property controller + * @type render + */ + controller?: any; + /** + * A reference to the `Matter.Engine` instance to be used. + * + * @property engine + * @type engine + */ + engine: Engine; + /** + * A reference to the element where the canvas is to be inserted (if `render.canvas` has not been specified) + * + * @property element + * @type HTMLElement + * @default null + * @deprecated + */ + element?: HTMLElement; + /** + * The canvas element to render to. If not specified, one will be created if `render.element` has been specified. + * + * @property canvas + * @type HTMLCanvasElement + * @default null + */ + canvas?: HTMLCanvasElement; + + /** + * The configuration options of the renderer. + * + * @property options + * @type {} + */ + options?: IRendererOptions; + + /** + * A `Bounds` object that specifies the drawing view region. + * Rendering will be automatically transformed and scaled to fit within the canvas size (`render.options.width` and `render.options.height`). + * This allows for creating views that can pan or zoom around the scene. + * You must also set `render.options.hasBounds` to `true` to enable bounded rendering. + * + * @property bounds + * @type bounds + */ + bounds?: Bounds; + + /** + * The 2d rendering context from the `render.canvas` element. + * + * @property context + * @type CanvasRenderingContext2D + */ + context?: CanvasRenderingContext2D; + + /** + * The sprite texture cache. + * + * @property textures + * @type {} + */ + textures?: any; + + + } + + export interface IRendererOptions { + /** + * The target width in pixels of the `render.canvas` to be created. + * + * @property options.width + * @type number + * @default 800 + */ + width?: number; + + /** + * The target height in pixels of the `render.canvas` to be created. + * + * @property options.height + * @type number + * @default 600 + */ + height?: number; + + /** + * A flag that specifies if `render.bounds` should be used when rendering. + * + * @property options.hasBounds + * @type boolean + * @default false + */ + hasBounds?: boolean; + + /** + * Render wireframes only + * @type boolean + * @default true + */ + wireframes?: boolean; + + /** + * Sets scene background + * @type string + * default undefined + */ + background?: string + + /** + * Sets wireframe background if `render.options.wireframes` is enabled + * @type string + * default undefined + */ + wireframeBackground?: string + + /** + * Sets opacity of sleeping body if `render.options.showSleeping` is enabled + * @type boolean + * default true + */ + showSleeping?: boolean; + } + + interface IRenderLookAtObject { + bounds?: Bounds; + position?: { + x: number; + y: number; + }; + min?: { + x: number; + y: number; + }; + max?: { + x: number; + y: number; + }; + } + + /** + * The `Matter.Render` module is a simple HTML5 canvas based renderer for visualising instances of `Matter.Engine`. + * It is intended for development and debugging purposes, but may also be suitable for simple games. + * It includes a number of drawing options including wireframe, vector with support for sprites and viewports. + * + * @class Render + */ + export class Render { + /** + * Creates a new renderer. The options parameter is an object that specifies any properties you wish to override the defaults. + * All properties have default values, and many are pre-calculated automatically based on other properties. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @param {object} [options] + * @return {render} A new renderer + */ + static create(options: IRenderDefinition): Render; + /** + * Continuously updates the render canvas on the `requestAnimationFrame` event. + * @method run + * @param {render} render + */ + static run(render: Render): void; + /** + * Ends execution of `Render.run` on the given `render`, by canceling the animation frame request event loop. + * @method stop + * @param {render} render + */ + static stop(render: Render): void; + /** + * Sets the pixel ratio of the renderer and updates the canvas. + * To automatically detect the correct ratio, pass the string `'auto'` for `pixelRatio`. + * @method setPixelRatio + * @param {render} render + * @param {number} pixelRatio + */ + static setPixelRatio(render: Render, pixelRatio: number): void; + /** + * Renders the given `engine`'s `Matter.World` object. + * This is the entry point for all rendering and should be called every time the scene changes. + * @method world + * @param {engine} engine + */ + static world(render: Render): void; + /** + * Positions and sizes the viewport around the given object bounds. + * @method lookAt + * @param {Render} render + * @param {IRenderLookAtObject | IRenderLookAtObject[]} objects + * @param {Vector} paddiing + * @param {boolean} center + */ + static lookAt(render: Render, objects: IRenderLookAtObject | IRenderLookAtObject[], paddiing?: Vector, center?: boolean): void; + + /** + * A back-reference to the `Matter.Render` module. + * + * @property controller + * @type render + */ + controller: any; + /** + * A reference to the element where the canvas is to be inserted (if `render.canvas` has not been specified) + * + * @property element + * @type HTMLElement + * @default null + */ + element: HTMLElement; + /** + * The canvas element to render to. If not specified, one will be created if `render.element` has been specified. + * + * @property canvas + * @type HTMLCanvasElement + * @default null + */ + canvas: HTMLCanvasElement; + + /** + * The configuration options of the renderer. + * + * @property options + * @type {} + */ + options: IRendererOptions; + + /** + * A `Bounds` object that specifies the drawing view region. + * Rendering will be automatically transformed and scaled to fit within the canvas size (`render.options.width` and `render.options.height`). + * This allows for creating views that can pan or zoom around the scene. + * You must also set `render.options.hasBounds` to `true` to enable bounded rendering. + * + * @property bounds + * @type bounds + */ + bounds: Bounds; + + /** + * The 2d rendering context from the `render.canvas` element. + * + * @property context + * @type CanvasRenderingContext2D + */ + context: CanvasRenderingContext2D; + + /** + * The sprite texture cache. + * + * @property textures + * @type {} + */ + textures: any; + } + + + export interface IRunnerOptions { + /** + * A `Boolean` that specifies if the runner should use a fixed timestep (otherwise it is variable). + * If timing is fixed, then the apparent simulation speed will change depending on the frame rate (but behaviour will be deterministic). + * If the timing is variable, then the apparent simulation speed will be constant (approximately, but at the cost of determininism). + * + * @property isFixed + * @type boolean + * @default false + */ + isFixed?: boolean; + + /** + * A `Number` that specifies the time step between updates in milliseconds. + * If `engine.timing.isFixed` is set to `true`, then `delta` is fixed. + * If it is `false`, then `delta` can dynamically change to maintain the correct apparent simulation speed. + * + * @property delta + * @type number + * @default 1000 / 60 + */ + delta?: number; + + /** + * A flag that specifies whether the runner is running or not. + * @property enabled + * @type boolean + * @default true + */ + enabled?: boolean; + } + + /** + * The `Matter.Runner` module is an optional utility which provides a game loop, + * that handles updating and rendering a `Matter.Engine` for you within a browser. + * It is intended for demo and testing purposes, but may be adequate for simple games. + * If you are using your own game loop instead, then you do not need the `Matter.Runner` module. + * Instead just call `Engine.update(engine, delta)` in your own loop. + * Note that the method `Engine.run` is an alias for `Runner.run`. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Runner + */ + export class Runner { + /** + * Creates a new Runner. The options parameter is an object that specifies any properties you wish to override the defaults. + * @method create + * @param {} options + */ + static create(options?: IRunnerOptions): Runner; + /** + * Continuously ticks a `Matter.Engine` by calling `Runner.tick` on the `requestAnimationFrame` event. + * @method run + * @param {engine} engine + */ + static run(runner: Runner, engine: Engine): Runner; + /** + * Continuously ticks a `Matter.Engine` by calling `Runner.tick` on the `requestAnimationFrame` event. + * @method run + * @param {engine} engine + */ + static run(engine: Engine): Runner; + /** + * A game loop utility that updates the engine and renderer by one step (a 'tick'). + * Features delta smoothing, time correction and fixed or dynamic timing. + * Triggers `beforeTick`, `tick` and `afterTick` events on the engine. + * Consider just `Engine.update(engine, delta)` if you're using your own loop. + * @method tick + * @param {runner} runner + * @param {engine} engine + * @param {number} time + */ + static tick(runner: Runner, engine: Engine, time: number): void; + /** + * Ends execution of `Runner.run` on the given `runner`, by canceling the animation frame request event loop. + * If you wish to only temporarily pause the engine, see `engine.enabled` instead. + * @method stop + * @param {runner} runner + */ + static stop(runner: Runner): void; + /** + * Alias for `Runner.run`. + * @method start + * @param {runner} runner + * @param {engine} engine + */ + static start(runner: Runner, engine: Engine): void; + + /** + * A flag that specifies whether the runner is running or not. + * + * @property enabled + * @type boolean + * @default true + */ + enabled: boolean; + + /** + * A `Boolean` that specifies if the runner should use a fixed timestep (otherwise it is variable). + * If timing is fixed, then the apparent simulation speed will change depending on the frame rate (but behaviour will be deterministic). + * If the timing is variable, then the apparent simulation speed will be constant (approximately, but at the cost of determininism). + * + * @property isFixed + * @type boolean + * @default false + */ + isFixed: boolean; + + /** + * A `Number` that specifies the time step between updates in milliseconds. + * If `engine.timing.isFixed` is set to `true`, then `delta` is fixed. + * If it is `false`, then `delta` can dynamically change to maintain the correct apparent simulation speed. + * + * @property delta + * @type number + * @default 1000 / 60 + */ + delta: number; + } + + /** + * The `Matter.Sleeping` module contains methods to manage the sleeping state of bodies. + * + * @class Sleeping + */ + export class Sleeping { + static set(body: Body, isSleeping: boolean): void; + } + + /** + * The `Matter.Svg` module contains methods for converting SVG images into an array of vector points. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Svg + */ + export class Svg { + /** + * Converts an SVG path into an array of vector points. + * If the input path forms a concave shape, you must decompose the result into convex parts before use. + * See `Bodies.fromVertices` which provides support for this. + * Note that this function is not guaranteed to support complex paths (such as those with holes). + * @method pathToVertices + * @param {SVGPathElement} path + * @param {Number} [sampleLength=15] + * @return {Vector[]} points + */ + static pathToVertices(path: SVGPathElement, sampleLength: number): Array; + } + + /** + * The `Matter.Vector` module contains methods for creating and manipulating vectors. + * Vectors are the basis of all the geometry related operations in the engine. + * A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Vector + */ + export class Vector { + x: number; + y: number; + + /** + * Creates a new vector. + * @method create + * @param {number} x + * @param {number} y + * @return {vector} A new vector + */ + static create(x?: number, y?: number): Vector; + + /** + * Returns a new vector with `x` and `y` copied from the given `vector`. + * @method clone + * @param {vector} vector + * @return {vector} A new cloned vector + */ + static clone(vector: Vector): Vector; + + + /** + * Returns the cross-product of three vectors. + * @method cross3 + * @param {vector} vectorA + * @param {vector} vectorB + * @param {vector} vectorC + * @return {number} The cross product of the three vectors + */ + static cross3(vectorA: Vector, vectorB: Vector, vectorC: Vector):number; + + /** + * Adds the two vectors. + * @method add + * @param {vector} vectorA + * @param {vector} vectorB + * @param {vector} [output] + * @return {vector} A new vector of vectorA and vectorB added + */ + static add(vectorA: Vector, vectorB: Vector, output?: Vector): Vector; + + /** + * Returns the angle in radians between the two vectors relative to the x-axis. + * @method angle + * @param {vector} vectorA + * @param {vector} vectorB + * @return {number} The angle in radians + */ + static angle(vectorA: Vector, vectorB: Vector): number; + + /** + * Returns the cross-product of two vectors. + * @method cross + * @param {vector} vectorA + * @param {vector} vectorB + * @return {number} The cross product of the two vectors + */ + static cross(vectorA: Vector, vectorB: Vector): number; + + /** + * Divides a vector and a scalar. + * @method div + * @param {vector} vector + * @param {number} scalar + * @return {vector} A new vector divided by scalar + */ + static div(vector: Vector, scalar: number): Vector; + + /** + * Returns the dot-product of two vectors. + * @method dot + * @param {vector} vectorA + * @param {vector} vectorB + * @return {number} The dot product of the two vectors + */ + static dot(vectorA: Vector, vectorB: Vector): number; + + /** + * Returns the magnitude (length) of a vector. + * @method magnitude + * @param {vector} vector + * @return {number} The magnitude of the vector + */ + static magnitude(vector: Vector): number; + + /** + * Returns the magnitude (length) of a vector (therefore saving a `sqrt` operation). + * @method magnitudeSquared + * @param {vector} vector + * @return {number} The squared magnitude of the vector + */ + static magnitudeSquared(vector: Vector): number; + + /** + * Multiplies a vector and a scalar. + * @method mult + * @param {vector} vector + * @param {number} scalar + * @return {vector} A new vector multiplied by scalar + */ + static mult(vector: Vector, scalar: number): Vector; + + /** + * Negates both components of a vector such that it points in the opposite direction. + * @method neg + * @param {vector} vector + * @return {vector} The negated vector + */ + static neg(vector: Vector): Vector; + + /** + * Normalises a vector (such that its magnitude is `1`). + * @method normalise + * @param {vector} vector + * @return {vector} A new vector normalised + */ + static normalise(vector: Vector): Vector; + + /** + * Returns the perpendicular vector. Set `negate` to true for the perpendicular in the opposite direction. + * @method perp + * @param {vector} vector + * @param {bool} [negate=false] + * @return {vector} The perpendicular vector + */ + static perp(vector: Vector, negate?: boolean): Vector; + + /** + * Rotates the vector about (0, 0) by specified angle. + * @method rotate + * @param {vector} vector + * @param {number} angle + * @return {vector} A new vector rotated about (0, 0) + */ + static rotate(vector: Vector, angle: number): Vector; + + /** + * Rotates the vector about a specified point by specified angle. + * @method rotateAbout + * @param {vector} vector + * @param {number} angle + * @param {vector} point + * @param {vector} [output] + * @return {vector} A new vector rotated about the point + */ + static rotateAbout(vector: Vector, angle: number, point: Vector, output?: Vector): Vector; + + /** + * Subtracts the two vectors. + * @method sub + * @param {vector} vectorA + * @param {vector} vectorB + * @param {vector} [output] + * @return {vector} A new vector of vectorA and vectorB subtracted + */ + static sub(vectorA: Vector, vectorB: Vector, optional?: Vector): Vector; + } + + /** + * The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices. + * A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`. + * A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull). + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class Vertices + */ + export class Vertices { + /** + * Returns the average (mean) of the set of vertices. + * @method mean + * @param {vertices} vertices + * @return {vector} The average point + */ + static mean(vertices: Array): Array; + + /** + * Sorts the input vertices into clockwise order in place. + * @method clockwiseSort + * @param {vertices} vertices + * @return {vertices} vertices + */ + static clockwiseSort(vertices: Array): Array; + + /** + * Returns true if the vertices form a convex shape (vertices must be in clockwise order). + * @method isConvex + * @param {vertices} vertices + * @return {bool} `true` if the `vertices` are convex, `false` if not (or `null` if not computable). + */ + static isConvex(vertices: Array): boolean; + + /** + * Returns the convex hull of the input vertices as a new array of points. + * @method hull + * @param {vertices} vertices + * @return [vertex] vertices + */ + static hull(vertices: Array): Array; + + /** + * Returns the area of the set of vertices. + * @method area + * @param {vertices} vertices + * @param {bool} signed + * @return {number} The area + */ + static area(vertices: Array, signed: boolean): number; + + /** + * Returns the centre (centroid) of the set of vertices. + * @method centre + * @param {vertices} vertices + * @return {vector} The centre point + */ + static centre(vertices: Array): Vector; + + /** + * Chamfers a set of vertices by giving them rounded corners, returns a new set of vertices. + * The radius parameter is a single number or an array to specify the radius for each vertex. + * @method chamfer + * @param {vertices} vertices + * @param {number[]} radius + * @param {number} quality + * @param {number} qualityMin + * @param {number} qualityMax + * @return {vertices} vertices + */ + static chamfer(vertices: Array, radius: number | Array, quality: number, qualityMin: number, qualityMax: number): Array; + + + /** + * Returns `true` if the `point` is inside the set of `vertices`. + * @method contains + * @param {vertices} vertices + * @param {vector} point + * @return {boolean} True if the vertices contains point, otherwise false + */ + static contains(vertices: Array, point: Vector): boolean; + + /** + * Creates a new set of `Matter.Body` compatible vertices. + * The `points` argument accepts an array of `Matter.Vector` points orientated around the origin `(0, 0)`, for example: + * + * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }] + * + * The `Vertices.create` method returns a new array of vertices, which are similar to Matter.Vector objects, + * but with some additional references required for efficient collision detection routines. + * + * Note that the `body` argument is not optional, a `Matter.Body` reference must be provided. + * + * @method create + * @param {vector[]} points + * @param {body} body + * @return {vertices} vertices + */ + static create(points: Array, body: Body): Array; + + /** + * Parses a string containing ordered x y pairs separated by spaces (and optionally commas), + * into a `Matter.Vertices` object for the given `Matter.Body`. + * For parsing SVG paths, see `Svg.pathToVertices`. + * @method fromPath + * @param {string} path + * @param {body} body + * @return {vertices} vertices + */ + static fromPath(path: string, body: Body): Array; + + /** + * Returns the moment of inertia (second moment of area) of the set of vertices given the total mass. + * @method inertia + * @param {vertices} vertices + * @param {number} mass + * @return {number} The polygon's moment of inertia + */ + static inertia(vertices: Array, mass: number): number; + + /** + * Rotates the set of vertices in-place. + * @method rotate + * @param {vertices} vertices + * @param {number} angle + * @param {vector} point + * @return {vertices} vertices + */ + static rotate(vertices: Array, angle: number, point: Vector): Array; + + /** + * Scales the vertices from a point (default is centre) in-place. + * @method scale + * @param {vertices} vertices + * @param {number} scaleX + * @param {number} scaleY + * @param {vector} point + * @return {vertices} vertices + */ + static scale(vertices: Array, scaleX: number, scaleY: number, point: Vector): Array; + + /** + * Translates the set of vertices in-place. + * @method translate + * @param {vertices} vertices + * @param {vector} vector + * @param {number} scalar + * @return {vertices} vertices + */ + static translate(vertices: Array, vector: Vector, scalar: number): Array; + } + + interface IWorldDefinition extends ICompositeDefinition { + gravity?: Gravity; + bounds?: Bounds; + } + + interface Gravity extends Vector { + scale: number; + } + + /** + * The `Matter.World` module contains methods for creating and manipulating the world composite. + * A `Matter.World` is a `Matter.Composite` body, which is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`. + * A `Matter.World` has a few additional properties including `gravity` and `bounds`. + * It is important to use the functions in the `Matter.Composite` module to modify the world composite, rather than directly modifying its properties. + * There are also a few methods here that alias those in `Matter.Composite` for easier readability. + * + * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). + * + * @class World + * @extends Composite + */ + export class World extends Composite { + /** + * Add objects or arrays of objects of types: Body, Constraint, Composite + * @param world + * @param body + * @returns world + */ + static add(world: World, body: Body | Array | Composite | Array | Constraint | Array | MouseConstraint): World; + + /** + * An alias for Composite.addBody since World is also a Composite + * @method addBody + * @param {world} world + * @param {body} body + * @return {world} The original world with the body added + */ + static addBody(world: World, body: Body): World; + + /** + * An alias for Composite.add since World is also a Composite + * @method addComposite + * @param {world} world + * @param {composite} composite + * @return {world} The original world with the objects from composite added + */ + static addComposite(world: World, composite: Composite): World; + + /** + * An alias for Composite.addConstraint since World is also a Composite + * @method addConstraint + * @param {world} world + * @param {constraint} constraint + * @return {world} The original world with the constraint added + */ + static addConstraint(world: World, constraint: Constraint): World; + + /** + * An alias for Composite.clear since World is also a Composite + * @method clear + * @param {world} world + * @param {boolean} keepStatic + */ + static clear(world: World, keepStatic: boolean): void; + + /** + * Creates a new world composite. The options parameter is an object that specifies any properties you wish to override the defaults. + * See the properties section below for detailed information on what you can pass via the `options` object. + * @method create + * @constructor + * @param {} options + * @return {world} A new world + */ + static create(options: IWorldDefinition): World; + + gravity: Gravity; + bounds: Bounds; + } + + export interface ICollisionFilter { + category?: number; + mask?: number; + group?: number; + } + + export interface IMousePoint { + x: number; + y: number; + } + + export class Mouse { + static create(element: HTMLElement): Mouse; + static setElement(mouse: Mouse, element: HTMLElement): void; + static clearSourceEvents(mouse: Mouse): void; + static setOffset(mouse: Mouse, offset: Vector): void; + static setScale(mouse: Mouse, scale: Vector): void; + + element: HTMLElement; + absolute: IMousePoint; + position: IMousePoint; + mousedownPosition: IMousePoint; + mouseupPosition: IMousePoint; + offset: IMousePoint; + scale: IMousePoint; + wheelDelta: number; + button: number; + pixelRatio: number; + } + + export class Common { + /** + * Extends the object in the first argument using the object in the second argument. + * @method extend + * @param {} obj + * @param {boolean} deep + * @return {} obj extended + */ + static extend(obj: object, deep: boolean): object + + /** + * Creates a new clone of the object, if deep is true references will also be cloned. + * @method clone + * @param {} obj + * @param {bool} deep + * @return {} obj cloned + */ + static clone(obj: object, deep: boolean): object + + /** + * Returns the list of keys for the given object. + * @method keys + * @param {} obj + * @return {string[]} keys + */ + static keys(obj: object): Array + + /** + * Returns the list of values for the given object. + * @method values + * @param {} obj + * @return {array} Array of the objects property values + */ + static values(obj: object): Array + + /** + * Gets a value from `base` relative to the `path` string. + * @method get + * @param {} obj The base object + * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz' + * @param {number} [begin] Path slice begin + * @param {number} [end] Path slice end + * @return {} The object at the given path + */ + static get(obj: object, path: string, begin: number, end: number): object + + /** + * Sets a value on `base` relative to the given `path` string. + * @method set + * @param {} obj The base object + * @param {string} path The path relative to `base`, e.g. 'Foo.Bar.baz' + * @param {} val The value to set + * @param {number} [begin] Path slice begin + * @param {number} [end] Path slice end + * @return {} Pass through `val` for chaining + */ + static set(obj: object, path: string, val: object, begin: number, end: number): Object + + /** + * Shuffles the given array in-place. + * The function uses a seeded random generator. + * @method shuffle + * @param {array} array + * @return {array} array shuffled randomly + */ + static shuffle(array: Array): Array + + /** + * Randomly chooses a value from a list with equal probability. + * The function uses a seeded random generator. + * @method choose + * @param {array} choices + * @return {object} A random choice object from the array + */ + static choose(choices: Array): any + + /** + * Returns true if the object is a HTMLElement, otherwise false. + * @method isElement + * @param {object} obj + * @return {boolean} True if the object is a HTMLElement, otherwise false + */ + static isElement(obj: object): boolean + + /** + * Returns true if the object is an array. + * @method isArray + * @param {object} obj + * @return {boolean} True if the object is an array, otherwise false + */ + static isArray(obj: object): boolean + + /** + * Returns true if the object is a function. + * @method isFunction + * @param {object} obj + * @return {boolean} True if the object is a function, otherwise false + */ + static isFunction(obj: object): boolean + + /** + * Returns true if the object is a plain object. + * @method isPlainObject + * @param {object} obj + * @return {boolean} True if the object is a plain object, otherwise false + */ + static isPlainObject(obj: object): boolean + + /** + * Returns true if the object is a string. + * @method isString + * @param {object} obj + * @return {boolean} True if the object is a string, otherwise false + */ + static isString(obj: object): boolean + + /** + * Returns the given value clamped between a minimum and maximum value. + * @method clamp + * @param {number} value + * @param {number} min + * @param {number} max + * @return {number} The value clamped between min and max inclusive + */ + static clamp(value: number, min: number, max: number): number + + /** + * Returns the sign of the given value. + * @method sign + * @param {number} value + * @return {number} -1 if negative, +1 if 0 or positive + */ + static sign(value: number): number + + /** + * Returns the current timestamp since the time origin (e.g. from page load). + * The result will be high-resolution including decimal places if available. + * @method now + * @return {number} the current timestamp + */ + static now(): number + + /** + * Returns a random value between a minimum and a maximum value inclusive. + * The function uses a seeded random generator. + * @method random + * @param {number} min + * @param {number} max + * @return {number} A random number between min and max inclusive + */ + static random(min?: number, max?: number): number + + /** + * Converts a CSS hex colour string into an integer. + * @method colorToNumber + * @param {string} colorString + * @return {number} An integer representing the CSS hex string + */ + static colorToNumber(colorString: string): number + + /** + * Shows a `console.log` message only if the current `Common.logLevel` allows it. + * The message will be prefixed with 'matter-js' to make it easily identifiable. + * @method log + * @param ...objs {} The objects to log. + */ + static log(): any + + /** + * Shows a `console.info` message only if the current `Common.logLevel` allows it. + * The message will be prefixed with 'matter-js' to make it easily identifiable. + * @method info + * @param ...objs {} The objects to log. + */ + static info(): any + + /** + * Shows a `console.warn` message only if the current `Common.logLevel` allows it. + * The message will be prefixed with 'matter-js' to make it easily identifiable. + * @method warn + * @param ...objs {} The objects to log. + */ + static warn(): any + + /** + * Returns the next unique sequential ID. + * @method nextId + * @return {number} Unique sequential ID + */ + static nextId(): number + + /** + * A cross browser compatible indexOf implementation. + * @method indexOf + * @param {array} haystack + * @param {object} needle + * @return {number} The position of needle in haystack, otherwise -1. + */ + static indexOf(haystack: Array, needle: object): number + + /** + * A cross browser compatible array map implementation. + * @method map + * @param {array} list + * @param {function} func + * @return {array} Values from list transformed by func. + */ + static map(list: Array, funct: Function): Array + + /** + * Takes a directed graph and returns the partially ordered set of vertices in topological order. + * Circular dependencies are allowed. + * @method topologicalSort + * @param {object} graph + * @return {array} Partially ordered set of vertices in topological order. + */ + static topologicalSort(graph: object): Array + + /** + * Takes _n_ functions as arguments and returns a new function that calls them in order. + * The arguments applied when calling the new function will also be applied to every function passed. + * The value of `this` refers to the last value returned in the chain that was not `undefined`. + * Therefore if a passed function does not return a value, the previously returned value is maintained. + * After all passed functions have been called the new function returns the last returned value (if any). + * If any of the passed functions are a chain, then the chain will be flattened. + * @method chain + * @param ...funcs {function} The functions to chain. + * @return {function} A new function that calls the passed functions in order. + */ + static chain(): Function + + /** + * Chains a function to excute before the original function on the given `path` relative to `base`. + * See also docs for `Common.chain`. + * @method chainPathBefore + * @param {} base The base object + * @param {string} path The path relative to `base` + * @param {function} func The function to chain before the original + * @return {function} The chained function that replaced the original + */ + static chainPathBefore(base: object, path: string, func: Function): Function + + /** + * Chains a function to excute after the original function on the given `path` relative to `base`. + * See also docs for `Common.chain`. + * @method chainPathAfter + * @param {} base The base object + * @param {string} path The path relative to `base` + * @param {function} func The function to chain after the original + * @return {function} The chained function that replaced the original + */ + static chainPathAfter(base: object, path: string, func: Function): Function + + /** + * Used to require external libraries outside of the bundle. + * It first looks for the `globalName` on the environment's global namespace. + * If the global is not found, it will fall back to using the standard `require` using the `moduleName`. + * @private + * @method _requireGlobal + * @param {string} globalName The global module name + * @param {string} moduleName The fallback CommonJS module name + * @return {} The loaded module + */ + static _requireGlobal(globalName: string, moduleName: string): any + } + + export interface IEvent { + /** + * The name of the event + */ + name: string; + /** + * The source object of the event + */ + source: T; + } + + export interface IEventComposite extends IEvent { + /** + * EventObjects (may be a single body, constraint, composite or a mixed array of these) + */ + object: any; + } + + export interface IEventTimestamped extends IEvent { + /** + * The engine.timing.timestamp of the event + */ + timestamp: number; + } + + export interface IEventCollision extends IEventTimestamped { + /** + * The collision pair + */ + pairs: Array; + } + + export interface IMouseEvent extends IEvent { + name: 'mousedown' | 'mousemove' | 'mouseup'; + } + + export class Events { + /** + * Fired when a body starts sleeping (where `this` is the body). + * + * @event sleepStart + * @this {body} The body that has started sleeping + * @param {} event An event object + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Body, name: 'sleepStart', callback: (e: IEvent) => void): void; + /** + * Fired when a body ends sleeping (where `this` is the body). + * + * @event sleepEnd + * @this {body} The body that has ended sleeping + * @param {} event An event object + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Body, name: 'sleepEnd', callback: (e: IEvent) => void): void; + + /** + * Fired when a call to `Composite.add` is made, before objects have been added. + * + * @event beforeAdd + * @param {} event An event object + * @param {} event.object The object(s) to be added (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'beforeAdd', callback: (e: IEventComposite) => void): void; + + /** + * Fired when a call to `Composite.add` is made, after objects have been added. + * + * @event afterAdd + * @param {} event An event object + * @param {} event.object The object(s) that have been added (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'afterAdd', callback: (e: IEventComposite) => void): void; + + /** + * Fired when a call to `Composite.remove` is made, before objects have been removed. + * + * @event beforeRemove + * @param {} event An event object + * @param {} event.object The object(s) to be removed (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'beforeRemove', callback: (e: IEventComposite) => void): void; + + /** + * Fired when a call to `Composite.remove` is made, after objects have been removed. + * + * @event afterRemove + * @param {} event An event object + * @param {} event.object The object(s) that have been removed (may be a single body, constraint, composite or a mixed array of these) + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'afterRemove', callback: (e: IEventComposite) => void): void; + + + /** + * Fired after engine update and all collision events + * + * @event afterUpdate + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'afterUpdate', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired before rendering + * + * @event beforeRender + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'beforeRender', callback: (e: IEventTimestamped) => void): void; + /** + * Fired after rendering + * + * @event afterRender + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'afterRender', callback: (e: IEventTimestamped) => void): void; + + + /** + * Fired just before an update + * + * @event beforeUpdate + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'beforeUpdate', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired after engine update, provides a list of all pairs that are colliding in the current tick (if any) + * + * @event collisionActive + * @param {} event An event object + * @param {} event.pairs List of affected pairs + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'collisionActive', callback: (e: IEventCollision) => void): void; + + + /** + * Fired after engine update, provides a list of all pairs that have ended collision in the current tick (if any) + * + * @event collisionEnd + * @param {} event An event object + * @param {} event.pairs List of affected pairs + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'collisionEnd', callback: (e: IEventCollision) => void): void; + + /** + * Fired after engine update, provides a list of all pairs that have started to collide in the current tick (if any) + * + * @event collisionStart + * @param {} event An event object + * @param {} event.pairs List of affected pairs + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'collisionStart', callback: (e: IEventCollision) => void): void; + + /** + * Fired at the start of a tick, before any updates to the engine or timing + * + * @event beforeTick + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'beforeTick', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired after engine timing updated, but just before update + * + * @event tick + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'tick', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired at the end of a tick, after engine update and after rendering + * + * @event afterTick + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'afterTick', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired before rendering + * + * @event beforeRender + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'beforeRender', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired after rendering + * + * @event afterRender + * @param {} event An event object + * @param {number} event.timestamp The engine.timing.timestamp of the event + * @param {} event.source The source object of the event + * @param {} event.name The name of the event + */ + static on(obj: Engine, name: 'afterRender', callback: (e: IEventTimestamped) => void): void; + + /** + * Fired when the mouse is down (or a touch has started) during the last step + * @param obj + * @param name + * @param callback + */ + static on(obj: MouseConstraint, name: 'mousedown', callback: (e: IMouseEvent) => void): void; + + /** + * Fired when the mouse has moved (or a touch moves) during the last step + * @param obj + * @param name + * @param callback + */ + static on(obj: MouseConstraint, name: 'mousemove', callback: (e: IMouseEvent) => void): void; + + /** + * Fired when the mouse is up (or a touch has ended) during the last step + * @param obj + * @param name + * @param callback + */ + static on(obj: MouseConstraint, name: 'mouseup', callback: (e: IMouseEvent) => void): void; + + + static on(obj: any, name: string, callback: (e: any) => void): void; + + /** + * Removes the given event callback. If no callback, clears all callbacks in eventNames. If no eventNames, clears all events. + * + * @param obj + * @param eventName + * @param callback + */ + static off(obj: any, eventName: string, callback: (e: any) => void): void; + + /** + * Fires all the callbacks subscribed to the given object's eventName, in the order they subscribed, if any. + * + * @param object + * @param eventNames + * @param event + */ + static trigger(object: any, eventNames: string, event?: any): void; + } + + type Dependency = {name: string, range: string} + | {name: string, version: string} + | string; + + export class Plugin { + name: string; + version: string; + install: () => void; + for?: string; + + /** + * Registers a plugin object so it can be resolved later by name. + * @method register + * @param plugin {} The plugin to register. + * @return {object} The plugin. + */ + static register(plugin: Plugin): Plugin; + + /** + * Resolves a dependency to a plugin object from the registry if it exists. + * The `dependency` may contain a version, but only the name matters when resolving. + * @method resolve + * @param dependency {string} The dependency. + * @return {object} The plugin if resolved, otherwise `undefined`. + */ + static resolve(dependency: string): Plugin | undefined; + + /** + * Returns `true` if the object meets the minimum standard to be considered a plugin. + * This means it must define the following properties: + * - `name` + * - `version` + * - `install` + * @method isPlugin + * @param obj {} The obj to test. + * @return {boolean} `true` if the object can be considered a plugin otherwise `false`. + */ + static isPlugin(obj: {}): boolean; + + /** + * Returns a pretty printed plugin name and version. + * @method toString + * @param plugin {} The plugin. + * @return {string} Pretty printed plugin name and version. + */ + static toString(plugin: string | Plugin): string; + + /** + * Returns `true` if `plugin.for` is applicable to `module` by comparing against `module.name` and `module.version`. + * If `plugin.for` is not specified then it is assumed to be applicable. + * The value of `plugin.for` is a string of the format `'module-name'` or `'module-name@version'`. + * @method isFor + * @param plugin {} The plugin. + * @param module {} The module. + * @return {boolean} `true` if `plugin.for` is applicable to `module`, otherwise `false`. + */ + static isFor(plugin: Plugin, module: {name?: string, [_: string]: any}): boolean; + + /** + * Installs the plugins by calling `plugin.install` on each plugin specified in `plugins` if passed, otherwise `module.uses`. + * For installing plugins on `Matter` see the convenience function `Matter.use`. + * Plugins may be specified either by their name or a reference to the plugin object. + * Plugins themselves may specify further dependencies, but each plugin is installed only once. + * Order is important, a topological sort is performed to find the best resulting order of installation. + * This sorting attempts to satisfy every dependency's requested ordering, but may not be exact in all cases. + * This function logs the resulting status of each dependency in the console, along with any warnings. + * - A green tick ✅ indicates a dependency was resolved and installed. + * - An orange diamond 🔶 indicates a dependency was resolved but a warning was thrown for it or one if its dependencies. + * - A red cross ❌ indicates a dependency could not be resolved. + * Avoid calling this function multiple times on the same module unless you intend to manually control installation order. + * @method use + * @param module {} The module install plugins on. + * @param [plugins=module.uses] {} The plugins to install on module (optional, defaults to `module.uses`). + */ + static use( + module: {uses?: (Plugin | string)[]; [_: string]: any}, + plugins: (Plugin | string)[] + ): void; + + /** + * Recursively finds all of a module's dependencies and returns a flat dependency graph. + * @method dependencies + * @param module {} The module. + * @return {object} A dependency graph. + */ + static dependencies( + module: Dependency, + tracked?: {[_: string]: string[]} + ): {[_: string]: string[]} | string | undefined + + /** + * Parses a dependency string into its components. + * The `dependency` is a string of the format `'module-name'` or `'module-name@version'`. + * See documentation for `Plugin.versionParse` for a description of the format. + * This function can also handle dependencies that are already resolved (e.g. a module object). + * @method dependencyParse + * @param dependency {string} The dependency of the format `'module-name'` or `'module-name@version'`. + * @return {object} The dependency parsed into its components. + */ + static dependencyParse(dependency: Dependency) : {name: string, range: string}; + + /** + * Parses a version string into its components. + * Versions are strictly of the format `x.y.z` (as in [semver](http://semver.org/)). + * Versions may optionally have a prerelease tag in the format `x.y.z-alpha`. + * Ranges are a strict subset of [npm ranges](https://docs.npmjs.com/misc/semver#advanced-range-syntax). + * Only the following range types are supported: + * - Tilde ranges e.g. `~1.2.3` + * - Caret ranges e.g. `^1.2.3` + * - Exact version e.g. `1.2.3` + * - Any version `*` + * @method versionParse + * @param range {string} The version string. + * @return {object} The version range parsed into its components. + */ + static versionParse(range: string) : { + isRange: boolean, + version: string, + range: string, + operator: string + parts: number[], + prerelease: string, + number: number + }; + + /** + * Returns `true` if `version` satisfies the given `range`. + * See documentation for `Plugin.versionParse` for a description of the format. + * If a version or range is not specified, then any version (`*`) is assumed to satisfy. + * @method versionSatisfies + * @param version {string} The version string. + * @param range {string} The range string. + * @return {boolean} `true` if `version` satisfies `range`, otherwise `false`. + */ + static versionSatisfies(version: string, range: string): boolean; + } +} + +/*****************************\ +|* * * * Ct.js additions * * *| +\****************************/ + +type MatterEventCallback = (event: Matter.IEventCollision) => void; + +declare namespace ct { + namespace matter { + function on(event: string, callback: MatterEventCallback): void; + function off(event: string, callback: MatterEventCallback): void; + /** + * Moves a copy to a new position without changing its velocity. + */ + function teleport(copy: Copy, x: number, y: number): void; + /** + * Applies a force onto a copy. The resulting velocity depends on object's mass and friction. + * You can optionally define a point from which the force is applied to make the copy spin. + */ + function push(copy: Copy, forceX: number, forceY: number, fromX?: number, fromY?: number): void; + /** + * Sets copy's angular velocity. + */ + function spin(copy: Copy, speed: number): void; + /** + * Rotates a copy to the defined angle. + */ + function rotate(copy: Copy, angle: number): void; + /** + * Rotates a copy by the defined angle. + */ + function rotateBy(copy: Copy, angle: number): void; + /** + * Scales the copy and its physical object. + */ + function scale(copy: Copy, x: number, y: number): void; + /** + * Sets copy's velocity instantly. + */ + function launch(copy: Copy, hspeed: number, vspeed: number): void; + + /** + * Pins a copy in place, making it spin around its center of mass + * but preventing any other movement. + */ + function pin(copy: Copy): void; + /** + * Ties a copy to a specific position in space, making it swing around it. + */ + function tie(copy: Copy, position: ISimplePoint, stiffness?: number, damping?: number): void; + /** + * Puts a copy on a rope. It is similar to `ct.matter.tie`, but the length of a rope is defined + * explicitly, and starts from the copy's current position. + */ + function rope(copy: Copy, length: number, stiffness?: number, damping?: number): void; + /** + * Ties two copies together with a rope. + */ + function tieTogether(copy1: Copy, copy2: Copy, stiffness?: number, damping?: number): void; + + /** + * Calculates a good approximation of an impact two colliding copies caused to each other. + */ + function getImpact(pair: Matter.IPair): number; + } +} diff --git a/src/examples/2DPhysics.ict b/src/examples/2DPhysics.ict new file mode 100644 index 000000000..cf99e65be --- /dev/null +++ b/src/examples/2DPhysics.ict @@ -0,0 +1,1157 @@ +ctjsVersion: 1.5.1 +notes: /* empty */ +libs: + fittoscreen: + mode: scaleFit + mouse: {} + sound.howler: {} + matter: + matterUseStaticDeltaTime: true +textures: + - name: Star + untill: 0 + grid: + - 1 + - 1 + axis: + - 64.5 + - 67.5 + marginx: 0 + marginy: 0 + imgWidth: 128 + imgHeight: 128 + width: 128 + height: 128 + offx: 0 + offy: 0 + origname: ibfbb5de9-367a-438a-8cab-ea88479c51be.png + shape: strip + left: 0 + right: 787 + top: 0 + bottom: 692 + uid: bfbb5de9-367a-438a-8cab-ea88479c51be + padding: 1 + source: 'D:\JettyCat\img\ic9a62030-151c-429e-a2ce-3e829a79cb05.png_prev@2.png' + lastmod: 1615542695704 + stripPoints: + - x: -0.75 + 'y': -65.75 + - x: 11 + 'y': -58.25 + - x: 24 + 'y': -33.25 + - x: 60.75 + 'y': -24.5 + - x: 64.5 + 'y': -10 + - x: 39.75 + 'y': 15.25 + - x: 44.25 + 'y': 49.25 + - x: 29 + 'y': 59.75 + - x: -0.5 + 'y': 42.75 + - x: -29.921346167118823 + 'y': 59.885763470431215 + - x: -45.2195710804483 + 'y': 49.45615108543885 + - x: -40.87630005786883 + 'y': 15.43577488492599 + - x: -65.74239608827918 + 'y': -9.699902313160635 + - x: -62.05925582802869 + 'y': -24.21702936445152 + - x: -25.349968411049232 + 'y': -33.13629039536623 + - x: -12.465313208428675 + 'y': -58.19593245804509 + closedStrip: true + symmetryStrip: true + - name: WoodenPlank + untill: 0 + grid: + - 1 + - 1 + axis: + - 110 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 220 + imgHeight: 70 + width: 220 + height: 70 + offx: 0 + offy: 0 + origname: i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png + shape: rect + left: 110 + right: 110 + top: 35 + bottom: 35 + uid: 9afd54d7-1265-4ba0-b5de-5226b3c7e2fb + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Wood elements\elementWood012.png' + lastmod: 1616891166294 + - name: WoodenSquare + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: i41f7c3b3-abc8-4940-8919-9114a884d7f2.png + shape: rect + left: 35 + right: 35 + top: 35 + bottom: 35 + uid: 41f7c3b3-abc8-4940-8919-9114a884d7f2 + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Wood elements\elementWood010.png' + lastmod: 1616891205921 + tiled: false + - name: alienPink_square + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png + shape: rect + left: 35 + right: 35 + top: 35 + bottom: 35 + uid: 6c8a3edf-d5fe-4916-b63c-2201c099d28f + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Aliens\alienPink_square.png' + lastmod: 1616890309571 + - name: alienGreen_round + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: i8a5f385a-d547-4d2d-9641-b1856738c62a.png + shape: circle + left: 35 + right: 35 + top: 35 + bottom: 35 + uid: 8a5f385a-d547-4d2d-9641-b1856738c62a + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Aliens\alienGreen_round.png' + r: 35 + lastmod: 1616890345324 + - name: colored_grass + untill: 0 + grid: + - 1 + - 1 + axis: + - 0 + - 0 + marginx: 0 + marginy: 0 + imgWidth: 1024 + imgHeight: 1024 + width: 1024 + height: 1024 + offx: 0 + offy: 0 + origname: if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png + shape: rect + left: 0 + right: 1024 + top: 0 + bottom: 1024 + uid: f6a40cf4-e9c0-47ff-afa8-6cdc259ef17e + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Backgrounds\blue_grass.png' + tiled: true + lastmod: 1616891207354 + - name: grass + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png + shape: rect + left: 35 + right: 35 + top: 35 + bottom: 35 + uid: 375a4a5e-64e5-410f-aa6f-3bcfc9804519 + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Other\grass.png' + lastmod: 1615556407594 + - name: WoodenTriangle + untill: 0 + grid: + - 1 + - 1 + axis: + - 70 + - 43 + marginx: 0 + marginy: 0 + imgWidth: 140 + imgHeight: 70 + width: 140 + height: 70 + offx: 0 + offy: 0 + origname: i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png + shape: strip + left: 70 + right: 70 + top: 35 + bottom: 35 + uid: 0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Wood elements\elementWood054.png' + stripPoints: + - x: -0.0 + 'y': -43 + - x: 70 + 'y': 26 + - x: -70 + 'y': 26 + closedStrip: true + lastmod: 1616891300000 + - name: elementMetal013 + untill: 0 + grid: + - 1 + - 1 + axis: + - 110 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 220 + imgHeight: 70 + width: 220 + height: 70 + offx: 0 + offy: 0 + origname: i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png + shape: rect + left: 110 + right: 110 + top: 35 + bottom: 35 + uid: 56ab43ae-1b27-4b5e-9e49-fbbe74d42597 + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Metal elements\elementMetal013.png' + lastmod: 1615557926300 + - name: Slingshot + untill: 0 + grid: + - 2 + - 1 + axis: + - 70 + - 60 + marginx: 0 + marginy: 0 + imgWidth: 304 + imgHeight: 221 + width: 152 + height: 221 + offx: 0 + offy: 0 + origname: i37dfad62-8372-4804-8416-765039343b61.png + shape: rect + left: 70 + right: 82 + top: 60 + bottom: 161 + uid: 37dfad62-8372-4804-8416-765039343b61 + padding: 1 + source: 'C:\Users\Master\Desktop\Slingshot.png' + lastmod: 1616892923665 + - name: elementMetal001 + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: ic4d4030a-b640-44be-bded-26a5c030f542.png + shape: circle + left: 35 + right: 35 + top: 35 + bottom: 35 + uid: c4d4030a-b640-44be-bded-26a5c030f542 + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Metal elements\elementMetal001.png' + r: 35 + lastmod: 1615704333828 + - name: elementMetal000 + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: i3a4eba8d-8b33-478e-95e5-3833099c1a03.png + shape: strip + left: 0 + right: 140 + top: 0 + bottom: 70 + uid: 3a4eba8d-8b33-478e-95e5-3833099c1a03 + padding: 3 + source: 'D:\Downloads\physicspack\PNG\Metal elements\elementMetal002.png' + lastmod: 1616892926979 + stripPoints: + - x: -35 + 'y': -35 + - x: 35 + 'y': 35 + - x: -35 + 'y': 35 + closedStrip: true + - name: Confetti + untill: 0 + grid: + - 2 + - 2 + axis: + - 0 + - 0 + marginx: 0 + marginy: 0 + imgWidth: 1024 + imgHeight: 1024 + width: 512 + height: 512 + offx: 0 + offy: 0 + origname: if878c588-3c26-486b-a20f-b23ffab4d579.png + shape: rect + left: 0 + right: 512 + top: 0 + bottom: 512 + uid: f878c588-3c26-486b-a20f-b23ffab4d579 + padding: 3 + source: data\particles\Confetti_2x2.png + lastmod: 1616895609998 + - name: WoodenSquare_Damaged + untill: 0 + grid: + - 1 + - 1 + axis: + - 35 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 70 + imgHeight: 70 + width: 70 + height: 70 + offx: 0 + offy: 0 + origname: iabdeba09-af47-4b39-a276-fa2e59b164aa.png + shape: rect + left: 35 + right: 35 + top: 35 + bottom: 35 + uid: abdeba09-af47-4b39-a276-fa2e59b164aa + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Wood elements\elementWood045.png' + lastmod: 1616891224599 + - name: WoodenTriangle_Damaged + untill: 0 + grid: + - 1 + - 1 + axis: + - 70 + - 43 + marginx: 0 + marginy: 0 + imgWidth: 140 + imgHeight: 70 + width: 140 + height: 70 + offx: 0 + offy: 0 + origname: ifc52b049-910a-4e96-adcf-378553c0818c.png + shape: strip + left: 70 + right: 70 + top: 43 + bottom: 27 + uid: fc52b049-910a-4e96-adcf-378553c0818c + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Wood elements\elementWood043.png' + lastmod: 1616891305648 + stripPoints: + - x: 0 + 'y': -43 + - x: 70 + 'y': 26 + - x: -70 + 'y': 26 + closedStrip: true + - name: WoodenPlank_Damaged + untill: 0 + grid: + - 1 + - 1 + axis: + - 110 + - 35 + marginx: 0 + marginy: 0 + imgWidth: 220 + imgHeight: 70 + width: 220 + height: 70 + offx: 0 + offy: 0 + origname: i03040255-0c4f-4605-aa7f-8a146a75675f.png + shape: rect + left: 110 + right: 110 + top: 35 + bottom: 35 + uid: 03040255-0c4f-4605-aa7f-8a146a75675f + padding: 1 + source: 'D:\Downloads\physicspack\PNG\Wood elements\elementWood047.png' + lastmod: 1616891232841 +skeletons: [] +types: + - name: Alien_Launched + depth: 0 + oncreate: |- + this.tag = 'Alien'; + + this.timeout = ct.speed * 5; + onstep: |- + this.timeout--; + if (this.timeout <= 0) { + this.kill = true; + } + ondraw: '' + ondestroy: |- + ct.emitters.fire('FX_Burst', this.xprev, this.yprev, { + tint: 0x6EBA9D + }); + texture: 8a5f385a-d547-4d2d-9641-b1856738c62a + extends: + matterEnable: true + matterRestitution: 0.7 + matterMass: 5 + matterDensity: 0.003 + uid: 556178d8-6886-4718-a5dd-b7dbf74e4547 + lastmod: 1616894158784 + - name: AlienTarget + depth: 0 + oncreate: this.tag = 'Alien'; + onstep: this.move(); + ondraw: '' + ondestroy: |- + ct.emitters.fire('FX_Burst', this.xprev, this.yprev, { + tint: 0xFF85DA + }); + texture: 6c8a3edf-d5fe-4916-b63c-2201c099d28f + extends: + matterEnable: true + uid: beb36708-4cce-4b50-a3c3-f7e2edc1d994 + lastmod: 1616890301062 + - name: WoodenSquare + depth: 0 + oncreate: |- + this.tag = 'Wooden'; + this.damage = 0; + onstep: |- + if (this.damage > 150) { + this.kill = true; + } + ondraw: |- + if (this.damage > 75 && this.tex !== 'WoodenSquare_damaged') { + this.tex = 'WoodenSquare_Damaged'; + } + ondestroy: |- + ct.emitters.fire('FX_Burst', this.xprev, this.yprev, { + tint: 0xAB763E + }); + texture: 41f7c3b3-abc8-4940-8919-9114a884d7f2 + extends: + matterEnable: true + matterRestitution: 0.4 + matterFriction: 10 + matterFrictionStatic: 3.1 + matterFrictionAir: 0.05 + matterMass: 1 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + lastmod: 1616891394690 + - name: WoodenPlank + depth: 0 + oncreate: |- + this.tag = 'Wooden'; + this.damage = 0; + onstep: |- + if (this.damage > 300) { + this.kill = true; + } + ondraw: |- + if (this.damage > 100 && this.tex !== 'WoodenPlank_damaged') { + this.tex = 'WoodenPlank_Damaged'; + } + ondestroy: |- + ct.emitters.fire('FX_Burst', this.xprev, this.yprev, { + tint: 0xAB763E + }); + texture: 9afd54d7-1265-4ba0-b5de-5226b3c7e2fb + extends: + matterEnable: true + matterRestitution: 0.4 + matterMass: 1 + matterFriction: 10 + matterFrictionStatic: 3.1 + matterFrictionAir: 0.05 + uid: 256006c5-c853-40a5-a277-3bc1df64d226 + lastmod: 1616895635325 + - name: grass + depth: 0 + oncreate: '' + onstep: this.move(); + ondraw: '' + ondestroy: '' + texture: 375a4a5e-64e5-410f-aa6f-3bcfc9804519 + extends: + matterEnable: true + matterStatic: true + matterMass: 10000 + matterFriction: 15 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + lastmod: 1615557554543 + - name: WoodenTriangle + depth: 0 + oncreate: |- + this.tag = 'Wooden'; + this.damage = 0; + onstep: |- + if (this.damage > 250) { + this.kill = true; + } + ondraw: |- + if (this.damage > 100 && this.tex !== 'WoodenTriangle_damaged') { + this.tex = 'WoodenTriangle_Damaged'; + } + ondestroy: |- + ct.emitters.fire('FX_Burst', this.xprev, this.yprev, { + tint: 0xAB763E + }); + texture: 0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b + extends: + matterEnable: true + matterFriction: 10 + matterFrictionStatic: 3.1 + matterFrictionAir: 0.05 + matterMass: 1 + matterFixPivot: + - 0 + - 11 + uid: 7f79638a-a14f-4ec8-8826-981ff954c738 + lastmod: 1616895639247 + - name: Slingshot + depth: 0 + oncreate: '' + onstep: |- + if (ct.actions.Pointer.pressed && ct.mouse.hovers(this)) { + ct.types.copy('Alien_Dragging', this.x, this.y); + } + ondraw: '' + ondestroy: '' + texture: 37dfad62-8372-4804-8416-765039343b61 + extends: {} + uid: 070d18cf-978a-4874-ba4d-1aadd0d4f58a + lastmod: 1616892056278 + - name: Alien_Dragging + depth: 0 + oncreate: '' + onstep: |- + if (ct.actions.Pointer.released) { + const speedModifier = 0.3, + maxSpeed = 50; + this.kill = true; + const missile = ct.types.copy('Alien_Launched', this.x, this.y); + const slingshot = ct.types.list['Slingshot'][0]; + var hspeed = (slingshot.x - this.x) * speedModifier, + vspeed = (slingshot.y - this.y) * speedModifier, + l = ct.u.pdc(0, 0, hspeed, vspeed); + if (l > maxSpeed) { + hspeed /= l / maxSpeed; + vspeed /= l / maxSpeed; + } + ct.matter.launch(missile, hspeed, vspeed); + } + ondraw: | + const slingshot = ct.types.list['Slingshot'][0], + maxLength = 150; + let dx = ct.mouse.x - slingshot.x, + dy = ct.mouse.y - slingshot.y, + l = ct.u.pdc(0, 0, dx, dy); + + if (l > maxLength) { + dx /= l / maxLength, + dy /= l / maxLength; + } + + this.x = slingshot.x + dx; + this.y = slingshot.y + dy; + ondestroy: '' + texture: 8a5f385a-d547-4d2d-9641-b1856738c62a + extends: + matterEnable: false + matterRestitution: 0.7 + uid: 5b9b41e7-52db-44a2-b5d2-016407e259dc + lastmod: 1616891549758 + - name: elementMetal013 + depth: 0 + oncreate: this.tag = 'Metal'; + onstep: this.move(); + ondraw: '' + ondestroy: '' + texture: 56ab43ae-1b27-4b5e-9e49-fbbe74d42597 + extends: + matterEnable: true + matterConstraint: pinpoint + matterFrictionStatic: 0.1 + matterFrictionAir: 0.1 + matterDensity: 0.01 + matterRestitution: 0.6 + uid: 8e4e1fe0-54f6-4c9f-a468-99a94b05803f + lastmod: 1616892744865 + - name: elementMetal011 + depth: 0 + oncreate: this.tag = 'Metal'; + onstep: this.move(); + ondraw: '' + ondestroy: '' + texture: c4d4030a-b640-44be-bded-26a5c030f542 + extends: + matterMass: 10 + matterEnable: true + matterDensity: 0.005 + matterRestitution: 0.6 + uid: 54e149bb-f36a-48c0-98f5-181451bac20c + lastmod: 1616892752365 + - name: elementMetal000 + depth: 0 + oncreate: this.tag = 'Metal'; + onstep: this.move(); + ondraw: '' + ondestroy: '' + texture: 3a4eba8d-8b33-478e-95e5-3833099c1a03 + extends: + matterStatic: true + matterEnable: true + matterDensity: 0.005 + matterRestitution: 0.5 + matterFixPivot: + - 4 + - 4 + uid: 82c03796-7419-4f22-944c-78c1209c6874 + lastmod: 1616892936227 +sounds: + - name: Impact_Wooden + uid: ccfe7f50-d4d3-4570-95e9-75d5d73bef0a + origname: sccfe7f50-d4d3-4570-95e9-75d5d73bef0a.ogg + lastmod: 1616407436515 + - name: Impact_Metal + uid: cbca4dd5-7369-48d5-b3b7-e9b0055e2eda + origname: scbca4dd5-7369-48d5-b3b7-e9b0055e2eda.ogg + lastmod: 1616407498544 + - name: Impact_Alien + uid: 3142b705-6de5-4f57-9b70-c9bc3fb4cdad + origname: s3142b705-6de5-4f57-9b70-c9bc3fb4cdad.ogg + lastmod: 1616407549522 +styles: [] +rooms: + - name: HolericAliens + oncreate: | + // Listen for collisions in the world + ct.matter.on('collisionStart', e => { + // Loop over every collision in a frame + for (const pair of e.pairs) { + // Get how strong the impact was + // We will use it for damage calculation to aliens and wooden blocks + const impact = ct.matter.getImpact(pair); + + // Each pair has bodyA and bodyB — two objects that has collided. + // This little loop applies checks for both bodies + const bodies = [pair.bodyA, pair.bodyB]; + for (const body of bodies) { + // Does a body belong to a copy of type "AlienTarget"? + if (body.copy.type === 'AlienTarget') { + // If it was too strong, destroy the alien. + if (impact > 75) { + body.copy.kill = true; + } + } + + // Apply cumulative damage for wooden blocks + // Tags are set in types' On Create code + if (body.copy.tag === 'Wooden') { + // Ignore weak strikes + if (impact >= 25) { + // I apply a damage multiplier 0.35 bc initial values turned out to be too destructive, + // and I'm too lazy to walk over three blocks and change damage thresholds there. + body.copy.damage += impact * 0.35; + // Texture change and destruction are coded in types' On Step and Draw events. + } + } + + // Play sounds on considerable collisions + if (impact >= 25) { + if (body.copy.tag) { + ct.sound.spawn('Impact_' + body.copy.tag); + } + } + } + } + }); + onstep: '' + ondraw: '' + onleave: '' + width: 1640 + height: 900 + backgrounds: + - depth: -10 + texture: f6a40cf4-e9c0-47ff-afa8-6cdc259ef17e + extends: {} + copies: + - x: 905 + 'y': 770 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 905 + 'y': 700 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 905 + 'y': 630 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 980 + 'y': 560 + uid: 256006c5-c853-40a5-a277-3bc1df64d226 + exts: {} + - x: 1054 + 'y': 770 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1054 + 'y': 700 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1054 + 'y': 630 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 980 + 'y': 766 + uid: beb36708-4cce-4b50-a3c3-f7e2edc1d994 + exts: {} + - x: 1050 + 'y': 490 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 980 + 'y': 490 + uid: beb36708-4cce-4b50-a3c3-f7e2edc1d994 + exts: {} + - x: 1120 + 'y': 350 + uid: 256006c5-c853-40a5-a277-3bc1df64d226 + exts: {} + - x: 1190 + 'y': 420 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1190 + 'y': 490 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1190 + 'y': 700 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1190 + 'y': 770 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1260 + 'y': 630 + uid: 256006c5-c853-40a5-a277-3bc1df64d226 + exts: {} + - x: 1330 + 'y': 700 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1330 + 'y': 770 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1120 + 'y': 280 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1190 + 'y': 560 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 1288 + 'y': 559 + uid: beb36708-4cce-4b50-a3c3-f7e2edc1d994 + exts: {} + - x: 910 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 980 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1050 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1120 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1190 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1260 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1330 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1400 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1470 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1540 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1610 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 840 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 770 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 700 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 560 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 630 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 490 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 420 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 350 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 280 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 210 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 140 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 70 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 0 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1680 + 'y': 840 + uid: 9150bbba-a1a8-4fc8-837d-68589f3d5074 + exts: {} + - x: 1120 + 'y': 210 + uid: 7f79638a-a14f-4ec8-8826-981ff954c738 + exts: {} + - x: 1024 + 'y': 278 + uid: beb36708-4cce-4b50-a3c3-f7e2edc1d994 + exts: {} + - x: 700 + 'y': 140 + uid: 8e4e1fe0-54f6-4c9f-a468-99a94b05803f + exts: {} + - x: 630 + 'y': 70 + uid: 54e149bb-f36a-48c0-98f5-181451bac20c + exts: {} + - x: 770 + 'y': 70 + uid: 54e149bb-f36a-48c0-98f5-181451bac20c + exts: {} + - x: 225 + 'y': 646 + uid: 070d18cf-978a-4874-ba4d-1aadd0d4f58a + exts: {} + - x: 568 + 'y': 770 + uid: 7f79638a-a14f-4ec8-8826-981ff954c738 + exts: {} + - x: 700 + 'y': 770 + uid: 7f79638a-a14f-4ec8-8826-981ff954c738 + exts: {} + - x: 1050 + 'y': 420 + uid: 6fd118b6-633f-4beb-93ec-2dd5c965fdd5 + exts: {} + - x: 630 + 'y': 700 + uid: 54e149bb-f36a-48c0-98f5-181451bac20c + exts: {} + tx: 2.2 + ty: 1 + tiles: + - depth: -10 + tiles: [] + extends: {} + uid: 125036f1-3a14-4fc3-ae95-2d29a5c56244 + thumbnail: 2d29a5c56244 + extends: + matterGravity: + - 0 + - 1 + gridX: 70 + gridY: 70 + lastmod: 1616896076747 +actions: + - name: Pointer + methods: + - code: mouse.Left +emitterTandems: + - name: FX_Burst + origname: pta85a19f1cde1 + emitters: + - texture: f878c588-3c26-486b-a20f-b23ffab4d579 + openedTabs: + - texture + - spawning + - gravity + - scaling + - colors + settings: + alpha: + list: + - value: 0 + time: 0 + - time: 0.15079365079365079 + value: 0.75 + - value: 1 + time: 0.5 + - value: 0 + time: 1 + isStepped: false + scale: + list: + - value: 0.18000000000000002 + time: 0 + - value: 0.039999999999999994 + time: 1 + isStepped: false + color: + list: + - value: FF85DA + time: 0 + - time: 0.15079365079365079 + value: FFFFFF + - value: FFFFFF + time: 0.5 + - value: FFFFFF + time: 1 + isStepped: false + blendMode: normal + speed: + list: + - value: 675 + time: 0 + - value: 100 + time: 1 + isStepped: false + startRotation: + min: 0 + max: 360 + rotationSpeed: + min: 0 + max: 0 + rotationAcceleration: 0 + lifetime: + min: 0.35 + max: 1 + frequency: 0.008 + spawnChance: 1 + particlesPerWave: 1 + angleStart: 270 + emitterLifetime: 0.1 + maxParticles: 1000 + maxSpeed: 0 + pos: + x: 0 + 'y': 0 + acceleration: + x: 0 + 'y': 1000 + addAtBack: false + spawnType: circle + spawnCircle: + x: 0 + 'y': 0 + r: 41 + delay: 0 + particleSpacing: 360 + minimumScaleMultiplier: 0.26 + minimumSpeedMultiplier: 0.15 + uid: 02de95c8-e4d6-41a2-aced-793d64657985 + showShapeVisualizer: false + previewTexture: 6c8a3edf-d5fe-4916-b63c-2201c099d28f +scripts: [] +starting: 0 +settings: + authoring: + author: '' + site: '' + title: '' + version: + - 0 + - 0 + - 0 + versionPostfix: '' + rendering: + usePixiLegacy: true + maxFPS: 60 + pixelatedrender: false + highDensity: true + desktopMode: maximized + export: + windows: true + linux: true + mac: true + functionWrap: false + codeModifier: none + branding: + icon: -1 + accent: '#446adb' + invertPreloaderScheme: true + fps: 30 +fonts: [] +palette: + - '#FF85DA' + - '#6EBA9D' + - '#9E703F' +startroom: 125036f1-3a14-4fc3-ae95-2d29a5c56244 diff --git a/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png b/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png new file mode 100644 index 000000000..e10f7c7d9 Binary files /dev/null and b/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png differ diff --git a/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png_prev.png b/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png_prev.png new file mode 100644 index 000000000..43b87a41b Binary files /dev/null and b/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png_prev@2.png b/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png_prev@2.png new file mode 100644 index 000000000..c17f4a71e Binary files /dev/null and b/src/examples/2DPhysics/img/i03040255-0c4f-4605-aa7f-8a146a75675f.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png b/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png new file mode 100644 index 000000000..dc5348d7f Binary files /dev/null and b/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png differ diff --git a/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png_prev.png b/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png_prev.png new file mode 100644 index 000000000..c5d23a2bf Binary files /dev/null and b/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png_prev@2.png b/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png_prev@2.png new file mode 100644 index 000000000..10f2177c3 Binary files /dev/null and b/src/examples/2DPhysics/img/i0f0e39f3-05bd-47e1-88d2-7dbf7bc3596b.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png b/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png new file mode 100644 index 000000000..5f9178456 Binary files /dev/null and b/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png differ diff --git a/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png_prev.png b/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png_prev.png new file mode 100644 index 000000000..7f2c1af04 Binary files /dev/null and b/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png_prev@2.png b/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png_prev@2.png new file mode 100644 index 000000000..6019f64dd Binary files /dev/null and b/src/examples/2DPhysics/img/i375a4a5e-64e5-410f-aa6f-3bcfc9804519.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png b/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png new file mode 100644 index 000000000..934c7d195 Binary files /dev/null and b/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png differ diff --git a/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png_prev.png b/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png_prev.png new file mode 100644 index 000000000..0abcccef5 Binary files /dev/null and b/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png_prev@2.png b/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png_prev@2.png new file mode 100644 index 000000000..be2919426 Binary files /dev/null and b/src/examples/2DPhysics/img/i37dfad62-8372-4804-8416-765039343b61.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png b/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png new file mode 100644 index 000000000..cd0f0603e Binary files /dev/null and b/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png differ diff --git a/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png_prev.png b/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png_prev.png new file mode 100644 index 000000000..c8e03f4ae Binary files /dev/null and b/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png_prev@2.png b/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png_prev@2.png new file mode 100644 index 000000000..f80ecd8e4 Binary files /dev/null and b/src/examples/2DPhysics/img/i3a4eba8d-8b33-478e-95e5-3833099c1a03.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png b/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png new file mode 100644 index 000000000..c77a82188 Binary files /dev/null and b/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png differ diff --git a/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png_prev.png b/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png_prev.png new file mode 100644 index 000000000..d8acf2b60 Binary files /dev/null and b/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png_prev@2.png b/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png_prev@2.png new file mode 100644 index 000000000..bd7614b5e Binary files /dev/null and b/src/examples/2DPhysics/img/i41f7c3b3-abc8-4940-8919-9114a884d7f2.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png b/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png new file mode 100644 index 000000000..ef1edf87d Binary files /dev/null and b/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png differ diff --git a/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png_prev.png b/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png_prev.png new file mode 100644 index 000000000..49ed833fb Binary files /dev/null and b/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png_prev@2.png b/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png_prev@2.png new file mode 100644 index 000000000..5a4995c45 Binary files /dev/null and b/src/examples/2DPhysics/img/i56ab43ae-1b27-4b5e-9e49-fbbe74d42597.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png b/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png new file mode 100644 index 000000000..36060d07b Binary files /dev/null and b/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png differ diff --git a/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png_prev.png b/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png_prev.png new file mode 100644 index 000000000..c94fe2b05 Binary files /dev/null and b/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png_prev@2.png b/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png_prev@2.png new file mode 100644 index 000000000..9658c6292 Binary files /dev/null and b/src/examples/2DPhysics/img/i6c8a3edf-d5fe-4916-b63c-2201c099d28f.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png b/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png new file mode 100644 index 000000000..e9f6db0e2 Binary files /dev/null and b/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png differ diff --git a/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png_prev.png b/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png_prev.png new file mode 100644 index 000000000..525b20407 Binary files /dev/null and b/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png_prev@2.png b/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png_prev@2.png new file mode 100644 index 000000000..8416504cb Binary files /dev/null and b/src/examples/2DPhysics/img/i8a5f385a-d547-4d2d-9641-b1856738c62a.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png b/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png new file mode 100644 index 000000000..f8a8168d9 Binary files /dev/null and b/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png differ diff --git a/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png_prev.png b/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png_prev.png new file mode 100644 index 000000000..6e652c6f7 Binary files /dev/null and b/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png_prev@2.png b/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png_prev@2.png new file mode 100644 index 000000000..bde065870 Binary files /dev/null and b/src/examples/2DPhysics/img/i961b4fd2-4ed0-4864-890e-dfd79086129b.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png b/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png new file mode 100644 index 000000000..c67e25a0c Binary files /dev/null and b/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png differ diff --git a/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png_prev.png b/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png_prev.png new file mode 100644 index 000000000..2900a26e4 Binary files /dev/null and b/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png_prev@2.png b/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png_prev@2.png new file mode 100644 index 000000000..615212731 Binary files /dev/null and b/src/examples/2DPhysics/img/i9afd54d7-1265-4ba0-b5de-5226b3c7e2fb.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png b/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png new file mode 100644 index 000000000..b5d8ae027 Binary files /dev/null and b/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png differ diff --git a/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png_prev.png b/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png_prev.png new file mode 100644 index 000000000..aa69d2ab3 Binary files /dev/null and b/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png_prev.png differ diff --git a/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png_prev@2.png b/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png_prev@2.png new file mode 100644 index 000000000..da49e4674 Binary files /dev/null and b/src/examples/2DPhysics/img/i9e6feb47-e8bd-4832-a1f4-de20729e9fa2.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png b/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png new file mode 100644 index 000000000..de46e08a3 Binary files /dev/null and b/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png differ diff --git a/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png_prev.png b/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png_prev.png new file mode 100644 index 000000000..2c1e937bd Binary files /dev/null and b/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png_prev.png differ diff --git a/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png_prev@2.png b/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png_prev@2.png new file mode 100644 index 000000000..cc7e344ca Binary files /dev/null and b/src/examples/2DPhysics/img/iabdeba09-af47-4b39-a276-fa2e59b164aa.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png b/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png new file mode 100644 index 000000000..39154f84a Binary files /dev/null and b/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png differ diff --git a/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png_prev.png b/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png_prev.png new file mode 100644 index 000000000..35ea710c1 Binary files /dev/null and b/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png_prev.png differ diff --git a/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png_prev@2.png b/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png_prev@2.png new file mode 100644 index 000000000..f02879c67 Binary files /dev/null and b/src/examples/2DPhysics/img/ic4d4030a-b640-44be-bded-26a5c030f542.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png b/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png new file mode 100644 index 000000000..cf470c9a1 Binary files /dev/null and b/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png differ diff --git a/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png_prev.png b/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png_prev.png new file mode 100644 index 000000000..61e9bfa1f Binary files /dev/null and b/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png_prev.png differ diff --git a/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png_prev@2.png b/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png_prev@2.png new file mode 100644 index 000000000..84cd9e046 Binary files /dev/null and b/src/examples/2DPhysics/img/if6a40cf4-e9c0-47ff-afa8-6cdc259ef17e.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png b/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png new file mode 100644 index 000000000..8d85509b9 Binary files /dev/null and b/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png differ diff --git a/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png_prev.png b/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png_prev.png new file mode 100644 index 000000000..13394ac89 Binary files /dev/null and b/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png_prev.png differ diff --git a/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png_prev@2.png b/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png_prev@2.png new file mode 100644 index 000000000..a0b2e46bd Binary files /dev/null and b/src/examples/2DPhysics/img/if878c588-3c26-486b-a20f-b23ffab4d579.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png b/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png new file mode 100644 index 000000000..0b71aa819 Binary files /dev/null and b/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png differ diff --git a/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png_prev.png b/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png_prev.png new file mode 100644 index 000000000..30de9f33c Binary files /dev/null and b/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png_prev.png differ diff --git a/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png_prev@2.png b/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png_prev@2.png new file mode 100644 index 000000000..0344a9190 Binary files /dev/null and b/src/examples/2DPhysics/img/ifc52b049-910a-4e96-adcf-378553c0818c.png_prev@2.png differ diff --git a/src/examples/2DPhysics/img/r2d29a5c56244.png b/src/examples/2DPhysics/img/r2d29a5c56244.png new file mode 100644 index 000000000..e7749ae9c Binary files /dev/null and b/src/examples/2DPhysics/img/r2d29a5c56244.png differ diff --git a/src/examples/2DPhysics/img/splash.png b/src/examples/2DPhysics/img/splash.png new file mode 100644 index 000000000..e7749ae9c Binary files /dev/null and b/src/examples/2DPhysics/img/splash.png differ diff --git a/src/examples/2DPhysics/snd/s3142b705-6de5-4f57-9b70-c9bc3fb4cdad.ogg b/src/examples/2DPhysics/snd/s3142b705-6de5-4f57-9b70-c9bc3fb4cdad.ogg new file mode 100644 index 000000000..aa0b41485 Binary files /dev/null and b/src/examples/2DPhysics/snd/s3142b705-6de5-4f57-9b70-c9bc3fb4cdad.ogg differ diff --git a/src/examples/2DPhysics/snd/scbca4dd5-7369-48d5-b3b7-e9b0055e2eda.ogg b/src/examples/2DPhysics/snd/scbca4dd5-7369-48d5-b3b7-e9b0055e2eda.ogg new file mode 100644 index 000000000..c7571219c Binary files /dev/null and b/src/examples/2DPhysics/snd/scbca4dd5-7369-48d5-b3b7-e9b0055e2eda.ogg differ diff --git a/src/examples/2DPhysics/snd/sccfe7f50-d4d3-4570-95e9-75d5d73bef0a.ogg b/src/examples/2DPhysics/snd/sccfe7f50-d4d3-4570-95e9-75d5d73bef0a.ogg new file mode 100644 index 000000000..70d13ee30 Binary files /dev/null and b/src/examples/2DPhysics/snd/sccfe7f50-d4d3-4570-95e9-75d5d73bef0a.ogg differ