[SOLVED][QB64] Need help with the hour hand of my clock

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
wilou
Newbie
Posts: 6
Joined: Mon Apr 18, 2016 8:50 am

[SOLVED][QB64] Need help with the hour hand of my clock

Post by wilou »

Hello,

I've decided to code an analog clock using a portion of code I found on https://qb64sourcecode.com/:
https://qb64sourcecode.com/task12code2.png

Everything is going fine but one : the hour hand.
It moves one time on each new hour and I'd like to make it move as time passes by.
I've tried differents values, but so far, I didn't succeed.

Here is my code:

Code: Select all

'Horloge analogique

_TITLE "Horloge analogique vintage"

SCREEN _NEWIMAGE(640, 320, 32)

Blanc& = _RGB32(255, 255, 255)
Jaune& = _RGB32(255, 255, 0)
Cyan& = _RGB32(64, 224, 208)
Vert& = _RGB32(0, 255, 0)
Rouge& = _RGB32(255, 0, 0)
Noir& = _RGB32(0, 0, 0)
Gris& = _RGB32(63, 63, 63)

Pi2! = 8 * ATN(1)
sec! = Pi2! / 60
min! = Pi2! / 60
heure! = Pi2! / 60
arc! = Pi2! / 12
arc2! = Pi2! / 60

FOR t! = 0 TO Pi2! STEP arc!
    cx% = CINT(COS(t!) * 70)
    cy% = CINT(SIN(t!) * 70)
    CIRCLE (cx% + 320, cy% + 160), 1, Vert&
    CIRCLE (cx% + 320, cy% + 160), 2, Vert&
NEXT t!

DO
    _LIMIT 1000
    CIRCLE (320, 160), 1, Blanc&
    CIRCLE (320, 160), 2, Blanc&
    CIRCLE (320, 160), 3, Blanc&
    Year% = VAL(RIGHT$(DATE$, 4))
    Jour% = VAL(RIGHT$(DATE$, 7))
    Mois% = VAL(RIGHT$(DATE$, 11))
    LOCATE 2, 28
    COLOR Cyan&

    mois$ = LEFT$(DATE$, 2)
    M = VAL(mois$)
    SELECT CASE M
        CASE 1: Lune$ = "janvier"
        CASE 2: Lune$ = "février"
        CASE 3: Lune$ = "mars"
        CASE 4: Lune$ = "avril"
        CASE 5: Lune$ = "mai"
        CASE 6: Lune$ = "juin"
        CASE 7: Lune$ = "juillet"
        CASE 8: Lune$ = "août"
        CASE 9: Lune$ = "septembre"
        CASE 10: Lune$ = "octobre"
        CASE 11: Lune$ = "novembre"
        CASE 12: Lune$ = "décembre"
    END SELECT

    Longueur = LEN(Lune$) + 17
    LOCATE 2, (80 - Longueur - 3)
    PRINT Jour%; Lune$; Year%; "| "; TIME$
    Seconds% = VAL(RIGHT$(TIME$, 2)) - 15
    S! = sec! * Seconds%
    Minutes% = VAL(RIGHT$(TIME$, 5)) - 15
    M! = min! * Minutes%
    Heure% = VAL(RIGHT$(TIME$, 8)) - 15
    H! = (heure! * 5) * Heure%

    IF Heure% >= 13 OR Heure% <= 24 THEN Heure% = Heure% - 12

    IF VAL(RIGHT$(TIME$, 5)) >= 12 THEN
        _LIMIT 1000
        H! = H! + 0.016
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 24 THEN
        _LIMIT 1000
        H! = H! + 0.033
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 36 THEN
        _LIMIT 1000
        H! = H! + 0.05
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 48 THEN
        _LIMIT 1000
        H! = H! + 0.067
    END IF

    IF VAL(RIGHT$(TIME$, 5)) = 0 AND VAL(RIGHT$(TIME$, 2)) = 0 THEN
        _LIMIT 1000
        BEEP
    END IF

    Sx% = CINT(COS(S!) * 50)
    Sy% = CINT(SIN(S!) * 50)
    Mx% = CINT(COS(M!) * 60)
    My% = CINT(SIN(M!) * 60)
    Hx% = CINT(COS(H!) * 45)
    Hy% = CINT(SIN(H!) * 45)
    LINE (320, 160)-(Sx% + 320, Sy% + 160), Rouge&
    LINE (320, 160)-(Mx% + 320, My% + 160), Jaune&
    LINE (320, 160)-(Hx% + 320, Hy% + 160), Jaune&
    DO
        _LIMIT 1000
        Verif% = VAL(RIGHT$(TIME$, 2)) - 15
        Verif1% = VAL(RIGHT$(TIME$, 5)) - 15
        Verif2% = VAL(RIGHT$(TIME$, 8)) - 15
    LOOP UNTIL Verif% <> Seconds% OR Verif1% <> Minutes% OR Verif2% <> Heure%
    _DISPLAY
    LINE (320, 160)-(Sx% + 320, Sy% + 160), Noir&
    LINE (320, 160)-(Mx% + 320, My% + 160), Noir&
    LINE (320, 160)-(Hx% + 320, Hy% + 160), Noir&
    LOCATE 18, 45
    COLOR Jaune&
    PRINT "Clic gauche ou <"; CHR$(144); "chap> pour quitter"
    Mouse = _MOUSEINPUT
    K$ = INKEY$
    IF K$ = CHR$(27) OR _MOUSEBUTTON(1) THEN SYSTEM
