p5.js Beginner - RNG not working - random

So i just wanted to make a generator that generates a random value every 10 seconds. And instead it generates a random value every frame after 10 seconds of waiting. Please correct me.
var imgs = [];
var a = 0
function randomizea() {
a = int(random(5));
}
function setup() {
createCanvas(1400, 850);
// for (var i=0; i<5; i++) {
// imgs[i] = loadImage("data/img"+i+".png");
// }
}
function draw() {
background(150, 100, 150);
setInterval(randomizea, 1000);
// image(imgs[a], 0, 0);
text(a, 0, 50);
}

You should generally not use setInterval() with P5.js. Instead, rely on the timing mechanisms that P5.js already gives you.
Here's a simple example that would print something to the console every 10 seconds:
function draw(){
if(frameCount % 600 == 0){
console.log("here");
}
}
Since 60 frames fire per second, then 600 frames is 10 seconds. We use the % modulus operator to check that the frameCount variable is a multiple of 600, which means that we're at a multiple of 10 seconds.
You could also use the millis() function and check whether a certain time has elapsed.
Related posts:
How to make a delay in processing project?
How can I draw only every x frames?
Removing element from ArrayList every 500 frames
Timing based events in Processing
How to add +1 to variable every 10 seconds in Processing?
How to create something happen when time = x
making a “poke back” program in processing
Processing: How do i create an object every “x” time
Timer using frameRate and frame counter reliable?
Adding delay in Processing
Please also consult the P5.js reference for more information.

Related

Is there a way to have a delay in between code in p5.js

