Hello World
原文地址:https://piqnt.com/planck.js/docs/hello-world#creating-a-world。
本节将通过一个简单示例,逐步介绍如何创建物理世界、一个平台和一个小箱子。
创建世界
每个 Planck.js 程序都从创建 World 对象开始。World 是物理系统的核心,负责管理对象、物理交互并运行模拟。
创建世界只需实例化 World 类,可以选择是否设置重力加速度:
let world = new World({
gravity: {x: 0, y: -10},
});
现在物理世界已就绪,接下来开始向其中添加内容。
创建一个平台
创建平台的步骤如下:
- 使用 world 对象在某位置创建刚体。
- 创建一个夹具(fixture),通过它在刚体上附加一个形状。
第一步:通过向 world 对象传入刚体属性来创建一个平台对象。通过刚体属性可指定平台的类型和初始位置:
let platform = world.createBody({
type: "static",
position: {x: 0, y: -10},
angle: Math.PI * 0.1
});
刚体默认为“静态(static)”类型。静态刚体不会与其他静态刚体碰撞,且不可移动。
第二步:创建夹具 Fixture,在刚体上附加一个形状 Shape:
platform.createFixture({
shape: new Edge({x: -50, y: 0}, {x: +50, y: 0}),
});
形状仅具有几何属性(如顶点或半径),不包含物理属性。夹具用于将形状附加到刚体,并为刚体添加物理属性(如密度、摩擦系数等)。一个刚体可以拥有任意数量的形状。
形状的几何坐标是相对于刚体本地坐标系的。夹具本身没有位置和角度。因此当刚体移动时,其上的所有夹具/形状会随之移动。不支持在刚体上单独移动或修改形状。
Planck.js 是刚体引擎,其许多设计基于刚体模型假设。会变形的物体并非刚体,违反此原则将导致诸多问题。因此请勿移动或修改附加到刚体上的形状。
每个夹具——包括静态夹具都必须具有一个父刚体,但你可以将所有静态夹具附加到同一个静态刚体上。
静态刚体的质量默认为零,因此无需指定密度。后续我们将学习如何使用夹具属性自定义物理行为。
创建动态箱子
创建动态箱子的步骤与平台类似。主要区别在于,除了尺寸不同外,动态刚体需要指定质量属性。
首先使用 createBody 创建刚体。由于刚体默认为静态类型,构建时需要显式设置刚体的类型 type 为动态:
let body = world.createBody({
type: "dynamic",
position: {x: 0, y: 4}
});
注意:若希望刚体能响应力的作用而运动,必须将其类型 type 设置为动态 dynamic。
接着通过夹具定义创建并附加一个箱形形状:
body.createFixture({
shape: new Box(1.0, 1.0),
density: 1.0,
friction: 0.3,
});
注意这里将密度设为 1.0(默认密度为 0)。设置夹具的密度会自动更新刚体的质量。同时将形状的摩擦系数设为 0.3。
重要提示:动态刚体应至少包含一个密度非零的夹具,否则会出现异常行为。
您可以在一个刚体上添加任意数量的夹具,每个夹具都会贡献总质量。
箱形尺寸是以 half-width 和 half-height(类似圆形的半径)。因此本例中地面箱子的宽度(x 轴)和高度(y 轴)均为 2 个单位。
单位系统
Planck.js 默认调校为使用米、千克、秒单位制。因此您可以将尺寸单位视为米。当物体尺寸接近典型现实物体大小时,Planck.js 通常能发挥最佳效果。例如,一个桶的高度约 1 米。由于浮点运算的限制,使用 Planck.js 模拟冰川或尘埃颗粒的运动并不合适。如果您使用其他单位(如像素),可以修改 Settings.lengthUnitsPerMeter 的值。例如,若采用像素单位且桶高为 80 像素,可将 lengthUnitsPerMeter 设置为 80。
演示
原文并没有演示,以下代码是自己补充的:
<div id="canvas-container" style="width: 80%; aspect-ratio:4/3; margin:auto "></div>
<script src="images/soft/Planckjs/planck-with-testbed.min.js"></script>
<script>
const { Vec2, Transform, Polygon, Circle,FrictionJoint, World, Edge, Testbed } = planck;
let world = new World({
gravity: { x: 0, y: -10 },
});
let platform1 = world.createBody({
type: "static",
position: { x: 0, y: 0 },
angle: -Math.PI * 0.1
});
platform1.createFixture({
shape: new Edge({ x: -50, y: 0 }, { x: 0, y: 0 }),
});
let platform2 = world.createBody({
type: "static",
position: { x: 0, y: 0 },
});
platform2.createFixture({
shape: new Edge({ x: 0, y: 0 }, { x: +50, y: +30 }),
});
let body1 = world.createBody({
type: "dynamic",
position: { x: -30, y: 20 }
});
body1.createFixture({
shape: new Circle(1.0, 1.0),
density: 1.0,
friction: 0.3,
});
let body2 = world.createBody({
type: "dynamic",
position: { x: -20, y: 20 }
});
body2.createFixture({
shape: new Circle(1.0, 1.0),
density: 1.0,
friction: 0,
});
window.addEventListener('DOMContentLoaded', function () {
const canvas = document.querySelector('body > canvas:first-child');
const container = document.getElementById('canvas-container');
container.appendChild(canvas);
// 调整canvas样式以适应容器
canvas.style.cssText = `width: 100%; height: 100%; display: block; background-color: rgb(34, 34, 34); `;
const testbed = Testbed.mount();
testbed.start(world);
});
</script>
添加了 2 个球,其中一个有摩擦,另一个光滑,添加了 2 个平台形成对接斜面,模拟伽利略理想斜面实验。并使用 planck.js 自带的渲染器 Testbed 绘制画面。
发布时间:2025/12/14 上午10:58:13 阅读次数:346
