Task

Draw a clock.



More specific:

 Draw a time keeping device. It can be a stopwatch, hourglass, sundial, a mouth counting "one thousand and one", anything. Only showing the seconds is required, e.g.: a watch with just a second hand will suffice. However, it must clearly change every second, and the change must cycle every so often (one minute, 30 seconds, etc.) It must be drawn; printing a string of numbers to your terminal doesn't qualify. Both text-based and graphical drawing are OK.
 The clock is unlikely to be used to control space flights, so it needs not be hyper-accurate, but it should be usable, meaning if one can read the seconds off the clock, it must agree with the system clock.
 A clock is rarely (never?) a major application: don't be a CPU hog and poll the system timer every microsecond, use a proper timer/signal/event from your system or language instead. For a bad example, many OpenGL programs update the frame-buffer in a busy loop even if no redraw is needed, which is very undesirable for this task.
 A clock is rarely (never?) a major application: try to keep your code simple and to the point. Don't write something too elaborate or convoluted, instead do whatever is natural, concise and clear in your language.


Key points
 animate simple object
 timed event 
 polling system resources 
 code clarity


' version 05-04-2017
' compile with: fbc -s gui
 
Const As Double deg2rad = Atn(1) / 45
Const As UInteger w = 199, h = 199
Const As UInteger x0 = w \ 2, y0 = h \ 2 ' center
 
Dim As UInteger x, x1, x2, x3, y, y1, y2, y3
Dim As String sys_time, press
Dim As Integer hours, minutes, seconds
Dim As Double angle, a_sin, a_cos
 
ScreenRes w, h, 8  ' 8bit color depth (palette)
WindowTitle "Simple Clock"
 
' create image 8bit (palette) and set pixels to 15 (white)
Dim clockdial As Any Ptr = ImageCreate(w, h, 15, 8)
 
If clockdial = 0 Then
    Print "Failed to create image."
    Sleep
    End -1
End If
 
' draw clockdial in memory
Circle clockdial, (x0, y0), 94 ,0
Circle clockdial, (x0, y0), 90 ,0
 
For x = 0 To 174 Step 6
    a_sin = Sin(x * deg2rad)
    a_cos = Cos(x * deg2rad)
 
    x1 = 94 * a_sin : y1 = 94 * a_cos
    If x Mod 30 = 0 Then
        x2 = 85 * a_sin : y2 = 85 * a_cos
    Else
        x2 = 90 * a_sin : y2 = 90 * a_cos
    End If
 
    Line clockdial, (x0 + x1, y0 + y1) - (x0 + x2, y0 + y2), 0
    Line clockdial, (x0 - x1, y0 - y1) - (x0 - x2, y0 - y2), 0
Next
 
'draw clock 
Do
    sys_time = Time
    hours   = (sys_time[0] - Asc("0")) * 10 + sys_time[1] - Asc("0")
    minutes = (sys_time[3] - Asc("0")) * 10 + sys_time[4] - Asc("0")
    seconds = (sys_time[6] - Asc("0")) * 10 + sys_time[7] - Asc("0")
 
    If hours > 12 Then hours -= 12
 
    angle = (180 - (hours * 30 + minutes / 2)) * deg2rad
    x1 = 65 * Sin(angle)
    y1 = 65 * Cos(angle)
 
    angle = (180 - (minutes * 6 + seconds / 10)) * deg2rad
    x2 = 80 * Sin(angle)
    y2 = 80 * Cos(angle)
 
    angle = (180 - seconds * 6) * deg2rad
    x3 = 90 * Sin(angle)
    y3 = 90 * Cos(angle)
 
    ScreenLock
    ' load image, setting pixels
    Put (0, 0), clockdial, PSet
    Line (x0, y0) - (x0 + x1, y0 + y1), 1   ' hour hand blue
    Line (x0, y0) - (x0 + x2, y0 + y2), 2   ' minute hand green
    Line (x0, y0) - (x0 + x3, y0 + y3), 12  ' second hand red
    ScreenUnLock
 
    Sleep 300, 1 ' wait 300 ms, don't respond to keys pressed
 
    ' press esc or mouse click on close window to stop program
    press = InKey
    If press = Chr(27) Or press = Chr(255) + "k" Then Exit Do
 
Loop
 
ImageDestroy(clockdial)
 
End