如何在下面的代码中为sin线设置动画以沿y轴移动,以某种方式看起来更像是移动水波?
- 如果您取出速度和加速代码,您将看到我尝试使用的内容
float scaleVal = 6.0;
float angleInc = 0.19;
float velocity=0.0;
float acceleration=0.01;
void setup(){
size(750,750);
stroke(255);
}
void draw(){
background (0);
float angle=0.0;
for (int offset = -10; offset < width+10; offset += 10) {
for (int y = 1; y <= height; y += 3) {
float x = offset + (sin(angle) * scaleVal);
line(x, y, x, y+2);
angle += angleInc;
velocity += acceleration;
y += velocity;
}
angle += PI;
}
}
答案 0 :(得分:1)
尝试使用sin()
更改y位置而不是x。
x位置可以简单地递增。
数学可能令人生畏,但是一旦掌握了它,就会变得很有趣。 想象一下,在笛卡尔坐标系中绕半径为1.0的圆(0是中心,x和y向右增加,向下减小,向左和向上减小):
基本上它就像一个转换器:你插入一个0到360度的角度或TWO_PI
弧度(因为sin与弧度的角度一起工作),你得到一个介于-1.0和1.0之间的值。
如果要绘制正弦波,则必须绘制多个点:
sin()
函数的结果来获得上下变化的值。最后要做的是将sin()
函数的结果乘以更大的数字,以便将正弦波(从-1.0到1.0)缩放到更适合屏幕的大小。
这是一个快速评论的演示,你可以使用鼠标位置来玩:
function setup(){
createCanvas(640,100);
}
function draw(){
background(255);
var numberOfPoints = 1+(mouseX/2);
//how often apart will the points be
var widthPerPoint = width / numberOfPoints;
//how much will the angle change from one point to another
var anglePerPoint = TWO_PI/numberOfPoints;
var waveHeight = 25;
for(var i = 0; i < numberOfPoints; i++){
var x = i * widthPerPoint;
var y = sin(anglePerPoint * i) * waveHeight;
ellipse(x,50 + y,5,5);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
它的主旨是这一行:
var y = sin(anglePerPoint * i) * waveHeight;
可以细分为:
//increment the angle
var incrementedAngle = anglePerPoint * i;
//compute sine (-1.0,1.0)
var sine = sin(incrementedAngle);
//scale sine result
var waveY = sine * waveHeight;
一旦你可以绘制静态正弦波,就可以很容易地制作动画:在每个点添加一个增加值的角度增量。这会增加角度,并且基本上围绕圆圈(TWO_PI
)。
您可以创建自己的变量,以自己的速度增加或增加
可以轻松使用基于时间(millis()
)或框架(frameCount
)的增加值,您可以按比例缩小(除以大数...或者更好,然后乘以一小部分数):
function setup(){
createCanvas(640,100);
}
function draw(){
background(255);
var numberOfPoints = 1+(mouseX/2);
//how often apart will the points be
var widthPerPoint = width / numberOfPoints;
//how much will the angle change from one point to another
var anglePerPoint = TWO_PI/numberOfPoints;
var waveHeight = 25;
for(var i = 0; i < numberOfPoints; i++){
var x = i * widthPerPoint;
var y = sin(anglePerPoint * i + frameCount * 0.01) * waveHeight;
ellipse(x,50 + y,5,5);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
希望上面的动画和简单演示有助于说明这一点。 更简单的说法是,它有点过时了:你画的点只能上下移动,但是每个点都沿着圆圈增加一个角度。
查看Reuben Margolin's kinectic sculpture system demo:
(我建议查看整个PopTech的演讲:它鼓舞人心)
您也应该查看Processing SineWave example。
这是一个更复杂的封装概念,在一个可恢复的函数中绘制多个波来暗示大气的角度:
int numWaves = 5;
void setup(){
size(400,400);
noStroke();
}
void draw(){
background(255);
for(int i = 0 ; i < numWaves; i++){
fill(30,120,180,map(i,0,numWaves-1,192,32));
drawSineWave(HALF_PI,0.00025 * (i+1),50 + (10 * i),8,width,mouseY);
}
fill(255);
text("drag mouse x to change number of waves",10,height-10);
}
/*
* radians - how often does the wave cycle (larges values = more peaks)
* speed - how fast is the wave moving
* amplitude - how high is the wave (from centre point)
* detail - how many points are used to draw the wave (small=angled, many = smooth)
* y - y centre of the wave
*/
void drawSineWave(float radians,float speed,float amplitude,int detail,float size,float y){
beginShape();
vertex(0,height);//fix to bottom
//compute the distance between each point
float xoffset = size / detail;
//compute angle offset between each point
float angleIncrement = radians / detail;
//for each point
for(int i = 0 ; i <= detail; i++){
//compute x position
float px = xoffset * i;
//use sine function compute y
//millis() * speed is like an ever increasing angle
//to which we add the angle increment for each point (so the the angle changes as we traverse x
//the result of sine is a value between -1.0 and 1.0 which we multiply to the amplitude (height of the wave)
//finally add the y offset
float py = y + (sin((millis() * speed) + angleIncrement * i) * amplitude);
//add the point
vertex(px,py);
}
vertex(size,height);//fix to bottom
endShape();
}
void mouseDragged(){
numWaves = 1+(int)mouseX/40;
}
你也可以在下面运行:
var numWaves = 5;
function setup(){
createCanvas(400,400);
noStroke();
}
function draw(){
background(255);
for(var i = 0 ; i < numWaves; i++){
fill(30,120,180,map(i,0,numWaves-1,192,32));
drawSineWave(HALF_PI,0.00025 * (i+1),50 + (10 * i),8,width,mouseY);
}
fill(255);
text("drag mouse x to change number of waves",10,height-10);
}
/*
* radians - how often does the wave cycle (larges values = more peaks)
* speed - how fast is the wave moving
* amplitude - how high is the wave (from centre point)
* detail - how many points are used to draw the wave (small=angled, many = smooth)
* y - y centre of the wave
*/
function drawSineWave(radians,speed,amplitude,detail,size,y){
beginShape();
vertex(0,height);//fix to bottom
//compute the distance between each point
var xoffset = size / detail;
var angleIncrement = radians / detail;
for(var i = 0 ; i <= detail; i++){
var px = xoffset * i;
var py = y + (sin((millis() * speed) + angleIncrement * i) * amplitude);
vertex(px,py);
}
vertex(size,height);//fix to bottom
endShape();
}
function mouseDragged(){
numWaves = ceil(mouseX/40);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
我在渲染方面唯一的其他建议是与beginShape()一起玩。不必担心每条线的绘制位置,只需在vertex(x,y)
/ beginShape()
次调用之间传递一堆点(通过endShape()
),然后让Processing为您连接点。 / p>
答案 1 :(得分:0)
Stack Overflow并非真正针对一般&#34;我如何做到这一点&#34;输入问题。它更具体&#34;我试过X,期待Y,但得到Z而不是#34;输入问题。话虽如此,我会尝试在一般意义上提供帮助。
如果你想要动画上下动画,你必须随着时间的推移修改它的Y位置。
一种方法是使用sin()
或cos()
函数提出一个在-1
和1
之间交替的值,然后您可以将其乘以一个高度并添加到一个中心:
void setup() {
size(100, 200);
}
void draw() {
background (0);
float centerY = height/2;
float waveHeight = 75;
float input = frameCount/10.0;
float ballY = centerY+sin(input)*waveHeight;
ellipse(width/2, ballY, 10, 10);
}
另一种方法是自己跟踪位置和速度。当位置达到最小值或最大值时,只需反转速度。像这样:
float ballY = 100;
float ySpeed = 1;
void setup() {
size(100, 200);
}
void draw() {
background (0);
ballY += ySpeed;
if(ballY < 0 || ballY > height){
ySpeed *= -1;
}
ellipse(width/2, ballY, 10, 10);
}
您也可以使用lerp()
功能。关键是有一百万种不同的方法可以做到这一点。您可以做的最好的事情是尝试并在遇到问题时发布MCVE。祝你好运。