0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2024-12-26 13:49:01 -05:00

Merge branch 'browser-tests'

This commit is contained in:
liabru 2015-08-04 20:31:00 +01:00
commit a6b82c17e0
88 changed files with 1404106 additions and 9 deletions

1
.gitignore vendored
View file

@ -6,3 +6,4 @@ matter-doc-theme
build/matter-dev.js
build/matter-dev.min.js
demo/js/lib/matter-dev.js
tests/browser/diffs

View file

@ -31,8 +31,8 @@
"undef": true,
"-W079": true, // Silence redefinition errors (they are false positives).
"predef": [
"Matter", "window", "document", "Element", "MatterTools", "PIXI",
"$", "Image", "navigator", "setTimeout", "decomp", "HTMLElement",
"Matter", "window", "document", "Element", "MatterTools", "PIXI", "phantom",
"$", "Image", "navigator", "setTimeout", "decomp", "HTMLElement", "require",
"Body", "Composite", "World", "Contact", "Detector", "Grid",
"Pairs", "Pair", "Resolver", "SAT", "Constraint", "MouseConstraint",
"Common", "Engine", "Mouse", "Sleeping", "Bodies", "Composites",

View file

@ -1,6 +1,11 @@
language: node_js
sudo: false
node_js:
- "0.10"
before_install: npm install -g grunt-cli
before_install:
- npm install -g grunt-cli
- mkdir travis-phantomjs
- wget https://s3.amazonaws.com/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2
- tar -xvf $PWD/travis-phantomjs/phantomjs-2.0.0-ubuntu-12.04.tar.bz2 -C $PWD/travis-phantomjs
- export PATH=$PWD/travis-phantomjs:$PATH
install: npm install
before_script: grunt

View file

@ -57,7 +57,7 @@ module.exports = function(grunt) {
options: {
jshintrc: '.jshintrc'
},
all: ['src/**/*.js', 'demo/js/*.js', '!src/module/*']
all: ['src/**/*.js', 'demo/js/*.js', 'test/browser/TestDemo.js', '!src/module/*']
},
connect: {
watch: {
@ -66,6 +66,11 @@ module.exports = function(grunt) {
open: 'http://localhost:9000/demo/dev.html',
livereload: 9001
}
},
serve: {
options: {
port: 9000
}
}
},
watch: {
@ -107,6 +112,19 @@ module.exports = function(grunt) {
src: 'build/<%= buildName %>.js',
dest: 'build/<%= buildName %>.js'
}
},
shell: {
testDemo: {
command: function(arg) {
arg = arg ? ' --' + arg : '';
return 'phantomjs test/browser/TestDemo.js' + arg;
},
options: {
execOptions: {
timeout: 1000 * 60
}
}
}
}
});
@ -118,11 +136,26 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-yuidoc');
grunt.loadNpmTasks('grunt-preprocess');
grunt.loadNpmTasks('grunt-shell');
grunt.registerTask('default', ['test', 'build']);
grunt.registerTask('test', ['jshint']);
grunt.registerTask('test', ['jshint', 'test:demo']);
grunt.registerTask('test:all', ['build:dev', 'connect:serve', 'test']);
grunt.registerTask('dev', ['build:dev', 'connect:watch', 'watch']);
grunt.registerTask('test:demo', function() {
var updateAll = grunt.option('updateAll'),
diff = grunt.option('diff');
if (updateAll) {
grunt.task.run('shell:testDemo:updateAll');
} else if (diff) {
grunt.task.run('shell:testDemo:diff');
} else {
grunt.task.run('shell:testDemo');
}
});
grunt.registerTask('build', function(mode) {
var isDev = (mode === 'dev'),
isRelease = (mode === 'release'),

View file

@ -25,6 +25,7 @@
}
var Demo = {};
Matter.Demo = Demo;
var _engine,
_gui,
@ -1608,6 +1609,9 @@
var demoSelect = document.getElementById('demo-select'),
demoReset = document.getElementById('demo-reset');
// engine reference for external use
Matter.Demo._engine = _engine;
// create a Matter.Gui
if (!_isMobile && Gui) {
_gui = Gui.create(_engine);

View file

@ -20,6 +20,7 @@
"rigid body physics"
],
"devDependencies": {
"fast-json-patch": "^0.5.4",
"grunt": "~0.4.2",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-connect": "~0.6.0",
@ -28,11 +29,12 @@
"grunt-contrib-uglify": "~0.2.7",
"grunt-contrib-watch": "~0.5.3",
"grunt-contrib-yuidoc": "~0.5.1",
"grunt-preprocess": "^4.1.0"
"grunt-preprocess": "^4.1.0",
"grunt-shell": "^1.1.2"
},
"scripts": {
"dev": "npm install && grunt dev",
"test": "grunt test"
"test": "grunt test:all"
},
"dependencies": {}
}

184
test/browser/TestDemo.js Normal file
View file

