Is there a way to have a delay in between code in p5.js - 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

Related

how do you make things random only once per time drawn in p5?

I am trying to make my variable random once per time drawn
It's not clear why this warrants a question on StackOverflow, simply assign the variable a random value in the your draw() function. One way to do this is using the random().
let x;
function setup() {
createCanvas(windowWidth, windowHeight);
// slow down the frame rate so the circle doesn't jump around so quickly.
frameRate(2);
}
function draw() {
background(220);
x = random(0, width);
circle(x, height / 2, 40);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

how to interpolate between two consecutive points with a smooth curve in p5.js

I intend to have an ellipse move smoothly between the stop points while keep rotating. It'll rotate for 1sec at point (20,50), transition to (40,70) on a smooth curve (bezier or random polynomial) and rotate till 3sec and move on to (160,190)
The current issue is that it jumps between stop points rather than move smoothly.
var angle=0;
var x=[20,40,160] // x coordinates for stop points
var y=[50,70,190] // y coordinates for stop points
var t=[1000,2000,4000] // time for stop points
var i=0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
frameRate(30);
translate(x[i],y[i]);
rotate(angle);
if (millis() >= t[i] & millis() < t[i+1]){
i+=1
}
fill(0);
ellipse(0,0, 20, 80);
angle++
}
There are a lot of different ways to do this, and which approach you take depends on exactly how you want your code to behave.
Similar to the answer to your last question, you need to show the movement between the points.
Right now you're moving directly from one point to another. You need to show the intermediate steps.
Here are a few things to look into:
The frameCount variable holds the current frame number. This is useful for exact timing of behaviors that you want to trigger on specific frames.
The millis() function returns the number of milliseconds the sketch has been running. This is useful for duration-based logic, where you want to do something after a certain number of seconds.
The lerp() function allows you to calculate values that change over time.
You could also use delta values, where you move the X and Y values by some amount each frame.
Here's an example of that last approach:
var circleX = 20;
var circleY = 20;
var mode = 'move right';
function setup() {
createCanvas(400, 400);
}
function draw() {
background(200);
ellipse(circleX, circleY, 20, 20);
if (mode == 'move right') {
circleX++;
if (dist(circleX, circleY, 380, 20) < 1) {
mode = 'move down';
}
} else if (mode == 'move down') {
circleY++;
if (dist(circleX, circleY, 380, 380) < 1) {
mode = 'move left';
}
} else if (mode == 'move left') {
circleX--;
if (dist(circleX, circleY, 20, 380) < 1) {
mode = 'move up';
}
} else if (mode == 'move up') {
circleY--;
if (dist(circleX, circleY, 20, 20) < 1) {
mode = 'move right';
}
}
}
But please note that this code is just an example, and there's a ton of room for improvement here. The important thing is that you need to move the scene a little bit each frame, instead of going directly from one point to another.

p5.js Beginner - RNG not working

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.

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);
}
}

Animate rotation in Unity3d

I'm working on a 2D game in Unity3D (using Orthello 2D).
Since I switched from Cocos2d and CoronaSDK, I'm wondering if there's a way of implementing the following behaviour for a sprite (or any Unity3D object) as it worked in Corona:
object = ...
transition.to ( object, { time = 1000, rotation = object.rotation + 100, onComplete = function ()
// do something
end })
So a sprite rotates by 100 degrees over 1 second.
In my script attached to a sprite I can have a rotation in my Update () function, but it's a bit different approach...
You can do it easily in an Update function.
float timer = 0f;
void Update()
{
if(timer <= 1)
{
// Time.deltaTime*100 will make sure we are moving at a constant speed of 100 per second
transform.Rotate(0f,0f,Time.deltaTime*100);
// Increment the timer so we know when to stop
timer += Time.deltaTime;
}
}
If you need to do another 100 degrees rotation you will just have to reset the timer.
You can see different version of the Rotate function here and more information about the lifesaver Time.deltaTime value here
There are several differnt ways of doing that. For example using a coroutine:
IEnumerator TweenRotation(Transform trans, Quaternion destRot, float speed, float threshold )
{
float angleDist = Quaternion.Angle(trans.rotation, destRot);
while (angleDist > threshold)
{
trans.rotation = Quaternion.RotateTowards(trans.rotation, destRot, Time.deltaTime * speed);
yield return null;
float angleDist = Quaternion.Angle(trans.rotation, destRot);
}
}

Resources