Best Python code snippet using locust
Body.js
Source:Body.js
1/**2* The `Matter.Body` module contains methods for creating and manipulating body models.3* A `Matter.Body` is a rigid body that can be simulated by a `Matter.Engine`.4* Factories for commonly used body configurations (such as rectangles, circles and other polygons) can be found in the module `Matter.Bodies`.5*6* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).7* @class Body8*/9var Body = {};10module.exports = Body;11var Vertices = require('../geometry/Vertices');12var Vector = require('../geometry/Vector');13var Sleeping = require('../core/Sleeping');14var Render = require('../render/Render');15var Common = require('../core/Common');16var Bounds = require('../geometry/Bounds');17var Axes = require('../geometry/Axes');18(function() {19 Body._inertiaScale = 4;20 Body._nextCollidingGroupId = 1;21 Body._nextNonCollidingGroupId = -1;22 Body._nextCategory = 0x0001;23 /**24 * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults.25 * All properties have default values, and many are pre-calculated automatically based on other properties.26 * Vertices must be specified in clockwise order.27 * See the properties section below for detailed information on what you can pass via the `options` object.28 * @method create29 * @param {} options30 * @return {body} body31 */32 Body.create = function(options) {33 var defaults = {34 id: Common.nextId(),35 type: 'body',36 label: 'Body',37 parts: [],38 plugin: {},39 angle: 0,40 vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),41 position: { x: 0, y: 0 },42 force: { x: 0, y: 0 },43 torque: 0,44 positionImpulse: { x: 0, y: 0 },45 constraintImpulse: { x: 0, y: 0, angle: 0 },46 totalContacts: 0,47 speed: 0,48 angularSpeed: 0,49 velocity: { x: 0, y: 0 },50 angularVelocity: 0,51 isSensor: false,52 isStatic: false,53 isSleeping: false,54 motion: 0,55 sleepThreshold: 60,56 density: 0.001,57 restitution: 0,58 friction: 0.1,59 frictionStatic: 0.5,60 frictionAir: 0.01,61 collisionFilter: {62 category: 0x0001,63 mask: 0xFFFFFFFF,64 group: 065 },66 slop: 0.05,67 timeScale: 1,68 render: {69 visible: true,70 opacity: 1,71 sprite: {72 xScale: 1,73 yScale: 1,74 xOffset: 0,75 yOffset: 076 },77 lineWidth: 078 },79 events: null,80 bounds: null,81 chamfer: null,82 circleRadius: 0,83 positionPrev: null,84 anglePrev: 0,85 parent: null,86 axes: null,87 area: 0,88 mass: 0,89 inertia: 0,90 _original: null91 };92 var body = Common.extend(defaults, options);93 _initProperties(body, options);94 return body;95 };96 /**97 * Returns the next unique group index for which bodies will collide.98 * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide.99 * See `body.collisionFilter` for more information.100 * @method nextGroup101 * @param {bool} [isNonColliding=false]102 * @return {Number} Unique group index103 */104 Body.nextGroup = function(isNonColliding) {105 if (isNonColliding)106 return Body._nextNonCollidingGroupId--;107 return Body._nextCollidingGroupId++;108 };109 /**110 * Returns the next unique category bitfield (starting after the initial default category `0x0001`).111 * There are 32 available. See `body.collisionFilter` for more information.112 * @method nextCategory113 * @return {Number} Unique category bitfield114 */115 Body.nextCategory = function() {116 Body._nextCategory = Body._nextCategory << 1;117 return Body._nextCategory;118 };119 /**120 * Initialises body properties.121 * @method _initProperties122 * @private123 * @param {body} body124 * @param {} [options]125 */126 var _initProperties = function(body, options) {127 options = options || {};128 // init required properties (order is important)129 Body.set(body, {130 bounds: body.bounds || Bounds.create(body.vertices),131 positionPrev: body.positionPrev || Vector.clone(body.position),132 anglePrev: body.anglePrev || body.angle,133 vertices: body.vertices,134 parts: body.parts || [body],135 isStatic: body.isStatic,136 isSleeping: body.isSleeping,137 parent: body.parent || body138 });139 Vertices.rotate(body.vertices, body.angle, body.position);140 Axes.rotate(body.axes, body.angle);141 Bounds.update(body.bounds, body.vertices, body.velocity);142 // allow options to override the automatically calculated properties143 Body.set(body, {144 axes: options.axes || body.axes,145 area: options.area || body.area,146 mass: options.mass || body.mass,147 inertia: options.inertia || body.inertia148 });149 // render properties150 var defaultFillStyle = (body.isStatic ? '#2e2b44' : Common.choose(['#006BA6', '#0496FF', '#FFBC42', '#D81159', '#8F2D56'])),151 defaultStrokeStyle = '#000';152 body.render.fillStyle = body.render.fillStyle || defaultFillStyle;153 body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;154 body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);155 body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);156 };157 /**158 * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist.159 * Prefer to use the actual setter functions in performance critical situations.160 * @method set161 * @param {body} body162 * @param {} settings A property name (or map of properties and values) to set on the body.163 * @param {} value The value to set if `settings` is a single property name.164 */165 Body.set = function(body, settings, value) {166 var property;167 if (typeof settings === 'string') {168 property = settings;169 settings = {};170 settings[property] = value;171 }172 for (property in settings) {173 if (!Object.prototype.hasOwnProperty.call(settings, property))174 continue;175 value = settings[property];176 switch (property) {177 case 'isStatic':178 Body.setStatic(body, value);179 break;180 case 'isSleeping':181 Sleeping.set(body, value);182 break;183 case 'mass':184 Body.setMass(body, value);185 break;186 case 'density':187 Body.setDensity(body, value);188 break;189 case 'inertia':190 Body.setInertia(body, value);191 break;192 case 'vertices':193 Body.setVertices(body, value);194 break;195 case 'position':196 Body.setPosition(body, value);197 break;198 case 'angle':199 Body.setAngle(body, value);200 break;201 case 'velocity':202 Body.setVelocity(body, value);203 break;204 case 'angularVelocity':205 Body.setAngularVelocity(body, value);206 break;207 case 'parts':208 Body.setParts(body, value);209 break;210 case 'centre':211 Body.setCentre(body, value);212 break;213 default:214 body[property] = value;215 }216 }217 };218 /**219 * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity.220 * @method setStatic221 * @param {body} body222 * @param {bool} isStatic223 */224 Body.setStatic = function(body, isStatic) {225 for (var i = 0; i < body.parts.length; i++) {226 var part = body.parts[i];227 part.isStatic = isStatic;228 if (isStatic) {229 part._original = {230 restitution: part.restitution,231 friction: part.friction,232 mass: part.mass,233 inertia: part.inertia,234 density: part.density,235 inverseMass: part.inverseMass,236 inverseInertia: part.inverseInertia237 };238 part.restitution = 0;239 part.friction = 1;240 part.mass = part.inertia = part.density = Infinity;241 part.inverseMass = part.inverseInertia = 0;242 part.positionPrev.x = part.position.x;243 part.positionPrev.y = part.position.y;244 part.anglePrev = part.angle;245 part.angularVelocity = 0;246 part.speed = 0;247 part.angularSpeed = 0;248 part.motion = 0;249 } else if (part._original) {250 part.restitution = part._original.restitution;251 part.friction = part._original.friction;252 part.mass = part._original.mass;253 part.inertia = part._original.inertia;254 part.density = part._original.density;255 part.inverseMass = part._original.inverseMass;256 part.inverseInertia = part._original.inverseInertia;257 part._original = null;258 }259 }260 };261 /**262 * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change.263 * @method setMass264 * @param {body} body265 * @param {number} mass266 */267 Body.setMass = function(body, mass) {268 var moment = body.inertia / (body.mass / 6);269 body.inertia = moment * (mass / 6);270 body.inverseInertia = 1 / body.inertia;271 body.mass = mass;272 body.inverseMass = 1 / body.mass;273 body.density = body.mass / body.area;274 };275 /**276 * Sets the density of the body. Mass and inertia are automatically updated to reflect the change.277 * @method setDensity278 * @param {body} body279 * @param {number} density280 */281 Body.setDensity = function(body, density) {282 Body.setMass(body, density * body.area);283 body.density = density;284 };285 /**286 * Sets the moment of inertia (i.e. second moment of area) of the body. 287 * Inverse inertia is automatically updated to reflect the change. Mass is not changed.288 * @method setInertia289 * @param {body} body290 * @param {number} inertia291 */292 Body.setInertia = function(body, inertia) {293 body.inertia = inertia;294 body.inverseInertia = 1 / body.inertia;295 };296 /**297 * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`).298 * Vertices will be automatically transformed to be orientated around their centre of mass as the origin.299 * They are then automatically translated to world space based on `body.position`.300 *301 * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array).302 * Vertices must form a convex hull, concave hulls are not supported.303 *304 * @method setVertices305 * @param {body} body306 * @param {vector[]} vertices307 */308 Body.setVertices = function(body, vertices) {309 // change vertices310 if (vertices[0].body === body) {311 body.vertices = vertices;312 } else {313 body.vertices = Vertices.create(vertices, body);314 }315 // update properties316 body.axes = Axes.fromVertices(body.vertices);317 body.area = Vertices.area(body.vertices);318 Body.setMass(body, body.density * body.area);319 // orient vertices around the centre of mass at origin (0, 0)320 var centre = Vertices.centre(body.vertices);321 Vertices.translate(body.vertices, centre, -1);322 // update inertia while vertices are at origin (0, 0)323 Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass));324 // update geometry325 Vertices.translate(body.vertices, body.position);326 Bounds.update(body.bounds, body.vertices, body.velocity);327 };328 /**329 * Sets the parts of the `body` and updates mass, inertia and centroid.330 * Each part will have its parent set to `body`.331 * By default the convex hull will be automatically computed and set on `body`, unless `autoHull` is set to `false.`332 * Note that this method will ensure that the first part in `body.parts` will always be the `body`.333 * @method setParts334 * @param {body} body335 * @param [body] parts336 * @param {bool} [autoHull=true]337 */338 Body.setParts = function(body, parts, autoHull) {339 var i;340 // add all the parts, ensuring that the first part is always the parent body341 parts = parts.slice(0);342 body.parts.length = 0;343 body.parts.push(body);344 body.parent = body;345 for (i = 0; i < parts.length; i++) {346 var part = parts[i];347 if (part !== body) {348 part.parent = body;349 body.parts.push(part);350 }351 }352 if (body.parts.length === 1)353 return;354 autoHull = typeof autoHull !== 'undefined' ? autoHull : true;355 // find the convex hull of all parts to set on the parent body356 if (autoHull) {357 var vertices = [];358 for (i = 0; i < parts.length; i++) {359 vertices = vertices.concat(parts[i].vertices);360 }361 Vertices.clockwiseSort(vertices);362 var hull = Vertices.hull(vertices),363 hullCentre = Vertices.centre(hull);364 Body.setVertices(body, hull);365 Vertices.translate(body.vertices, hullCentre);366 }367 // sum the properties of all compound parts of the parent body368 var total = Body._totalProperties(body);369 body.area = total.area;370 body.parent = body;371 body.position.x = total.centre.x;372 body.position.y = total.centre.y;373 body.positionPrev.x = total.centre.x;374 body.positionPrev.y = total.centre.y;375 Body.setMass(body, total.mass);376 Body.setInertia(body, total.inertia);377 Body.setPosition(body, total.centre);378 };379 /**380 * Set the centre of mass of the body. 381 * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation.382 * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density.383 * This is equal to moving `body.position` but not the `body.vertices`.384 * Invalid if the `centre` falls outside the body's convex hull.385 * @method setCentre386 * @param {body} body387 * @param {vector} centre388 * @param {bool} relative389 */390 Body.setCentre = function(body, centre, relative) {391 if (!relative) {392 body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x);393 body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y);394 body.position.x = centre.x;395 body.position.y = centre.y;396 } else {397 body.positionPrev.x += centre.x;398 body.positionPrev.y += centre.y;399 body.position.x += centre.x;400 body.position.y += centre.y;401 }402 };403 /**404 * Sets the position of the body instantly. Velocity, angle, force etc. are unchanged.405 * @method setPosition406 * @param {body} body407 * @param {vector} position408 */409 Body.setPosition = function(body, position) {410 var delta = Vector.sub(position, body.position);411 body.positionPrev.x += delta.x;412 body.positionPrev.y += delta.y;413 for (var i = 0; i < body.parts.length; i++) {414 var part = body.parts[i];415 part.position.x += delta.x;416 part.position.y += delta.y;417 Vertices.translate(part.vertices, delta);418 Bounds.update(part.bounds, part.vertices, body.velocity);419 }420 };421 /**422 * Sets the angle of the body instantly. Angular velocity, position, force etc. are unchanged.423 * @method setAngle424 * @param {body} body425 * @param {number} angle426 */427 Body.setAngle = function(body, angle) {428 var delta = angle - body.angle;429 body.anglePrev += delta;430 for (var i = 0; i < body.parts.length; i++) {431 var part = body.parts[i];432 part.angle += delta;433 Vertices.rotate(part.vertices, delta, body.position);434 Axes.rotate(part.axes, delta);435 Bounds.update(part.bounds, part.vertices, body.velocity);436 if (i > 0) {437 Vector.rotateAbout(part.position, delta, body.position, part.position);438 }439 }440 };441 /**442 * Sets the linear velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`.443 * @method setVelocity444 * @param {body} body445 * @param {vector} velocity446 */447 Body.setVelocity = function(body, velocity) {448 body.positionPrev.x = body.position.x - velocity.x;449 body.positionPrev.y = body.position.y - velocity.y;450 body.velocity.x = velocity.x;451 body.velocity.y = velocity.y;452 body.speed = Vector.magnitude(body.velocity);453 };454 /**455 * Sets the angular velocity of the body instantly. Position, angle, force etc. are unchanged. See also `Body.applyForce`.456 * @method setAngularVelocity457 * @param {body} body458 * @param {number} velocity459 */460 Body.setAngularVelocity = function(body, velocity) {461 body.anglePrev = body.angle - velocity;462 body.angularVelocity = velocity;463 body.angularSpeed = Math.abs(body.angularVelocity);464 };465 /**466 * Moves a body by a given vector relative to its current position, without imparting any velocity.467 * @method translate468 * @param {body} body469 * @param {vector} translation470 */471 Body.translate = function(body, translation) {472 Body.setPosition(body, Vector.add(body.position, translation));473 };474 /**475 * Rotates a body by a given angle relative to its current angle, without imparting any angular velocity.476 * @method rotate477 * @param {body} body478 * @param {number} rotation479 * @param {vector} [point]480 */481 Body.rotate = function(body, rotation, point) {482 if (!point) {483 Body.setAngle(body, body.angle + rotation);484 } else {485 var cos = Math.cos(rotation),486 sin = Math.sin(rotation),487 dx = body.position.x - point.x,488 dy = body.position.y - point.y;489 490 Body.setPosition(body, {491 x: point.x + (dx * cos - dy * sin),492 y: point.y + (dx * sin + dy * cos)493 });494 Body.setAngle(body, body.angle + rotation);495 }496 };497 /**498 * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre).499 * @method scale500 * @param {body} body501 * @param {number} scaleX502 * @param {number} scaleY503 * @param {vector} [point]504 */505 Body.scale = function(body, scaleX, scaleY, point) {506 var totalArea = 0,507 totalInertia = 0;508 point = point || body.position;509 for (var i = 0; i < body.parts.length; i++) {510 var part = body.parts[i];511 // scale vertices512 Vertices.scale(part.vertices, scaleX, scaleY, point);513 // update properties514 part.axes = Axes.fromVertices(part.vertices);515 part.area = Vertices.area(part.vertices);516 Body.setMass(part, body.density * part.area);517 // update inertia (requires vertices to be at origin)518 Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });519 Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass));520 Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });521 if (i > 0) {522 totalArea += part.area;523 totalInertia += part.inertia;524 }525 // scale position526 part.position.x = point.x + (part.position.x - point.x) * scaleX;527 part.position.y = point.y + (part.position.y - point.y) * scaleY;528 // update bounds529 Bounds.update(part.bounds, part.vertices, body.velocity);530 }531 // handle parent body532 if (body.parts.length > 1) {533 body.area = totalArea;534 if (!body.isStatic) {535 Body.setMass(body, body.density * totalArea);536 Body.setInertia(body, totalInertia);537 }538 }539 // handle circles540 if (body.circleRadius) { 541 if (scaleX === scaleY) {542 body.circleRadius *= scaleX;543 } else {544 // body is no longer a circle545 body.circleRadius = null;546 }547 }548 };549 /**550 * Performs a simulation step for the given `body`, including updating position and angle using Verlet integration.551 * @method update552 * @param {body} body553 * @param {number} deltaTime554 * @param {number} timeScale555 * @param {number} correction556 */557 Body.update = function(body, deltaTime, timeScale, correction) {558 var deltaTimeSquared = Math.pow(deltaTime * timeScale * body.timeScale, 2);559 // from the previous step560 var frictionAir = 1 - body.frictionAir * timeScale * body.timeScale,561 velocityPrevX = body.position.x - body.positionPrev.x,562 velocityPrevY = body.position.y - body.positionPrev.y;563 // update velocity with Verlet integration564 body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;565 body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;566 body.positionPrev.x = body.position.x;567 body.positionPrev.y = body.position.y;568 body.position.x += body.velocity.x;569 body.position.y += body.velocity.y;570 // update angular velocity with Verlet integration571 body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;572 body.anglePrev = body.angle;573 body.angle += body.angularVelocity;574 // track speed and acceleration575 body.speed = Vector.magnitude(body.velocity);576 body.angularSpeed = Math.abs(body.angularVelocity);577 // transform the body geometry578 for (var i = 0; i < body.parts.length; i++) {579 var part = body.parts[i];580 Vertices.translate(part.vertices, body.velocity);581 582 if (i > 0) {583 part.position.x += body.velocity.x;584 part.position.y += body.velocity.y;585 }586 if (body.angularVelocity !== 0) {587 Vertices.rotate(part.vertices, body.angularVelocity, body.position);588 Axes.rotate(part.axes, body.angularVelocity);589 if (i > 0) {590 Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position);591 }592 }593 Bounds.update(part.bounds, part.vertices, body.velocity);594 }595 };596 /**597 * Applies a force to a body from a given world-space position, including resulting torque.598 * @method applyForce599 * @param {body} body600 * @param {vector} position601 * @param {vector} force602 */603 Body.applyForce = function(body, position, force) {604 body.force.x += force.x;605 body.force.y += force.y;606 var offset = { x: position.x - body.position.x, y: position.y - body.position.y };607 body.torque += offset.x * force.y - offset.y * force.x;608 };609 /**610 * Returns the sums of the properties of all compound parts of the parent body.611 * @method _totalProperties612 * @private613 * @param {body} body614 * @return {}615 */616 Body._totalProperties = function(body) {617 // from equations at:618 // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory619 // http://output.to/sideway/default.asp?qno=121100087620 var properties = {621 mass: 0,622 area: 0,623 inertia: 0,624 centre: { x: 0, y: 0 }625 };626 // sum the properties of all compound parts of the parent body627 for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {628 var part = body.parts[i],629 mass = part.mass !== Infinity ? part.mass : 1;630 properties.mass += mass;631 properties.area += part.area;632 properties.inertia += part.inertia;633 properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass));634 }635 properties.centre = Vector.div(properties.centre, properties.mass);636 return properties;637 };638 /*639 *640 * Events Documentation641 *642 */643 /**644 * Fired when a body starts sleeping (where `this` is the body).645 *646 * @event sleepStart647 * @this {body} The body that has started sleeping648 * @param {} event An event object649 * @param {} event.source The source object of the event650 * @param {} event.name The name of the event651 */652 /**653 * Fired when a body ends sleeping (where `this` is the body).654 *655 * @event sleepEnd656 * @this {body} The body that has ended sleeping657 * @param {} event An event object658 * @param {} event.source The source object of the event659 * @param {} event.name The name of the event660 */661 /*662 *663 * Properties Documentation664 *665 */666 /**667 * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`.668 *669 * @property id670 * @type number671 */672 /**673 * A `String` denoting the type of object.674 *675 * @property type676 * @type string677 * @default "body"678 * @readOnly679 */680 /**681 * An arbitrary `String` name to help the user identify and manage bodies.682 *683 * @property label684 * @type string685 * @default "Body"686 */687 /**688 * An array of bodies that make up this body. 689 * The first body in the array must always be a self reference to the current body instance.690 * All bodies in the `parts` array together form a single rigid compound body.691 * Parts are allowed to overlap, have gaps or holes or even form concave bodies.692 * Parts themselves should never be added to a `World`, only the parent body should be.693 * Use `Body.setParts` when setting parts to ensure correct updates of all properties.694 *695 * @property parts696 * @type body[]697 */698 /**699 * An object reserved for storing plugin-specific properties.700 *701 * @property plugin702 * @type {}703 */704 /**705 * A self reference if the body is _not_ a part of another body.706 * Otherwise this is a reference to the body that this is a part of.707 * See `body.parts`.708 *709 * @property parent710 * @type body711 */712 /**713 * A `Number` specifying the angle of the body, in radians.714 *715 * @property angle716 * @type number717 * @default 0718 */719 /**720 * An array of `Vector` objects that specify the convex hull of the rigid body.721 * These should be provided about the origin `(0, 0)`. E.g.722 *723 * [{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]724 *725 * 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).726 * The `Vector` objects are also augmented with additional properties required for efficient collision detection. 727 *728 * Other properties such as `inertia` and `bounds` are automatically calculated from the passed vertices (unless provided via `options`).729 * Concave hulls are not currently supported. The module `Matter.Vertices` contains useful methods for working with vertices.730 *731 * @property vertices732 * @type vector[]733 */734 /**735 * A `Vector` that specifies the current world-space position of the body.736 *737 * @property position738 * @type vector739 * @default { x: 0, y: 0 }740 */741 /**742 * A `Vector` that specifies the force to apply in the current step. It is zeroed after every `Body.update`. See also `Body.applyForce`.743 *744 * @property force745 * @type vector746 * @default { x: 0, y: 0 }747 */748 /**749 * A `Number` that specifies the torque (turning force) to apply in the current step. It is zeroed after every `Body.update`.750 *751 * @property torque752 * @type number753 * @default 0754 */755 /**756 * 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`).757 *758 * @readOnly759 * @property speed760 * @type number761 * @default 0762 */763 /**764 * 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`).765 *766 * @readOnly767 * @property angularSpeed768 * @type number769 * @default 0770 */771 /**772 * A `Vector` that _measures_ the current velocity of the body after the last `Body.update`. It is read-only. 773 * 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).774 *775 * @readOnly776 * @property velocity777 * @type vector778 * @default { x: 0, y: 0 }779 */780 /**781 * A `Number` that _measures_ the current angular velocity of the body after the last `Body.update`. It is read-only. 782 * 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).783 *784 * @readOnly785 * @property angularVelocity786 * @type number787 * @default 0788 */789 /**790 * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed.791 * 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.792 *793 * @property isStatic794 * @type boolean795 * @default false796 */797 /**798 * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically.799 *800 * @property isSensor801 * @type boolean802 * @default false803 */804 /**805 * 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.806 * If you need to set a body as sleeping, you should use `Sleeping.set` as this requires more than just setting this flag.807 *808 * @property isSleeping809 * @type boolean810 * @default false811 */812 /**813 * 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.814 * It is used and updated by the `Matter.Sleeping` module during simulation to decide if a body has come to rest.815 *816 * @readOnly817 * @property motion818 * @type number819 * @default 0820 */821 /**822 * 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).823 *824 * @property sleepThreshold825 * @type number826 * @default 60827 */828 /**829 * A `Number` that defines the density of the body, that is its mass per unit area.830 * If you pass the density via `Body.create` the `mass` property is automatically calculated for you based on the size (area) of the object.831 * 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).832 *833 * @property density834 * @type number835 * @default 0.001836 */837 /**838 * A `Number` that defines the mass of the body, although it may be more appropriate to specify the `density` property instead.839 * If you modify this value, you must also modify the `body.inverseMass` property (`1 / mass`).840 *841 * @property mass842 * @type number843 */844 /**845 * A `Number` that defines the inverse mass of the body (`1 / mass`).846 * If you modify this value, you must also modify the `body.mass` property.847 *848 * @property inverseMass849 * @type number850 */851 /**852 * A `Number` that defines the moment of inertia (i.e. second moment of area) of the body.853 * It is automatically calculated from the given convex hull (`vertices` array) and density in `Body.create`.854 * If you modify this value, you must also modify the `body.inverseInertia` property (`1 / inertia`).855 *856 * @property inertia857 * @type number858 */859 /**860 * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`).861 * If you modify this value, you must also modify the `body.inertia` property.862 *863 * @property inverseInertia864 * @type number865 */866 /**867 * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`.868 * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. 869 * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy.870 * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula:871 *872 * Math.max(bodyA.restitution, bodyB.restitution)873 *874 * @property restitution875 * @type number876 * @default 0877 */878 /**879 * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`.880 * A value of `0` means that the body may slide indefinitely.881 * A value of `1` means the body may come to a stop almost instantly after a force is applied.882 *883 * The effects of the value may be non-linear. 884 * High values may be unstable depending on the body.885 * The engine uses a Coulomb friction model including static and kinetic friction.886 * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula:887 *888 * Math.min(bodyA.friction, bodyB.friction)889 *890 * @property friction891 * @type number892 * @default 0.1893 */894 /**895 * A `Number` that defines the static friction of the body (in the Coulomb friction model). 896 * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used.897 * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary.898 * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction.899 *900 * @property frictionStatic901 * @type number902 * @default 0.5903 */904 /**905 * A `Number` that defines the air friction of the body (air resistance). 906 * A value of `0` means the body will never slow as it moves through space.907 * The higher the value, the faster a body slows when moving through space.908 * The effects of the value are non-linear. 909 *910 * @property frictionAir911 * @type number912 * @default 0.01913 */914 /**915 * An `Object` that specifies the collision filtering properties of this body.916 *917 * Collisions between two bodies will obey the following rules:918 * - If the two bodies have the same non-zero value of `collisionFilter.group`,919 * they will always collide if the value is positive, and they will never collide920 * if the value is negative.921 * - If the two bodies have different values of `collisionFilter.group` or if one922 * (or both) of the bodies has a value of 0, then the category/mask rules apply as follows:923 *924 * Each body belongs to a collision category, given by `collisionFilter.category`. This925 * value is used as a bit field and the category should have only one bit set, meaning that926 * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32927 * different collision categories available.928 *929 * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies930 * the categories it collides with (the value is the bitwise AND value of all these categories).931 *932 * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's933 * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0`934 * are both true.935 *936 * @property collisionFilter937 * @type object938 */939 /**940 * An Integer `Number`, that specifies the collision group this body belongs to.941 * See `body.collisionFilter` for more information.942 *943 * @property collisionFilter.group944 * @type object945 * @default 0946 */947 /**948 * A bit field that specifies the collision category this body belongs to.949 * The category value should have only one bit set, for example `0x0001`.950 * This means there are up to 32 unique collision categories available.951 * See `body.collisionFilter` for more information.952 *953 * @property collisionFilter.category954 * @type object955 * @default 1956 */957 /**958 * A bit mask that specifies the collision categories this body may collide with.959 * See `body.collisionFilter` for more information.960 *961 * @property collisionFilter.mask962 * @type object963 * @default -1964 */965 /**966 * A `Number` that specifies a tolerance on how far a body is allowed to 'sink' or rotate into other bodies.967 * Avoid changing this value unless you understand the purpose of `slop` in physics engines.968 * The default should generally suffice, although very large bodies may require larger values for stable stacking.969 *970 * @property slop971 * @type number972 * @default 0.05973 */974 /**975 * 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.976 *977 * @property timeScale978 * @type number979 * @default 1980 */981 /**982 * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.983 *984 * @property render985 * @type object986 */987 /**988 * A flag that indicates if the body should be rendered.989 *990 * @property render.visible991 * @type boolean992 * @default true993 */994 /**995 * Sets the opacity to use when rendering.996 *997 * @property render.opacity998 * @type number999 * @default 11000 */1001 /**1002 * An `Object` that defines the sprite properties to use when rendering, if any.1003 *1004 * @property render.sprite1005 * @type object1006 */1007 /**1008 * An `String` that defines the path to the image to use as the sprite texture, if any.1009 *1010 * @property render.sprite.texture1011 * @type string1012 */1013 1014 /**1015 * A `Number` that defines the scaling in the x-axis for the sprite, if any.1016 *1017 * @property render.sprite.xScale1018 * @type number1019 * @default 11020 */1021 /**1022 * A `Number` that defines the scaling in the y-axis for the sprite, if any.1023 *1024 * @property render.sprite.yScale1025 * @type number1026 * @default 11027 */1028 /**1029 * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width).1030 *1031 * @property render.sprite.xOffset1032 * @type number1033 * @default 01034 */1035 /**1036 * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height).1037 *1038 * @property render.sprite.yOffset1039 * @type number1040 * @default 01041 */1042 /**1043 * A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined).1044 * A value of `0` means no outline will be rendered.1045 *1046 * @property render.lineWidth1047 * @type number1048 * @default 01049 */1050 /**1051 * A `String` that defines the fill style to use when rendering the body (if a sprite is not defined).1052 * It is the same as when using a canvas, so it accepts CSS style property values.1053 *1054 * @property render.fillStyle1055 * @type string1056 * @default a random colour1057 */1058 /**1059 * A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined).1060 * It is the same as when using a canvas, so it accepts CSS style property values.1061 *1062 * @property render.strokeStyle1063 * @type string1064 * @default a random colour1065 */1066 /**1067 * An array of unique axis vectors (edge normals) used for collision detection.1068 * These are automatically calculated from the given convex hull (`vertices` array) in `Body.create`.1069 * They are constantly updated by `Body.update` during the simulation.1070 *1071 * @property axes1072 * @type vector[]1073 */1074 1075 /**1076 * A `Number` that _measures_ the area of the body's convex hull, calculated at creation by `Body.create`.1077 *1078 * @property area1079 * @type string1080 * @default 1081 */1082 /**1083 * A `Bounds` object that defines the AABB region for the body.1084 * It is automatically calculated from the given convex hull (`vertices` array) in `Body.create` and constantly updated by `Body.update` during simulation.1085 *1086 * @property bounds1087 * @type bounds1088 */...
TilemapCollision.js
Source:TilemapCollision.js
1/**2* @author Richard Davey <rich@photonstorm.com>3* @copyright 2016 Photon Storm Ltd.4* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}5*/6/**7* The Arcade Physics Tile map collision methods.8*9* @class Phaser.Physics.Arcade.TilemapCollision10* @constructor11*/12Phaser.Physics.Arcade.TilemapCollision = function () {};13Phaser.Physics.Arcade.TilemapCollision.prototype = {14 /**15 * @property {number} TILE_BIAS - A value added to the delta values during collision with tiles. Adjust this if you get tunneling.16 */17 TILE_BIAS: 16,18 /**19 * An internal function. Use Phaser.Physics.Arcade.collide instead.20 *21 * @method Phaser.Physics.Arcade#collideSpriteVsTilemapLayer22 * @private23 * @param {Phaser.Sprite} sprite - The sprite to check.24 * @param {Phaser.TilemapLayer} tilemapLayer - The layer to check.25 * @param {function} collideCallback - An optional callback function that is called if the objects collide. The two objects will be passed to this function in the same order in which you specified them.26 * @param {function} processCallback - A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then collision will only happen if processCallback returns true. The two objects will be passed to this function in the same order in which you specified them.27 * @param {object} callbackContext - The context in which to run the callbacks.28 * @param {boolean} overlapOnly - Just run an overlap or a full collision.29 */30 collideSpriteVsTilemapLayer: function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) {31 if (!sprite.body)32 {33 return;34 }35 var mapData = tilemapLayer.getTiles(36 sprite.body.position.x - sprite.body.tilePadding.x - tilemapLayer.getTileOffsetX(),37 sprite.body.position.y - sprite.body.tilePadding.y - tilemapLayer.getTileOffsetY(),38 sprite.body.width + sprite.body.tilePadding.x,39 sprite.body.height + sprite.body.tilePadding.y,40 false, false);41 if (mapData.length === 0)42 {43 return;44 }45 for (var i = 0; i < mapData.length; i++)46 {47 if (processCallback)48 {49 if (processCallback.call(callbackContext, sprite, mapData[i]))50 {51 if (this.separateTile(i, sprite.body, mapData[i], tilemapLayer, overlapOnly))52 {53 this._total++;54 if (collideCallback)55 {56 collideCallback.call(callbackContext, sprite, mapData[i]);57 }58 }59 }60 }61 else62 {63 if (this.separateTile(i, sprite.body, mapData[i], tilemapLayer, overlapOnly))64 {65 this._total++;66 if (collideCallback)67 {68 collideCallback.call(callbackContext, sprite, mapData[i]);69 }70 }71 }72 }73 },74 /**75 * An internal function. Use Phaser.Physics.Arcade.collide instead.76 *77 * @private78 * @method Phaser.Physics.Arcade#collideGroupVsTilemapLayer79 * @param {Phaser.Group} group - The Group to check.80 * @param {Phaser.TilemapLayer} tilemapLayer - The layer to check.81 * @param {function} collideCallback - An optional callback function that is called if the objects collide. The two objects will be passed to this function in the same order in which you specified them.82 * @param {function} processCallback - A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then collision will only happen if processCallback returns true. The two objects will be passed to this function in the same order in which you specified them.83 * @param {object} callbackContext - The context in which to run the callbacks.84 * @param {boolean} overlapOnly - Just run an overlap or a full collision.85 */86 collideGroupVsTilemapLayer: function (group, tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly) {87 if (group.length === 0)88 {89 return;90 }91 for (var i = 0; i < group.children.length; i++)92 {93 if (group.children[i].exists)94 {95 this.collideSpriteVsTilemapLayer(group.children[i], tilemapLayer, collideCallback, processCallback, callbackContext, overlapOnly);96 }97 }98 },99 /**100 * The core separation function to separate a physics body and a tile.101 *102 * @private103 * @method Phaser.Physics.Arcade#separateTile104 * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate.105 * @param {Phaser.Tile} tile - The tile to collide against.106 * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against.107 * @return {boolean} Returns true if the body was separated, otherwise false.108 */109 separateTile: function (i, body, tile, tilemapLayer, overlapOnly) {110 if (!body.enable)111 {112 return false;113 }114 115 var tilemapLayerOffsetX = tilemapLayer.getTileOffsetX();116 var tilemapLayerOffsetY = tilemapLayer.getTileOffsetY();117 // We re-check for collision in case body was separated in a previous step118 if (!tile.intersects((body.position.x - tilemapLayerOffsetX), (body.position.y - tilemapLayerOffsetY), (body.right - tilemapLayerOffsetX), (body.bottom - tilemapLayerOffsetY)))119 {120 // no collision so bail out (separated in a previous step)121 return false;122 }123 else if (overlapOnly)124 {125 // There is an overlap, and we don't need to separate. Bail.126 return true;127 }128 // They overlap. Any custom callbacks?129 // A local callback always takes priority over a layer level callback130 if (tile.collisionCallback && !tile.collisionCallback.call(tile.collisionCallbackContext, body.sprite, tile))131 {132 // If it returns true then we can carry on, otherwise we should abort.133 return false;134 }135 else if (typeof tile.layer.callbacks !== 'undefined' && tile.layer.callbacks[tile.index] && !tile.layer.callbacks[tile.index].callback.call(tile.layer.callbacks[tile.index].callbackContext, body.sprite, tile))136 {137 // If it returns true then we can carry on, otherwise we should abort.138 return false;139 }140 // We don't need to go any further if this tile doesn't actually separate141 if (!tile.faceLeft && !tile.faceRight && !tile.faceTop && !tile.faceBottom)142 {143 // This could happen if the tile was meant to be collided with re: a callback, but otherwise isn't needed for separation144 return false;145 }146 var ox = 0;147 var oy = 0;148 var minX = 0;149 var minY = 1;150 if (body.deltaAbsX() > body.deltaAbsY())151 {152 // Moving faster horizontally, check X axis first153 minX = -1;154 }155 else if (body.deltaAbsX() < body.deltaAbsY())156 {157 // Moving faster vertically, check Y axis first158 minY = -1;159 }160 if (body.deltaX() !== 0 && body.deltaY() !== 0 && (tile.faceLeft || tile.faceRight) && (tile.faceTop || tile.faceBottom))161 {162 // We only need do this if both axis have checking faces AND we're moving in both directions163 minX = Math.min(Math.abs((body.position.x - tilemapLayerOffsetX) - tile.right), Math.abs((body.right - tilemapLayerOffsetX) - tile.left));164 minY = Math.min(Math.abs((body.position.y - tilemapLayerOffsetY) - tile.bottom), Math.abs((body.bottom - tilemapLayerOffsetY) - tile.top));165 }166 if (minX < minY)167 {168 if (tile.faceLeft || tile.faceRight)169 {170 ox = this.tileCheckX(body, tile, tilemapLayer);171 // That's horizontal done, check if we still intersects? If not then we can return now172 if (ox !== 0 && !tile.intersects((body.position.x - tilemapLayerOffsetX), (body.position.y - tilemapLayerOffsetY), (body.right - tilemapLayerOffsetX), (body.bottom - tilemapLayerOffsetY)))173 {174 return true;175 }176 }177 if (tile.faceTop || tile.faceBottom)178 {179 oy = this.tileCheckY(body, tile, tilemapLayer);180 }181 }182 else183 {184 if (tile.faceTop || tile.faceBottom)185 {186 oy = this.tileCheckY(body, tile, tilemapLayer);187 // That's vertical done, check if we still intersects? If not then we can return now188 if (oy !== 0 && !tile.intersects((body.position.x - tilemapLayerOffsetX), (body.position.y - tilemapLayerOffsetY), (body.right - tilemapLayerOffsetX), (body.bottom - tilemapLayerOffsetY)))189 {190 return true;191 }192 }193 if (tile.faceLeft || tile.faceRight)194 {195 ox = this.tileCheckX(body, tile, tilemapLayer);196 }197 }198 return (ox !== 0 || oy !== 0);199 },200 /**201 * Check the body against the given tile on the X axis.202 *203 * @private204 * @method Phaser.Physics.Arcade#tileCheckX205 * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate.206 * @param {Phaser.Tile} tile - The tile to check.207 * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against.208 * @return {number} The amount of separation that occurred.209 */210 tileCheckX: function (body, tile, tilemapLayer) {211 var ox = 0;212 var tilemapLayerOffsetX = tilemapLayer.getTileOffsetX();213 if (body.deltaX() < 0 && !body.blocked.left && tile.collideRight && body.checkCollision.left)214 {215 // Body is moving LEFT216 if (tile.faceRight && (body.x - tilemapLayerOffsetX) < tile.right)217 {218 ox = (body.x - tilemapLayerOffsetX) - tile.right;219 if (ox < -this.TILE_BIAS)220 {221 ox = 0;222 }223 }224 }225 else if (body.deltaX() > 0 && !body.blocked.right && tile.collideLeft && body.checkCollision.right)226 {227 // Body is moving RIGHT228 if (tile.faceLeft && (body.right - tilemapLayerOffsetX) > tile.left)229 {230 ox = (body.right - tilemapLayerOffsetX) - tile.left;231 if (ox > this.TILE_BIAS)232 {233 ox = 0;234 }235 }236 }237 if (ox !== 0)238 {239 if (body.customSeparateX)240 {241 body.overlapX = ox;242 }243 else244 {245 this.processTileSeparationX(body, ox);246 }247 }248 return ox;249 },250 /**251 * Check the body against the given tile on the Y axis.252 *253 * @private254 * @method Phaser.Physics.Arcade#tileCheckY255 * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate.256 * @param {Phaser.Tile} tile - The tile to check.257 * @param {Phaser.TilemapLayer} tilemapLayer - The tilemapLayer to collide against.258 * @return {number} The amount of separation that occurred.259 */260 tileCheckY: function (body, tile, tilemapLayer) {261 var oy = 0;262 var tilemapLayerOffsetY = tilemapLayer.getTileOffsetY();263 if (body.deltaY() < 0 && !body.blocked.up && tile.collideDown && body.checkCollision.up)264 {265 // Body is moving UP266 if (tile.faceBottom && (body.y - tilemapLayerOffsetY) < tile.bottom)267 {268 oy = (body.y - tilemapLayerOffsetY) - tile.bottom;269 if (oy < -this.TILE_BIAS)270 {271 oy = 0;272 }273 }274 }275 else if (body.deltaY() > 0 && !body.blocked.down && tile.collideUp && body.checkCollision.down)276 {277 // Body is moving DOWN278 if (tile.faceTop && (body.bottom - tilemapLayerOffsetY) > tile.top)279 {280 oy = (body.bottom - tilemapLayerOffsetY) - tile.top;281 if (oy > this.TILE_BIAS)282 {283 oy = 0;284 }285 }286 }287 if (oy !== 0)288 {289 if (body.customSeparateY)290 {291 body.overlapY = oy;292 }293 else294 {295 this.processTileSeparationY(body, oy);296 }297 }298 return oy;299 },300 /**301 * Internal function to process the separation of a physics body from a tile.302 *303 * @private304 * @method Phaser.Physics.Arcade#processTileSeparationX305 * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate.306 * @param {number} x - The x separation amount.307 */308 processTileSeparationX: function (body, x) {309 if (x < 0)310 {311 body.blocked.left = true;312 }313 else if (x > 0)314 {315 body.blocked.right = true;316 }317 body.position.x -= x;318 if (body.bounce.x === 0)319 {320 body.velocity.x = 0;321 }322 else323 {324 body.velocity.x = -body.velocity.x * body.bounce.x;325 }326 },327 /**328 * Internal function to process the separation of a physics body from a tile.329 *330 * @private331 * @method Phaser.Physics.Arcade#processTileSeparationY332 * @param {Phaser.Physics.Arcade.Body} body - The Body object to separate.333 * @param {number} y - The y separation amount.334 */335 processTileSeparationY: function (body, y) {336 if (y < 0)337 {338 body.blocked.up = true;339 }340 else if (y > 0)341 {342 body.blocked.down = true;343 }344 body.position.y -= y;345 if (body.bounce.y === 0)346 {347 body.velocity.y = 0;348 }349 else350 {351 body.velocity.y = -body.velocity.y * body.bounce.y;352 }353 }354};355// Merge this with the Arcade Physics prototype...
Composites.js
Source:Composites.js
1/**2* The `Matter.Composites` module contains factory methods for creating composite bodies3* with commonly used configurations (such as stacks and chains).4*5* See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).6*7* @class Composites8*/9var Composites = {};10module.exports = Composites;11var Composite = require('../body/Composite');12var Constraint = require('../constraint/Constraint');13var Common = require('../core/Common');14var Body = require('../body/Body');15var Bodies = require('./Bodies');16(function() {17 /**18 * Create a new composite containing bodies created in the callback in a grid arrangement.19 * This function uses the body's bounds to prevent overlaps.20 * @method stack21 * @param {number} xx22 * @param {number} yy23 * @param {number} columns24 * @param {number} rows25 * @param {number} columnGap26 * @param {number} rowGap27 * @param {function} callback28 * @return {composite} A new composite containing objects created in the callback29 */30 Composites.stack = function(xx, yy, columns, rows, columnGap, rowGap, callback) {31 var stack = Composite.create({ label: 'Stack' }),32 x = xx,33 y = yy,34 lastBody,35 i = 0;36 for (var row = 0; row < rows; row++) {37 var maxHeight = 0;38 39 for (var column = 0; column < columns; column++) {40 var body = callback(x, y, column, row, lastBody, i);41 42 if (body) {43 var bodyHeight = body.bounds.max.y - body.bounds.min.y,44 bodyWidth = body.bounds.max.x - body.bounds.min.x; 45 if (bodyHeight > maxHeight)46 maxHeight = bodyHeight;47 48 Body.translate(body, { x: bodyWidth * 0.5, y: bodyHeight * 0.5 });49 x = body.bounds.max.x + columnGap;50 Composite.addBody(stack, body);51 52 lastBody = body;53 i += 1;54 } else {55 x += columnGap;56 }57 }58 59 y += maxHeight + rowGap;60 x = xx;61 }62 return stack;63 };64 65 /**66 * Chains all bodies in the given composite together using constraints.67 * @method chain68 * @param {composite} composite69 * @param {number} xOffsetA70 * @param {number} yOffsetA71 * @param {number} xOffsetB72 * @param {number} yOffsetB73 * @param {object} options74 * @return {composite} A new composite containing objects chained together with constraints75 */76 Composites.chain = function(composite, xOffsetA, yOffsetA, xOffsetB, yOffsetB, options) {77 var bodies = composite.bodies;78 79 for (var i = 1; i < bodies.length; i++) {80 var bodyA = bodies[i - 1],81 bodyB = bodies[i],82 bodyAHeight = bodyA.bounds.max.y - bodyA.bounds.min.y,83 bodyAWidth = bodyA.bounds.max.x - bodyA.bounds.min.x, 84 bodyBHeight = bodyB.bounds.max.y - bodyB.bounds.min.y,85 bodyBWidth = bodyB.bounds.max.x - bodyB.bounds.min.x;86 87 var defaults = {88 bodyA: bodyA,89 pointA: { x: bodyAWidth * xOffsetA, y: bodyAHeight * yOffsetA },90 bodyB: bodyB,91 pointB: { x: bodyBWidth * xOffsetB, y: bodyBHeight * yOffsetB }92 };93 94 var constraint = Common.extend(defaults, options);95 96 Composite.addConstraint(composite, Constraint.create(constraint));97 }98 composite.label += ' Chain';99 100 return composite;101 };102 /**103 * Connects bodies in the composite with constraints in a grid pattern, with optional cross braces.104 * @method mesh105 * @param {composite} composite106 * @param {number} columns107 * @param {number} rows108 * @param {boolean} crossBrace109 * @param {object} options110 * @return {composite} The composite containing objects meshed together with constraints111 */112 Composites.mesh = function(composite, columns, rows, crossBrace, options) {113 var bodies = composite.bodies,114 row,115 col,116 bodyA,117 bodyB,118 bodyC;119 120 for (row = 0; row < rows; row++) {121 for (col = 1; col < columns; col++) {122 bodyA = bodies[(col - 1) + (row * columns)];123 bodyB = bodies[col + (row * columns)];124 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));125 }126 if (row > 0) {127 for (col = 0; col < columns; col++) {128 bodyA = bodies[col + ((row - 1) * columns)];129 bodyB = bodies[col + (row * columns)];130 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyA, bodyB: bodyB }, options)));131 if (crossBrace && col > 0) {132 bodyC = bodies[(col - 1) + ((row - 1) * columns)];133 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));134 }135 if (crossBrace && col < columns - 1) {136 bodyC = bodies[(col + 1) + ((row - 1) * columns)];137 Composite.addConstraint(composite, Constraint.create(Common.extend({ bodyA: bodyC, bodyB: bodyB }, options)));138 }139 }140 }141 }142 composite.label += ' Mesh';143 144 return composite;145 };146 147 /**148 * Create a new composite containing bodies created in the callback in a pyramid arrangement.149 * This function uses the body's bounds to prevent overlaps.150 * @method pyramid151 * @param {number} xx152 * @param {number} yy153 * @param {number} columns154 * @param {number} rows155 * @param {number} columnGap156 * @param {number} rowGap157 * @param {function} callback158 * @return {composite} A new composite containing objects created in the callback159 */160 Composites.pyramid = function(xx, yy, columns, rows, columnGap, rowGap, callback) {161 return Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y, column, row, lastBody, i) {162 var actualRows = Math.min(rows, Math.ceil(columns / 2)),163 lastBodyWidth = lastBody ? lastBody.bounds.max.x - lastBody.bounds.min.x : 0;164 165 if (row > actualRows)166 return;167 168 // reverse row order169 row = actualRows - row;170 171 var start = row,172 end = columns - 1 - row;173 if (column < start || column > end)174 return;175 176 // retroactively fix the first body's position, since width was unknown177 if (i === 1) {178 Body.translate(lastBody, { x: (column + (columns % 2 === 1 ? 1 : -1)) * lastBodyWidth, y: 0 });179 }180 var xOffset = lastBody ? column * lastBodyWidth : 0;181 182 return callback(xx + xOffset + column * columnGap, y, column, row, lastBody, i);183 });184 };185 /**186 * Creates a composite with a Newton's Cradle setup of bodies and constraints.187 * @method newtonsCradle188 * @param {number} xx189 * @param {number} yy190 * @param {number} number191 * @param {number} size192 * @param {number} length193 * @return {composite} A new composite newtonsCradle body194 */195 Composites.newtonsCradle = function(xx, yy, number, size, length) {196 var newtonsCradle = Composite.create({ label: 'Newtons Cradle' });197 for (var i = 0; i < number; i++) {198 var separation = 1.9,199 circle = Bodies.circle(xx + i * (size * separation), yy + length, size, 200 { inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }),201 constraint = Constraint.create({ pointA: { x: xx + i * (size * separation), y: yy }, bodyB: circle });202 Composite.addBody(newtonsCradle, circle);203 Composite.addConstraint(newtonsCradle, constraint);204 }205 return newtonsCradle;206 };207 208 /**209 * Creates a composite with simple car setup of bodies and constraints.210 * @method car211 * @param {number} xx212 * @param {number} yy213 * @param {number} width214 * @param {number} height215 * @param {number} wheelSize216 * @return {composite} A new composite car body217 */218 Composites.car = function(xx, yy, width, height, wheelSize) {219 var group = Body.nextGroup(true),220 wheelBase = 20,221 wheelAOffset = -width * 0.5 + wheelBase,222 wheelBOffset = width * 0.5 - wheelBase,223 wheelYOffset = 0;224 225 var car = Composite.create({ label: 'Car' }),226 body = Bodies.rectangle(xx, yy, width, height, { 227 collisionFilter: {228 group: group229 },230 chamfer: {231 radius: height * 0.5232 },233 density: 0.0002234 });235 236 var wheelA = Bodies.circle(xx + wheelAOffset, yy + wheelYOffset, wheelSize, { 237 collisionFilter: {238 group: group239 },240 friction: 0.8241 });242 243 var wheelB = Bodies.circle(xx + wheelBOffset, yy + wheelYOffset, wheelSize, { 244 collisionFilter: {245 group: group246 },247 friction: 0.8248 });249 250 var axelA = Constraint.create({251 bodyB: body,252 pointB: { x: wheelAOffset, y: wheelYOffset },253 bodyA: wheelA,254 stiffness: 1,255 length: 0256 });257 258 var axelB = Constraint.create({259 bodyB: body,260 pointB: { x: wheelBOffset, y: wheelYOffset },261 bodyA: wheelB,262 stiffness: 1,263 length: 0264 });265 266 Composite.addBody(car, body);267 Composite.addBody(car, wheelA);268 Composite.addBody(car, wheelB);269 Composite.addConstraint(car, axelA);270 Composite.addConstraint(car, axelB);271 return car;272 };273 /**274 * Creates a simple soft body like object.275 * @method softBody276 * @param {number} xx277 * @param {number} yy278 * @param {number} columns279 * @param {number} rows280 * @param {number} columnGap281 * @param {number} rowGap282 * @param {boolean} crossBrace283 * @param {number} particleRadius284 * @param {} particleOptions285 * @param {} constraintOptions286 * @return {composite} A new composite softBody287 */288 Composites.softBody = function(xx, yy, columns, rows, columnGap, rowGap, crossBrace, particleRadius, particleOptions, constraintOptions) {289 particleOptions = Common.extend({ inertia: Infinity }, particleOptions);290 constraintOptions = Common.extend({ stiffness: 0.2, render: { type: 'line', anchors: false } }, constraintOptions);291 var softBody = Composites.stack(xx, yy, columns, rows, columnGap, rowGap, function(x, y) {292 return Bodies.circle(x, y, particleRadius, particleOptions);293 });294 Composites.mesh(softBody, columns, rows, crossBrace, constraintOptions);295 softBody.label = 'Soft Body';296 return softBody;297 };...
default.js
Source:default.js
1var express = require('express');2var router = express.Router();3var Default = require("../models/default.js");4router.route('/')5 .get(function(req, res){6 Default.find(function(err, defaults){7 if(err){console.log(err);}8 res.send(defaults);9 });10 })11 /* the following post route will only ever be used once.12 * it is there to provide the initial values for the calculator13 * which will be generated everytime this application is14 * loaded fresh on a new server.15 */16 .post(function(req, res){17 var defaults = new Default({18 monthlyRentTenantDef:req.body.monthlyRentTenantDef,19 monthlyRentTenantMin:req.body.monthlyRentTenantMin,20 monthlyRentTenantMax:req.body.monthlyRentTenantMax,21 monthlyRentPersonalDef:req.body.monthlyRentPersonalDef,22 monthlyRentPersonalMin:req.body.monthlyRentPersonalMin,23 monthlyRentPersonalMax:req.body.monthlyRentPersonalMax,24 targetPriceDef:req.body.targetPriceDef,25 targetPriceMin:req.body.targetPriceMin,26 targetPriceMax:req.body.targetPriceMax,27 downPaymentPercentageDef:req.body.downPaymentPercentageDef,28 downPaymentPercentageMin:req.body.downPaymentPercentageMin,29 downPaymentPercentageMax:req.body.downPaymentPercentageMax,30 mortgageRateDef:req.body.mortgageRateDef,31 mortgageRateMin:req.body.mortgageRateMin,32 mortgageRateMax:req.body.mortgageRateMax,33 yearsAmmoritizedDef:req.body.yearsAmmoritizedDef,34 yearsAmmoritizedMin:req.body.yearsAmmoritizedMin,35 yearsAmmoritizedMax:req.body.yearsAmmoritizedMax,36 incomeDef:req.body.incomeDef,37 incomeMin:req.body.incomeMin,38 incomeMax:req.body.incomeMax,39 mortgageYearsDef:req.body.mortgageYearsDef,40 mortgageYearsMin:req.body.mortgageYearsMin,41 mortgageYearsMax:req.body.mortgageYearsMax,42 vacancyDef:req.body.vacancyDef,43 vacancyMin:req.body.vacancyMin,44 vacancyMax:req.body.vacancyMax,45 propertyTaxDef:req.body.propertyTaxDef,46 propertyTaxMin:req.body.propertyTaxMin,47 propertyTaxMax:req.body.propertyTaxMax,48 assocDuesDef:req.body.assocDuesDef,49 assocDuesMin:req.body.assocDuesMin,50 assocDuesMax:req.body.assocDuesMax,51 managementDef:req.body.managementDef,52 managementMin:req.body.managementMin,53 managementMax:req.body.managementMax,54 miscDef:req.body.miscDef,55 miscMin:req.body.miscMin,56 miscMax:req.body.miscMax,57 insuranceAnnualDef:req.body.insuranceAnnualDef,58 insuranceAnnualMin:req.body.insuranceAnnualMin,59 insuranceAnnualMax:req.body.insuranceAnnualMax,60 utilsDef:req.body.utilsDef,61 utilsMin:req.body.utilsMin,62 utilsMax:req.body.utilsMax,63 legalAccountingDef:req.body.legalAccountingDef,64 legalAccountingMin:req.body.legalAccountingMin,65 legalAccountingMax:req.body.legalAccountingMax,66 taxBracketDef:req.body.taxBracketDef,67 taxBracketMin:req.body.taxBracketMin,68 taxBracketMax:req.body.taxBracketMax,69 repairValueDef:req.body.repairValueDef,70 repairValueMin:req.body.repairValueMin,71 repairValueMax:req.body.repairValueMax,72 yearsDef:req.body.yearsDef,73 yearsMin:req.body.yearsMin,74 yearsMax:req.body.yearsMax,75 zipCode: req.body.zipCode,76 renterInsuranceDef: req.body.renterInsuranceDef,77 renterInsuranceMin: req.body.renterInsuranceMin,78 renterInsuranceMax:req.body.renterInsuranceMax,79 appreciationRateDef:req.body.appreciationRateDef,80 appreciationRateMin:req.body.appreciationRateMin,81 appreciationRateMax:req.body.appreciationRateMax,82 appreciationRateHomeDef:req.body.appreciationRateHomeDef,83 appreciationRateHomeMin:req.body.appreciationRateHomeMin,84 appreciationRateHomeMax:req.body.appreciationRateHomeMax,85 duplexBuyDef:req.body.duplexBuyDef,86 duplexBuyMin:req.body.duplexBuyMin,87 duplexBuyMax:req.body.duplexBuyMax88 });89 defaults.save(function(err, defaults){90 if(err) console.log(err);91 res.send(defaults);92 });93 });94 router.route('/:id').put(function(req, res){95 Default.findById(req.body._id, function(err, defaults){96 if(err) res.send(err);97 console.log(req.body);98 defaults.monthlyRentTenantDef = req.body.monthlyRentTenantDef;99 defaults.monthlyRentTenantMin = req.body.monthlyRentTenantMin;100 defaults.monthlyRentTenantMax = req.body.monthlyRentTenantMax;101 defaults.monthlyRentPersonalDef = req.body.monthlyRentPersonalDef;102 defaults.monthlyRentPersonalMin = req.body.monthlyRentPersonalMin;103 defaults.monthlyRentPersonalMax = req.body.monthlyRentPersonalMax;104 defaults.targetPriceDef = req.body.targetPriceDef;105 defaults.targetPriceMin = req.body.targetPriceMin;106 defaults.targetPriceMax = req.body.targetPriceMax;107 defaults.downPaymentPercentageDef = req.body.downPaymentPercentageDef;108 defaults.downPaymentPercentageMin = req.body.downPaymentPercentageMin;109 defaults.downPaymentPercentageMax = req.body.downPaymentPercentageMax;110 defaults.mortgageRateDef = req.body.mortgageRateDef;111 defaults.mortgageRateMin = req.body.mortgageRateMin;112 defaults.mortgageRateMax = req.body.mortgageRateMax;113 defaults.yearsAmmoritizedDef = req.body.yearsAmmoritizedDef;114 defaults.yearsAmmoritizedMin = req.body.yearsAmmoritizedMin;115 defaults.yearsAmmoritizedMax = req.body.yearsAmmoritizedMax;116 defaults.incomeDef = req.body.incomeDef;117 defaults.incomeMin = req.body.incomeMin;118 defaults.incomeMax = req.body.incomeMax;119 defaults.mortgageYearsDef = req.body.mortgageYearsDef;120 defaults.mortgageYearsMin = req.body.mortgageYearsMin;121 defaults.mortgageYearsMax = req.body.mortgageYearsMax;122 defaults.vacancyDef = req.body.vacancyDef;123 defaults.vacancyMin = req.body.vacancyMin;124 defaults.vacancyMax = req.body.vacancyMax;125 defaults.propertyTaxDef = req.body.propertyTaxDef;126 defaults.propertyTaxMin = req.body.propertyTaxMin;127 defaults.propertyTaxMax = req.body.propertyTaxMax;128 defaults.assocDuesDef = req.body.assocDuesDef;129 defaults.assocDuesMin = req.body.assocDuesMin;130 defaults.assocDuesMax = req.body.assocDuesMax;131 defaults.managementDef = req.body.managementDef;132 defaults.managementMin = req.body.managementMin;133 defaults.managementMax = req.body.managementMax;134 defaults.miscDef = req.body.miscDef;135 defaults.miscMin = req.body.miscMin;136 defaults.miscMax = req.body.miscMax;137 defaults.insuranceAnnualDef = req.body.insuranceAnnualDef;138 defaults.insuranceAnnualMin = req.body.insuranceAnnualMin;139 defaults.insuranceAnnualMax = req.body.insuranceAnnualMax;140 defaults.utilsDef = req.body.utilsDef;141 defaults.utilsMin = req.body.utilsMin;142 defaults.utilsMax = req.body.utilsMax;143 defaults.legalAccountingDef = req.body.legalAccountingDef;144 defaults.legalAccountingMin = req.body.legalAccountingMin;145 defaults.legalAccountingMax = req.body.legalAccountingMax;146 defaults.taxBracketDef = req.body.taxBracketDef;147 defaults.taxBracketMin = req.body.taxBracketMin;148 defaults.taxBracketMax = req.body.taxBracketMax;149 defaults.repairValueDef = req.body.repairValueDef;150 defaults.repairValueMin = req.body.repairValueMin;151 defaults.repairValueMax = req.body.repairValueMax;152 defaults.yearsDef = req.body.yearsDef;153 defaults.yearsMin = req.body.yearsMin;154 defaults.yearsMax = req.body.yearsMax;155 defaults.zipCode = req.body.zipCode;156 defaults.renterInsuranceDef= req.body.renterInsuranceDef;157 defaults.renterInsuranceMin =req.body.renterInsuranceMin;158 defaults.renterInsuranceMax =req.body.renterInsuranceMax;159 defaults.appreciationRateDef=req.body.appreciationRateDef;160 defaults.appreciationRateMin=req.body.appreciationRateMin;161 defaults.appreciationRateMax=req.body.appreciationRateMax;162 defaults.appreciationRateHomeDef=req.body.appreciationRateHomeDef;163 defaults.appreciationRateHomeMin=req.body.appreciationRateHomeMin;164 defaults.appreciationRateHomeMax=req.body.appreciationRateHomeMax;165 defaults.duplexBuyDef=req.body.duplexBuyDef;166 defaults.duplexBuyMin=req.body.duplexBuyMin;167 defaults.duplexBuyMax=req.body.duplexBuyMax;168 defaults.save(function(err){169 if(err) res.send(err);170 res.json({message: 'defaults have been updated!'});171 });172 });173 });...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!