@ -0,0 +1,184 @@
var page = require('webpage').create();
var fs = require('fs');
var Resurrect = require('./lib/resurrect');
var compare = require('fast-json-patch').compare;
var system = require('system');
var demo,
frames = 10,
testUrl = 'http://localhost:9000/demo/dev.html',
refsPath = 'test/browser/refs',
diffsPath = 'test/browser/diffs';
var update = arg('--update'),
updateAll = typeof arg('--updateAll') !== 'undefined',
diff = arg('--diff');
var resurrect = new Resurrect({ cleanup: true }),
created = [],
changed = [];
var test = function(status) {
if (status === 'fail') {
console.log('failed to load', testUrl);
console.log('check dev server is running!');
console.log('use `grunt dev`');
phantom.exit(1);
return;
}
var demos = page.evaluate(function() {
var demoSelect = document.getElementById('demo-select'),
options = Array.prototype.slice.call(demoSelect);
return options.map(function(o) { return o.value; });
});
fs.removeTree(diffsPath);
if (diff) {
fs.makeDirectory(diffsPath);
}
for (var i = 0; i < demos.length; i += 1) {
demo = demos[i];
var hasChanged = false,
hasCreated = false,
forceUpdate = update === demo || updateAll,
worldStartPath = refsPath + '/' + demo + '/' + demo + '-0.json',
worldEndPath = refsPath + '/' + demo + '/' + demo + '-' + frames + '.json',
worldStartDiffPath = diffsPath + '/' + demo + '/' + demo + '-0.json',
worldEndDiffPath = diffsPath + '/' + demo + '/' + demo + '-' + frames + '.json';
var worldStart = page.evaluate(function(demo) {
var engine = Matter.Demo._engine;
Matter.Runner.stop(engine);
if (!(demo in Matter.Demo)) {
throw '\'' + demo + '\' is not defined in Matter.Demo';
}
Matter.Demo[demo]();
return engine.world;
}, demo);
var worldEnd = page.evaluate(function(demo, frames) {
var engine = Matter.Demo._engine;
for (var j = 0; j <= frames; j += 1) {
Matter.Events.trigger(engine, 'tick', { timestamp: engine.timing.timestamp });
Matter.Engine.update(engine, engine.timing.delta);
Matter.Events.trigger(engine, 'afterTick', { timestamp: engine.timing.timestamp });
}
return engine.world;
}, demo, frames);
if (fs.exists(worldStartPath)) {
var worldStartRef = resurrect.resurrect(fs.read(worldStartPath));
var worldStartDiff = compare(worldStartRef, worldStart);
if (worldStartDiff.length !== 0) {
if (diff) {
fs.write(worldStartDiffPath, JSON.stringify(worldStartDiff, null, 2), 'w');
}
if (forceUpdate) {
hasCreated = true;
fs.write(worldStartPath, resurrect.stringify(worldStart, null, 2), 'w');
} else {
hasChanged = true;
}
}
} else {
hasCreated = true;
fs.write(worldStartPath, resurrect.stringify(worldStart, null, 2), 'w');
}
if (fs.exists(worldEndPath)) {
var worldEndRef = resurrect.resurrect(fs.read(worldEndPath));
var worldEndDiff = compare(worldEndRef, worldEnd);
if (worldEndDiff.length !== 0) {
if (diff) {
fs.write(worldEndDiffPath, JSON.stringify(worldEndDiff, null, 2), 'w');
}
if (forceUpdate) {
hasCreated = true;
fs.write(worldEndPath, resurrect.stringify(worldEnd, null, 2), 'w');
} else {
hasChanged = true;
}
}
} else {
hasCreated = true;
fs.write(worldEndPath, resurrect.stringify(worldEnd, null, 2), 'w');
}
if (hasChanged) {
changed.push("'" + demo + "'");
system.stdout.write('x');
} else if (hasCreated) {
created.push("'" + demo + "'");
system.stdout.write('+');
} else {
system.stdout.write('.');
}
}
if (created.length > 0) {
console.log('\nupdated', created.join(', '));
}
var isOk = changed.length === 0 ? 1 : 0;
console.log('');
if (isOk) {
console.log('ok');
} else {
console.log('\nchanges detected on:');
console.log(changed.join(', '));
console.log('\nreview, then --update [name] or --updateAll');
console.log('use --diff for diff log');
}
phantom.exit(!isOk);
};
function arg(name) {
var index = system.args.indexOf(name);
if (index >= 0) {
return system.args[index + 1] || true;
}
return undefined;
}
page.onError = function(msg, trace) {
setTimeout(function() {
var msgStack = ['testing \'' + demo + '\'', msg];
if (trace && trace.length) {
trace.forEach(function(t) {
msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (fn: ' + t.function +')' : ''));
});
}
console.log(msgStack.join('\n'));
phantom.exit(1);
}, 0);
};
page.onResourceReceived = function(res) {
setTimeout(function() {
if (res.stage === 'end'
&& (res.status !== 304 && res.status !== 200 && res.status !== null)) {
console.log('error', res.status, res.url);
phantom.exit(1);
}
}, 0);
};
phantom.onError = page.onError;
page.open(testUrl, test);

