Answered Countdown & Clock

  • Saturday, November 24, 2012 4:29 PM
     
      Has Code

    Hi,

    I wanted to write a little program that starts a countdown after someone clicks on a button. But when the button is clicked the program freezes until the countdown ran out. I tried these possibilities:

    c = Clock.Minute
    
    While c = Clock.Minute
    'wait for the first minute
    EndWhile
    
    While c <> Clock.Minute
    'wait for an hour
    EndWhile
    Program.Delay(3600000)

    My second problem is a clock. I want the clock to update every second. I've allready made this, but i'm using a GraphicsWindow and so everytime it updates it writes over the time written before. I got allready something else written in this GraphicsWindow and so I dont want to use GraphicsWindow.Clear() to clean up.

    I'm quite a green horn in Small Basic, so if these problems are nooby just toast me.

    BlackSc0rp

All Replies

  • Saturday, November 24, 2012 4:47 PM
    Moderator
     
     Answered Has Code

    Problem 1]  The reason it freezes is that it enters the While loop and keeps repeating the loop until the time is ellapsed.  While the loop is running the cpu is continuously working flat out doing the loop and appears to freeze.  To stop the freezing, give the program time to refresh the window etc by adding a Program.Delay inside the loop, say Program.Delay(20) 1/50th sec (plenty of time to stop it freezing).

    Problem 2] To just clear a region of the GraphicsWindow so you can overwrite with a new time, just use GraphicsWindow.FillRectangle to clear a small region with the bakground colour.

    Example show some of this:

    GraphicsWindow.BackgroundColor = "LightBlue"
    While "True"
      GraphicsWindow.BrushColor = GraphicsWindow.BackgroundColor
      GraphicsWindow.FillRectangle(10,10,100,40)
      GraphicsWindow.BrushColor = "Black"
      GraphicsWindow.DrawText(12,12,Clock.Hour+":"+Clock.Minute+":"+Clock.Second)
      Program.Delay(20)
    EndWhile

  • Saturday, November 24, 2012 5:23 PM
     
     Answered
    show GKV447 its run

    Best Regards Martin

    • Marked As Answer by BlackSc0rp Sunday, November 25, 2012 9:29 AM
    •  
  • Saturday, November 24, 2012 6:51 PM
     
     Proposed

    show SXV526 its a good alarmclock,


    Best Regards Martin

  • Sunday, November 25, 2012 10:32 AM
     
     

    looks like i'm doing everything like you but, my clock is still flattering, maybe could you have a look on that? RHQ594

    Thanks, BlackSc0rp

  • Sunday, November 25, 2012 2:45 PM
     
     

    Thanks for the answer,

    but the program freezes, even if I implement a delay of 20 milliseconds.

  • Sunday, November 25, 2012 2:58 PM
     
     

    I imported RHQ594, and added Program.Delay(1000) just before the EndWhile.

    The program worked flawless!


    Jan [ WhTurner ] The Netherlands

  • Sunday, November 25, 2012 4:14 PM
     
     

    Thanks, I've just put the Delay to low

    BlackSc0rp

  • Sunday, November 25, 2012 5:00 PM
    Answerer
     
     Answered Has Code

    Heyya BlackSc0rp!

    Some tips for you:

    Small Basic is always displaying what is being drawn to screen.

    So, when you try to use any of the GraphicsWindow's drawing methods too fast, like -> GraphicsWindow.FillRectangle(10,10  100,40), flickering may happen!

    Those types are only ideal for static drawings, that is, something that won't change once drawn and stays quiet at the background.

    Your clock display's drawing changes every 1 second. Thus, it's not static, but dynamic!

    For dynamic drawings, the ideal is to use the Shapes object category. And 1 of them is Shapes.AddText(), which you can change the text being displayed w/o having to clear previous one beforehand. And it happens smoothly, w/o any flickering!

    Besides displaying any text, you can move it anywhere across the GraphicsWindow, w/o erasing any drawings below it. Also w/o flickering!

    Another useful object category for your program is Timer. It keeps calling back a subroutine you choose after a period of time you set has passed. For example:

    • Timer.Tick = Seconds  -> Sets Sub Seconds as its callback event subroutine.
    • Timer.Interval = 1000 -> Sets & activates the callback to happen each 1000 ms.  ( 1 second = 1000 milliseconds = 1 FPS )

    In short, you just put the code you want to be always called back inside the subroutine set by Timer.Tick in a period of Timer.Interval!

    In your case, that code would be -> Shapes.SetText( display, Clock.Time ), which changes the displayed text to current clock time!

    Here's a very simple example code, well commented; so you can study it to learn all the concepts above:  RHQ594-0

    '  Countdown & Clock
    '  by BlackSc0rp (2012/Nov)
    '  remixed by GoToLoop
    
    '  RHQ594-0
    
    '  http://social.msdn.microsoft.com/Forums/en-US/smallbasic/thread/f2768efb-8f3b-4ff4-b162-333cfdb780b7
    
    gw = GraphicsWindow.Width   ' stores GraphicsWindow's dimensions
    gh = GraphicsWindow.Height
    fs = 64                     '  text font size for clock display
    
    GraphicsWindow.Title = "Countdown & Clock"
    GraphicsWindow.BackgroundColor = "Yellow" GraphicsWindow.BrushColor = "Black" GraphicsWindow.FontBold = "True" GraphicsWindow.FontSize = fs display = Shapes.AddText( Clock.Time ) ' creates text shape object to display current clock time Shapes.Move( display gw/2 - fs*3, gh/2 - fs*2/3 ) ' places clock at about the center of GraphicsWindow Timer.Tick = Seconds ' triggered event subroutine to change the text displayed by shape object -> display Timer.Interval = 1000 ' it's called-back every 1 second ( 1 second = 1000 milliseconds ) Sub Seconds Shapes.SetText( display, Clock.Time ) ' changes displayed text to current clock time EndSub

    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)

    • Edited by GoToLoopEditor Sunday, November 25, 2012 5:27 PM
    • Marked As Answer by BlackSc0rp Monday, November 26, 2012 2:14 PM
    •  
  • Sunday, November 25, 2012 5:37 PM
     
     

    Hallo BlaSc0rp,

    ich habe 2 Zeilen eingefügt. Mit der variablen PD kann man das flackern des Bildschirms verhindern. Am Ende der While-Schleife habe ich "Program.Delay(PD)" eingefügt damit eine Pause gemacht wird und das Flackern verhindert wird.

    Importiere mal das Programm RHQ594-1 und setz für PD unterschiedliche Werte ein.

    Viel Spass beim Programmieren

    Martin


    Best Regards Martin

  • Monday, November 26, 2012 3:06 PM
     
      Has Code

    Thanks to GoToLoop and martmen for the answers.

    Finally, I got it. Dont know why but using a variable to set the Delay helped to stop flickering. -->

    While uhrCheck = 0
      ...
      ...
      ...
      Program.Delay(1000) ' keeps flickering
    EndWhile
    
    delay = 1000
    
    While uhrCheck = 0
      ...
      ...
      ...
      Program.Delay(delay) ' stops flickering

    @GoToLoop:

    I've allready used the Timer method, but I thought, the clock was flickering cause of that. But I think i'm gonna use it again. Thanks for your good explanation. Actually I didnt even know that there's a possibility to use Shapes.AddText or stuff like that.

    But I still cant get arround with the countdown without freezing... Someone got an idea?

    BlackSc0rp



    • Edited by BlackSc0rp Monday, November 26, 2012 3:23 PM
    •  
  • Monday, November 26, 2012 4:31 PM
    Answerer
     
      Has Code

    Hello again!

    Expanded previous example to include a variable for countdown seconds -> cd = 60.

    Since Sub Seconds is called back every 1 second (1000 milliseconds), it's an excellent opportunity to put code to decrease our countdown's variable!

    For now, it just places its display at the running program's window title-bar.

    Check it out:   RHQ594-2

    '  Countdown & Clock (v2.0)
    '  by BlackSc0rp (2012/Nov)
    '  remixed by GoToLoop
    
    '  RHQ594-2
    
    '  http://social.msdn.microsoft.com/Forums/en-US/smallbasic/thread/f2768efb-8f3b-4ff4-b162-333cfdb780b7
    
    gw = GraphicsWindow.Width   ' stores GraphicsWindow's dimensions
    gh = GraphicsWindow.Height
    fs = 64                     '  text font size for clock display
    cd = 60                     '  countdown seconds
    
    GraphicsWindow.BackgroundColor = "Yellow"
    GraphicsWindow.BrushColor = "Black"
    
    GraphicsWindow.FontBold = "True"
    GraphicsWindow.FontSize = fs
    
    display = Shapes.AddText( Clock.Time )              ' creates text shape object to display current clock time
    Shapes.Move( display  gw/2 - fs*3, gh/2 - fs*2/3 )  ' places clock at about the center of GraphicsWindow
    
    Timer.Tick = Seconds   ' triggered event subroutine to change the text displayed by shape object -> display
    Timer.Interval = 1000  ' it's called-back every 1 second ( 1 second = 1000 milliseconds )
    
    
    Sub Seconds
      
      If cd > 0 Then
        cd = cd - 1  ' 1 second less for countdown
      EndIf
      
      Shapes.SetText( display, Clock.Time )  ' changes displayed text to current clock time
      
      GraphicsWindow.Title = "Countdown: " + cd + " seconds"  ' displays countdown as title bar
      
    EndSub

    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)

  • Tuesday, November 27, 2012 4:53 PM
     
     

    Hey GoToLoop,

    Nice idea with putting the countdown into the subroutine, but I would like to start the countdown after a button is clicked, while the clock allready is displayed.

    Is there a possibility to have 2 different Timer.Tick?

    BlackSc0rp

  • Tuesday, November 27, 2012 6:03 PM
    Answerer
     
     Answered Has Code

    Only 1 Timer.Tick can be active, although that can be changed to another subroutine at any time!

    But a simpler solution would be to create a flag state variable, which would be turned on w/ isActive = "True", and turned off w/ isActive = "False".

    So within Sub Seconds, besides testing if cd > 0 Then, just include the flag variable as well:

    If isActive And cd > 0 Then
      cd = cd - 1  ' 1 second less for countdown
    Else
      isActive = "False"  ' turns off countdown
    EndIf

    But in a more compact way, you wouldn't even need a flag variable for it, since you can consider that countdown is active if cd > 0 by itself.

    So, rather than create an extra variable (and an extra check) for it.

    Inside the code where you check whether the user clicked on the start countdown button, just assign a number > 0 to variable cd.

    To turn it off abruptly, just make cd = 0!  ;-)

    An extra flag variable would only be necessary if you had the need to pause/resume the countdown at any given moment!


    Click on "Propose As Answer" if some post solves your problem or "Vote As Helpful" if some post has been useful to you! (^_^)

    • Edited by GoToLoopEditor Tuesday, November 27, 2012 6:22 PM
    • Marked As Answer by BlackSc0rp Wednesday, November 28, 2012 4:04 PM
    •  
  • Wednesday, November 28, 2012 4:16 PM
     
     

    Finally made it :)  Thaaaanks GoToLoop, you really helped me :)

    KXC882   I've commented it in german

    BlackSc0rp