feat: real (Matter.js) physics :)
This commit is contained in:
parent
ea9c116c7f
commit
7d2037d870
|
@ -50,7 +50,7 @@ class MobileBase extends Trait {
|
|||
return;
|
||||
}
|
||||
if (this.entity.is('physical')) {
|
||||
this.entity.applyImpulse(this.requestedMovement);
|
||||
this.entity.applyImpulse(this.requestedMovement, elapsed);
|
||||
}
|
||||
else {
|
||||
const requestedMovement = Vector.scale(
|
||||
|
|
|
@ -80,9 +80,9 @@ export class Physical extends decorate(Trait) {
|
|||
}
|
||||
},
|
||||
|
||||
applyImpulse: (impulse) => {
|
||||
applyImpulse: (impulse, elapsed) => {
|
||||
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);
|
||||
}
|
||||
|
||||
applyImpulse(vector) {
|
||||
this.impulse = Vector.add(this.impulse, vector);
|
||||
applyImpulse(vector, elapsed) {
|
||||
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()) {
|
||||
const body = entity.body;
|
||||
const translation = Vector.add(
|
||||
Vector.scale(body.impulse, elapsed),
|
||||
body.impulse,
|
||||
body.force,
|
||||
);
|
||||
body.position = Vector.add(body.position, translation);
|
||||
|
@ -155,7 +155,7 @@ export class World extends AbstractWorld {
|
|||
const contacts = body.contacts;
|
||||
if (contacts.size > 0) {
|
||||
const translation = Vector.add(
|
||||
Vector.scale(body.impulse, elapsed),
|
||||
body.impulse,
|
||||
body.force,
|
||||
);
|
||||
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",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"main": "index.js",
|
||||
"author": "cha0s",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"matter-js": "0.14.2"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user