View file

@ -0,0 +1,542 @@
/**
* # ResurrectJS
* @version 1.0.3
* @license Public Domain
*
* ResurrectJS preserves object behavior (prototypes) and reference
* circularity with a special JSON encoding. Unlike regular JSON,
* Date, RegExp, DOM objects, and `undefined` are also properly
* preserved.
*
* ## Examples
*
* function Foo() {}
* Foo.prototype.greet = function() { return "hello"; };
*
* // Behavior is preserved:
* var necromancer = new Resurrect();
* var json = necromancer.stringify(new Foo());
* var foo = necromancer.resurrect(json);
* foo.greet(); // => "hello"
*
* // References to the same object are preserved:
* json = necromancer.stringify([foo, foo]);
* var array = necromancer.resurrect(json);
* array[0] === array[1]; // => true
* array[1].greet(); // => "hello"
*
* // Dates are restored properly
* json = necromancer.stringify(new Date());
* var date = necromancer.resurrect(json);
* Object.prototype.toString.call(date); // => "[object Date]"
*
* ## Options
*
* Options are provided to the constructor as an object with these
* properties:
*
* prefix ('#'): A prefix string used for temporary properties added
* to objects during serialization and deserialization. It is
* important that you don't use any properties beginning with this
* string. This option must be consistent between both
* serialization and deserialization.
*
* cleanup (false): Perform full property cleanup after both
* serialization and deserialization using the `delete`
* operator. This may cause performance penalties (breaking hidden
* classes in V8) on objects that ResurrectJS touches, so enable
* with care.
*
* revive (true): Restore behavior (__proto__) to objects that have
* been resurrected. If this is set to false during serialization,
* resurrection information will not be encoded. You still get
* circularity and Date support.
*
* resolver (Resurrect.NamespaceResolver(window)): Converts between
* a name and a prototype. Create a custom resolver if your
* constructors are not stored in global variables. The resolver
* has two methods: getName(object) and getPrototype(string).
*
* For example,
*
* var necromancer = new Resurrect({
* prefix: '__#',
* cleanup: true
* });
*
* ## Caveats
*
* * With the default resolver, all constructors must be named and
* stored in the global variable under that name. This is required
* so that the prototypes can be looked up and reconnected at
* resurrection time.
*
* * The wrapper objects Boolean, String, and Number will be
* unwrapped. This means extra properties added to these objects
* will not be preserved.
*
* * Functions cannot ever be serialized. Resurrect will throw an
* error if a function is found when traversing a data structure.
*
* @see http://nullprogram.com/blog/2013/03/28/
*/
/**
* @param {Object} [options] See options documentation.
* @namespace
* @constructor
*/
function Resurrect(options) {
this.table = null;
this.prefix = '#';
this.cleanup = false;
this.revive = true;
for (var option in options) {
if (options.hasOwnProperty(option)) {
this[option] = options[option];
}
}
this.refcode = this.prefix + 'id';
this.origcode = this.prefix + 'original';
this.buildcode = this.prefix + '.';
this.valuecode = this.prefix + 'v';
}
if (module)
module.exports = Resurrect;
/**
* Portable access to the global object (window, global).
* Uses indirect eval.
* @constant
*/
Resurrect.GLOBAL = (0, eval)('this');
/**
* Escape special regular expression characters in a string.
* @param {string} string
* @returns {string} The string escaped for exact matches.
* @see http://stackoverflow.com/a/6969486
*/
Resurrect.escapeRegExp = function (string) {
return string.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};
/* Helper Objects */
/**
* @param {string} [message]
* @constructor
*/
Resurrect.prototype.Error = function ResurrectError(message) {
this.message = message || '';
this.stack = new Error().stack;
};
Resurrect.prototype.Error.prototype = Object.create(Error.prototype);
Resurrect.prototype.Error.prototype.name = 'ResurrectError';
/**
* Resolves prototypes through the properties on an object and
* constructor names.
* @param {Object} scope
* @constructor
*/
Resurrect.NamespaceResolver = function(scope) {
this.scope = scope;
};
/**
* Gets the prototype of the given property name from an object. If
* not found, it throws an error.
* @param {string} name
* @returns {Object}
* @method
*/
Resurrect.NamespaceResolver.prototype.getPrototype = function(name) {
var constructor = this.scope[name];
if (constructor) {
return constructor.prototype;
} else {
throw new Resurrect.prototype.Error('Unknown constructor: ' + name);
}
};
/**
* Get the prototype name for an object, to be fetched later with getPrototype.
* @param {Object} object
* @returns {?string} Null if the constructor is Object.
* @method
*/
Resurrect.NamespaceResolver.prototype.getName = function(object) {
var constructor = object.constructor.name;
if (constructor == null) { // IE
var funcPattern = /^\s*function\s*([A-Za-z0-9_$]*)/;
constructor = funcPattern.exec(object.constructor)[1];
}
if (constructor === '') {
var msg = "Can't serialize objects with anonymous constructors.";
throw new Resurrect.prototype.Error(msg);
} else if (constructor === 'Object' || constructor === 'Array') {
return null;
} else {
return constructor;
}
};
/* Set the default resolver searches the global object. */
Resurrect.prototype.resolver =
new Resurrect.NamespaceResolver(Resurrect.GLOBAL);
/**
* Create a DOM node from HTML source; behaves like a constructor.
* @param {string} html
* @constructor
*/
Resurrect.Node = function(html) {
var div = document.createElement('div');
div.innerHTML = html;
return div.firstChild;
};
/* Type Tests */
/**
* @param {string} type
* @returns {Function} A function that tests for type.
*/
Resurrect.is = function(type) {
var string = '[object ' + type + ']';
return function(object) {
return Object.prototype.toString.call(object) === string;
};
};
Resurrect.isArray = Resurrect.is('Array');
Resurrect.isString = Resurrect.is('String');
Resurrect.isBoolean = Resurrect.is('Boolean');
Resurrect.isNumber = Resurrect.is('Number');
Resurrect.isFunction = Resurrect.is('Function');
Resurrect.isDate = Resurrect.is('Date');
Resurrect.isRegExp = Resurrect.is('RegExp');
Resurrect.isObject = Resurrect.is('Object');
Resurrect.isAtom = function(object) {
return !Resurrect.isObject(object) && !Resurrect.isArray(object);
};
/**
* @param {*} object
* @returns {boolean} True if object is a primitive or a primitive wrapper.
*/
Resurrect.isPrimitive = function(object) {
return object == null ||
Resurrect.isNumber(object) ||
Resurrect.isString(object) ||
Resurrect.isBoolean(object);
};
/* Methods */
/**
* Create a reference (encoding) to an object.
* @param {(Object|undefined)} object
* @returns {Object}
* @method
*/
Resurrect.prototype.ref = function(object) {
var ref = {};
if (object === undefined) {
ref[this.prefix] = -1;
} else {
ref[this.prefix] = object[this.refcode];
}
return ref;
};
/**
* Lookup an object in the table by reference object.
* @param {Object} ref
* @returns {(Object|undefined)}
* @method
*/
Resurrect.prototype.deref = function(ref) {
return this.table[ref[this.prefix]];
};
/**
* Put a temporary identifier on an object and store it in the table.
* @param {Object} object
* @returns {number} The unique identifier number.
* @method
*/
Resurrect.prototype.tag = function(object) {
if (this.revive) {
var constructor = this.resolver.getName(object);
if (constructor) {
var proto = Object.getPrototypeOf(object);
if (this.resolver.getPrototype(constructor) !== proto) {
throw new this.Error('Constructor mismatch!');
} else {
object[this.prefix] = constructor;
}
}
}
object[this.refcode] = this.table.length;
this.table.push(object);
return object[this.refcode];
};
/**
* Create a builder object (encoding) for serialization.
* @param {string} name The name of the constructor.
* @param value The value to pass to the constructor.
* @returns {Object}
* @method
*/
Resurrect.prototype.builder = function(name, value) {
var builder = {};
builder[this.buildcode] = name;
builder[this.valuecode] = value;
return builder;
};
/**
* Build a value from a deserialized builder.
* @param {Object} ref
* @returns {Object}
* @method
* @see http://stackoverflow.com/a/14378462
* @see http://nullprogram.com/blog/2013/03/24/
*/
Resurrect.prototype.build = function(ref) {
var type = ref[this.buildcode].split(/\./).reduce(function(object, name) {
return object[name];
}, Resurrect.GLOBAL);
/* Brilliant hack by kybernetikos: */
var args = [null].concat(ref[this.valuecode]);
var factory = type.bind.apply(type, args);
var result = new factory();
if (Resurrect.isPrimitive(result)) {
return result.valueOf(); // unwrap
} else {
return result;
}
};
/**
* Dereference or build an object or value from an encoding.
* @param {Object} ref
* @returns {(Object|undefined)}
* @method
*/
Resurrect.prototype.decode = function(ref) {
if (this.prefix in ref) {
return this.deref(ref);
} else if (this.buildcode in ref) {
return this.build(ref);
} else {
throw new this.Error('Unknown encoding.');
}
};
/**
* @param {Object} object
* @returns {boolean} True if the provided object is tagged for serialization.
* @method
*/
Resurrect.prototype.isTagged = function(object) {
return (this.refcode in object) && (object[this.refcode] != null);
};
/**
* Visit root and all its ancestors, visiting atoms with f.
* @param {*} root
* @param {Function} f
* @param {Function} replacer
* @returns {*} A fresh copy of root to be serialized.
* @method
*/
Resurrect.prototype.visit = function(root, f, replacer) {
if (Resurrect.isAtom(root)) {
return f(root);
} else if (!this.isTagged(root)) {
var copy = null;
if (Resurrect.isArray(root)) {
copy = [];
root[this.refcode] = this.tag(copy);
for (var i = 0; i < root.length; i++) {
copy.push(this.visit(root[i], f, replacer));
}
} else { /* Object */
copy = Object.create(Object.getPrototypeOf(root));
root[this.refcode] = this.tag(copy);
for (var key in root) {
var value = root[key];
if (root.hasOwnProperty(key)) {
if (replacer && value !== undefined) {
// Call replacer like JSON.stringify's replacer
value = replacer.call(root, key, root[key]);
if (value === undefined) {
continue; // Omit from result
}
}
copy[key] = this.visit(value, f, replacer);
}
}
}
copy[this.origcode] = root;
return this.ref(copy);
} else {
return this.ref(root);
}
};
/**
* Manage special atom values, possibly returning an encoding.
* @param {*} atom
* @returns {*}
* @method
*/
Resurrect.prototype.handleAtom = function(atom) {
var Node = Resurrect.GLOBAL.Node || function() {};
if (Resurrect.isFunction(atom)) {
throw new this.Error("Can't serialize functions.");
} else if (atom instanceof Node) {
var xmls = new XMLSerializer();
return this.builder('Resurrect.Node', [xmls.serializeToString(atom)]);
} else if (Resurrect.isDate(atom)) {
return this.builder('Date', [atom.toISOString()]);
} else if (Resurrect.isRegExp(atom)) {
var args = atom.toString().match(/\/(.+)\/([gimy]*)/).slice(1);
return this.builder('RegExp', args);
} else if (atom === undefined) {
return this.ref(undefined);
} else if (Resurrect.isNumber(atom) && (isNaN(atom) || !isFinite(atom))) {
return this.builder('Number', [atom.toString()]);
} else {
return atom;
}
};
/**
* Hides intrusive keys from a user-supplied replacer.
* @param {Function} replacer function of two arguments (key, value)
* @returns {Function} A function that skips the replacer for intrusive keys.
* @method
*/
Resurrect.prototype.replacerWrapper = function(replacer) {
var skip = new RegExp('^' + Resurrect.escapeRegExp(this.prefix));
return function(k, v) {
if (skip.test(k)) {
return v;
} else {
return replacer(k, v);
}
};
};
/**
* Serialize an arbitrary JavaScript object, carefully preserving it.
* @param {*} object
* @param {(Function|Array)} replacer
* @param {string} space
* @method
*/
Resurrect.prototype.stringify = function(object, replacer, space) {
if (Resurrect.isFunction(replacer)) {
replacer = this.replacerWrapper(replacer);
} else if (Resurrect.isArray(replacer)) {
var acceptKeys = replacer;
replacer = function(k, v) {
return acceptKeys.indexOf(k) >= 0 ? v : undefined;
};
}
if (Resurrect.isAtom(object)) {
return JSON.stringify(this.handleAtom(object), replacer, space);
} else {
this.table = [];
this.visit(object, this.handleAtom.bind(this), replacer);
for (var i = 0; i < this.table.length; i++) {
if (this.cleanup) {
delete this.table[i][this.origcode][this.refcode];
} else {
this.table[i][this.origcode][this.refcode] = null;
}
delete this.table[i][this.refcode];
delete this.table[i][this.origcode];
}
var table = this.table;
this.table = null;
return JSON.stringify(table, null, space);
}
};
/**
* Restore the __proto__ of the given object to the proper value.
* @param {Object} object
* @returns {Object} Its argument, or a copy, with the prototype restored.
* @method
*/
Resurrect.prototype.fixPrototype = function(object) {
if (this.prefix in object) {
var name = object[this.prefix];
var prototype = this.resolver.getPrototype(name);
if ('__proto__' in object) {
object.__proto__ = prototype;
if (this.cleanup) {
delete object[this.prefix];
}
return object;
} else { // IE
var copy = Object.create(prototype);
for (var key in object) {
if (object.hasOwnProperty(key) && key !== this.prefix) {
copy[key] = object[key];
}
}
return copy;
}
} else {
return object;
}
};
/**
* Deserialize an encoded object, restoring circularity and behavior.
* @param {string} string
* @returns {*} The decoded object or value.
* @method
*/
Resurrect.prototype.resurrect = function(string) {
var result = null;
var data = JSON.parse(string);
if (Resurrect.isArray(data)) {
this.table = data;
/* Restore __proto__. */
if (this.revive) {
for (var i = 0; i < this.table.length; i++) {
this.table[i] = this.fixPrototype(this.table[i]);
}
}
/* Re-establish object references and construct atoms. */
for (i = 0; i < this.table.length; i++) {
var object = this.table[i];
for (var key in object) {
if (object.hasOwnProperty(key)) {
if (!(Resurrect.isAtom(object[key]))) {
object[key] = this.decode(object[key]);
}
}
}
}
result = this.table[0];
} else if (Resurrect.isObject(data)) {
this.table = [];
result = this.decode(data);
} else {
result = data;
}
this.table = null;
return result;
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,889 @@
[
{
"bodies": {
"#": 1
},
"bounds": {
"#": 86
},
"composites": {
"#": 89
},
"constraints": {
"#": 90
},
"gravity": {
"#": 94
},
"id": 0,
"isModified": true,
"label": "World",
"parent": "",
"type": "composite"
},
[
{
"#": 2
},
{
"#": 23
},
{
"#": 44
},
{
"#": 65
}
],
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 40930.25,
"axes": {
"#": 3
},
"bounds": {
"#": 6
},
"collisionFilter": {
"#": 9
},
"constraintImpulse": {
"#": 10
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 11
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 0,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 12
},
"positionImpulse": {
"#": 13
},
"positionPrev": {
"#": 14
},
"render": {
"#": 15
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 17
},
"vertices": {
"#": 18
}
},
[
{
"#": 4
},
{
"#": 5
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 7
},
"min": {
"#": 8
}
},
{
"x": 805.25,
"y": 20.25
},
{
"x": -5.25,
"y": -30.25
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": -5
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": -5
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 16
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 19
},
{
"#": 20
},
{
"#": 21
},
{
"#": 22
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": -5.25,
"y": -30.25
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 805.25,
"y": -30.25
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 805.25,
"y": 20.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": -5.25,
"y": 20.25
},
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 40930.25,
"axes": {
"#": 24
},
"bounds": {
"#": 27
},
"collisionFilter": {
"#": 30
},
"constraintImpulse": {
"#": 31
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 32
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 1,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 33
},
"positionImpulse": {
"#": 34
},
"positionPrev": {
"#": 35
},
"render": {
"#": 36
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 38
},
"vertices": {
"#": 39
}
},
[
{
"#": 25
},
{
"#": 26
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 28
},
"min": {
"#": 29
}
},
{
"x": 805.25,
"y": 630.25
},
{
"x": -5.25,
"y": 579.75
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": 605
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": 605
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 37
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 40
},
{
"#": 41
},
{
"#": 42
},
{
"#": 43
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": -5.25,
"y": 579.75
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 805.25,
"y": 579.75
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 805.25,
"y": 630.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": -5.25,
"y": 630.25
},
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 30830.25,
"axes": {
"#": 45
},
"bounds": {
"#": 48
},
"collisionFilter": {
"#": 51
},
"constraintImpulse": {
"#": 52
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 53
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 2,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 54
},
"positionImpulse": {
"#": 55
},
"positionPrev": {
"#": 56
},
"render": {
"#": 57
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 59
},
"vertices": {
"#": 60
}
},
[
{
"#": 46
},
{
"#": 47
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 49
},
"min": {
"#": 50
}
},
{
"x": 830.25,
"y": 605.25
},
{
"x": 779.75,
"y": -5.25
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 805,
"y": 300
},
{
"x": 0,
"y": 0
},
{
"x": 805,
"y": 300
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 58
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 61
},
{
"#": 62
},
{
"#": 63
},
{
"#": 64
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": 779.75,
"y": -5.25
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 830.25,
"y": -5.25
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 830.25,
"y": 605.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": 779.75,
"y": 605.25
},
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 30830.25,
"axes": {
"#": 66
},
"bounds": {
"#": 69
},
"collisionFilter": {
"#": 72
},
"constraintImpulse": {
"#": 73
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 74
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 3,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 75
},
"positionImpulse": {
"#": 76
},
"positionPrev": {
"#": 77
},
"render": {
"#": 78
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 80
},
"vertices": {
"#": 81
}
},
[
{
"#": 67
},
{
"#": 68
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 70
},
"min": {
"#": 71
}
},
{
"x": 20.25,
"y": 605.25
},
{
"x": -30.25,
"y": -5.25
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": -5,
"y": 300
},
{
"x": 0,
"y": 0
},
{
"x": -5,
"y": 300
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 79
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 82
},
{
"#": 83
},
{
"#": 84
},
{
"#": 85
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": -30.25,
"y": -5.25
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 20.25,
"y": -5.25
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 20.25,
"y": 605.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": -30.25,
"y": 605.25
},
{
"max": {
"#": 87
},
"min": {
"#": 88
}
},
{
"x": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"Infinity"
]
}
},
{
"x": {
"#.": "Number",
"#v": [
"-Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"-Infinity"
]
}
},
[],
[
{
"#": 91
}
],
{
"angularStiffness": 1,
"bodyB": "",
"id": 1,
"label": "Mouse Constraint",
"length": 0.01,
"pointA": {
"#": 92
},
"pointB": "",
"render": {
"#": 93
},
"stiffness": 0.1,
"type": "constraint"
},
{
"x": 0,
"y": 0
},
{
"lineWidth": 3,
"strokeStyle": "#90EE90",
"visible": true
},
{
"x": 0,
"y": 1
}
]