LOOP UNTIL INKEY$ = CHR$(27)
And the part that's bothering me is this one:

Code: Select all

    IF VAL(RIGHT$(TIME$, 5)) >= 12 THEN
        _LIMIT 1000
        H! = H! + 0.016
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 24 THEN
        _LIMIT 1000
        H! = H! + 0.033
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 36 THEN
        _LIMIT 1000
        H! = H! + 0.05
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 48 THEN
        _LIMIT 1000
        H! = H! + 0.067
    END IF
I have the feeling that the numbers like 0.016, 0.033 and so on should be replaced by fractions, but I don't find what fractions.

Do you have an idea?

Thanks,

W.
Last edited by wilou on Wed Feb 23, 2022 1:51 am, edited 1 time in total.
wilou
Newbie
Posts: 6
Joined: Mon Apr 18, 2016 8:50 am

[QB64] Need help with the hour hand of my clock

Post by wilou »

Hello again,

Night brings advice! :)

I think I found the solution all alone. I had all the elements right in front of my eyes. And what is under our nose isn't always seen like it should be (philosophic moment of the day :D)

As you may have noticed, there is a arc2! variable declared, that I added to the original code, but not used.
Initially, I wanted to display points all around the clock for each minute. I tried but it didn't looked good, the clock is too small and I prefer the minimalistic look you can see now. So I only displayed a point every 5 minute (with the arc! variable).

But if the arc2! variable is coming handy as it was meant to display a dot for every minute, it can also be used to compute the placement of the hour hand! 8-)

