feat: real (Matter.js) physics :)
This commit is contained in:
parent
ea9c116c7f
commit
7d2037d870
|
@ -50,7 +50,7 @@ class MobileBase extends Trait {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.entity.is('physical')) {
|
if (this.entity.is('physical')) {
|
||||||
this.entity.applyImpulse(this.requestedMovement);
|
this.entity.applyImpulse(this.requestedMovement, elapsed);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const requestedMovement = Vector.scale(
|
const requestedMovement = Vector.scale(
|
||||||
|
|
|
@ -80,9 +80,9 @@ export class Physical extends decorate(Trait) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
applyImpulse: (impulse) => {
|
applyImpulse: (impulse, elapsed) => {
|
||||||
if (this._world) {
|
if (this._world) {
|
||||||
this._body.applyImpulse(impulse);
|
this._body.applyImpulse(impulse, elapsed);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,11 @@ export class Body extends decorate(AbstractBody) {
|
||||||
this.force = Vector.add(this.force, vector);
|
this.force = Vector.add(this.force, vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyImpulse(vector) {
|
applyImpulse(vector, elapsed) {
|
||||||
this.impulse = Vector.add(this.impulse, vector);
|
this.impulse = Vector.add(
|
||||||
|
this.impulse,
|
||||||
|
Vector.scale(vector, elapsed)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ export class World extends AbstractWorld {
|
||||||
for (const entity of this.entities.values()) {
|
for (const entity of this.entities.values()) {
|
||||||
const body = entity.body;
|
const body = entity.body;
|
||||||
const translation = Vector.add(
|
const translation = Vector.add(
|
||||||
Vector.scale(body.impulse, elapsed),
|
body.impulse,
|
||||||
body.force,
|
body.force,
|
||||||
);
|
);
|
||||||
body.position = Vector.add(body.position, translation);
|
body.position = Vector.add(body.position, translation);
|
||||||
|
@ -155,7 +155,7 @@ export class World extends AbstractWorld {
|
||||||
const contacts = body.contacts;
|
const contacts = body.contacts;
|
||||||
if (contacts.size > 0) {
|
if (contacts.size > 0) {
|
||||||
const translation = Vector.add(
|
const translation = Vector.add(
|
||||||
Vector.scale(body.impulse, elapsed),
|
body.impulse,
|
||||||
body.force,
|
body.force,
|
||||||
);
|
);
|
||||||
body.position = Vector.sub(body.position, translation);
|
body.position = Vector.sub(body.position, translation);
|
||||||
|
|
74
packages/physics/matter/body.js
Normal file
74
packages/physics/matter/body.js
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import {Composite, Bodies, Body as MatterBody} from 'matter-js';
|
||||||
|
|
||||||
|
import {Vector} from '@avocado/math';
|
||||||
|
import {ShapeList, PolygonShape, RectangleShape} from '@avocado/physics';
|
||||||
|
|
||||||
|
import {AbstractBody} from '../abstract/body';
|
||||||
|
import { Rectangle } from '../../math';
|
||||||
|
|
||||||
|
export class Body extends AbstractBody {
|
||||||
|
|
||||||
|
constructor(shape) {
|
||||||
|
super(shape);
|
||||||
|
this.matterBody = this.constructor.bodyFromShape(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyForce(force) {
|
||||||
|
MatterBody.applyForce(
|
||||||
|
this.matterBody,
|
||||||
|
this.matterBody.position,
|
||||||
|
{
|
||||||
|
x: force[0],
|
||||||
|
y: force[1],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyImpulse(impulse, elapsed) {
|
||||||
|
impulse = Vector.scale(impulse, elapsed);
|
||||||
|
MatterBody.translate(this.matterBody, {
|
||||||
|
x: impulse[0],
|
||||||
|
y: impulse[1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bodyFromShape(shape) {
|
||||||
|
if (shape instanceof RectangleShape) {
|
||||||
|
return Bodies.rectangle(
|
||||||
|
shape.x,
|
||||||
|
shape.y,
|
||||||
|
shape.width,
|
||||||
|
shape.height,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (shape instanceof PolygonShape) {
|
||||||
|
const vectors = [];
|
||||||
|
for (const vertice of shape) {
|
||||||
|
vectors.push({
|
||||||
|
x: vertice[0],
|
||||||
|
y: vertice[1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Bodies.fromVertices(
|
||||||
|
shape.x,
|
||||||
|
shape.y,
|
||||||
|
vectors,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get position() {
|
||||||
|
return [
|
||||||
|
this.matterBody.position.x,
|
||||||
|
this.matterBody.position.y,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
set position(position) {
|
||||||
|
MatterBody.setPosition(this.matterBody, {
|
||||||
|
x: position[0],
|
||||||
|
y: position[1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
packages/physics/matter/world.js
Normal file
47
packages/physics/matter/world.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import {Engine, World as MatterWorld} from 'matter-js';
|
||||||
|
|
||||||
|
import {Body} from './body';
|
||||||
|
import {AbstractWorld} from '../abstract/world';
|
||||||
|
|
||||||
|
export class World extends AbstractWorld {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
const world = MatterWorld.create({
|
||||||
|
gravity: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
scale: 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.engine = Engine.create({
|
||||||
|
world,
|
||||||
|
});
|
||||||
|
this.lastElapsed = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
addBody(body) {
|
||||||
|
MatterWorld.add(this.engine.world, body.matterBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
createBody(shape) {
|
||||||
|
return new Body(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBody(body) {
|
||||||
|
super.removeBody(body);
|
||||||
|
MatterWorld.remove(this.engine.world, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
tick(elapsed) {
|
||||||
|
// Milliseconds.
|
||||||
|
elapsed = elapsed * 1000;
|
||||||
|
const correction = this.lastElapsed ? elapsed / this.lastElapsed : 1;
|
||||||
|
// Update simulation.
|
||||||
|
Engine.update(this.engine, elapsed, correction)
|
||||||
|
this.lastElapsed = elapsed;
|
||||||
|
// Propagate.
|
||||||
|
super.tick(elapsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "@avocado/physics",
|
"name": "@avocado/physics",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "cha0s",
|
"author": "cha0s",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"matter-js": "0.14.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user