View file

@ -0,0 +1,929 @@
[
{
"bodies": {
"#": 1
},
"bounds": {
"#": 90
},
"composites": {
"#": 93
},
"constraints": {
"#": 94
},
"gravity": {
"#": 98
},
"id": 0,
"isModified": false,
"label": "World",
"parent": "",
"type": "composite"
},
[
{
"#": 2
},
{
"#": 24
},
{
"#": 46
},
{
"#": 68
}
],
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 40930.25,
"axes": {
"#": 3
},
"bounds": {
"#": 6
},
"collisionFilter": {
"#": 9
},
"constraintImpulse": {
"#": 10
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 11
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 0,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 12
},
"positionImpulse": {
"#": 13
},
"positionPrev": {
"#": 14
},
"region": {
"#": 15
},
"render": {
"#": 16
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 18
},
"vertices": {
"#": 19
}
},
[
{
"#": 4
},
{
"#": 5
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 7
},
"min": {
"#": 8
}
},
{
"x": 805.25,
"y": 20.25
},
{
"x": -5.25,
"y": -30.25
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": -5
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": -5
},
{
"endCol": 16,
"endRow": 0,
"id": "-1,16,-1,0",
"startCol": -1,
"startRow": -1
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 17
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 20
},
{
"#": 21
},
{
"#": 22
},
{
"#": 23
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": -5.25,
"y": -30.25
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 805.25,
"y": -30.25
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 805.25,
"y": 20.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": -5.25,
"y": 20.25
},
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 40930.25,
"axes": {
"#": 25
},
"bounds": {
"#": 28
},
"collisionFilter": {
"#": 31
},
"constraintImpulse": {
"#": 32
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 33
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 1,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 34
},
"positionImpulse": {
"#": 35
},
"positionPrev": {
"#": 36
},
"region": {
"#": 37
},
"render": {
"#": 38
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 40
},
"vertices": {
"#": 41
}
},
[
{
"#": 26
},
{
"#": 27
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 29
},
"min": {
"#": 30
}
},
{
"x": 805.25,
"y": 630.25
},
{
"x": -5.25,
"y": 579.75
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": 605
},
{
"x": 0,
"y": 0
},
{
"x": 400,
"y": 605
},
{
"endCol": 16,
"endRow": 13,
"id": "-1,16,12,13",
"startCol": -1,
"startRow": 12
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 39
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 42
},
{
"#": 43
},
{
"#": 44
},
{
"#": 45
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": -5.25,
"y": 579.75
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 805.25,
"y": 579.75
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 805.25,
"y": 630.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": -5.25,
"y": 630.25
},
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 30830.25,
"axes": {
"#": 47
},
"bounds": {
"#": 50
},
"collisionFilter": {
"#": 53
},
"constraintImpulse": {
"#": 54
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 55
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 2,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 56
},
"positionImpulse": {
"#": 57
},
"positionPrev": {
"#": 58
},
"region": {
"#": 59
},
"render": {
"#": 60
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 62
},
"vertices": {
"#": 63
}
},
[
{
"#": 48
},
{
"#": 49
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 51
},
"min": {
"#": 52
}
},
{
"x": 830.25,
"y": 605.25
},
{
"x": 779.75,
"y": -5.25
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": 805,
"y": 300
},
{
"x": 0,
"y": 0
},
{
"x": 805,
"y": 300
},
{
"endCol": 17,
"endRow": 12,
"id": "16,17,-1,12",
"startCol": 16,
"startRow": -1
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 61
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 64
},
{
"#": 65
},
{
"#": 66
},
{
"#": 67
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": 779.75,
"y": -5.25
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 830.25,
"y": -5.25
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 830.25,
"y": 605.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": 779.75,
"y": 605.25
},
{
"angle": 0,
"anglePrev": 0,
"angularSpeed": 0,
"angularVelocity": 0,
"area": 30830.25,
"axes": {
"#": 69
},
"bounds": {
"#": 72
},
"collisionFilter": {
"#": 75
},
"constraintImpulse": {
"#": 76
},
"density": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"force": {
"#": 77
},
"friction": 1,
"frictionAir": 0.01,
"frictionStatic": 0.5,
"id": 3,
"inertia": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"inverseInertia": 0,
"inverseMass": 0,
"isSleeping": false,
"isStatic": true,
"label": "Rectangle Body",
"mass": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"motion": 0,
"parent": null,
"position": {
"#": 78
},
"positionImpulse": {
"#": 79
},
"positionPrev": {
"#": 80
},
"region": {
"#": 81
},
"render": {
"#": 82
},
"restitution": 0,
"sleepCounter": 0,
"sleepThreshold": 60,
"slop": 0.05,
"speed": 0,
"timeScale": 1,
"torque": 0,
"totalContacts": 0,
"type": "body",
"velocity": {
"#": 84
},
"vertices": {
"#": 85
}
},
[
{
"#": 70
},
{
"#": 71
}
],
{
"x": 0,
"y": 1
},
{
"x": -1,
"y": 0
},
{
"max": {
"#": 73
},
"min": {
"#": 74
}
},
{
"x": 20.25,
"y": 605.25
},
{
"x": -30.25,
"y": -5.25
},
{
"category": 1,
"group": 0,
"mask": 4294967295
},
{
"angle": 0,
"x": 0,
"y": 0
},
{
"x": 0,
"y": 0
},
{
"x": -5,
"y": 300
},
{
"x": 0,
"y": 0
},
{
"x": -5,
"y": 300
},
{
"endCol": 0,
"endRow": 12,
"id": "-1,0,-1,12",
"startCol": -1,
"startRow": -1
},
{
"fillStyle": "#eeeeee",
"lineWidth": 1.5,
"sprite": {
"#": 83
},
"strokeStyle": "#bbbbbb",
"visible": true
},
{
"xScale": 1,
"yScale": 1
},
{
"x": 0,
"y": 0
},
[
{
"#": 86
},
{
"#": 87
},
{
"#": 88
},
{
"#": 89
}
],
{
"body": null,
"index": 0,
"isInternal": false,
"x": -30.25,
"y": -5.25
},
{
"body": null,
"index": 1,
"isInternal": false,
"x": 20.25,
"y": -5.25
},
{
"body": null,
"index": 2,
"isInternal": false,
"x": 20.25,
"y": 605.25
},
{
"body": null,
"index": 3,
"isInternal": false,
"x": -30.25,
"y": 605.25
},
{
"max": {
"#": 91
},
"min": {
"#": 92
}
},
{
"x": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"Infinity"
]
}
},
{
"x": {
"#.": "Number",
"#v": [
"-Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"-Infinity"
]
}
},
[],
[
{
"#": 95
}
],
{
"angularStiffness": 1,
"bodyB": "",
"id": 1,
"label": "Mouse Constraint",
"length": 0.01,
"pointA": {
"#": 96
},
"pointB": "",
"render": {
"#": 97
},
"stiffness": 0.1,
"type": "constraint"
},
{
"x": 0,
"y": 0
},
{
"lineWidth": 3,
"strokeStyle": "#90EE90",
"visible": true
},
{
"x": 0,
"y": 1
}
]