So, I updated my code as follows (still no fractions and the calculations don't happen at the same place) :

Code: Select all

'Horloge analogique

_TITLE "Horloge analogique vintage"

SCREEN _NEWIMAGE(640, 320, 32)

Blanc& = _RGB32(255, 255, 255)
Jaune& = _RGB32(255, 255, 0)
Cyan& = _RGB32(64, 224, 208)
Vert& = _RGB32(0, 255, 0)
Rouge& = _RGB32(255, 0, 0)
Noir& = _RGB32(0, 0, 0)
Gris& = _RGB32(63, 63, 63)

Pi2! = 8 * ATN(1)
sec! = Pi2! / 60
min! = Pi2! / 60
heure! = Pi2! / 60
arc! = Pi2! / 12
arc2! = Pi2! / 60

FOR t! = 0 TO Pi2! STEP arc!
    cx% = CINT(COS(t!) * 70)
    cy% = CINT(SIN(t!) * 70)
    CIRCLE (cx% + 320, cy% + 160), 1, Vert&
    CIRCLE (cx% + 320, cy% + 160), 2, Vert&
NEXT t!

DO
    _LIMIT 1000
    CIRCLE (320, 160), 1, Blanc&
    CIRCLE (320, 160), 2, Blanc&
    CIRCLE (320, 160), 3, Blanc&
    Year% = VAL(RIGHT$(DATE$, 4))
    Jour% = VAL(RIGHT$(DATE$, 7))
    Mois% = VAL(RIGHT$(DATE$, 11))
    LOCATE 2, 28
    COLOR Cyan&

    mois$ = LEFT$(DATE$, 2)
    M = VAL(mois$)
    SELECT CASE M
        CASE 1: Lune$ = "janvier"
        CASE 2: Lune$ = "février"
        CASE 3: Lune$ = "mars"
        CASE 4: Lune$ = "avril"
        CASE 5: Lune$ = "mai"
        CASE 6: Lune$ = "juin"
        CASE 7: Lune$ = "juillet"
        CASE 8: Lune$ = "août"
        CASE 9: Lune$ = "septembre"
        CASE 10: Lune$ = "octobre"
        CASE 11: Lune$ = "novembre"
        CASE 12: Lune$ = "décembre"
    END SELECT

    Longueur = LEN(Lune$) + 17
    LOCATE 2, (80 - Longueur - 3)
    PRINT Jour%; Lune$; Year%; "| "; TIME$

    Seconds% = VAL(RIGHT$(TIME$, 2)) - 15
    S! = sec! * Seconds%
    Minutes% = VAL(RIGHT$(TIME$, 5)) - 15
    M! = min! * Minutes%
    Heure% = VAL(RIGHT$(TIME$, 8)) - 15
    H! = (heure! * 5) * Heure%

    IF Heure% >= 13 OR Heure% <= 24 THEN Heure% = Heure% - 12

    IF VAL(RIGHT$(TIME$, 5)) = 0 AND VAL(RIGHT$(TIME$, 2)) = 0 THEN
        _LIMIT 1000
        BEEP
    END IF

    Sx% = CINT(COS(S!) * 50)
    Sy% = CINT(SIN(S!) * 50)
    Mx% = CINT(COS(M!) * 60)
    My% = CINT(SIN(M!) * 60)
    Hx% = CINT(COS(H!) * 45)
    Hy% = CINT(SIN(H!) * 45)

    IF VAL(RIGHT$(TIME$, 5)) >= 12 THEN
        _LIMIT 1000
        H! = H! + heure!
        Hx% = CINT(COS(H!) * 45)
        Hy% = CINT(SIN(H!) * 45)
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 24 THEN
        _LIMIT 1000
        H! = H! + heure!
        Hx% = CINT(COS(H!) * 45)
        Hy% = CINT(SIN(H!) * 45)
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 36 THEN
        _LIMIT 1000
        H! = H! + heure!
        Hx% = CINT(COS(H!) * 45)
        Hy% = CINT(SIN(H!) * 45)
    END IF
    IF VAL(RIGHT$(TIME$, 5)) >= 48 THEN
        _LIMIT 1000
        H! = H! + heure!
        Hx% = CINT(COS(H!) * 45)
        Hy% = CINT(SIN(H!) * 45)
    END IF

    LINE (320, 160)-(Sx% + 320, Sy% + 160), Rouge&
    LINE (320, 160)-(Mx% + 320, My% + 160), Jaune&
    LINE (320, 160)-(Hx% + 320, Hy% + 160), Jaune&

    DO
        _LIMIT 1000
        Verif% = VAL(RIGHT$(TIME$, 2)) - 15
        Verif1% = VAL(RIGHT$(TIME$, 5)) - 15
        Verif2% = VAL(RIGHT$(TIME$, 8)) - 15
    LOOP UNTIL Verif% <> Seconds% OR Verif1% <> Minutes% OR Verif2% <> Heure%

    _DISPLAY

    LINE (320, 160)-(Sx% + 320, Sy% + 160), Noir&
    LINE (320, 160)-(Mx% + 320, My% + 160), Noir&
    LINE (320, 160)-(Hx% + 320, Hy% + 160), Noir&

    LOCATE 18, 45
    COLOR Jaune&
    PRINT "Clic gauche ou <"; CHR$(144); "chap> pour quitter"
    Mouse = _MOUSEINPUT
    K$ = INKEY$
    IF K$ = CHR$(27) OR _MOUSEBUTTON(1) THEN SYSTEM
LOOP UNTIL INKEY$ = CHR$(27)
Thank you to those who have read me. Hope this code will be useful to someone one day. I might beef it up by setting up an alarm system for example, or give the choice between different sizes. :)

