在处理中激活sin波

时间:2016-10-27 18:19:47

标签: processing

如何在下面的代码中为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;
  }
}

2 个答案:

答案 0 :(得分:1)

尝试使用sin()更改y位置而不是x。 x位置可以简单地递增。

数学可能令人生畏,但是一旦掌握了它,就会变得很有趣。 想象一下,在笛卡尔坐标系中绕半径为1.0的圆(0是中心,x和y向右增加,向下减小,向左和向上减小):

  • 假设你从圆圈的顶部,最高值,长度半径(1.0)开始。
  • 当您减小角度时,x向左移动,但y将向中心移动(0.0)
  • 然后x会在接近中心时增加,y会下降到圆圈的底部(-1.0)
  • 然后x将继续增加,直到它到达圆的右边缘,y值将增加并到达垂直中心(0.0)
  • 最后x会减小,直到达到水平中心,y会增加并回到圆圈顶部(1.0)

此图片解释得非常好: sine wave from circle

基本上它就像一个转换器:你插入一个0到360度的角度或TWO_PI弧度(因为sin与弧度的角度一起工作),你得到一个介于-1.0和1.0之间的值。

如果要绘制正弦波,则必须绘制多个点:

  • x位置将直接增加值
  • y位置会增加角度,但使用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

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()函数提出一个在-11之间交替的值,然后您可以将其乘以一个高度并添加到一个中心:

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。祝你好运。