So I want to have a delay in my Draw function so that when I want to do
Xoffset = Xoffset + 1.5
I do not go from 0 to 30 in a secnd, but I want there to be some delay in the code so that I can easily manage it. I usually use scratch and if you are unfimiliar to that the command for a code delay is
Wait(Insert amount of seconds you want to delay here)
So when you start a part of the code, and the Wait is set to 2, the input will go off, wait 2 seconds, and then move on the the line of code below. I am trying to replicate that but in p5.js.
To detail my comment above, you could do something like this:
var xOffset = 0;
// time delay vars
// current time "snapshot" (imagine pressing the lap time button)
var time;
// the interval to wait between time "snapshots": 2s (2000 milliseconds) in this case
var wait = 2000;
function setup() {
createCanvas(300, 300);
//store the current time
time = millis();
}
function draw() {
background(220);
//check if the difference between now and the previously stored time
// is greater than the wait interval
if(millis() - time >= wait){
console.log(wait, "ms passed");
//if it is, do something
xOffset = xOffset + 1.5;
//also update the stored time
time = millis();
}
circle(xOffset, 150, 60);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
I'm not sure what the main purpose of the delay is:
is it to slow things down for debugging purposes
is to go into a series a states (e.g. ball moves up for 2s, then right
2s, etc.),
is to animate/smoothly interpolate between two positions within a given
time ?
Maybe something else completely ?
If you simply want to slow things down, perhaps it might be simpler to adjust the frameRate():
var xOffset = 0;
function setup() {
createCanvas(300, 300);
// update 1 frame every two seconds => 0.5 fps
frameRate(0.5);
}
function draw() {
background(220);
xOffset = xOffset + 1.5;
circle(xOffset, 150, 60);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Processing still has a delay() function, but p5.js doesn't.
Personally I'm not a fan of blocking behaviour like this and prefer the millis() options even though it's more verbose. That being said, if the program/demo you write is super simple delay() might just be enough.
Even if delay() is missing you could use js setTimeout() with a Promise, but that's getting into more advanced JS as Paul already mentioned:
var xOffset = 0;
function setup() {
createCanvas(300, 300);
// prevent p5's default draw() updates
noLoop();
}
function draw() {
background(220);
xOffset = xOffset + 1.5;
circle(xOffset, 150, 60);
// wait 2s then call draw() manually
delay(2000).then(draw);
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
Now, if you want to create a smooth animation from a start x offset to an end offset in a set amount of seconds you'd need a different approach.
You can find a p5.js example at the of this answer:
var startTime;
var duration = 2000;
var startValue = 0;
var endValue = 300;
var currentValue = startValue;
function setup(){
createCanvas(300, 300);
textAlign(RIGHT);
startTime = millis();
}
function draw(){
background(255);
moveCircle();
drawCircle();
}
function drawCircle() {
circle(currentValue, 150, 60);
}
function moveCircle(){
var progress = (float)(millis()-startTime)/duration;//millis()-startTime = difference in time from start until now
if(progress < 1.0) currentValue = startValue + (endValue * progress);//the current value is the final value scaled/multiplied by the ratio between the current duration of the update and the total duration
}
function mousePressed(){//reset value and time
currentValue = startValue;
startTime = millis();
}
function keyPressed(){//update duration
if(key == '-') if(duration > 0) duration -= 100;
if(key == '=' || key == '+') duration += 100;
console.log("duration: " + duration);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
And if you're comfortable using external libraries you could simply use a tweening library such as gsap:
var x = 0;
function setup(){
createCanvas(300, 300);
// animate "this" global object's x property to 300 in 2 seconds
gsap.to(this, {x: 300, duration: 2});
}
function draw(){
background(255);
circle(x, 150, 60);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.8.0/gsap.min.js"></script>
Notice the animation has a bit of easing (default ease out) which could be nice.
In JavaScript, unlike Scratch, there is not a good way to delay synchronous* code. The reason for this is that all the functionality of a webpage is run using a single thread. Which means that while there can be multiple sequences of instructions performing different pieces of functionality, only one of those sequences can execute at a time. Therefore if you did something to delay the execution of JavaScript within the draw() function, it would block all other functionality, making the browser tab unresponsive (and potentially causing the browser to halt your JavaScript altogether).
Instead of pausing a series of JavaScript statements like one would do in Scratch, it is necessary to either use the amount of time that has elapsed as part of a condition that determines whether some code should run (which is what the example George shared in the comments does), or to use the built in setTimeout() function to schedule some code to run some number of milliseconds in the future (but you would not want to call setTimeout() from draw() because it would repeatedly schedule the code every frame).
* note: there are also ways to create delays using asynchronous javascript code, but this is a more advanced topic

Processing saveFrame every 40 msec

I'm trying to create a graphic synchronized with a video at 25 frames/sec. I'm trying to save one frame every 40 msec, but I can't get 25 frames per sec, but only one image.
Can someone help me?
int t1;
int count;
void setup(){
size(400,100);
background(0);
stroke(255);
fill(250);
line(10,0,10,100);
line(260,0,260,100);
for (int i=10;i<251;i+=10){
t1=millis();
while(millis()-t1 < 40) {
count++;
}
rect(10,50,i,10);
//saveFrame("line-####.png");
}
}
void draw(){}
The problem in your code is that the canvas is updated only after the end of a frame, which means that your rectangles do exist but are not displayed until your setup() ends. This is why, even tho your code correctly waits 40 milliseconds before drawing a new rectangle, nothing is shown until the for loop ends: before ending the frame, Processing is waiting to complete the for loop.
However, in Processing draw() is called a certain amount of times per second, this amount of times is specified by the function frameRate() (default is 60).
Thus you can just set frameRate to 25 and save an image each time draw() is called.
noLoop() is used to stop calling draw(), in this case, once the rectangles are all drawn.
int count;
void setup()
{
frameRate(25);
size(400,100);
background(0);
stroke(255);
fill(250);
line(10,0,10,100);
line(260,0,260,100);
}
void draw()
{
rect(10,50,count,10);
saveFrame("line-####.png");
count += 10;
if(count > 251)
{
noLoop();
}
}

Processing - lines get bigger progressively

so I have in a file the coordinates and the seconds I want to make a line get bigger progressively. In the file, I have x1, x2 (regarding the first point coordinates), x2, y2 (2nd point coordinates), and the time (in seconds) I want to start growing the line, in the second point direction.
This is my code:
//TO READ LINES
import processing.video.*;
Movie myMovie;
Table table;
float duration, time;
int row_no=1;
int clickcount = 0;
void setup() {
size(640,480);
myMovie = new Movie(this, "draft.mov");
myMovie.loop();
table = loadTable("data/new.csv");
}
void draw() {
duration = myMovie.duration();
time = myMovie.time();
image(myMovie, 0, 0);
if(time>= table.getFloat(row_no, 4)){
strokeWeight(15);
stroke(255,14,255);
float a = table.getFloat(row_no, 0);
float b = table.getFloat(row_no,1);
line(table.getFloat(row_no,0),table.getFloat(row_no, 1), a, b);
a = a + 2;
b = b + 2;
}
}
// Called every time a new frame is available to read
void movieEvent(Movie m) {
m.read();
} `
As Niccolo advises, break your problem down first, take out anything you don't need and go one step at a time.
In terms or taking stuff out, based on the description of your goals, it doesn't sound like code has anything to do with playing back a movie, so take that code out to simplify. (The only reason I could think of for using a movie is to use it's current time to control the lines, but unless you want a movie background you shouldn't need that)
In the draw() loop there are a few things that look odd:
if(time>= table.getFloat(row_no, 4)){ assuming the 5th column in the .csv file holds the cue time for the current row in seconds, this condition will trigger only once potentially as there's nothing incrementing row_no
line(table.getFloat(row_no,0),table.getFloat(row_no, 1), a, b); isn't probably what you're after and might be a typo because a and b have retrieved from the same .csv columns (0 and 1), which means you're line's start and end position are in the exact position (therefore not rendering a line). perhaps you meant line(table.getFloat(row_no,2),table.getFloat(row_no, 3), a, b); ?
a = a + 2; and b = b + 2;: the x,y positions for one of the points may be offset by 2, but the new positions are never used past this point. In the next draw() iteration a and b are redefined, and therefore the offset is lost.
Let's go through breaking the problem down:
I have in a file the coordinates and the seconds I want to make a line get bigger progressively. In the file, I have x1, x2 (regarding the first point coordinates), x2, y2 (2nd point coordinates), and the time (in seconds) I want to start growing the line, in the second point direction.
load and parse the data (rows containing line coordinates (x1,y1,x2,y2) and time(in seconds))
"make a line get bigger progressively" - animate (interpolate) between the current line (.csv row coordinates) and the next line based on the specified time in seconds)
and even further, if starting from scratch, more as a "how to":
interpolate between one value an another (ignoring time for now, keeping task independent and as simple as possible)
keep track of time as a parameter for interpolating between values
parsing .csv rows
interpolating between 4 four values
incrementing .csv rows based on animation time
Luckily, Processing provides a built-in function for linearly interpolating between values lerp()(lerp = linear interpolation for short).
It takes three parameters:
a value to animate from (start)
a value to animate to (stop)
an interpolation amount (between 0.0 and 1.0)
and it returns one value: the value in between the start and stop values.
Think of the interpolation amount as a percentage (0 = 0%, 0.5 = 50%, 1.0 = 100%).
Here's a basic sketch to illustrate the concept:
void draw(){
background(255);
//map time to an interpolation normalized value
float t = map(mouseX,0,width,0.0,1.0);
//interpolate the values
float size = lerp(10,90,constrain(t,0.0,1.0));
ellipse(50,50,size,size);
}
the snippet a p5.js demo you can run bellow:
function setup() {
createCanvas(100,100);
}
function draw(){
background(255);
//map time to an interpolation normalized value
var t = map(mouseX,0,width,0.0,1.0);
//interpolate the values
var size = lerp(10,90,constrain(t,0.0,1.0));
ellipse(50,50,size,size);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>
if you move your mouse on the x axis you'll notice the size goes between 10 and 90 pixels in diameter based on the mouse position.
Step 1 done!
Next up, you can use millis() to keep track of time and simply map() between time in millis (mapping the current time between the start and end time to the 0.0 - 1.0 range):
float seconds = 3.5;
//the time in millis since the last update
int previousMillis;
//the current time in millis
int currentMillis;
//the time in millis until the next event
int nextMillis;
void setup(){
previousMillis = millis();
currentMillis = millis();
nextMillis = currentMillis + (int)(seconds * 1000);
}
void draw(){
background(255);
//update the current timer continously
currentMillis = millis();
//map the current time from the previous to the next time as a normalized value (0,0 to 1.0) range
float t = map(currentMillis,previousMillis,nextMillis,0.0,1.0);
//interpolate the values
float size = lerp(10,90,constrain(t,0.0,1.0));
ellipse(50,50,size,size);
}
and as a p5.js runnable demo:
var seconds = 3.5;
//the time in millis since the last update
var previousMillis;
//the current time in millis
var currentMillis;
//the time in millis until the next event
var nextMillis;
function setup(){
previousMillis = millis();
currentMillis = millis();
nextMillis = currentMillis + (int)(seconds * 1000);
}
function draw(){
background(255);
//update the current timer continously
currentMillis = millis();
//map the current time from the previous to the next time as a normalized value (0,0 to 1.0) range
var t = map(currentMillis,previousMillis,nextMillis,0.0,1.0);
//interpolate the values
var size = lerp(10,90,constrain(t,0.0,1.0));
ellipse(50,50,size,size);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>
That's step2 done and it looks like you've got a hand of step 3 (parsing the .csv values) already :)
Step 4 should be trivial once you understand how to interpolate one value: just do it 4 times for different variables!
Step 5 is simple as you simply need to check if row_no goes beyond the table's row count.
row_no = row_no + 1;
if(row_no > table.getRowCount()) row_no = 0;
One neat thing you could do is use the modulo operator(%) to do the same as a mathematical expression:
row_no = (row_no + 1) % table.getRowCount();
In conclusion, let's assume you're .csv file looks a little like this:
x1,y1,x2,y2,seconds
5,5,95,5,4
95,5,95,95,3
95,95,5,95,2
5,95,5,5,1
One way to put it all together would be something like this:
Table table;
int row_no = 0;
//the time in millis since the last update
int previousMillis;
//the current time in millis
int currentMillis;
//the time in millis until the next event
int nextMillis;
//where to animate the line from
float x1Start,y1Start,x2Start,y2Start;
//where to animate the line to
float x1Stop,y1Stop,x2Stop,y2Stop;
//currently interpolated line positions
float x1Lerp,y1Lerp,x2Lerp,y2Lerp;
void setup(){
size(100,100);
strokeWeight(3);
fill(0);
table = loadTable("data/new.csv","header, csv");
//printing the table in console, handy just for debugging/double checking values
println("data");
for(int i = 0 ; i <= table.getRowCount(); i++){
print(table.getColumnTitle(i)+"\t");
}
println();
for(int i = 0 ; i < table.getRowCount(); i++){
TableRow row = table.getRow(i);
for(int j = 0; j < row.getColumnCount(); j++){
print(row.getFloat(j) + "\t");
}
println();
}
//fetch lines and seconds from the current and next rows
updateFromRow();
}
void updateFromRow(){
//update times
previousMillis = millis();
currentMillis = millis();
//get the current row and it's line coordinates
TableRow currentRow = table.getRow(row_no);
x1Start = currentRow.getFloat("x1");
y1Start = currentRow.getFloat("y1");
x2Start = currentRow.getFloat("x2");
y2Start = currentRow.getFloat("y2");
//get the next row and it's line coordinates - notice % module is used to easily loop back to 0 once row_no goes beyond the number of table rows
TableRow nextRow = table.getRow((row_no + 1) % table.getRowCount());
x1Stop = nextRow.getFloat("x1");
y1Stop = nextRow.getFloat("y1");
x2Stop = nextRow.getFloat("x2");
y2Stop = nextRow.getFloat("y2");
//get the duration in seconds, convert it to millis( * 1000) and add it to the current millis
nextMillis = currentMillis + (int)(currentRow.getFloat("seconds") * 1000);
println("updated from row: " + row_no);
}
void draw(){
background(255);
//update the current timer continously
currentMillis = millis();
//map the current time from the previous to the next time as a normalized value (0,0 to 1.0) range
float t = map(currentMillis,previousMillis,nextMillis,0.0,1.0);
//if the current interpolation value is above 1.0
if(t > 1.0){
t = 0;
//increment the row
row_no++;
//if the current row counter is above the total number of rows, reset back 0
if(row_no >= table.getRowCount()){
row_no = 0;
}
//update values from incremented row (lines and their coordinates + time)
updateFromRow();
}
text("t:"+t,15,20);
//constrain interpolated value between 0.0 and 1.0
float interpolationAmount = constrain(t,0.0,1.0);
//linearly interpolate (lerp) between the current and next line coordinates
x1Lerp = lerp(x1Start,x1Stop,interpolationAmount);
y1Lerp = lerp(y1Start,y1Stop,interpolationAmount);
x2Lerp = lerp(x2Start,x2Stop,interpolationAmount);
y2Lerp = lerp(y2Start,y2Stop,interpolationAmount);
//finally, render the interpolated line
line(x1Lerp,y1Lerp,x2Lerp,y2Lerp);
}
In terms of keeping track of the data, the line coordinates can be stored using PVector instances (...the x,y components set() from .csv data and the line points can be interpolated in pairs via PVector's lerp()).
So far we've only been using linear interpolation, but you might also want to look into easing and tweening.

Hold noLoop() for certain amount of time

I'm attempting to create a very simple "whack-a-mole" type game, designed for students new to p5.js, and Processing in general.
Currently, I've created an array, and a random search within that array that randomly picks a square and makes it brown (a "mole", for now).
How do I make it so that after selecting a square, it stays there for a couple seconds, and then jumps to the next one, using basic p5?
I've managed to implement noLoop(), which can stop the search, but after a certain time I want it to resume.
Here's the code I have so far:
function setup() {
createCanvas(610,610)
}
function draw() {
var grid = []
for (var x = 0; x < 6; x += 1){
grid[x]=0;
for (var y = 0; y < 6; y += 1){
rand=round(random(360))
grid[x][y]=0
if (rand==0){
grid[x]=1
grid[y]=1
noLoop()
}
if (grid[x]==0 || grid[y]==0){
fill(76,153,0)
rect((x*100+10),(y*100+10),90,90)
}
if (grid[x]>0 && grid[y]>0){
fill(102,51,0)
rect((x*100+10),(y*100+10),90,90)
}
}
}
}
Instead of using noLoop(), you could keep looping at 60 frames per second, but then use the millis() function to keep track of the elapsed time.
Here's an example that shows a circle for 1 second whenever the user clicks:
var clickTime;
function mousePressed(){
clickTime = millis();
}
function draw() {
background(0);
if(millis() < clickTime + 1000){
ellipse(width/2, height/2, width/4, height/4);
}
}
Edit: Another approach is to use the % operator along with the frameCount variable in order to do something every X frames. This examples draws a circle in a random position every 60 frames:
function draw() {
if (frameCount % 60 == 0) {
background(0);
ellipse(random(width), random(height), width / 4, height / 4);
}
}

is highcharts able to render 1000 points per second?

recently I'm doing a project showing a spectrum.
Here is the official demo of dynamic update chart:
http://www.hcharts.cn/demo/highstock/dynamic-update
Now i wish to see if i could update 1000 points per second on the chart, specifically, execute addPoint() 1000 times over 1s. I wrote a chunk of code like this:
for(var i = 0; i < 1000; i++){
var x = (new Date()).getTime(), // current time
y = Math.round(Math.random() * 100);
series.addPoint([x, y], true, true);
console.log(count++);
}
soon i found it is unable to render on the web page. Then i console.log a variable, which started from 0 to 1000, after 200 it became very slow. Anyone who could give me a solution? thanks

Resources