本次教程我们将介绍如何基于 p5.js 来实现经典的 starfield 星空隧道的的效果,教程将会涉及到粒子系统和物体的运动模拟等。
从上面的运行效果中可以看到很多星星从屏幕中心出现,然后以直线向往运动,最终消失在屏幕上,要实现这样的效果,需要考虑到如下几个方面:
- 需要展示大量的星星,同时星星的运动方式具有统一性,所以我们需要提供一个粒子系统来生成星星。
- 要模拟出星星从远及近的运动,在不考虑 3D 的情况下,我们可以让星星在开始运动时速度较慢,随时间的推移速度慢慢增加,如此呈现出星星从很远的地方运动过来的感觉。
粒子系统生成星星
基于粒子系统,我们可以很方便地模拟有统一运动特征的大量物体的运动行为,粒子通常具有位置、速度、加速度、颜色、大小等特性。下面是一个简单的粒子实现。
试试点击看看粒子的生成和运动。
上面是一个简单的粒子系统实现,包括了粒子的生成的,粒子的运动,粒子的绘制和粒子的边缘检测几个功能。
代码实现层面比较简单,主要分为 update 和 draw 两个方法,update 方法中基于运动模型更新每一帧粒子的状态信息,draw 方法中基于粒子当前的位置信息来绘制粒子。
唯一需要主要的是我们使用了 mouseClicked 的事件来响应鼠标的点击
function mouseClicked() {
const star = new Star(createVector(mouseX, mouseY))
star.accelration = p5.Vector.fromAngle(random(Math.PI * 2)).mult(0.1)
stars.push(star)
}
当鼠标点击时,通过 p5.Vector.fromAngle
获取一个随机的向量,将其缩小 0.1 倍,来初始化粒子的加速度,基于加速度可以实现粒子速度由慢到快的变化。
实现星星从中心到屏幕的运动
从前面的效果中我们知道星星是从中心点出发,最终消失在屏幕之外的,所以我们需要确定星星运动的方向。
如下图所示
要计算星星的运动方向,我们只需要计算出从中心点指向星星初始化位置的向量即可。
// 随机生成一个星星的位置
const startPosition = createVector(random(width), random(height))
// 中心点的位置
const centerPosition = createVector(width / 2, height / 2)
// 从中心点指向星星位置的向量,即星星的运动方向
const direction = p5.Vector.sub(startPosition, centerPosition)
由此我们计算出了星星的运动方向,我们可以使用这个向量来作为初始化星星加速度的基础。
下面是具体的代码实现。
点击查看星星的运动和消失效果
合在一起
基于上一小节的代码,我们加上星星初始化的逻辑,就完成了我们最终的效果。
const starCount = parseInt(width * height / (width + height))
这段代码是用来动态确定星星个数的,基于长宽的密度比例,我们生成了数量较为合适的星星数。
同时我们增加了一个小小的拖尾效果和星星的绘制大小变化,让星星在远处看起来小些,近处看起来大一些。
更进一步
看完了本教程,相信你已经可以自己独立做出一个星空的效果了,你还可以探索一下其他的变化,让你的画创作如众不同。下面是一些可能的点:
- 我们最终实现的效果和文章开头的效果是有些不一样的,开头的效果绘制出来了线条,而最终我们只绘制了圆形,你能修改一下实现文章开头的效果么?
- 现在的星星都是灰白颜色,你可以增加一些色盘,让星星展示不一样的颜色么?
- 我们实现了星星从中心出发消失在屏幕外的效果,你能实现星星从屏幕外出发消失在屏幕中心的效果么?
快来动手试试吧。