如何用 Javascript 创建一个简单的物理引擎 - 第一部分
我们运用物理,观察物理的运作,在日常生活中,我们所做的每一件事都体验着物理。如何在代码中添加物理特性,并让代码也能体验自然的力量?我将在关于物理引擎的文章中向您解释这一点。
什么是物理引擎?
它没什么太复杂的。它是一个包含所有物理相关函数的集合。
物理引擎起什么作用?
物理引擎可以模拟任何代码中的对象的物理。
编写物理引擎需要什么?
答案是数学
是的,您只需要了解基本的数学和一些简单的物理术语,就可以创建您的第一个物理引擎。
让我们从最基础的部分开始。假设你正在创建一个场景,希望你的物体(比如一个球)与另一个物体(比如一堵墙)发生反应。
嗯,最显而易见的办法就是硬编码。但那样还有什么意思呢?:D
我们需要我们的元素与我们抛给它们的所有东西进行互动。
它可以是一根羽毛、一块石头、一头大象,基本上任何物体……好吧,我可能听起来有点儿太过火了。那么,我们开始吧,向你展示如何构建你自己的物理引擎。
您需要开始做的事情:
- 代码编辑器
- 物理方程
1.代码编辑器
我们将使用 JavaScript 进行编码,如果使用 JS,所有这些动画最好使用 Canvas。因此,最适合使用的库是p5.js。
p5 是一个简单而强大的 JavaScript 库,它拥有绘制、移动或以最简洁的方式对代码元素进行任何操作所需的所有功能。这里有一个很棒的资源,可以帮助您入门 p5。
接下来,我们将从代码编辑器的设置开始。
步骤 1:转到https://editor.p5js.org/(如果您已经有帐户,请注册或登录)并开始在工作区中编码。
步骤 2:好了,完成了。
2. 物理方程
希望你们还留着学校的物理书。我们也可以参考维基百科查找任何我们想要的物理公式。这部分我们将讨论一些简单的概念,比如运动。因为我们使用的是网页编辑器,所以不需要任何设置。p5.js 网页编辑器会帮我们搞定一切。
p5.js也遵循相同的 JavaScript 编码规范。所以,如果您熟悉 Web 概念,那么太好了!您快成功了。
对于新手来说,让我带您快速了解一下编辑器。
这是编辑器。它分为两部分:编码工作区和预览区。(如果您的屏幕看起来不一样,不用担心。我刚刚更改了主题)。
让我们从你在编辑器上看到的元素开始,那就是
- 菜单栏
- 开始和停止
- 自动刷新
- 姓名
- 设置
- 项目文件夹
- 编码空间
- 预览
菜单栏:
与其他编辑器一样,这是一个标准的菜单栏。现在我们需要了解“文件”->“新建”。这将创建一个新的项目。
开始和停止:
点击“开始”按钮将编译并运行您的代码,并在预览选项卡上预览。点击“停止”按钮将停止编译。
自动刷新:[不推荐]
虽然我不使用自动刷新功能,但它对其他人来说可能很方便。如果您在运行代码时更改了代码,自动刷新功能会刷新预览。
姓名:
您的项目名称。p5 编辑器将提供有趣的随机名称,您可以选择保留或根据需要更改。
设置:
您猜对了,所有的小调整都可以在设置下进行,以便您制作自己的编辑器。
项目文件夹:
所有项目文件都放在项目文件夹下。您可以根据需要添加其他文件夹,但现在我们先简化操作,只添加一个文件。
编码空间:
一切魔法都在这里发生。你所有的代码和逻辑都将汇聚在一起,形成一件杰作。
预览:
在这里您将看到您的杰作栩栩如生。
在进一步讨论之前,让我们讨论一下项目文件夹下的 3 个默认文件
index.html - 这是 Web 应用的起始页。您将在这里链接脚本 (JS) 文件和样式 (CSS) 文件。
style.css - 这被称为样式表,您可以在其中修改 html 文件或 js 文件中使用的任何元素的所有样式属性。
sketch.js - 这是我们感兴趣的,也是我们将进行更多编程的,这基本上是我们画布的起点。
默认情况下,sketch.js 将为您提供一个样板模板来帮助您入门。
让我们解密每个词的含义。
1. 设置()
function setup() {
createCanvas(400, 400);
}
在代码编译开始时,setup 函数会被调用一次。
createCanvas 在预览中创建一个具有指定宽度和高度的画布。
2.draw()
function draw() {
background(220);
}
画布或元素主体中的每个时间戳都会调用 draw 函数。在更新对象的任何更改时,Draw 函数特别有用。
让我们从第一个例子开始。
- 开始一个新项目
- 选择Sketch -> 添加文件。这会提示你输入文件名。输入“Ball”作为文件名,你会看到你的文件列在项目文件夹下。
- 让我们向Ball.js添加一些代码。
class Ball {
constructor() {
this.location = createVector(width / 2, height / 2);
this.velocity = createVector(2, 3);
}
display() {
fill(255);
ellipse(this.location.x, this.location.y, 40, 40);
}
move() {
this.location.add(this.velocity);
}
bounce() {
if (this.location.x < 20 || this.location.x > width - 20) {
this.velocity.x = this.velocity.x * -1;
}
if (this.location.y < 20 || this.location.y > height - 20) {
this.velocity.y = this.velocity.y * -1;
}
}
}
这是怎么回事?是不是有点困惑?让我来解释一下。
我们刚刚创建了一个 Ball 类,并为其提供了一些函数。很简单吧?别被这些数学知识搞糊涂了。
constructor(){
this.location = createVector(width/2,height/2);
this.velocity = createVector(2,3);
}
我们使用构造函数创建了两个向量。在数学中,向量不过是一个具有 x 和 y 值(或根据定义,大小和方向)的对象。就像你在图表上绘制的点一样,我们将根据坐标系绘制对象。
在这种情况下,我们将创建一个位置向量,它将跟踪我们的对象相对于画布的位置,我们将创建另一个速度向量,它将跟踪对象的移动速度,因为速度就是你移动的速度,对吗?
display(){
fill(255);
ellipse(this.location.x,this.location.y,40,40)
}
让我们在画布上显示 Ball 对象。我们将创建一个名为 display 的用户定义函数,然后绘制一个椭圆。椭圆是 p5.js 预定义的形状。我们想要一个圆形,因此我们为椭圆传递相同的半径。我们将使用在构造函数中创建的位置向量来显示椭圆。
move(){
this.location.add(this.velocity);
}
让我们根据球体的速度来移动它。因此,任何位于 x1, y1 的物体,要到达另一个位置 x2, y2,都必须以一定的速度移动才能到达 x2, y2。因此,我们将在位置向量上添加一个恒定速度。这样,对于每个时间戳,我们都会得到一个新的位置,它是上一个位置与速度之和。
bounce(){
if(this.location.x<20 || this.location.x>width-20){
this.velocity.x = this.velocity.x*-1;
}
if(this.location.y<20 || this.location.y>height-20){
this.velocity.y = this.velocity.y*-1;
}
}
让我们添加一个 bounce 函数,让它更有趣一些。它的作用是寻找画布边界,并将球保持在画布内。
当现实生活中的球撞到墙壁时,墙壁会对球施加相等的力,但由于球比墙壁轻得多,所以球会移动或反弹,而墙壁则会保持不变。
在代码中,我们无法让边界推动球,所以我们将球的速度设为负数,这样当球碰到任何边界时,它都会朝相反的方向移动。真是太简单了。
现在让我们在sketch.js中添加一些代码
let ball;
function setup() {
createCanvas(600, 600);
ball = new Ball();
}
function draw() {
background(0);
ball.move();
ball.bounce();
ball.display();
}
让我们创建一个 ball 变量,以便在 setup 函数中创建 Ball 类的实例。现在,ball 变量可以访问 Ball 类的所有函数。
对于每个绘制循环,球都会移动,球对象会检查弹跳并改变位置,然后球对象会显示在循环时间戳中的位置。
一切都结束了吧?点击“运行”按钮,一切就开始了,对吧?
不行!!!每个程序员都会犯这个错误。就连我也花了好几个小时来找它为什么运行不起来。原因如下。
永远不要忘记在 index.html 中的脚本下添加你的 js 文件。
现在你已经准备好了!继续并单击“运行”按钮,这样你就有了第一个物理模拟程序。
您将看到以下内容:
好了,你的第一个物理引擎就完成了。接下来的步骤中,我们将讨论如何让它看起来更逼真。现在就来尝试调整一下数值吧。