physics
This commit is contained in:
210
main.js
210
main.js
@ -1,58 +1,182 @@
|
||||
import * as PIXI from 'pixi.js';
|
||||
|
||||
import * as p2 from 'p2'
|
||||
import './style.css'
|
||||
|
||||
function randomInt(max) {
|
||||
return Math.floor(Math.random() * (max + 1))
|
||||
}
|
||||
|
||||
// Create the application helper and add its render target to the page
|
||||
let app = new PIXI.Application({ width: 640, height: 360 });
|
||||
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
|
||||
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
|
||||
|
||||
let app = new PIXI.Application({
|
||||
width: vw,
|
||||
height: vh,
|
||||
antialias: true,
|
||||
backgroundColor: 0xffffff
|
||||
});
|
||||
document.body.appendChild(app.view);
|
||||
|
||||
// Create window frame
|
||||
let frame = new PIXI.Graphics();
|
||||
frame.beginFill(0x666666);
|
||||
frame.lineStyle({ color: 0xffffff, width: 4, alignment: 0 });
|
||||
frame.drawRect(0, 0, 208, 208);
|
||||
frame.position.set(320 - 100, 180 - 100);
|
||||
app.stage.addChild(frame);
|
||||
|
||||
// Create a graphics object to define our mask
|
||||
let mask = new PIXI.Graphics();
|
||||
// Add the rectangular area to show
|
||||
mask.beginFill(0xffffff);
|
||||
mask.drawRect(0,0,200,200);
|
||||
mask.endFill();
|
||||
class PhysicsObject {
|
||||
body;
|
||||
shape;
|
||||
graphics;
|
||||
parentContainer;
|
||||
|
||||
// Add container that will hold our masked content
|
||||
let maskContainer = new PIXI.Container();
|
||||
// Set the mask to use our graphics object from above
|
||||
maskContainer.mask = mask;
|
||||
// Add the mask as a child, so that the mask is positioned relative to its parent
|
||||
maskContainer.addChild(mask);
|
||||
// Offset by the window's frame width
|
||||
maskContainer.position.set(4,4);
|
||||
// And add the container to the window!
|
||||
frame.addChild(maskContainer);
|
||||
constructor(body, shape, graphics) {
|
||||
this.body = body;
|
||||
this.shape = shape;
|
||||
this.graphics = graphics;
|
||||
|
||||
// Create contents for the masked container
|
||||
let text = new PIXI.Text(
|
||||
'This text will scroll up and be masked, so you can see how masking works. Lorem ipsum and all that.\n\n' +
|
||||
'You can put anything in the container and it will be masked!',
|
||||
{
|
||||
fontSize: 24,
|
||||
fill: 0x1010ff,
|
||||
wordWrap: true,
|
||||
wordWrapWidth: 180
|
||||
this.body.addShape(this.shape);
|
||||
|
||||
this.graphics.interactive = true;
|
||||
this.graphics.on('click', (e) => {
|
||||
this.body.applyImpulse([0, 25]);
|
||||
})
|
||||
}
|
||||
);
|
||||
text.x = 10;
|
||||
maskContainer.addChild(text);
|
||||
|
||||
// Add a ticker callback to scroll the text up and down
|
||||
let elapsed = 0.0;
|
||||
assign(world, container) {
|
||||
world.addBody(this.body);
|
||||
container.addChild(this.graphics);
|
||||
}
|
||||
|
||||
update() {
|
||||
// Transfer positions of the physics objects to Pixi.js
|
||||
this.graphics.position.x = this.body.position[0];
|
||||
this.graphics.position.y = this.body.position[1];
|
||||
this.graphics.rotation = this.body.angle;
|
||||
}
|
||||
}
|
||||
|
||||
let worldObjects = [];
|
||||
|
||||
let zoom = 15;
|
||||
let world = new p2.World({ gravity: [0, -9.81] });
|
||||
// Add a plane
|
||||
|
||||
// let planeShape = new p2.Plane();
|
||||
// let planeBody = new p2.Body({
|
||||
// position: [0, -2]
|
||||
// });
|
||||
// planeBody.addShape(planeShape);
|
||||
// world.addBody(planeBody);
|
||||
|
||||
let container = new PIXI.Container();
|
||||
container.interactive = true;
|
||||
container.position.x = app.renderer.width / 2; // center at origin
|
||||
container.position.y = app.renderer.height / 2 + 50;
|
||||
container.scale.x = zoom; // zoom in
|
||||
container.scale.y = -zoom; // Note: we flip the y axis to make "up" the physics "up"
|
||||
container.on('mousedown', e => {
|
||||
console.log(e.data.global.x, e.data.global.y)
|
||||
})
|
||||
app.stage.addChild(container);
|
||||
|
||||
// Add a box
|
||||
let box = new PhysicsObject(
|
||||
new p2.Body({
|
||||
mass: 1,
|
||||
position: [0, 2],
|
||||
angularVelocity: 1
|
||||
}),
|
||||
new p2.Box({
|
||||
width: 2,
|
||||
height: 1
|
||||
}),
|
||||
new PIXI.Graphics()
|
||||
)
|
||||
box.graphics.beginFill(randomInt(0xffffff));
|
||||
box.graphics.drawRect(
|
||||
-box.shape.width / 2, -box.shape.height / 2,
|
||||
box.shape.width, box.shape.height);
|
||||
box.graphics.endFill();
|
||||
|
||||
box.assign(world, container);
|
||||
worldObjects.push(box);
|
||||
|
||||
let box2 = new PhysicsObject(
|
||||
new p2.Body({
|
||||
mass: 2,
|
||||
position: [-1, 3],
|
||||
angularVelocity: 0
|
||||
}),
|
||||
new p2.Box({
|
||||
width: 2,
|
||||
height: 1
|
||||
}),
|
||||
new PIXI.Graphics()
|
||||
)
|
||||
box2.graphics.beginFill(0x00ff00);
|
||||
box2.graphics.drawRect(
|
||||
-box.shape.width / 2, -box.shape.height / 2,
|
||||
box.shape.width, box.shape.height);
|
||||
box2.graphics.endFill();
|
||||
|
||||
box2.assign(world, container);
|
||||
worldObjects.push(box2);
|
||||
|
||||
|
||||
// static ground box
|
||||
let box3 = new PhysicsObject(
|
||||
new p2.Body({
|
||||
mass: 0,
|
||||
position: [0, -2]
|
||||
}),
|
||||
new p2.Box({
|
||||
width: 50,
|
||||
height: 0.2
|
||||
}),
|
||||
new PIXI.Graphics()
|
||||
)
|
||||
box3.graphics.beginFill(0x666666);
|
||||
box3.graphics.drawRect(
|
||||
-box3.shape.width / 2, -box3.shape.height / 2,
|
||||
box3.shape.width, box3.shape.height);
|
||||
box3.graphics.endFill();
|
||||
|
||||
box3.assign(world, container);
|
||||
worldObjects.push(box3);
|
||||
|
||||
app.ticker.add((delta) => {
|
||||
// Update the text's y coordinate to scroll it
|
||||
elapsed += delta;
|
||||
text.y = 10 + -100.0 + Math.cos(elapsed/50.0) * 100.0;
|
||||
world.step(1 / 60);
|
||||
worldObjects.forEach(o => o.update());
|
||||
});
|
||||
|
||||
function randomBox() {
|
||||
let width = 1 + Math.random() * 3;
|
||||
let height = 1 + Math.random() * 3;
|
||||
// Add a box
|
||||
let box = new PhysicsObject(
|
||||
new p2.Body({
|
||||
mass: 0.5 * Math.sqrt(width * height),
|
||||
position: [randomInt(25) - 12.5, randomInt(10) + 5],
|
||||
angularVelocity: 0
|
||||
}),
|
||||
new p2.Box({
|
||||
width: width,
|
||||
height: height
|
||||
}),
|
||||
new PIXI.Graphics()
|
||||
)
|
||||
box.graphics.beginFill(randomInt(0xffffff));
|
||||
box.graphics.drawRect(
|
||||
-box.shape.width / 2, -box.shape.height / 2,
|
||||
box.shape.width, box.shape.height);
|
||||
box.graphics.endFill();
|
||||
|
||||
box.assign(world, container);
|
||||
worldObjects.push(box);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
function doZoom(e) {
|
||||
zoom += -e.deltaY * 0.05;
|
||||
zoom = Math.min(Math.max(1, zoom), 100)
|
||||
container.scale.x = zoom; // zoom in
|
||||
container.scale.y = -zoom; // Note: we flip the y axis to make "up" the physics
|
||||
}
|
||||
window.addEventListener('wheel', doZoom)
|
||||
window.addEventListener('click', randomBox)
|
@ -10,6 +10,7 @@
|
||||
"vite": "^2.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"p2": "^0.7.1",
|
||||
"pixi.js": "^6.1.2"
|
||||
}
|
||||
}
|
||||
|
11
style.css
11
style.css
@ -1,8 +1,3 @@
|
||||
#app {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
body {
|
||||
margin: 0; padding: 0; overflow: hidden;
|
||||
}
|
12
yarn.lock
12
yarn.lock
@ -251,6 +251,13 @@ object-assign@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
p2@^0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/p2/-/p2-0.7.1.tgz#25f2474d9bc3a6d3140a1da26a67c9e118ac9543"
|
||||
integrity sha1-JfJHTZvDptMUCh2iamfJ4RislUM=
|
||||
dependencies:
|
||||
poly-decomp "0.1.1"
|
||||
|
||||
path-parse@^1.0.6:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
@ -297,6 +304,11 @@ pixi.js@^6.1.2:
|
||||
"@pixi/ticker" "6.1.2"
|
||||
"@pixi/utils" "6.1.2"
|
||||
|
||||
poly-decomp@0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/poly-decomp/-/poly-decomp-0.1.1.tgz#9f68c4fa558663791c9ba4c2df7283f3096c23c9"
|
||||
integrity sha1-n2jE+lWGY3kcm6TC33KD8wlsI8k=
|
||||
|
||||
postcss@^8.3.6:
|
||||
version "8.3.6"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea"
|
||||
|
Reference in New Issue
Block a user