Explanation of the code that went into the Chess Clock
Link to the Chess clock post
This is a very long post but for those of you who are interested – it should be a helpful read.
In this project we have seven places to put some code.
- onEnter Action
- Left Button
- Right Button
- Up Button
- Down Button
- Stop (S) Button
- Reset (R) Button
We are also using four variables that are made in Captivate in order to be displayed.
- The variable m1 for the minutes on the left clock
- The variable s1 for the seconds on the left clock
- The variable m2 for the minutes on the right clock
- The variable s2 for the seconds on the right clock
Let’s take a look at the code for each of these areas.
Number 1: onEnter Action
There is quite a bit happening in the onEnter Action, primarily because it is where we define all of our functions as well. I will share the code a little bit at a time and follow it up by an explanation. There are basically a few lines at the beginning for activity prep and then four functions.
- cp.disable(“clickL”);
- cp.disable(“clickR”);
- cp.disable(“stopBtn”);
- var clock1;
- var clock2;
- checkDigits();
- checkDigits2();
These lines are all activity prep. So – as soon as we enter the slide, we are going to do the following.
- Disable the button named “clickL”. This is the top clock button on the left.
- Disable the button named “clickR”. This is the top clock button on the right.
- Disable the button named “stopBtn”. This is the (S) button on the right side.
- Declare the variable for clock1. This is the clock on the left.
- Declare the variable for clock2. This is the clock on the right.
- Call the checkDigits() This function takes care of the left clock leading zeroes.
- Call the checkDigits2() This function takes care of the right clock leading zeroes.
In essence – when the page is first launched, the default state is that the clock is not running and is set for zero time and both top buttons are at their mid-point which is where neither clock runs. We disable a few buttons until other conditions are met first. The top two buttons cannot be tapped until a time has been provided. The stop button is disabled because time is not running.
The two clock variables are used with our two timer functions so that we can perform a clearTimeout (more on that later).
Finally, we call two functions to check the digits on both clocks and convert them to show both zeroes. Captivate will strip out leading zeroes and only display one and for the time, I wanted the seconds to always show two digits so if there was 5 seconds left, for example, the display would read 0 : 05 instead of 0 : 5. In the default state we want to see 0 : 00 in each display.
Here is how the checkDigits() function looks.
1 function checkDigits() {
2 s1=s1.toString();
3 if (s1==0) {
4 s1=”00″;
5 }
6 if (s1==1) {
7 s1=”01″;
8 }
9 if (s1==2) {
10 s1=”02″;
11 }
12 if (s1==3) {
13 s1=”03″;
14 }
15 if (s1==4) {
16 s1=”04″;
17 }
18 if (s1==5) {
19 s1=”05″;
20 }
21 if (s1==6) {
22 s1=”06″;
23 }
24 if (s1==7) {
25 s1=”07″;
26 }
27 if (s1==8) {
28 s1=”08″;
29 }
30 if (s1==9) {
31 s1=”09″;
32 }
33 }
- In the first line we declare the function
- In the second line we set the s1 variable to be a string because we need the display to be in string form to show the leading zeroes.
- Then we have an if statement for each of the numbers 0 through 9. Basically we say depending on which single digit is the value –
- Change it to a two digit string with a leading zero.
- Close the if statement.
6-32. Repeat the if statements for the rest of the numbers. - Close the function
The checkDigits2() function is exactly the same except we reference the s2 variable for the seconds display on the other clock. As such all of the s1 variable references you see above are changed to s2.
Now we have two timer functions – one for each of the two clocks.
1 function timer1() {
2 clock1 = setTimeout(function() {
3 –s1;
4 checkDigits();
5 if ((s1 == -1) && (m1>0)) {
6 s1=59;
7 –m1
8 gsap.to(“#secondsc”, {rotate: “+=6”, duration: 0.25, ease: “none”});
9 gsap.to(“#minutesc”, {rotate: “+=6”, duration: 0.25, ease: “none”});
10 timer1();
11 }
12 else if ((s1>0) && (m1>0)) {
13 gsap.to(“#secondsc”, {rotate: “+=6”, duration: 0.25, ease: “none”});
14 timer1();
15 }
16 else if ((s1==0) && (m1>0)) {
17 gsap.to(“#secondsc”, {rotate: “+=6”, duration: 0.25, ease: “none”});
18 timer1();
19 }
20 else if (s1>0) {
21 gsap.to(“#secondsc”, {rotate: “+=6”, duration: 0.25, ease: “none”});
22 timer1();
23 }
24 else {
25 gsap.to(“#secondsc”, {rotate: “+=6”, duration: 0.25, ease: “none”});
26 clearTimeout(clock1);
27 }
28 },1000);
29 }
- First we declare the function timer1()
- Remember that clock1 variable? Here we use it to assign the setTimeout function
- Reduce the s1 (seconds) variable on the first clock by 1
- Run the checkDigits() function in case we ran into single digits with the seconds
- Here we begin a series of conditional statements based on some time changes. The first is to say that if we decrease our seconds to -1 and our minutes are still greater than 0
- That means we must set the seconds back to 59 as we countdown.
- Then we can now also decrease our minutes by 1 on the left clock
- Rotate the seconds hand clockwise by six degrees taking a quarter second
- Rotate the minute hand clockwise by six degrees taking a quarter second
- Stop here – rerun this timer
- Close the first if condition
- If we run the timer and the first condition is false check if both seconds and minutes are greater than zero and if so…
- Just rotate the second hand by six degrees taking a quarter second
- Stop here – rerun this timer
- Close the second if condition
- If the first two conditions are false, check that seconds exactly equals 0 and minutes are greater than zero and if so…
- Just rotate the second hand by six degrees taking a quarter second
- Stop here – rerun this timer
- Close the third if condition
- If the first three are all false, just check to see if the seconds are greater than zero and if so…
- Just rotate the second hand by six degrees taking a quarter second
- Stop here – rerun this timer
- Close the fourth if condition
- If all four prior conditions are false (ie. We have reached zero)
- Rotate the second hand by six degrees taking one quarter second
- Cancel this timer
- Close the final condition
- Closing for the timeout function – everything between 2 and 28 run every 1000 ms (1 second) until cancelled by reaching zero or stopped by the stop button. (more on that later)
- Close out the whole timer1 function
The timer2() function is exactly the same except we reference the s2 and m2 variables for the seconds display and minutes display respectively on the other clock. As such all of the s1 and m1 variable references you see above are changed to s2 and m2.
Number 2: Left Button on Top
Remember that the default state is that the buttons are at mid height and disabled until a minute value is entered.
1 cp.changeState(“btnR”,”up”);
2 cp.changeState(“btnL”,”down”);
3 cp.disable(“up”);
4 cp.disable(“down”);
5 cp.enable(“stopBtn”);
6 cp.disable(“clickL”);
7 cp.enable(“clickR”);
8 clearTimeout(clock1);
9 timer2();
Above are all the commands placed on the left button and below is the explanation.
- When we push down on the left button the right button goes up
- Left button goes down.
- As soon as a top button is pressed – disable the up button – this prevents adding time after the clocks have started.
- As soon as a top button is pressed – disable the down button – this prevents taking time off the clocks after they have started.
- As soon as a stop button is pressed – the clocks are active – therefore enable the stop button
- When the left button is down – disable it so it cannot be pressed again
- When the left button is down – enable the right button so it can be pressed
- Pressing the button ends your turn and passes it to the other player. Stop just this clock
- Start the other clock
Number 3: Right Button on Top
Remember that the default state is that the buttons are at mid height and disabled until a minute value is entered.
1 cp.changeState(“btnL”,”up”);
2 cp.changeState(“btnR”,”down”);
3 cp.disable(“up”);
4 cp.disable(“down”);
5 cp.enable(“stopBtn”);
6 cp.disable(“clickR”);
7 cp.enable(“clickL”);
8 clearTimeout(clock2);
9 timer1();
You should recognize that the commands on the right button are almost identical to the ones on the left button with just a few changes.
- When we push down on the right button the left button goes up
- Right button goes down.
- As soon as a top button is pressed – disable the up button – this prevents adding time after the clocks have started.
- As soon as a top button is pressed – disable the down button – this prevents taking time off the clocks after they have started.
- As soon as a stop button is pressed – the clocks are active – therefore enable the stop button
- When the right button is down – disable it so it cannot be pressed again
- When the right button is down – enable the left button so it can be pressed
- Pressing the button ends your turn and passes it to the other player. Stop just this clock
- Start the other clock
Number 4: Up Button
The up button is the triangle pointing up on the left side of the clock. It is used to increase the amount of time for each player. Therefore we need to update the clock faces and the digital displays
1 cp.disable(“up”);
2 setTimeout(function() {
3 cp.enable(“up”);
4 },250);
5 m1=m1+5;
6 m2=m2+5;
7 if ((m1>60) || (m2>60)) {
8 m1 = 60;
9 m2 = 60;
10 }
11 else {
12 gsap.to(“#minutesc”, {rotate: “-=30”, duration: 0.25, ease: “none”});
13 gsap.to(“#minutes2c”, {rotate: “-=30”, duration: 0.25, ease: “none”});
14 if (m1>0) {
15 cp.enable(“clickL”);
16 cp.enable(“clickR”);
17 }
18 }
Our clock only goes to 60 minutes per player so we have to accommodate for that as well.
Here is a look at each line of the code.
- When we press the up button – disable itself
- Declare a setTimeout function
- To enable the up button again
- In a quarter of a second. This was done so that there was not a hiccup in animation of the clock faces if a user spammed the up button real fast
- Increase the minutes for clock one by 5
- Increase the minutes for clock two by 5
- Here we have an if statement that says if either clock 1 or clock 2 minutes is over 60
- Set clock 1 minutes back to 60
- And set clock 2 minutes back to 60
- Close the if statement
- Now if the if statement condition was false (else)
- Rotate the minute hand counter-clockwise by six degrees taking a half second on clock 1
- Rotate the minute hand counter-clockwise by six degrees taking a half second on clock 2
- Then run a check to verify that minutes is more than 0 and if so…
- Enable the top left button and
- Enable the top right button
- Close the if statement
- Close the else statement
Number 5: Down Button
The down button is the triangle pointing up on the left side of the clock. It is used to decrease the amount of time for each player. Therefore we need to update the clock faces and the digital displays
1 cp.disable(“up”);
2 setTimeout(function() {
3 cp.enable(“down”);
4 },250);
5 m1=m1-5;
6 m2=m2-5;
7 if ((m1<0) || (m2<0)) {
8 m1 = 0;
9 m2 = 0;
10 }
11 else {
12 gsap.to(“#minutesc”, {rotate: “+=30”, duration: 0.25, ease: “none”});
13 gsap.to(“#minutes2c”, {rotate: “+=30”, duration: 0.25, ease: “none”});
14 if (m1==0) {
15 cp.disable(“clickL”);
16 cp.disable(“clickR”);
17 }
18 }
Our clock should not go below zero minutes per player so we have to accommodate for that as well.
Here is a look at each line of the code.
- When we press the down button – disable itself
- Declare a setTimeout function
- To enable the down button again
- In a quarter of a second. This was done so that there was not a hiccup in animation of the clock faces if a user spammed the down button real fast
- Decrease the minutes for clock one by 5
- Decrease the minutes for clock two by 5
- Here we have an if statement that says if either clock 1 or clock 2 minutes is below 0
- Set clock 1 minutes back to 0
- And set clock 2 minutes back to 0
- Close the if statement
- Now if the if statement condition was false (else)
- Rotate the minute hand clockwise by six degrees taking a half second on clock 1
- Rotate the minute hand clockwise by six degrees taking a half second on clock 2
- Then run a check to see if the minutes is equal to 0 and if so…
- Disable the top left button and
- Disable the top right button because we don’t want the top buttons to work unless a time is set
- Close the if statement
- Close the else statement
Number 6: Stop Button
The stop button, which is the “S” button on the right side of the clock, just has a few commands to pause functionality of the clock. This is meant to be a temporary situation or for when someone has declared checkmate.
1 cp.enable(“clickL”);
2 cp.enable(“clickR”);
3 cp.changeState(“btnL”,”mid”);
4 cp.changeState(“btnR”,”mid”);
5 clearTimeout(clock1);
6 clearTimeout(clock2);
When the stop button is pressed, the following happens
- We enable the clickL button
- We enable the clickR button – both are enabled as we are not tracking current states and so either side might need to restart the clock
- Change the left button to the mid state
- Change the right button to the mid state
- Stop clock number 1
- Stop clock number 2
Number 7: Reset Button
The reset button, as the name implies, will reset the clocks back to zero for the beginning of a new game. This is the “R” button on the right side of the clock. As such – there are a few more commands that need to take place.
1 cp.disable(“clickL”);
2 cp.disable(“clickR”);
3 cp.disable(“stopBtn”);
4 cp.changeState(“btnL”,”mid”);
5 cp.changeState(“btnR”,”mid”);
6 clearTimeout(clock1);
7 clearTimeout(clock2);
8 m1=0;
9 m2=0;
10 s1=0;
11 s2=0;
12 checkDigits();
13 checkDigits2();
14 cp.enable(“up”);
15 cp.enable(“down”);
16 gsap.to(“#minutesc”, {rotate: 0, duration: 0.25, ease: “none”});
17 gsap.to(“#minutes2c”, {rotate: 0, duration: 0.25, ease: “none”});
18 gsap.to(“#secondsc”, {rotate: 0, duration: 0.25, ease: “none”});
19 gsap.to(“#seconds2c”, {rotate: 0, duration: 0.25, ease: “none”});
Here is the explanation of the code above.
- Disable the button named “clickL”
- Disable the button named “clickR”
- Disable the button named “stopBtn”
- Change the state of the left button to show the middle position
- Change the state of the right button to show the middle position
- Stop clock 1
- Stop clock 2
- Set digital minutes for clock 1 back to 0
- Set digital minutes for clock 2 back to 0
- Set digital seconds for clock 1 back to 0
- Set digital seconds for clock 2 back to 0
- Run the checkDigits() function
- Run the checkDigits2() function
- Enable the up button on the left side
- Enable the down button on the left side
- Rotate the minutes hand on clock 1 back to 0 taking one quarter second
- Rotate the minutes hand on clock 2 back to 0 taking one quarter second
- Rotate the second hand on clock 1 back to 0 taking one quarter second
- Rotate the second hand on clock 2 back to 0 taking one quarter second
Yes – if you pull out the rotating elements – it simplifies the code quite a bit.
I was a part of my high school chess team many years ago and the clock face with moving hands is the image that remains in my mind. I just couldn’t make a countdown timer and call it a chess clock without at least trying to reconstruct that image.
So, alas, you have both.
Perfectly clear !…
I didn’t think it would have been so “difficult” !… I worked with your “Timer” code and thought it needed just some adjustments…
I think the GSAP concerns only the rotating “analogic” action ?… (Which is awesome, by the way !…)
But it would be “easy” to keep just the “digital” part of the code… and present just a “digital” countdown Chess Clock ?…
Big thank you for sharing your mind and your code !…
Take care and happy Captivating !
😉
You must be logged in to post a comment.