I am making a platformer type game and need help on knowing how to delay the time before going downwards on the jump function i have tried the thread function and it didn't work I do have a question related to that but if there are any alternatives please let me know that would be very much appreciate it.
Here's a way to delay something without stopping the program. It's a class I wrote a long time ago, when I was still a student, so I'm not proud of it but I think that it's a good way to introduce someone to millis().
Long story short, this class will let you enter a number of milliseconds it will wait for and you can, in your loop, test to see if the delay is expired or not. Here's the class:
class Delay {
int limit;
Delay (int l) {
limit = millis() + l;
}
boolean expired () {
return millis() > limit;
}
}
And here's an example of a program waiting 5000 millis (5 seconds) after a mouse click before letting you click again. It's pretty self-explanatory, but don't hesitate to ask questions about it:
int count;
Delay delay;
void setup() {
size(400, 400);
delay = new Delay(0);
}
void draw() {
background(255);
//
if (!delay.expired()) {
fill(color(255, 0, 0));
rect(100, 100, 100, 100);
fill(0);
text("Time before click is allowed: " + (delay.limit - millis()), 20, 20);
}
text("Time since last click: " + (millis() - count), 20, 40);
}
void mouseClicked() {
// only lets you start a new delay if the last one is expired
if (delay.expired()) {
delay = new Delay(5000);
count = millis();
}
}
class Delay {
int limit;
Delay (int l) {
limit = millis() + l;
}
boolean expired () {
return millis() > limit;
}
}
Knowing how to time stuff is important, but timing stuff like jumps in a platformer often include other considerations, like touching the ground or not. Still, I hope that this will help you.
Have fun!
Related
I used Coroutine in Unity quite a lot in my projects, they are useful because they allow me to delay functions or do things every X seconds.
Now I know how to use them, but I don't really know what is happening in the background and I am wondering their impact on performances. Are coroutine low/fast ?
For exemple, doing things every few seconds could be done in the Update function, but it can also be done in a coroutine with WaitForSeconds or with yield return null. Are they all as efficient as the others ?
I wrote different ways here, which should do the job in theory. But which ones are the best ? If they are all the same, WaitForSeconds seems easier to read and I might prefer it.
Update way
private float shootInterval = 5f;
private float counterDeltaTime = 0f;
private void Update() {
counterDeltaTime += Time.deltaTime;
if (counterDeltaTime >= shootInterval) {
Shoot();
counterDeltaTime = 0;
}
}
Coroutine way
yield return new WaitForSeconds
private void Start() {
StartCoroutine(ShootEvery(5f));
}
private IEnumerator ShootEvery(float seconds) {
yield return new WaitForSeconds(seconds);
Shoot();
StartCoroutine(ShootEvery(seconds));
}
yield return null
private void Start() {
StartCoroutine(ShootEvery(5f));
}
private IEnumerator ShootEvery(float seconds) {
float dt = 0;
while(dt < seconds) {
yield return null;
dt += Time.deltaTime;
}
Shoot();
StartCoroutine(ShootEvery(5f));
}
Thanks for answers
I'm trying to create a program that does something, waits for a set amount of time does another thing, then waits again. However, what actually happens is the program waits at the beginning then does both things without any delay between them.
var start, current
function setup() {
createCanvas(500, 550);
}
function draw() {
background(220);
print('a');
wait(500);
print('b');
wait(500);
}
function wait(time)
{
start = millis()
do
{
current = millis();
}
while(current < start + time)
}
The draw() function is executed several times per seconds (around 60 times per second, see framerate in the doc). This is also what we call a "draw loop".
Your logic seems to be very sequential (do this, then wait and to that, then wait and do another thing...), and maybe you should consider an other flow for your program than the draw loop.
If you want animation, the easy answer would be to stick to the answer provided by Rabbid76.
(read and compare elapsed time millis every time the draw loop executes).
If you want one-time events (things that happen only once when a wanted duration is reached), you should look into Promises (or async-await functions), also known as asynchronicity.
This subject can be confusing for beginners, but is very important in javascript.
Here is an example:
(link with p5 editor)
// notice we are NOT using the draw() loop here
function setup()
{
createCanvas(400, 400);
background('tomato')
// try commenting-out one of these:
doScheduleThings();
doAsyncAwaitThings();
}
// you can wait for a Promise to return with the javascript 'then' keyword
// the function execution's is not stopped but each '.then(...)' schedules a function for when the Promise 'sleep(...)' is resolved
function doScheduleThings()
{
sleep(2000).then(function() {
fill('orange')
ellipse(30,30, 50, 50)
})
sleep(1000).then(function() {
fill('yellow')
ellipse(130,30, 50, 50)
})
}
// you can also wait for a Promise to return with an async-await function
// the function's execution is stopped while waiting for each Promise to resolve
async function doAsyncAwaitThings()
{
await sleep(4000)
fill('blue')
rect(200,200, 50, 50)
await sleep(1000)
fill('cyan')
rect(300,200, 50, 50)
}
// a custom 'sleep' or wait' function, that returns a Promise that resolves only after a timeout
function sleep(millisecondsDuration)
{
return new Promise((resolve) => {
setTimeout(resolve, millisecondsDuration);
})
}
You cannot wait in the draw callback. The canvas is just updated when after draw was executed. You must evaluate the time in draw:
function draw() {
background(220);
let ms = millis()
if (ms < 500) {
// [...]
}
else if (ms < 1000) {
// [...]
}
else {
// [...]
}
}
As mentioned, the problem in your attempt is that you're waiting inside the draw() loop. This doesn't work, because draw() is going to be called continually.
A simple way to do it is the following:
function setup() {
//...
}
let task_done = false;
let last_done = 0;
function draw() {
const delay = 1000 //ms
if(!task_done) {
/* do something */
doSomething();
task_done = true;
last_done = millis();
}
else {
if(millis() - last_done > delay) {
task_done = false;
}
}
}
function doSomething() {
//...
}
It only executes something every delay ms.
I am using code like this on a particle electron to report pulse counts from a flow meter on my kegerator to the particle cloud:
void meterInterrupt(void) {
detachInterrupt(pin);
ticks++;
cloudPending = 1;
attachInterrupt(pin, meterInterrupt, FALLING);
}
void publishStatus() {
if (!cloudPending) {
return;
}
cloudPending = 0;
getStatus(&statusMessage);
// status message contains number of ticks since last publish
bool published = Particle.publish("Ticks", statusMessage, PRIVATE);
if (published) {
resetMeters();
lastPublish = millis();
}
}
void loop() {
if ((millis() - lastPublish) >= 1000) {
publishStatus();
}
}
When I curl the event log into my terminal, I see two events for the first publish like so:
event: Ticks
data: {"data":"ticks:1","ttl":60,"published_at":"2018-07-03T22:35:01.008Z","coreid":"420052000351353337353037"}
event: hook-sent/Ticks
data: {"data":"","ttl":60,"published_at":"2018-07-03T22:35:01.130Z","coreid":"particle-internal"}
event: Ticks
data: {"data":"ticks:46","ttl":60,"published_at":"2018-07-03T22:35:01.193Z","coreid":"420052000351353337353037"}
event: hook-sent/Ticks
data: {"data":"","ttl":60,"published_at":"2018-07-03T22:35:01.303Z","coreid":"particle-internal"}
I don't see how this could happen. Why didn't it just report "ticks:47"? What am I missing?
UPDATE:
I did some further testing and noticed that Particle.publish is returning false the first time when it is actually completing successfully. Is this a timeout issue? The time difference between these publishes is only about 200ms.
OK, This is at least a partial answer.
It appears that Particle.publish is asynchronous. It returns the promise of an answer that starts out as false only eventually becomes true when/if the action is actually completed. If I wait an indeterminate amount of time (say delay(10)) after Particle.publish and before checking the return code, the return value will indicate the actual success or failure of the publish. My code cannot work because the ticks that are counted while I wait will be deleted when I reset the meters. WITH_ACK gives me the same behavior.
I will have to modify my code such that no ticks are lost during the long running Particle.publish . I am thinking that each statusMessage should go onto a list until it is ack'ed by the server.
FINAL ANSWER:
I modified the code to close the window during which I can receive ticks that will then be wiped out when I reset the counters. I do this by capturing the ticks into an array and then resetting the tick counter (meter). I am using a library called PublishQueueAsyncRK (cudos to rickkas7 This library is great!) so I can just fire it and forget it. Check it out on github.
void publishStatus() {
unsigned int counters[NUM_METERS];
unsigned int pending;
for (int i = 0; i < NUM_METERS; i++) {
meter_t *meter = &meters[i];
counters[i] = meter->ticks;
pending += counters[i];
resetMeter(i);
}
if (pending) {
String statusReport;
for (int i = 0; i < NUM_METERS; i++) {
statusReport.concat(String::format("%i:%u|", i+1, counters[i]));
}
publishReport(statusReport);
lastPublished = millis();
}
}
void publishReport(String report) {
if (report != "") {
publishQueue.publish("PourLittleTicks", report, PRIVATE);
}
}
void loop() {
if ((millis() - lastPublished) >= PUBLISH_INTERVAL) {
publishStatus();
}
}
I'm currently working on a project in which I want an image to pop up after 3 seconds. Once that image has popped up the user has to click on the image to make a "done" image pop up that will disappear automatically after 3 seconds.
I've got most of it working except for the disappearing part. Does anyone know how I can time the image to disappear after 3 seconds?
PImage medic;
PImage medicD;
float time;
float startTime;
final int waitpopup = 3000;
final int DISPLAY_DURATION = 3000;
boolean showimage = true;
boolean showclock = true;
boolean showimagedone = true;
boolean hasClicked;
Clock clock;
void setup (){
size (1080, 1920);
medic = loadImage("medic.png");
medicD = loadImage("medicD.png");
clock = new Clock(width /2, height /2);
time = millis();
}
void draw() {
background (0);
imageMode(CENTER);
if (showclock) clock.display();
if (showimage && millis() - time > waitpopup) {
image(medic, width/2, height/2, 540, 540);
} if (hasClicked == true) {
showimage = false;
image(medicD, width/2, height/2, 540, 540);
} if (millis() > startTime + DISPLAY_DURATION) {
showimagedone = false;
}
}
void mousePressed() {
hasClicked = true;
startTime = time;
}
You can use the millis() function or the frameCount variable to check how much time has gone by, then do something after X seconds or after X frames.
You're already doing some of the work with the showimagedone variable, but you need to use that variable to conditionally draw your image.
I recommend starting with a simpler example and getting that working. Here's one example:
int clickedFrame;
boolean on = false;
int duration = 60;
void draw(){
if(on){
background(255);
if(frameCount > clickedFrame + duration){
on = false;
}
}
else{
background(0);
}
}
void mousePressed(){
clickedFrame = frameCount;
on = true;
}
This code show a white background for one second whenever the user clicks the mouse. You need to do something similar with your images.
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 Processing reference for more information.
If you still can't get it working, please post a MCVE (not your full project!) in a new question and we'll go from there. Good luck.
I know this might already have been answered, but all the places where i found it, it wouldn't work properly. I'm making a game in Greenfoot and I'm having an issue. So I'm generating a random number every time a counter reaches 600, and then testing if that randomly generated number is equal to 1, and if it is, it creates an object. For some reason, the object will be created every time the counter reaches 600. I'm somewhat new to Java so it's probably something simple.
import greenfoot.*;
import java.util.Random;
/**
* Write a description of class Level_One here.
*
* #CuddlySpartan
*/
public class Level_One extends World
{
Counter counter = new Counter();
/**
* Constructor for objects of class Level_One.
*
*/
public Level_One()
{
super(750, 750, 1);
prepare();
}
public Counter getCounter()
{
return counter;
}
private void prepare()
{
addObject(counter, 150, 40);
Ninad ninad = new Ninad();
addObject(ninad, getWidth()/2, getHeight()/2);
Fail fail = new Fail();
addObject(fail, Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
private int spawnCounter = 0;
private int invincibleCounter = 0;
Random random = new Random();
private int randomNumber;
public void act()
{
controls();
{if (spawnCounter > 500) {
spawnCounter = 0;
addObject(new Fail(), Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
spawnCounter++;
{if (spawnCounterTwo > 300) {
spawnCounterTwo = 0;
addObject(new APlus(), Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
spawnCounterTwo++;
}
if (invincibleCounter > 600)
{
int randomNumber = random.nextInt(10);
if (randomNumber == 1)
{
Invincible invincible = new Invincible();
addObject(invincible, Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
invincibleCounter = 0;
}
if (randomNumber == 2)
{
Storm storm = new Storm();
addObject(storm, Greenfoot.getRandomNumber(getWidth()), Greenfoot.getRandomNumber(getHeight()));
}
else
{
}
}
invincibleCounter ++;
}
}
private int spawnCounterTwo = 100;
public void controls()
{
if (Greenfoot.isKeyDown("escape"))
{
Greenfoot.stop();
}
}
}
I'm not getting errors as it is compiling fine, but when i run it i have issues. Any help? Thanks in advance!
This is only speculation, since I cannot see the rest of your code, but I suspect that you are seeding your random number generator with some constant number. So every time you run your program, the random number generator generates numbers in the same order. In order to confirm this, please show some more code.
Also, your brackets do not match, so at least please show enough code to have matching curly braces.
Are you sure it is created exactly when the counter hits 600? You're incrementing the counter every frame, and at the default ~30 fps speed, that's twenty seconds. Then every frame after that, you're getting a random integer and have a 10% chance to make an Invincible. But 10% chance will on average come up within ten frames, which is 1/3 of a second. Then the counter will reset and you'll wait twenty more seconds, then create an Invincible within the next second, and so on. If you want a 10% chance every 20 seconds, you need to reset the Counter in the else branch, as well as the "then" branch (or just reset it just inside your very first if).