We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello.
I am coding a very simple game where you are controlling a green square that must get to the end of a maze as fast as possible. There is a timer that counts up when you start. I would like the timer to stop counting when you reach the end, and reset when you press 'V'. Also, when 'V' is pressed, I would like to reset the position of the green square. Can anyone help me with the code?
Thank you.
Answers
Post your code if you need more help.
https://Forum.Processing.org/two/discussion/26248/how-to-make-a-timer-in-processing#Item_5
Here is the code
/* Press 'q' to move up. Press 's' to move down. Press 'u' to move left. Press 'i' to move right. Press 'v' to restart. Get to the end as fast as possible. If you go on to the red areas, you will fail. */
float x = 10; float y = 380;
void setup(){ size(400,400); frameRate(60); }
void draw(){ background(255,0,0); fill(0,255,255); rect(0,200,30,201); rect(30,200,320,30); rect(80,200,20,-100); rect(100,100,30,20); rect(130,100,20,50); rect(150,130,20,20); rect(170,150,20,-100); rect(170,50,-50,20); rect(120,70,-20,-70);
if(x > 20 && y > 221){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 340 && y < 221 && y > 192){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 180 && y < 200){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 90 && x < 180 && y < 200 && y > 140){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 90 && x < 130 && y < 140 && y > 110){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 110 && x < 180 && y < 50 && y > 0){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > -1 && x < 80 && y < 200 && y > -1){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 80 && x < 100 && y < 100 && y > -1){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 100 && x < 170 && y < 100 && y > 60){ fill(255); textSize(140); text("FAIL",60,370); }
if(x > 140 && x < 170 && y > 100 && y < 130){ fill(255); textSize(140); text("FAIL",60,370); }
int sec = millis()/1000; fill(255); textSize(26); text(sec,300,30);
if(keyPressed){ if(key == 'v'||key == 'V'){ x = 10; y = 380; } }
if(y <2){
}
fill(0,255,0); rect(x,y,10,10);
if(keyPressed){ if(key == 'q'||key == 'Q'){ y = y - 1; } }
if(keyPressed){ if(key == 's'||key == 'S'){ y = y + 1; } }
if(keyPressed){ if(key == 'u'||key == 'U'){ x = x - 1; } }
if(keyPressed){ if(key == 'i'||key == 'I'){ x = x + 1; } }
if(x > width-10 ){ x = width-10; }
if(x < 0 ){ x = 0; }
if(y > height-10 ){ y = height-10; }
if(y < 0){ y = 0; } }
I did not create the class "green_square". Do I have to create it? Right now it is just a rectangle. I also did not create the class "timer".
Also, I would like the code to be like:
if(keyPressed){ if(key == 'v'||key == 'V'){ (The required code) } }
I am a little new to Java, by the way, so I really appreciate your patience.
TfGuy44, how did you copy/paste your code together with the line numbers and formatting?
Edit post, highlight code, press ctrl-o to format.
There's a sticky post that tells you exactly how to format things, but the above is usually enough.
Your code is very WET. WET stands for Write Everything Twice. WET stands for Write Everything Twice. WET stands for Write Everything Twice. Whoops, that's three times. Whoops, that's three times.
If you want to change something later, you have to change it in multiple places. If you want to change something later, you have to change it in multiple places.
You should try to write DRY code. You should try to write DRY code. DRY stands for Don't Repeat Yourself.
WET bad. DRY good.
For example:
You have this pattern a lot in your code. A check if the fail message should appear, then drawing the fail message. But you can DRY this WET code out, and have it so you only draw the fail message in one place:
Anyway, we'll get back to this in a bit... Let's address your timer issue first.
This is the timer's code:
The first line determines what value the timer is going to display. The rest draw that value. So we need to make sure we are setting the value for
sec
properly.What is this value? Well, it's supposed to be the number of seconds since the sketch started, right? Not exactly. It's really supposed to be the number of seconds SINCE THE TIMER RESET.
So, how do we know when the timer reset? Well, how do we know a time at all in a sketch? Ah ha! We have the function
millis()
that tells us how many milliseconds have passed since the sketch started! If we remember how many milliseconds had passed when the timer reset, we can use that value later to determine how many more milliseconds have passed since then.We'll need a new variable to remember when the reset happened.
So what happens when we reset? Well, we just record the current time.
So now we need to work out how many milliseconds have elapsed between when we reset (
count_at_reset
) and now (millis()
). That means we take the difference... subtract!And then convert that from milliseconds to seconds.
Try it! Post the new version of the code in a new post and we can tidy some more things up maybe...
Thank you, koogs
Idk where I had to put
void reset()
, so I just put it inside ofdraw()
. When I run the code, processing will say > unexpected token : void> . What's wrong with the code? Please help me fix it. Btw, I also did the DRYing.First, before anything else, please indent your code so it looks like code. Just press Ctrl + t in the editor to do this:
Next, let's learn about functions. Two of the built-in functions that processing knows about are
setup()
anddraw()
. First, Processing runssetup()
. Then Processing runsdraw()
forever. But there are other functions it can know about too. One good one to look into is `keyPressed().The thing about functions is that they can return values. For example:
This is simple addition. The function takes two numbers -
a
andb
- and returns their sum. We know that they are numbers because the wordint
before each of their names means that each is an integer. This is the type of thing that they are. Also notice that the function itself has the wordint
before it - this means that this function returns a number.Functions do not have to return anything. But they still need to have the type of thing that they return before their name. That's what
void
does - it means that this function doesn't return anything.Now that we know about functions, we can write our own! You said you didn't know where to put "the void reset()". Hopefully now it is clear that this "void reset()" is a NEW function that you are creating. It doesn't return any values, so the return type is
void
. The function's name isreset()
. You would put this at the same "level" as all the other function - NOT inside another one!You have DRYed out your code a little, I see, but there is still more to do. For one thing, you still have this line in there three times:
Even having it in there twice is repeating yourself! Can you make it so you only have this line in there once?
I understand that
void reset()
is a separate function and must go outside of draw. But no matter where I put it, I still cannot get the timer to reset. Can you help me fix the code? Also, I would like it if you could also help me stop the timer once the green square reaches the top.A
Here's a working example of a timer without a maze. Please understand it and try to incorporate it into your code to get your timer working. Post your attempt, or a version with a working timer if you have other issues you want to address.
I tried it in my processing sketch, but still it didn't work. Then I opened a new processing sketch and copy/pasted the code so I could experiment a little. It worked perfectly with no changes. I changed
void mousePressed
toif(keyPressed){
so that I could put it invoid()
. Then it didn't work. What's going on?The changes you've posted seem to work fine to me.
This simple timer now resets when
v
is pressed.If you're having trouble incorporating it into your other code, we need you to post the code of your attempt to help you resolve it.
Still not working. Can you please copy my code then fix it? I'm doing what you're doing except in a different way so that it will be in my preferences but it's still not working.
better use keyPressed() as a function because it registers a key only once
What is a timer?
You have to understand the principle of the timer to be able to build the timer into your code.
millis() runs on and on from the start of your code
so it's 1000, 2000, 3500, goes on
when you click "v" we want to restart.
But millis() is still running 11000, 13000....
So millis is not our friend here.
So we need a trick.
The trick is that we take the moment "v" is pressed (let's say at 11000 millis) and measure the time since then.
The core idea is to measure the time since then.
What's this "since then" in practice?
First of all :
Here we measure the time when v is pressed:
so you got to call
reset()
whenever v is pressed (or when you want a reset of time, e.g. at the end ofsetup()
)count_at_reset is now 11000 millis
BUT you need to use
count_at_reset
.The line to use the count_at_reset is that line
int difference = millis() - count_at_reset;
It gives you the time since we last pressed v / used the function
reset()
.Because
millis()
is now let's 32000 and count_at_reset is still 11000 millis so difference = 32000 - 11000 = 21000 millis since last "v". Good.so instead of
you want
What to do next
understand this
build that into your code
hit ctrl-t
and post your entire code here
I did that here but I am not gonna post your code...
Chrisir ;-)
It's important that you post your attempt as it is when you can't get something to work, because then TFguy44 or chrisir can point out your mistakes for you and help you correct those mistakes. If you do that they will also tell you why that thing is wrong and how you can do it better or differently. Then you never have to do that mistake again. But if you just post some code and expect someone else to just implement the rest of your idea, then you'll never learn not to do those mistakes, and you won't learn to know your own code.
THANK YOUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU but I'm not done yet (sorry). Now I would like you to help me stop the timer when the green square reaches the top.
First you need to register if the player has reached the target
So write something like this with right numbers:
now obviously when this Boolean variable that you define before setup as false becomes now true line 82 is not allowed to be executed
Make difference also a global variable
When done or questions hit ctrl-t and post entire code
Also later your game needs a state structure: your states are game, fail and targetReached
OK. So I've created the boolean to determine whether the player has reached the end or not. For now, I just made it so that if the boolean is true, then draw a rectangle. Of course I would want to make it so that the timer would stop instead. Could you help me with that? Thank you.
When true line 82 is not allowed to be executed
TfGuy44, I want to display the saved time. But how? Thank you.
Draw it! Use
text()
!you already display the saved time in line 86, just stop 82
as said int difference; before setup
I advised you to hit ctrl-t and post entire code.
You haven't done this and now again we talk about code we don't see.
how is it going? post your code?
Managed to draw the text, but I don't know how to stop it from updating. Could you help me with that?
Why don’t you try what I wrote about line 82 and difference??????
Sorry, I actually don't understand what you mean. Could you explain it in a different way? I'm still learning the basics, so I hope you will be patient for me.
sure:
you have to understand the principles and which line is doing what.
So in these lines there is all you need. Have you understood these lines?
Now falsely you added
Which is almost the SAME as above. Completely useless.
instead of using
if (!endReached ) {
in the first section you copied the section and implementedif (!endReached ) {
. That's wrong.Funny
NOT what I told you to do.
but now just delete this :
and keep this:
remember to hit ctrl-t
VERSION WITH STATES - FOR LATER !!!!!!!!!!
here is the version with states I keep speaking about.
As written, you need the states "normal play", "fail" and "WON".
It follows the standard wasd keys now
https://en.wikipedia.org/wiki/Arrow_keys#WASD_keys
the tunnel has now no black lines in it anymore
reminds me of a mole in its mole tunnels by the way - funny!
Congratulations to a cool game!
Best, Chrisir ;-)
Thanks, Chrisir. I have done what you said but if I get rid of these lines of code:
there will be an error: the variable "difference" does not exist. What should I do? Here is the entire code:
As I mentioned a few times now: define
difference
beforesetup()
Chrisir, I am very sorry but it is way too complicated for me. Could you make it simpler? Thank you. By the way, I changed the wasd keys to qusi keys as that is how I would like it to be. Could you also make this line of code:
in
if(keyPressed){
?the state approach is a new approach to replace the variables show_message and endReached
You should easily comprehend this concept if I't explain it
But for now
But for now, let's stick with the previous sketch version
You wrote:
I wrote:
Have you done this? In the old version not in the new approach with state
I don't understand because you are seeing it in a different order from what I see. It just confuses me a lot. I need to go now. I'll come back tomorrow.
+++++ TRADITIONAL VERSION WITHOUT STATES ++++++++
Version without states and corrected
difference
andsec
situation:Thank you very much. But if it is not too much trouble, could you make it so that the are states, but with simpler code?
I showed you how to make it with states.
Why don't YOU give it a try?
I don't see much coming from your site recently. The last task to display the time after
endReached
was really simple.Thank you Chrisir, TfGuy44, koogs, Eeyorelife and GoToLoop. I am very grateful for all of you. But I still don't understand all of the code. Chrisir, how did you get the timer and position of the green square to stop when the state is FAIL or WON? I really don't know. Can you show me the line(s) of code and then explain it, so that if I do something like this again, I won't need help. Btw, I also changed the code a little bit so that only the keys "qsuvi" will be used
We still talk about two different approaches now in parallel.
But anyway, you refer to the version with states, and so do I.
What I did
First to make
draw()
leaner I made a few things into functions with good names. Modularization is an important principle in programming.Then I wanted to have everything dictated by variable
state
so the program knows if we are in state play, fail or EndReached.For that purpose, I first moved everything from your
draw()
into the new functiondrawForNormal()
.Then I made
draw()
so that state dictates everything that happens. (switch()
is likeif(state==...else if(state==... else if(state==....
).draw()
is very short and nice:You asked
green square to stop
That's simple; the key inputs are registered in the function
inputs()
. I simply don't call it from drawForWon() but I call it from drawForNormal() and drawForFail().So it stops in state Won.
timer to stop
Similarly I have those lines in drawForNormal()
and I give them out using
text()
. So it changes all the time.On the other hand, I don't have these lines in drawForWon() but I still display
sec
usingtext()
. Sincesec
is global variable it has the value in drawForWon() it had the last time.Conclusion
The variable
state
dictates it all. So instead of usingendReached
ormessage
we just change the state.Remark
In these lines,
the check x > width is missing (y<0 would be target I guess)
Thank you very much. But when will this line of code do its thing?
never
but if you treat state false it could receive an unknown value and then this line will report an error
It’s just good practice to have a default section in switch as it is to have an else section in if else if....
When you change something in your code and make a mistake that effects state the message would appear and you instantly know what’s wrong.
Otherwise you would look for ages
Thank you very much, Chrisir.
;-)
Of course I have another question. Why aren't these lines of code working?
It's meant to be an easter egg.