W.

EDIT: well, finally, it didn't work and I modified the code again, using heure! instead of arc2! For a reason I ignore, I must do the same routine in the four "if... end if", as if the minutes influenced the hours (M! influences H!)? Strange! For now, that's good but I'll see how that evolves.

EDIT 2 : it runs for 5 hours straight and I didn't see anything wrong. I think it's good this time ! :)
Last edited by wilou on Wed Feb 23, 2022 1:53 am, edited 1 time in total.
MikeHawk
Veteran
Posts: 50
Joined: Sun Jul 08, 2018 11:23 am

Re: [QB64] Need help with the hour hand of my clock

Post by MikeHawk »

Hi there! I'm a little bit of an autist when it comes to numbers, so I'll use the TIMER function to extract the hour in number form rather than convert the TIME$ string (TIMER returns the number of seconds elapsed since midnight:)

EDIT: as it turns out, TIMER doesn't return the number of seconds elapsed since midnight under Windows and probably other platforms too. Mea maxima culpa.

Code: Select all

DIM t AS LONG
DIM s AS INTEGER, m AS INTEGER, h AS INTEGER
DIM sA AS INTEGER, mA AS INTEGER, hA as INTEGER

t = CLNG(TIMER)     ' get the integer part of the number of seconds since midnight
s = t MOD 60        ' seconds - MOD (modulo) returns the remainder of an integral division
m = (t \ 60) MOD 60 ' minutes - backslash for integral division (no fractional part)
h = t \ 3600        ' hours (3600 is the number of seconds in an hour)
The angle is determined as a proportion between the complete range (360 degrees on your clock) and the number of stops. For instance, seconds and minutes move the same amount of degrees per stop: 360 (your clock) / 60 (number of stops,) multiply by either the number of seconds or minutes:

Code: Select all

sA = 360 / 60 * s ' angle for the second hand, in degrees
mA = 360 / 60 * m ' angle for the minute hand, in degrees
For a "hard" hour hand with 12 stops, we divide 360 (your clock) by 12 (number of stops,) and multiply by the number of hours modulo 12 (modulo returns the remainder of an integral division, the result will be in range 0 to 11.) We do:

Code: Select all

hA = (360 / 12) * (h MOD 12) ' angle for the "hard" hour hand, in degrees
Now, if we want the hour hand to move, we need to know how much should it move, and when. Should it move every minute or every second? I'm going to say every minute... so we have to convert the number of hours to minutes, and then add the remaining number of minutes:

Code: Select all

DIM h2 AS INTEGER
DIM h2A AS INTEGER

