I'm trying to make a loop in p5.js that will draw small ellipses across the canvas. I've done something like this before, but the code was different.
There, when I wanted to try a loop, all I had to type was:
for (var i = 0; i < 200; i++) {}
The manual I'm using (Make: Getting Started with p5.js) tells me that the code to do this is similiar. This was an example it gave for drawing a bunch of lines:
for (var i = 20; i < 400; i += 8) {
line(i,40,i+60,80)
}
However, when I enter this code to even test it, it doesn't work. Can someone explain how to draw multiple small ellipses on the screen (I have variables set in place for the x and y coordinates of the ellipses so that they will be random)?
EDIT: This is a more full version of the code:
function draw() {
noStroke();
fill(fishCr,fishCg,fishCb);
arc(ellX,ellY,ellW,ellH,0,180);
arc(ellX+5,ellY-10,ellW/1.5,ellH/1.5,arcEl,50);
arc(ellX-45,ellY+20,ellW/1.5,ellH*1.5,340,110);
arc(ellX-60,ellY-10,ellW/1.5,ellH*2,arcT,40);
fill(0,200,255,0.5); //this is the start of the code in
//question
for (var i = 0; i < 200; i++) {
ellipse(bubX,bubY,5,5);
}
}
Please try to be more specific than saying it doesn't work. What exactly happens? What do you see in the JavaScript console?
You should also read up on a tutorial on for loops. Here is one I wrote for Processing, but the basic ideas are the same.
Your first for loop starts at 0 and increases by 1 until it reaches 200. Your second for loop starts at 20 and increases by 8 until it reaches 400.
Also note that you have an extra opening curly brace { in your second for loop.
If you still can't get it figured out, please post a MCVE that shows the problem. Good luck.
Edit: Take a look at your for loop:
for (var i = 0; i < 200; i++) {
ellipse(bubX,bubY,5,5);
}
Here you're drawing 200 circles, but you're drawing all of them at the same location, based on the bubX and bubY variables. You probably want to pass in random values here instead of the same variables every time.
createCanvas(500, 500);
function setup() {
for (var i = 0; i < 200; i++) {
ellipse(random(0, width), random(0, height), 5);
}
}
This creates a Canvas and draws 200 small circles at random locations.
Is this waht you are looking for?
Related
I recently created a simple program in Processing 3 to set each pixel to its position as a color.
void setup()
{
size(960,960);
}
void draw()
{
for(int j = 0;j < height;j++)
{
for(int i = 0;i < width;i++)
{
set(i,j,color(map(i,0,width,0,255),map(j,0,height,0,255),0));
}
}
}
How would I be able to implement this as a shader?
Note: I've already looked online and couldn't really find an answer for this.
If you're not very familiar with shaders yet, you should first take a look at this page: https://processing.org/tutorials/pshader/
What you'll probably want is to draw a rectangle that covers the entire screen, and use the built-in GLSL variable gl_FragCoord, which gives you the index of the current pixel in x and y much like your loop variables i and j. See https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/gl_FragCoord.xhtml for full documentation
Also keep in mind that the values output by the fragment shader are in the range 0 to 1 instead of 0 to 255. So in the end the relevant shader code might look something like:
uniform vec2 windowSize; //the shader doesn't know this automatically, so you'll need to pass it in yourself
void main() {
gl_FragColor = vec4(gl_FragCoord / windowSize, 0, 1);
}
I've implemented a selection sort algorithm in Processing 3.0 and I would like to display the bars as they are being sorted. The code is as follow:
ArrayList<Bar> sort() {
int smallest;
for (int i = 0; i < sortedBars.size(); i++) {
smallest = indexOfMinimum(i);
swap(sortedBars, smallest, i);
background(0);
for (int i2 = 0; i2 < sortedBars.size(); i2++) {
sortedBars.get(i2).display(i2, 255);
}
}
return sortedBars;}
however, this code only displays some bars in the initial state and the final state, skipping everything in between.
On the other hand, if I use a similar function, but that runs only one time
ArrayList<Bar> sort(int i) {
int smallest = indexOfMinimum(i);
swap(sortedBars, smallest, i);
return sortedBars;}
And then call it multiple times inside draw() function, it works just fine.
Am I doing something wrong?
edit: Forgot to mention, this is the display function:
void display(int position, color col) {
stroke(col);
line(position, height, position, height - barSize);}
Also, the Bar class has an attribute called barSie.
This is exactly how Processing is intended to work.
Processing is double-buffered, which means that it draws everything to an off-screen buffer before it copies that buffer to the screen. Usually that's a good thing, as it makes animations smoother. But like you've discovered, it prevents the "in-between" frames from showing.
To solve your problem, there are two approaches I can think of:
Option one: instead of using a for loop to do your iteration, use each call to the draw() function as one "step" in your algorithm. That would allow you to show one step per frame.
Option two: instead of drawing to the screen, draw each step of your algorithm to its own buffer, which you can create using the createGraphics() function. Either save the frames to disc, or in their own data structure. Then when the algorithm completes, you'll have a set of frames that you can then display.
Which approach you take really depends on you and what your end goal is. Good luck.
I am trying to store the motion detected from optical flow for frames in a video sequence and then use these stored motion vectors in order to predict the already known frames using just the first frame as a reference. I am currently using two processing sketches - the first sketch draws a motion vector for every pixel grid (each of width and height 10 pixels). This is done for every frame in the video sequence. The vector is only drawn in a grid if there is sufficient motion detected. The second sketch aims to reconstruct the video frames crudely from just the initial frame of the video sequence combined with information about the motion vectors got from the first sketch.
My approach so far is as follows: I am able to determine the size, position and direction of each motion vector drawn in the first sketch from four variables. By creating four arrays (two for the motion vector's x and y coordinate and another two for its length in the x and y direction), every time a motion vector is drawn I can append each of the four variables to the arrays mentioned above. This is done for each pixel grid throughout an entire frame where the vector is drawn and for each frame in the sequence - via for loops. Once the arrays are full, I can then save them to a text file as a list of strings. I then load these strings from the text file into the second sketch, along with the first frame of the video sequence. I load the strings into variables within a while loop in the draw function and convert them back into floats. I increment a variable by one each time the draw function is called - this moves on to the next frame (I used a specific number as a separator in my text-files which appears at the end of every frame - the loop searches for this number and then increments the variable by one, thus breaking the while loop and the draw function is called again for the subsequent frame). For each frame, I can draw 10 by 10 pixel boxes and move then by the parameters got from the text files in the first sketch. My problem is simply this: How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
Apologies for the length and complexity of my question. Any tips would be very much appreciated! I will add the code for the second sketch. I can also add the first sketch if required, but it's rather long and a lot of it is not my own. Here is the second sketch:
import processing.video.*;
Movie video;
PImage [] naturalMovie = new PImage [0];
String xlengths [];
String ylengths [];
String xpositions [];
String ypositions [];
int a = 0;
int c = 0;
int d = 0;
int p;
int gs = 10;
void setup(){
size(640, 480, JAVA2D);
xlengths = loadStrings("xlengths.txt");
ylengths = loadStrings("ylengths.txt");
xpositions = loadStrings("xpositions.txt");
ypositions = loadStrings("ypositions.txt");
video = new Movie(this, "sample1.mov");
video.play();
rectMode(CENTER);
}
void movieEvent(Movie m) {
m.read();
PImage f = createImage(m.width, m.height, ARGB);
f.set(0, 0, m);
f.resize(width, height);
naturalMovie = (PImage []) append(naturalMovie, f);
println("naturalMovie length: " + naturalMovie.length);
p = naturalMovie.length - 1;
}
void draw() {
if(naturalMovie.length >= p && p > 0){
if (c == 0){
image(naturalMovie[0], 0, 0);
}
d = c;
while (c == d && c < xlengths.length){
float u, v, x0, y0;
u = float(xlengths[a]);
v = float(ylengths[a]);
x0 = float(xpositions[a]);
y0 = float(ypositions[a]);
if (u != 1.0E-19){
//stroke(255,255,255);
//line(x0,y0,x0+u,y0+v);
PImage box;
box = get(int(x0-gs/2), int(y0 - gs/2), gs, gs);
image(box, x0-gs/2 +u, y0 - gs/2 +v, gs, gs);
if (a < xlengths.length - 1){
a += 1;
}
}
else if (u == 1.0E-19){
if (a < xlengths.length - 1){
c += 1;
a += 1;
}
}
}
}
}
Word to the wise: most people aren't going to read that wall of text. Try to "dumb down" your posts so they get to the details right away, without any extra information. You'll also be better off if you post an MCVE instead of only giving us half your code. Note that this does not mean posting your entire project. Instead, start over with a blank sketch and only create the most basic code required to show the problem. Don't include any of your movie logic, and hardcode as much as possible. We should be able to copy and paste your code onto our own machines to run it and see the problem.
All of that being said, I think I understand what you're asking.
How do I draw the motion of a particular frame without letting what I've have blitted to the screen in the previous frame affect what will be drawn for the next frame. My only way of getting my 10 by 10 pixel box is by using the get() function which gets pixels that are already drawn to the screen.
Separate your program into a view and a model. Right now you're using the screen (the view) to store all of your information, which is going to cause you headaches. Instead, store the state of your program into a set of variables (the model). For you, this might just be a bunch of PVector instances.
Let's say I have an ArrayList<PVector> that holds the current position of all of my vectors:
ArrayList<PVector> currentPositions = new ArrayList<PVector>();
void setup() {
size(500, 500);
for (int i = 0; i < 100; i++) {
currentPositions.add(new PVector(random(width), random(height)));
}
}
void draw(){
background(0);
for(PVector vector : currentPositions){
ellipse(vector.x, vector.y, 10, 10);
}
}
Notice that I'm just hardcoding their positions to be random. This is what your MCVE should do as well. And then in the draw() function, I'm simply drawing each vector. This is like drawing a single frame for you.
Now that we have that, we can create a nextFrame() function that moves the vectors based on the ArrayList (our model) and not what's drawn on the screen!
void nextFrame(){
for(PVector vector : currentPositions){
vector.x += random(-2, 2);
vector.y += random(-2, 2);
}
}
Again, I'm just hardcoding a random movement, but you would be reading these from your file. Then we just call the nextFrame() function as the last line in the draw() function:
If you're still having trouble, I highly recommend posting an MCVE similar to mine and posting a new question. Good luck.
I am using Processing to try and draw something and I'm stuck on a FOR loop that I'm trying to run.
I have a sketch that I would like to make shorter by taking advantage of the Translate and Rotate commands. However, for some reason I can't get this to work. If I comment out the first FOR loop ("for (int k = 0;...)" it draws, correctly, in one of my 8 quadrants. I just want to then rotate that 45 degrees, draw again, and continue until it goes full circle.
int hHeight, hWidth;
void setup(){
size(800,800);
hHeight = height/2;
hWidth = width/2;
background(0);
strokeWeight(.5);
}
void grid(){
stroke(255);
line(hWidth,0,hWidth,height);
line(0,hHeight,width,hHeight);
line(width,0,0,height);
line(0,0,width,height);
}
void rotatingGrid(float steps){ // This is the one I am having trouble with...
for (int k = 0; k == 8; k ++){ // loop this 8 times, to complete 8 rotations
pushMatrix();
translate(hWidth,hHeight);
rotate(radians(45));
for (int i = 0; i < hWidth; i+= steps){
line(i,0,hWidth-i,hHeight-i);
}
popMatrix();
}
}
void draw(){
stroke(255);
grid();
rotatingGrid(10);
}
So if you comment out the first FOR loop (and the closing bracket), it correctly works. How can I loop that, rotating it 7 times, instead of just putting the "rotate(radians(45))" and the FOR loop 7 more times?
Thanks for any advice or help.
the first for loop should be (int k = 0; k< 8; k++) if you want it to run 8 times. If you want the angle to go 45, 90, ... 360, then you can add a variable like this:
int angle = 0;
....
angle+=45;
rotate(radians(angle));
....
also, you may want to swap rotate and translate if you want to rotate about the object's origin instead of having it in a bigger circle, not sure what effect you want here.
I have multiple layers that I used for animation.
Lets say I have "1111". Each 1 is a layer. I want each layer rotate 10 degrees.
Is there any way to do these automatically without selecting each one independently.
Thanks.
you can write a script to loop through all the layers in your document and rotate using something similar to below.
var j = 10;
for (var i = 0; i < app.activeDocument.layers.length; i++) {
var lyr = app.activeDocument.layers[i];
lyr.rotate(j)
j = j + 10;
}