Pages

Sunday, 13 September 2020

Chapter 16 // Exercise 6 - Principles & Practice Using C++

In this exercise I am using Visual Studio 2017 and modified versions of the graphics files used throughout the chapters. You can find those versions through the link below.

Chapter 16 // Exercise 6

Make an "analog clock," that is, a clock with hands that move. You get the time of day from the operating system through a library call. A major part of this exercise is to find the functions that give you the time of day and a way of waiting for a short period of time(e.g., a second for a clock tick) and learn to use them based on the documentation you found. Hint: clock(), sleep().

Github: https://github.com/l-paz91/principles-practice/tree/master/Chapter%2016/Exercise%206


The most annoying thing about this exercise was learning that FLTK doesn't support rotating images. There is a way to implement it yourself but it involves getting all the pixel data and shifting it yourself to the new location and I can't be bothered. So I ended up just using some arrows which don't look great but they do the job.

Next I implemented the clock moving. It has three hands; one for hours, minutes and seconds. They use the C struct tm* which handily contains the current date in nice formats. AnimatedClock is its own shape and pretty much handles itself. ClockWindow has a member variable of type AnimatedClock and then ticks every second. In the gif, my PC clock was at 13:38 when I started the recording:



Originally I was trying to use Sleep(), which is a function specific to Windows that pauses the program for a given amout of milliseconds. This did not work how I wanted it to. FLTK has it's own built in timer system called Fl::Wait, we've already used it a few times before. I had a look at the documentation to see if there was a version of wait that takes in a "time value" and there is:
https://www.fltk.org/doc-1.4/classFl.html#af49654e35a0b636aa751dce5ff88a7f5

Here it mentions idle callbacks (i.e our button presses) and elapsed timeouts. I had another look round the documentation for what this meant and  found this:
https://www.fltk.org/doc-1.3/classFl.html#a23e63eb7cec3a27fa360e66c6e2b2e52

The two functions we are interested in are Fl::add_timeout and Fl::repeat_timeout. Using these are somewhat similar to registering tick functions in UE4 (the concept is essentially the same).

Fl::add_timeout requires 3 arguments; a time in seconds, a callback function and a reference to the object. So first, we register the new timeout in the constructor of our window:
(void*)this is very important otherwise on the next tick, fltk will not know what object you are referring to and you will most likely get a runtime error saying you are trying to access a nullptr.

We now create the call back function:
As standard we cast the given address to our window type and call the function we want calling when our timer elapses. The next line calls Fl::repeat_timeout, this is because Fl::add_timout is a oneshot and as such it will only be called once so we tell fltk to repeat the timeout every given time. This is useful because you might want it initially to go off for 1 second but then check every 10. We give it the callback function and use addr to specify our object. addr contains the address of this (our window) which we passed in in the constructor.

No comments:

Post a Comment