h2 = h MOD 12 ' hour, in range 0-11
h2 = h2 * 60  ' hour in minutes, in range 0-660 (661 values, max is 11 * 60)
h2 = h2 + m   ' hour with minutes included, in range 0-719 (720 values, max is 11 * 60 + 59)
So there you have it: 720 stops for a full cycle. So we divide 360 (your clock) by 720 (number of stops,) and multiply by the number of minutes (including the converted hours) and presto, you go the angle for your "soft" hour hand (moving every minute:)

Code: Select all

h2A = (360 / 720) * h2 ' angle for the "soft" hour hand, in degrees
I hope this helps.

EDIT: too late, you came up with your own solution to the problem.
Last edited by MikeHawk on Sat Feb 26, 2022 3:38 pm, edited 2 times in total.
wilou
Newbie
Posts: 6
Joined: Mon Apr 18, 2016 8:50 am

Re: [SOLVED][QB64] Need help with the hour hand of my clock

Post by wilou »

Hello,

Thanks for your reply. Indeed, I've found the solution by myself and I'm proud of it as it's the most difficult program I've done so far. 8)

And :
For a reason I ignore, I must do the same routine in the four "if... end if", as if the minutes influenced the hours (M! influences H!)?
I'm so stupid sometimes. At the beginning, I used arc2!, then two times arc2! then 3 times... But when I use arc2! for the first time (or heure!), the new H! is H! + heure! so I just have to add heure! again, not two, three or four times heure! (I had only considered the initial H! and not the H! that was increasing each 12 minutes)!

:)

W.
wilou
Newbie
Posts: 6
Joined: Mon Apr 18, 2016 8:50 am

[SOLVED][QB64] Need help with the hour hand of my clock

Post by wilou »

Hello,

Everything is still fine, but I did optimizations :