View file

@ -0,0 +1,96 @@
[
{
"bodies": {
"#": 1
},
"bounds": {
"#": 2
},
"composites": {
"#": 5
},
"constraints": {
"#": 6
},
"gravity": {
"#": 10
},
"id": 0,
"isModified": true,
"label": "World",
"parent": "",
"type": "composite"
},
[],
{
"max": {
"#": 3
},
"min": {
"#": 4
}
},
{
"x": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"Infinity"
]
}
},
{
"x": {
"#.": "Number",
"#v": [
"-Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"-Infinity"
]
}
},
[],
[
{
"#": 7
}
],
{
"angularStiffness": 1,
"bodyB": "",
"id": 1,
"label": "Mouse Constraint",
"length": 0.01,
"pointA": {
"#": 8
},
"pointB": "",
"render": {
"#": 9
},
"stiffness": 0.1,
"type": "constraint"
},
{
"x": 0,
"y": 0
},
{
"lineWidth": 3,
"strokeStyle": "#90EE90",
"visible": true
},
{
"x": 0,
"y": 1
}
]

View file

@ -0,0 +1,96 @@
[
{
"bodies": {
"#": 1
},
"bounds": {
"#": 2
},
"composites": {
"#": 5
},
"constraints": {
"#": 6
},
"gravity": {
"#": 10
},
"id": 0,
"isModified": false,
"label": "World",
"parent": "",
"type": "composite"
},
[],
{
"max": {
"#": 3
},
"min": {
"#": 4
}
},
{
"x": {
"#.": "Number",
"#v": [
"Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"Infinity"
]
}
},
{
"x": {
"#.": "Number",
"#v": [
"-Infinity"
]
},
"y": {
"#.": "Number",
"#v": [
"-Infinity"
]
}
},
[],
[
{
"#": 7
}
],
{
"angularStiffness": 1,
"bodyB": "",
"id": 1,
"label": "Mouse Constraint",
"length": 0.01,
"pointA": {
"#": 8
},
"pointB": "",
"render": {
"#": 9
},
"stiffness": 0.1,
"type": "constraint"
},
{
"x": 0,
"y": 0
},
{
"lineWidth": 3,
"strokeStyle": "#90EE90",
"visible": true
},
{
"x": 0,
"y": 1
}
]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff