The whole script would be preferable in this case. I anyway went ahead because it is fun.
What I would implement is what is known as a finite state machine. Your program can be in one of a number of states. What I described in post #19 are the states. You can place those states in an enum
to give them sensible names.
// states that our application can be in
enum FSM
{
WAITTRIGGER,
GROW,
HOLD,
SHRINK,
COMPLETE
};
// variable to hold the current application state
FSM applicationState = FSM.WAITTRIGGER;
For the understanding of this post, an enum
is nothing more than a list of options. The variable applicationState
can only have those options.
In the draw()
method you can implement the state machine; the framework can look like below making use of a switch/case.
void draw()
{
background(0xFF404040);
switch(applicationState)
{
case WAITTRIGGER:
break;
case GROW:
break;
case HOLD:
break;
case SHRINK:
break;
case COMPLETE:
break;
}
}
The intention is that once a step is complete, you go to another step. E.g. in WAITTRIGGER
you can go to GROW
when the mouse is pressed.
case WAITTRIGGER:
if(mousePressed == true)
{
applicationState = FSM.GROW;
}
break;
For the implementation, I have written methods for each state; this keeps draw()
quite clean. Below the framework
// states that our application can be in
enum FSM
{
WAITTRIGGER,
GROW,
HOLD,
SHRINK,
COMPLETE
};
// variable to hold the current application state
FSM applicationState = FSM.WAITTRIGGER;
// diameter of circle to dislay
int diameter = 0;
// max diameter
int maxDiameter = 750;
// speed at which the circle must grow / shrink
int speed = 14;
// last time that ellipse was updated
int lastCycleTime;
// modify circle every 10 ms
int cycleInterval = 10;
// keep track when circle reached maximum size
int waitStartTime;
// keep circle at maximum size for 5 seconds
int waitDuration = 2000;
// flag
boolean isMax = false;
int clickTime = 0; // Variable to store the time of the click
boolean clicked = false; // Indicator variable to check if a click has occurred
// remember the last state of the mouse
boolean lastMouseState = false;
void setup()
{
size(900, 900);
}
void draw()
{
background(0xFF404040);
switch(applicationState)
{
case WAITTRIGGER:
waitTrigger();
break;
case GROW:
grow();
break;
case HOLD:
hold();
break;
case SHRINK:
shrink();
break;
case COMPLETE:
complete();
break;
}
}
void waitTrigger()
{
}
void grow()
{
}
void hold()
{
}
void shrink()
{
}
void complete()
{
}
And we can start implementing those methods. Below is the full code. See if you can follow the approach; if not, ask !
Notes:
- When switching state, you set the variables that need changing for the next state. In above, in
waitTrigger()
we set theclickTime
so we can display the lapsed time. - The above methods change the state when needed.
- The above (main) methods handle (switching of) the state machine states; except for
complete()
. they call another method that does the actual work. - You can write a method called e.g.
fsm()
that contains the below content ofdraw()
and call that method from draw to keepdraw()
even cleaner. At this stage I don’t consider that necessary; it will become necessary when the size ofdraw()
grows out of hand and/or additional functionality is added todraw()
.
// states that our application can be in
enum FSM
{
WAITTRIGGER,
GROW,
HOLD,
SHRINK,
COMPLETE
};
// variable to hold the current application state
FSM applicationState = FSM.WAITTRIGGER;
// diameter of circle to dislay
int diameter = 0;
// max diameter
int maxDiameter = 750;
// speed at which the circle must grow / shrink
int speed = 14;
// last time that ellipse was updated
int lastCycleTime;
// modify circle every 10 ms
int cycleInterval = 10;
// keep track when circle reached maximum size
int waitStartTime;
// keep circle at maximum size for 5 seconds
int waitDuration = 2000;
// flag
boolean isMax = false;
int clickTime = 0; // Variable to store the time of the click
boolean clicked = false; // Indicator variable to check if a click has occurred
// remember the last state of the mouse
boolean lastMouseState = false;
void setup()
{
size(900, 900);
}
void draw()
{
background(0xFF404040);
switch(applicationState)
{
case WAITTRIGGER:
waitTrigger();
break;
case GROW:
grow();
break;
case HOLD:
hold();
break;
case SHRINK:
shrink();
break;
case COMPLETE:
complete();
break;
}
}
//////////////////////////////////////////////////////////////
// Finite state machine main methods
//////////////////////////////////////////////////////////////
/*
Finite state machine: wait for trigger
*/
void waitTrigger()
{
// wait for a change in state of the mouse
if (mousePressed != lastMouseState)
{
// remember the last mouse state
lastMouseState = mousePressed;
// if the state went from not pressed to pressed
if (mousePressed == true)
{
println("[WAITTRIGGER]Mouse pressed: Switching to GROW");
applicationState = FSM.GROW;
// setting the variables
clickTime = millis();
} //
else
{
println("[WAITTRIGGER]Mouse released");
}
}
}
/*
Finite state machine: grow circle
*/
void grow()
{
// display lapsed time
zeitangabe();
// grow the circle till it reached the maximum size
if (growCircle() == true)
{
println("[GROW]Complete: Switching to HOLD");
applicationState = FSM.HOLD;
// setting the variables
waitStartTime = millis();
println("delay started @ " + str(waitStartTime));
}
// if the mouse was released
if (mousePressed == false)
{
println("[GROW]Mouse released: Switching to COMPLETE");
applicationState = FSM.COMPLETE;
}
}
/*
Finite state machine: hold circle for a while
*/
void hold()
{
// display lapsed time
zeitangabe();
// draw circle till hold time lapsed
if (holdCircle() == true)
{
println("[HOLD]Complete: Switching to HOLD");
applicationState = FSM.SHRINK;
}
// if the mouse was released
if (mousePressed == false)
{
println("[HOLD]Mouse released: Switching to COMPLETE");
applicationState = FSM.COMPLETE;
}
}
/*
Finite state machine: shrink circle
*/
void shrink()
{
// display lapsed time
zeitangabe();
// shrink the circle till it reached the minimum size
if (shrinkCircle() == true)
{
println("[SHRINK]Complete: Switching to COMPLETE");
applicationState = FSM.COMPLETE;
}
// if the mouse was released
if (mousePressed == false)
{
println("[SHRINK]Mouse released: Switching to COMPLETE");
applicationState = FSM.COMPLETE;
}
}
/*
Finite state machine: process complete
*/
void complete()
{
diameter = 0;
println("[COMPLETE]Process complete: Switching to WAITTRIGGER");
applicationState = FSM.WAITTRIGGER;
}
//////////////////////////////////////////////////////////////
// Finite state machine helpers
//////////////////////////////////////////////////////////////
/*
Grow circle
Returns:
true when circle has reached maximum size, else false
*/
boolean growCircle()
{
// return value
boolean rb = false;
// draw ellipse
drawCircle();
// if it's time to update it
if (millis() - lastCycleTime >= cycleInterval)
{
// remember the time that we did update
lastCycleTime = millis();
// grow ellipse for the next update
diameter += speed;
}
if (diameter >= maxDiameter)
{
rb = true;
}
return rb;
}
/*
Shrink circle
Returns:
true when circle has reached minimum size, else false
*/
boolean shrinkCircle()
{
// return value
boolean rb = false;
// draw ellipse
drawCircle();
// if it's time to update it
if (millis() - lastCycleTime >= cycleInterval)
{
// remember the time that we did update
lastCycleTime = millis();
// shrink ellipse for the next update
diameter -= speed;
}
if (diameter < 0)
{
rb = true;
}
return rb;
}
/*
Hold circle
Returns:
true when time to hold circle has lapsed, else false
*/
boolean holdCircle()
{
boolean rb = false;
// draw circle with the last diameter
drawCircle();
if (millis() - waitStartTime >= waitDuration)
{
rb = true;
println("delay lapsed @ " + str(millis()));
}
return rb;
}
/*
Draw the circle
*/
void drawCircle()
{
fill(0xFF000000);
ellipse(width / 2, height / 2, diameter, diameter);
}
//////////////////////////////////////////////////////////////
// Other methods
//////////////////////////////////////////////////////////////
/*
Display lapsed time
*/
void zeitangabe()
{
long elapsedTime = millis() - clickTime;
fill(255);
textAlign(CENTER);
textSize(24);
text("Time elapsed: " + elapsedTime + " ms", width / 2, 50);
}