• the drawing of the seconds hand is the last thing displayed, as well as the center of the clock (the same color as the seconds hand). That gives the illusion of an hand that is above the others;
• I changed the size of the window (it was 640×320, it's now 320×320), the presentation is slightly different;
• I changed my arc2! variable, it was 2π/60, it's now 2π/120;
• when I found how to move the hour hand correctly, I made it move every 12 minutes, now, it moves every 6 minutes (that's why I changed arc2!);
• I had an IF… ENDIF for each minute on which I wanted the hour hand to move, I made a loop FOR I=6 TO 59 STEP 6 (I gained 45 lines of code just with that!);
• I added little stars to decorate (the number of them will vary depending on the length of the modified DATE$ string).

Here's the new code :

Code: Select all

'Horloge analogique

_TITLE "Horloge analogique vintage"

SCREEN _NEWIMAGE(320, 320, 32)

CONST Jaune& = _RGB32(255, 255, 0)
CONST Cyan& = _RGB32(64, 224, 208)
CONST Vert& = _RGB32(0, 255, 0)
CONST Rouge& = _RGB32(255, 0, 0)
CONST Noir& = _RGB32(0, 0, 0)

Pi2! = 8 * ATN(1)
sec! = Pi2! / 60
min! = Pi2! / 60
heure! = Pi2! / 60
arc! = Pi2! / 12
arc2! = Pi2! / 120

FOR t! = 0 TO Pi2! STEP arc!
    cx% = CINT(COS(t!) * 70)
    cy% = CINT(SIN(t!) * 70)
    CIRCLE (cx% + 160, cy% + 160), .5, Vert&
    CIRCLE (cx% + 160, cy% + 160), 1, Vert&
    CIRCLE (cx% + 160, cy% + 160), 2, Vert&
NEXT t!

DO
    _LIMIT 1000
    Year% = VAL(RIGHT$(DATE$, 4))
    Jour% = VAL(RIGHT$(DATE$, 7))
    Mois% = VAL(RIGHT$(DATE$, 11))

    mois$ = LEFT$(DATE$, 2)
    M = VAL(mois$)
    SELECT CASE M
        CASE 1: Lune$ = "janvier"
        CASE 2: Lune$ = "f" + CHR$(130) + "vrier"
        CASE 3: Lune$ = "mars"
        CASE 4: Lune$ = "avril"
        CASE 5: Lune$ = "mai"
        CASE 6: Lune$ = "juin"
        CASE 7: Lune$ = "juillet"
        CASE 8: Lune$ = "ao" + CHR$(150) + "t"
        CASE 9: Lune$ = "septembre"
        CASE 10: Lune$ = "octobre"
        CASE 11: Lune$ = "novembre"
        CASE 12: Lune$ = "d" + CHR$(130) + "cembre"
    END SELECT

    LOCATE 2, 1
    COLOR Cyan&
    PRINT " Horloge analogique vintage * ";
    COLOR Jaune&
    PRINT "(c) Wilou"

    Longueur = LEN(Lune$) + 17
    Stars = ((40 - Longueur - 3) - 1)
    FOR I = 2 TO Stars
        LOCATE 3, I
        COLOR Cyan&
        PRINT "*";
    NEXT I
    LOCATE 3, (40 - Longueur - 3)
    PRINT Jour%; Lune$; Year%; "| "; TIME$

    Seconds% = VAL(RIGHT$(TIME$, 2)) - 15
    s! = sec! * Seconds%
    Minutes% = VAL(RIGHT$(TIME$, 5)) - 15
    M! = min! * Minutes%
    Heure% = VAL(RIGHT$(TIME$, 8)) - 15
    H! = (heure! * 5) * Heure%

    IF Heure% >= 13 OR Heure% <= 24 THEN Heure% = Heure% - 12

    IF VAL(RIGHT$(TIME$, 5)) = 0 AND VAL(RIGHT$(TIME$, 2)) = 0 THEN
        _LIMIT 1000
        BEEP
    END IF

    Sx% = CINT(COS(s!) * 50)
    Sy% = CINT(SIN(s!) * 50)
    Mx% = CINT(COS(M!) * 60)
    My% = CINT(SIN(M!) * 60)
    Hx% = CINT(COS(H!) * 45)
    Hy% = CINT(SIN(H!) * 45)

    FOR I = 6 TO 59 STEP 6
        IF VAL(RIGHT$(TIME$, 5)) >= I THEN
            _LIMIT 1000
            H! = H! + arc2!
            Hx% = CINT(COS(H!) * 45)
            Hy% = CINT(SIN(H!) * 45)
        END IF
    NEXT I

    LINE (160, 160)-(Mx% + 160, My% + 160), Jaune&
    LINE (160, 160)-(Hx% + 160, Hy% + 160), Jaune&
    CIRCLE (160, 160), 1, Rouge&
    CIRCLE (160, 160), 2, Rouge&
    CIRCLE (160, 160), 3, Rouge&
    LINE (160, 160)-(Sx% + 160, Sy% + 160), Rouge&

    DO
        _LIMIT 1000
        Verif% = VAL(RIGHT$(TIME$, 2)) - 15
        Verif1% = VAL(RIGHT$(TIME$, 5)) - 15
        Verif2% = VAL(RIGHT$(TIME$, 8)) - 15
    LOOP UNTIL Verif% <> Seconds% OR Verif1% <> Minutes% OR Verif2% <> Heure%

    _DISPLAY

    LINE (160, 160)-(Sx% + 160, Sy% + 160), Noir&
    LINE (160, 160)-(Mx% + 160, My% + 160), Noir&
    LINE (160, 160)-(Hx% + 160, Hy% + 160), Noir&

    LOCATE 18, 4
    COLOR Jaune&
    PRINT "Clic gauche | <"; CHR$(144); "chap> pour quitter"
    Mouse = _MOUSEINPUT
    K$ = INKEY$
    IF K$ = CHR$(27) OR _MOUSEBUTTON(1) THEN SYSTEM
LOOP UNTIL INKEY$ = CHR$(27)
:)

W.
MikeHawk
Veteran
Posts: 50
Joined: Sun Jul 08, 2018 11:23 am

Re: [SOLVED][QB64] Need help with the hour hand of my clock

Post by MikeHawk »

Hi there!

It's cool to see you're still working on your clock. If I could suggest a bigger optimization, it would be to remove the several calls to COS(), SIN() and the two multiplications done every update for each hand because it's fairly costly. It's not a problem for a simple clock program but could become a true time waster on more complex loops. If memory is of no concern, you may precache the values you need for each hand: you calculate them once, store the result somewhere and just fetch the result as needed (there's a really simple feature for that called "arrays," I haven't seen any in your program so I assume you're not familiar with it yet.) If you want to preserve memory, precache SIN() and COS() for all 360 degrees.

A cool feature you may not know about: did you know you can use the STEP parameter on the second coordinate of LINE to make it relative to the 1st point, rather than absolute to the screen coordinate system? For instance:

Code: Select all

LINE (160, 160) - (160 + 20, 160 - 50), jaune&
Is equivalent to:

Code: Select all

LINE (160, 160) - STEP(20, -50), jaune&
Since we know about LINE STEP, why not build a custom type to keep the delta (the relative distance) between the hand origin and edge as X and Y values? Custom types allow you to create variables that contain other variables. So instead of having a variable that is "just" an integer, you can have a variable that contains multiple variables of different type (and those variables can also use custom types, like nesting dolls.) For instance:

Code: Select all

TYPE vec
  x AS INTEGER
  y AS INTEGER
END TYPE

DIM v AS vec

v.x = 20
v.y = -50

LINE(160, 160) - STEP(v.x, v.y), jaune&
Custom types are especially useful with arrays. Arrays are like a bunch of variables that have the same name and same type and can be identified by an index value. Arrays are one of the most essential things you'll ever learn in BASIC (or any programming language, really.) For instance, instead of doing:

Code: Select all

DIM x0 AS INTEGER, x1 AS INTEGER, x2 AS INTEGER, x3 AS INTEGER

x0 = -155
x1 = 1
x2 = 99
x3 = INT(RND * 100)

PRINT x0
PRINT x1
PRINT x2
PRINT x3
You can:

Code: Select all

DIM x(0 TO 3) AS INTEGER

x(0) = -155
x(1) = 1
x(2) = 99
x(3) = INT(RND * 100)

FOR i% = 0 TO 3
  PRINT x(i%)
NEXT i%
Now, we know that the seconds hand only needs 60 stops. So we just have to create an array of 60 elements (from 0 to 59,) perform the most complex operations there and store the result for later use:

Code: Select all

CONST PI = 3.14159

' our custom type
TYPE vec
  x AS INTEGER
  y AS INTEGER
END TYPE

' our seconds hand stops array
DIM sHand(0 to 59) AS vec

' fill the array
FOR i% = 0 to 59
  ‘ adding 270 degrees here is equivalent to removing 15 seconds later
  ' 360 is divided by 60 because the hand makes 60 stops per cycle
  rad! = (270 + (i% * (360 \ 60))) * (PI / 180)
  ' 50 is the length of the hand
  sHand(i%).x = COS(rad!) * 50
  sHand(i%).y = SIN(rad!) * 50
NEXT i%
Now that we have the values stored in sHand(), we no longer need to compute these numbers. We can start our main loop and access the X and Y delta stored in the array:

Code: Select all

DO
  ' Seconds% contains a value between 0 and 59
  Seconds% = VAL(RIGHT$(TIME$, 2))
  ' Get deltas from our array
  LINE(160,160) - STEP(sHand(Seconds%).x, sHand(Seconds%).y), jaune&
LOOP UNTIL LEN(INKEY$)
You can easily adapt that system to work with your minutes and hours. Or be super adventurous and write a routine to initialize any hand with any number of stops, like a hand that would only move every 20 minutes.
Post Reply