Showing posts with label graphics files. Show all posts
Showing posts with label graphics files. Show all posts

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.

Thursday, 12 March 2020

Programming: Principles & Practice - Fixing Files for Chapters 12

Chapter 12 had quite a bit of setup to get it working (and to be able to complete the exercises). Bjarne never actually mentions that you need to download extra files in order to get his examples working. He says at the start of the exercises "you need these" but doesn't give any other information. You can find the custom classes he's created here:

Not all of these are necessary for the graphics chapters. I have a few notes on getting them to compile though as they are hilariously outdated and the internet only turned up bits and pieces for working versions, so I begrudgingly spent an entire evening going through every bloody error. You can find the cleaned up versions on my github however, in the interest of knowledge, try going through and fixing the files.

1 - There are 2 Gui.h (one is all capitals). Use the uppercase GUI.h.

2 - Simple_window.cpp relies on a custom constructor for the next_button(Point()) member. This has been commented out in the code. In Point.h un-comment the two commented out constructors.

3 - Graph.cpp is a red mess.

  • Include Window.h at the top. 
  • Around line 316, change bool can_open to ifstream can_open.
  • In Graph.h add #include <FL/fl_draw.H> and <FL.Fl_Image.H> for reasons. And yes, the f and the is lowercase for some absurd reason and one contains a slash, the other a dot....
4. Simple_Window has two versions of wait_for_button(). In Simple_window.h change void wait_for_button() to void wait_for_button_modified(). Then add  bool wait_for_button();  above it. (This is because, at the time of writing this, I'm not sure if the modified version will be used at some point).

5. Simple_Window has two definitions for it's constructor. Delete the one in the header file and replace it with:
  • Simple_window(Point xy, int w, in h, const string& title);
6. Window is the Windows handle for a hwnd, files are not happy about this. Put all the code in namespace Graph_lib {code here} for the following files:
  • Simple_Window.h
  • Simple_window.cpp
7. Simple_window...again. 
  • next() already has a body. Delete the body from the .h file so it just reads void next();
  • cb_next() also already has a body. Delete the one in the cpp file as, with a quick glance, the one in the header looks safer; pointer usage wise that is.
8. They're not errors but all the mismatch warnings are annoying me. Regardless of how annoying they are, the phrase "if at first you don't succeed, #pragma disable warning" is not the approach to take...(as much as I want to). Where it says '<' signed/unsigned mismatch; changed the int to unsigned int (or remove the unsigned) till the warnings go away. 

There are two more warnings on Graph.cpp warning about conversion from double to int...seeing as how Point only uses ints I'm guessing floating point maths is not allowed so I wrapped the second part in a static_cast<int>(u.first*(p2.x - p1.x)); etc. 

9. Only two errors left. Graph_lib::Menu::Menu(...) already has a body (of course it does). Delete the one in the cpp file (they're the same...practically). And fixing that fixed the last error and it builds...YEAHHH.


Alright, I think that will do for the evening. I've been sat here for 2 hours just trying to do the bloody example a page into the chapter. 

Full code files:

EDIT 14/12/2020
I've just realised, I never posted the original cleaned up version of SimpleWindow.cpp...Whoops. I never saved the original copies but over Christmas break I'll fix up a new copy.

EDIT 01/01/2021
The link to Bjarne's original files above no longer works...It took me a good 10 minutes to navigate his website and realise that the old files are now provided as a zip file here:

He notes that they were recovered from the loss of his previous website which must've gone down sometime last year. These new files are slightly different to ones I downloaded; they appear to be newer. This batch does not contain a Simple_window.cpp as everything is defined in the header: