For some odd reason, the code below does not produce the desired effect. The sinewave is fine and functional, and the snippet of code below works perfectly, except for the movement forward, which is jolty.
I am using millis() and dividing by 1000 to convert to seconds, but the effect still produces what I would expect form using the second() function - the sinewave moving forward every 1 second. I want the lines to move horizontally smoothly, as the sinewave line does vertically. What have I done wrong?
int cyclesBeforeStopping = 4;
int distanceBeforeStopping = 400;
float frequency = 0.2; // in Hz
float peak = 25; // Highest point of wave
float trough = 275; // Lowest point of wave
float amplitudeOffset;
float forwardOffset;
float timeUntilStop = (1 / frequency) * cyclesBeforeStopping;
void setup(){
size(600,300);
frameRate(50);
forwardOffset = ForwardOffset();
}
void draw(){
background(255);
float forwardOffsetNow = forwardOffset * (millis() / 1000);
// Guidelines
line(50 + forwardOffsetNow, peak, 100 + forwardOffsetNow, peak);
line(50 + forwardOffsetNow, trough, 100 + forwardOffsetNow, trough);
// Sine line
float newPosition = NewPosition();
line(50 + forwardOffsetNow, newPosition, 100 + forwardOffsetNow, newPosition);
}
float ForwardOffset() {
float forwardOffsetVar = (distanceBeforeStopping) / timeUntilStop;
return forwardOffsetVar;
}
float NewPosition() {
float omega = TWO_PI * frequency;
float amplitude = trough - peak;
float halfway = peak + amplitude / 2;
float newPosition = halfway - (amplitude * sin(omega * millis() / 1000) / 2);
return newPosition;
}
A one dot solution :) just do:
float forwardOffsetNow = forwardOffset * (millis() / 1000.);//mind the dot after 1000
and also:
float newPosition = halfway - (amplitude * sin(omega * millis() / 1000.) / 2);
This is called integer division, well documented in Processing's wiki troubleshooting, here.
It can be avoided by using a dot or an f after the number, like:
millis()/1000.;
or
millis()/1000.0;
or
millis()/1000f;
All will work.
Related
I have successfully coded a static spiral using lines, and now I'm supposed to make the spiral rotate from frame to frame. I tried incrementing the angle used for the x and y positions of the end of the lines with each frame, but the spiral doesn't move at all.
void draw() {
for (int i = 0; i < 15 * NUM_LINES; i++) {
float lineEndX = width / 2 + radius * cos(angle + startAngle);
float lineEndY = height / 2 + radius * sin(angle + startAngle);
line (lineStartX, lineStartY, lineEndX, lineEndY);
lineStartX = lineEndX;
lineStartY = lineEndY;
radius = radius + 0.047;
angle += 0.01 % (TWO_PI * NUM_TURNS);
}
startAngle += START_ANGLE_CHANGE;
angle = 0;
}
Add background(255); to your draw function. Also define lineStartX, lineStartY and radius there so their values are reset every time the function is called.
void draw() {
background(255);
float lineEndX = width / 2;
float lineEndY = height / 2;
float radius = 5;
for (int i = 0; i < 15 * NUM_LINES; i++) {
float lineEndX = width / 2 + radius * cos(angle + startAngle);
float lineEndY = height / 2 + radius * sin(angle + startAngle);
line (lineStartX, lineStartY, lineEndX, lineEndY);
lineStartX = lineEndX;
lineStartY = lineEndY;
radius = radius + 0.047;
angle += 0.01 % (TWO_PI * NUM_TURNS);
}
startAngle += START_ANGLE_CHANGE;
angle = 0;
}
Working example here.
I wrote the following shader to render a pattern with a bunch of concentric circles. Eventually I want to have each rotating sphere be a light emitter to create something along these lines.
Of course right now I'm just doing the most basic part to render the different objects.
Unfortunately the shader is incredibly slow (16fps full screen on a high-end macbook). I'm pretty sure this is due to the numerous for loops and branching that I have in the shader. I'm wondering how I can pull off the geometry I'm trying to achieve in a more performance optimized way:
EDIT: you can run the shader here: https://www.shadertoy.com/view/lssyRH
One obvious optimization I am missing is that currently all the fragments are checked against the entire 24 surrounding circles. It would be pretty quick and easy to just discard these checks entirely by checking if the fragment intersects the outer bounds of the diagram. I guess I'm just trying to get a handle on how the best practice is of doing something like this.
#define N 10
#define M 5
#define K 24
#define M_PI 3.1415926535897932384626433832795
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float aspectRatio = iResolution.x / iResolution.y;
float h = 1.0;
float w = aspectRatio;
vec2 uv = vec2(fragCoord.x / iResolution.x * aspectRatio, fragCoord.y / iResolution.y);
float radius = 0.01;
float orbitR = 0.02;
float orbiterRadius = 0.005;
float centerRadius = 0.002;
float encloseR = 2.0 * orbitR;
float encloserRadius = 0.002;
float spacingX = (w / (float(N) + 1.0));
float spacingY = h / (float(M) + 1.0);
float x = 0.0;
float y = 0.0;
vec4 totalLight = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
// compute the center of the diagram
vec2 center = vec2(spacingX * (float(i) + 1.0), spacingY * (float(j) + 1.0));
x = center.x + orbitR * cos(iGlobalTime);
y = center.y + orbitR * sin(iGlobalTime);
vec2 bulb = vec2(x,y);
if (length(uv - center) < centerRadius) {
// frag intersects white center marker
fragColor = vec4(1.0);
return;
} else if (length(uv - bulb) < radius) {
// intersects rotating "light"
fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
return;
} else {
// intersects one of the enclosing 24 cylinders
for(int k = 0; k < K; k++) {
float theta = M_PI * 2.0 * float(k)/ float(K);
x = center.x + cos(theta) * encloseR;
y = center.y + sin(theta) * encloseR;
vec2 encloser = vec2(x,y);
if (length(uv - encloser) < encloserRadius) {
fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
return;
}
}
}
}
}
}
Keeping in mind that you want to optimize the fragment shader, and only the fragment shader:
Move the sin(iGlobalTime) and cos(iGlobalTime) out of the loops, these remain static over the whole draw call so no need to recalculate them every loop iteration.
GPUs employ vectorized instruction sets (SIMD) where possible, take advantage of that. You're wasting lots of cycles by doing multiple scalar ops where you could use a single vector instruction(see annotated code)
[Three years wiser me here: I'm not really sure if this statement is true in regards to how modern GPUs process the instructions, however it certainly does help readability and maybe even give a hint or two to the compiler]
Do your radius checks squared, save that sqrt(length) for when you really need it
Replace float casts of constants(your loop limits) with a float constant(intelligent shader compilers will already do this, not something to count on though)
Don't have undefined behavior in your shader(not writing to gl_FragColor)
Here is an optimized and annotated version of your shader(still containing that undefined behavior, just like the one you provided). Annotation is in the form of:
// annotation
// old code, if any
new code
#define N 10
// define float constant N
#define fN 10.
#define M 5
// define float constant M
#define fM 5.
#define K 24
// define float constant K
#define fK 24.
#define M_PI 3.1415926535897932384626433832795
// predefine 2 times PI
#define M_PI2 6.28318531
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
float aspectRatio = iResolution.x / iResolution.y;
// we dont need these separate
// float h = 1.0;
// float w = aspectRatio;
// use vector ops(2 divs 1 mul => 1 div 1 mul)
// vec2 uv = vec2(fragCoord.x / iResolution.x * aspectRatio, fragCoord.y / iResolution.y);
vec2 uv = fragCoord.xy / iResolution.xy;
uv.x *= aspectRatio;
// most of the following declarations should be predefined or marked as "const"...
float radius = 0.01;
// precalc squared radius
float radius2 = radius*radius;
float orbitR = 0.02;
float orbiterRadius = 0.005;
float centerRadius = 0.002;
// precalc squared center radius
float centerRadius2 = centerRadius * centerRadius;
float encloseR = 2.0 * orbitR;
float encloserRadius = 0.002;
// precalc squared encloser radius
float encloserRadius2 = encloserRadius * encloserRadius;
// Use float constants and vector ops here(2 casts 2 adds 2 divs => 1 add 1 div)
// float spacingX = w / (float(N) + 1.0);
// float spacingY = h / (float(M) + 1.0);
vec2 spacing = vec2(aspectRatio, 1.0) / (vec2(fN, fM)+1.);
// calc sin and cos of global time
// saves N*M(sin,cos,2 muls)
vec2 stct = vec2(sin(iGlobalTime), cos(iGlobalTime));
vec2 orbit = orbitR * stct;
// not needed anymore
// float x = 0.0;
// float y = 0.0;
// was never used
// vec4 totalLight = vec4(0.0, 0.0, 0.0, 1.0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
// compute the center of the diagram
// Use vector ops
// vec2 center = vec2(spacingX * (float(i) + 1.0), spacingY * (float(j) + 1.0));
vec2 center = spacing * (vec2(i,j)+1.0);
// Again use vector opts, use precalced time trig(orbit = orbitR * stct)
// x = center.x + orbitR * cos(iGlobalTime);
// y = center.y + orbitR * sin(iGlobalTime);
// vec2 bulb = vec2(x,y);
vec2 bulb = center + orbit;
// calculate offsets
vec2 centerOffset = uv - center;
vec2 bulbOffset = uv - bulb;
// use squared length check
// if (length(uv - center) < centerRadius) {
if (dot(centerOffset, centerOffset) < centerRadius2) {
// frag intersects white center marker
fragColor = vec4(1.0);
return;
// use squared length check
// } else if (length(uv - bulb) < radius) {
} else if (dot(bulbOffset, bulbOffset) < radius2) {
// Use precalced sin global time in stct.x
// intersects rotating "light"
fragColor = vec4(uv,0.5+0.5*stct.x,1.0);
return;
} else {
// intersects one of the enclosing 24 cylinders
for(int k = 0; k < K; k++) {
// use predefined 2*PI and float K
float theta = M_PI2 * float(k) / fK;
// Use vector ops(2 muls 2 adds => 1 mul 1 add)
// x = center.x + cos(theta) * encloseR;
// y = center.y + sin(theta) * encloseR;
// vec2 encloser = vec2(x,y);
vec2 encloseOffset = uv - (center + vec2(cos(theta),sin(theta)) * encloseR);
if (dot(encloseOffset,encloseOffset) < encloserRadius2) {
fragColor = vec4(uv,0.5+0.5*stct.x,1.0);
return;
}
}
}
}
}
}
I did a little more thinking ... I realized the best way to optimize it is to actually change the logic so that before doing intersection tests on the small circles it checks the bounds of the group of circles. This got it to run at 60fps:
Example here:
https://www.shadertoy.com/view/lssyRH
I`ve tried finding a similar error to mine to avoid asking a already repeated question but I cannot find anything. I apologise for the code being quite long. If somebody could explain to me what I am doing wrong I would greatly appreciate it. Thanks in advance.
// Physical Constants
float g=-9.81; // Gravity
float k=0.0; // Friction const (Try 0.02)
float m=0.25; // Mass kg
float dt=0.01; // Time step 10ms
// Boundary (starting) conditions
float vy=0; // Initial vertical velocity
float y=0.9; // Initial vertical position
float x=0; // Initial horizontal position
float vx=0.8; // Initial horizontal velocity
float t=0; // Initial time
Ball [] b;
void setup()
{
b=new Ball[50];
for(int i=0;i<50;i++)
{
b[i]=new Ball();
}
size(500, 500);
}
void draw()
{
background(255);
for(int i=0;i<50;i++)
{
b[i].advance();
b[i].draw_ball();
}
}
int Collision(int j,Ball b[])
{
int res=-1;
for(int i=0;i<50;i++)
{
if (i!=j)
{
float sep=sqrt(pow(b[i].x-b[j].x,2)+pow(b[i].y-b[j].y,2));
float rads=b[i].radius+b[j].radius;
if(sep<rads){ res=i;}
}
}
return(res);
}
class Ball
{
color c;
float radius;
float vy;
float y;
float x;
float vx;
float t;
Ball()
{
y=random(0.1,0.9);
vy=random(-1,1);
x=random(0.1,0.9);
vx=random(-1,1);
c=color(random(255),random(255), random(255));
radius = 0.01+random(0.04);
t=0;
}
void advance()
{
vy=vy+(g-((k/m)*vy))*dt;
y=y+(vy*dt);
vx=vx+(-((k/m)*vx))*dt;
x=x+(vx*dt);
t=t+dt;
if (y<=0) {vy=-vy; y=y+(vy*dt);}
if (x<=0) {vx=-vx; x=x+(vx*dt);}
if (x>=1) {vx=-vx; x=x+(vx*dt);}
}
{
b[i].advance();
int r=Collision(i,b); // Check if ball i collides with any balls in array b
if(r!=-1) // -1 means no collision, r is index that identifies ball in b
{
float nvxj = (b[i].vx * (b[i].radius - b[r].radius) + (2 * b[r].radius * b[r].vx)) /
(b[i].radius + b[r].radius);
float nvyj = (b[i].vy * (b[i].radius - b[r].radius) + (2 * b[r].radius * b[r].vy)) /
(b[i].radius + b[r].radius);
float nvxr = (b[r].vx * (b[r].radius - b[i].radius) + (2 * b[i].radius * b[i].vx)) /
(b[i].radius + b[r].radius);
float nvyr = (b[r].vy * (b[r].radius - b[i].radius) + (2 * b[i].radius * b[i].vy)) /
(b[i].radius + b[r].radius);
b[i].vx=nvxj;
b[i].vy=nvyj;
b[r].vx=nvxr;
b[r].vy=nvyr;
}
b[i].draw_ball();
void draw_ball()
{
float sx=map(x,0,1,0,width);
float sy=map(y,0,1,height-1,0);
float rx=map(radius,0,1,0,width);
float ry=map(radius,0,1,0,height);
fill(c);
ellipse(sx,sy,2*rx,2*ry);
}
}
You'll have better luck if you fix your indentation so you can better match up { } curly brackets.
You've got an advance() function, but then right after that function ends (find the matching closing curly bracket), you've got this disconnected snippet of code:
{
b[i].advance();
int r=Collision(i, b); // Check if ball i collides with any balls in array b
if (r!=-1) // -1 means no collision, r is index that identifies ball in b
{
float nvxj = (b[i].vx * (b[i].radius - b[r].radius) + (2 * b[r].radius * b[r].vx)) /
(b[i].radius + b[r].radius);
float nvyj = (b[i].vy * (b[i].radius - b[r].radius) + (2 * b[r].radius * b[r].vy)) /
(b[i].radius + b[r].radius);
float nvxr = (b[r].vx * (b[r].radius - b[i].radius) + (2 * b[i].radius * b[i].vx)) /
(b[i].radius + b[r].radius);
float nvyr = (b[r].vy * (b[r].radius - b[i].radius) + (2 * b[i].radius * b[i].vy)) /
(b[i].radius + b[r].radius);
b[i].vx=nvxj;
b[i].vy=nvyj;
b[r].vx=nvxr;
b[r].vy=nvyr;
}
b[i].draw_ball();
void draw_ball()
{
float sx=map(x, 0, 1, 0, width);
float sy=map(y, 0, 1, height-1, 0);
float rx=map(radius, 0, 1, 0, width);
float ry=map(radius, 0, 1, 0, height);
fill(c);
ellipse(sx, sy, 2*rx, 2*ry);
}
}
There's a lot going on here. It's not a syntax error to have a block of code inside { } curly brackets like this, but I'm not sure what you're expecting this code to do, or when you expect it to run. But your error is caused by the fact that you're using an i variable in this code that you haven't defined.
It is a syntax error to define a function inside { } curly brackets like this though.
To fix your problem, you need to take a step back and really think about where this section of code belongs.
how do I animate the sin lines in the following code to move along the y-axis, to somehow look more like moving water waves?
-if you take out the velocity and acceleration codes you will see what I was trying to work with
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;
}
}
Try using sin() to change the y position instead of x.
The x position can simply increment.
The math may be daunting, but it gets fun once you get the hang of it.
Imagine going around a circle with the radius of 1.0 in a cartesian coordinate system (0 is centre , x and y increase to the right and down and decrease towards left and top):
Let's say you start at the top, the highest value, the length radius of your circle (1.0).
As you decrease the angle, the x move to the left, but the y will go towards the centre( 0.0 )
then x will increase as it gets close to the centre and y will drop to bottom of the circle (-1.0)
then x will keep increasing until it reaches the right edge of the circle and the y value will increase and reach the vertical centre (0.0)
finally the x will decrease until it reaches the horizontal centre and y will increase and reach back to the top of the circle (1.0)
This image explains it pretty well:
Essentially it's like a converter: you plug in an angle from 0 to 360 degrees or TWO_PI radians (as sin works with angles in radians) and you get back a value between -1.0 and 1.0.
If you want to draw a sine wave, you have to draw multiple points:
the x position will increase value directly
the y position will increase the angle, but use the result of the sin() function to obtain a value that goes up and down.
The last thing to do is multiple the result of the sin() function by a larger number to essentially scale the sine wave (from -1.0 to 1.0) to a size more appropate for the screen.
Here's a quick commented demo you can use the mouse position to play with:
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>
The gist of it is this line:
var y = sin(anglePerPoint * i) * waveHeight;
which can be broken down to:
//increment the angle
var incrementedAngle = anglePerPoint * i;
//compute sine (-1.0,1.0)
var sine = sin(incrementedAngle);
//scale sine result
var waveY = sine * waveHeight;
Once you can draw a static sine wave, it's pretty easy to animate: to the angle increment at each point you add an increasing value. This increases the angle and essentially goes around the circle (TWO_PI) for you.
You can create your own variable to increase at your own rate or you
can easily use an increasing value based on time(millis()) or frame(frameCount) which you can scale down (divide by a large number...or better yet multiple by a small fractional number):
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>
Hopefully the animation and simple demos above help illustrate the point.
In even simpler terms, it's a bit of an illustion: you draw points that only move up and down, but each point use an increasing angle along the circle.
Have a look at Reuben Margolin's kinectic sculpture system demo:
(I recommend checking out the whole PopTech talk: it's inspiring)
You should have a look at the Processing SineWave example as well.
Here's a more complex encapsulating the notions in a resuable function to draw multiple waves to hint at an atmospheric perspective:
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;
}
Which you can also run bellow:
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>
The only other suggestion I have, in terms of rendering, it to have play with beginShape(). Rather than having to worry about where to draw each line, simply pass a bunch of points(via vertex(x,y)) in between beginShape()/endShape() calls and let Processing connect the dots for you.
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for more specific "I tried X, expected Y, but got Z instead" type questions. That being said, I'll try to help in a general sense.
If you want to animate something going up and down, you have to modify its Y position over time.
One approach is to use the sin() or cos() functions to come up with a value that alternates between -1 and 1, which you can then multiply by a height and add to a center:
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);
}
Another approach is to keep track of the position and speed yourself. When the position reaches a min or max, just reverse the speed. Something like this:
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);
}
You could also use the lerp() function. The point is that there are a million different ways to do this. The best thing you can do is to try something and post an MCVE if you get stuck. Good luck.
Here is my source code:
int index;
int num = 60;
float mx[] = new float[num];
float my[] = new float[num];
float explosion;
float x;
float y;
float px;
float py;
float xold;
float yold;
float xplode1;
float yplode1;
float xplode2;
float yplode2;
float xplode3;
float yplode3;
float xplode4;
float yplode4;
float easing = 0.05;
void setup() {
size(1366, 768);
noStroke();
// noFill();
fill(25, 155);
}
void draw() {
int which = frameCount % num;
explosion = explosion + 0.32;
background(92, 55, 169);
float targetX = mouseX;
float dx = targetX - px;
float lx = targetX - x;
if (abs(dx) > 1) {
mx[which] += dx * easing;
x += lx * easing;
if (mousePressed && (mouseButton == LEFT)) {
xplode1 = dx + 50 + sin(explosion)*30;
xplode2 = dx + 50 + sin(explosion)*30;
xplode3 = dx - 50 - sin(explosion)*30;
xplode4 = dx - 50 - sin(explosion)*30;
}
else {
xplode1 = -10;
xplode2 = -10;
xplode3 = -10;
xplode4 = -10;
}
}
float targetY = mouseY;
float dy = targetY - py;
float ly = targetY - y;
if (abs(dy) > 1) {
my[which] += dy * easing;
y += dy * easing;
if (mousePressed && (mouseButton == LEFT)) {
yplode1 = dy + 50 + sin(explosion)*30;
yplode2 = dy - 50 - sin(explosion)*30;
yplode3 = dy - 50 - sin(explosion)*30;
yplode4 = dy + 50 + sin(explosion)*30;
}
else {
yplode1 = -10;
yplode2 = -10;
yplode3 = -10;
yplode4 = -10;
}
}
for(int i = 0;i<num;i++){
index = (which + 1 + i) % num;
ellipse(mx[index], my[index], i, i);
}
ellipse(xplode1, yplode1, 10, 10);
ellipse(xplode2, yplode2, 10, 10);
ellipse(xplode3, yplode3, 10, 10);
ellipse(xplode4, yplode4, 10, 10);
}
I would like to have a trail of ~60 and also have some easing for the whole thing. I have got each feature working individually but when I added in the fading. There is quite alot of unneeded variables, I have not cleaned the code at all, I have been working on it for hours, I know there is probably a very simple solution that I just cannot see at the moment. Any help would be great, thanks.
Don't bite more than you can chew, learn the little things. Vectors will make your code much less messy. You can find a detailed description of the Vector class on the Processing site. In this way, instead of having two different variables xplode1 and xplode2, there will be one Vector object that stores both values. You may find those concepts difficult at first, but they'll be invalubale tools for future sketches.
If you feel comfortable with basic concepts such as variables, functions, conditionals and loops, start studying OOP (Object Oriented Programming). Again, Daniel Shiffman comes to help.
Also, be more specific when asking on StackOverflow. Solving a problem often means finding the right question.