comp.lang.ada
 help / color / mirror / Atom feed
* On-Screen Elapsed Time Display?
@ 2002-10-11 18:54 Dr Nancy's Sweetie
  2002-10-11 19:32 ` Jeffrey Carter
  0 siblings, 1 reply; 6+ messages in thread
From: Dr Nancy's Sweetie @ 2002-10-11 18:54 UTC (permalink / raw)


I searched Google a few times for this, and didn't seem to find it,
but maybe I just couldn't think of the Right Magic Keywords.  So
this is probably a stupid newbie question that's been answered 100
times.  (Maybe the next person to search on the keywords I came up
with will find this article and the helpful replies.)

I have written a game, and thought it might be more interesting with
"best times" file, so people can compete with each other.  It's
easy enough to add in something like this:

   type Time_T is new Long_Integer;
   Start_Time, Win_Time: Time_T;
   procedure Time ( Time : in out Time_T);
   pragma Import (C, Time);

and then set Win_Time when the player wins, subtract, and figure out
how long it took.

What I don't see easily (and maybe I'm just blind) is a good way to
get a display on the screen (the game uses ncurses) during play.
I can update the clock every time someone pushes a key, of course,
but that's kinda lame.

What I probably need is some Ada version setitimer().  Then it's
just a matter of set up a function that displays the clock, hook the
function to SIGALRM, and set the timer to 900ms.  I found the pragma
"Attach_Handler", and also found SIGALRM in Ada.Interrupts.Names.
But what's the Ada equivalent of "setitimer();"?

I can import setitimer(), and make Ada versions of struct timerval
and itimerval, but that's starting to feel like I'm overusing C,
and depending on Unixisms (which is bad for portability).

What is the Right Thing to do?  I'm using GNAT, if that makes any
difference.


Thanks,
Darren

Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
"Everybody writes that we have no chance, but, you know, the horse can't
 read." -- Wilson Brown, trainer of Kentucky Derby entry It'sallinthechase,
           May 2002  (odds 50-1 against)



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: On-Screen Elapsed Time Display?
  2002-10-11 18:54 On-Screen Elapsed Time Display? Dr Nancy's Sweetie
@ 2002-10-11 19:32 ` Jeffrey Carter
  2002-10-14 21:36   ` Dr Nancy's Sweetie
  2002-10-15 19:23   ` Dr Nancy's Sweetie
  0 siblings, 2 replies; 6+ messages in thread
From: Jeffrey Carter @ 2002-10-11 19:32 UTC (permalink / raw)


Dr Nancy's Sweetie wrote:
> I searched Google a few times for this, and didn't seem to find it,
> but maybe I just couldn't think of the Right Magic Keywords.  So
> this is probably a stupid newbie question that's been answered 100
> times.  (Maybe the next person to search on the keywords I came up
> with will find this article and the helpful replies.)
> 
> I have written a game, and thought it might be more interesting with
> "best times" file, so people can compete with each other.  It's
> easy enough to add in something like this:
> 
>    type Time_T is new Long_Integer;
>    Start_Time, Win_Time: Time_T;
>    procedure Time ( Time : in out Time_T);
>    pragma Import (C, Time);

You could also use Ada.Calendar (or Ada.Real_Time if that's not accurate 
enough :).

> 
> and then set Win_Time when the player wins, subtract, and figure out
> how long it took.
> 
> What I don't see easily (and maybe I'm just blind) is a good way to
> get a display on the screen (the game uses ncurses) during play.
> I can update the clock every time someone pushes a key, of course,
> but that's kinda lame.
> 
> What I probably need is some Ada version setitimer().  Then it's
> just a matter of set up a function that displays the clock, hook the
> function to SIGALRM, and set the timer to 900ms.  I found the pragma
> "Attach_Handler", and also found SIGALRM in Ada.Interrupts.Names.
> But what's the Ada equivalent of "setitimer();"?
> 
> I can import setitimer(), and make Ada versions of struct timerval
> and itimerval, but that's starting to feel like I'm overusing C,
> and depending on Unixisms (which is bad for portability).
> 
> What is the Right Thing to do?  I'm using GNAT, if that makes any
> difference.

Maybe you want another task that updates the time display every so often 
using "delay until". Then, of course, you have 2 tasks writing to the 
display, so you need to protect it, but that's simple enough. Create a 
protected queue on which tasks can put Strings to be displayed and the 
position at which to display them, then have a 3rd task that takes 
things off this queue and does the display. Have the queue block the 
display task if the queue is empty.

When dealing with an inherently concurrent problem, things are usually 
simpler if you use high-level concurrency constructs.

-- 
Jeff Carter
"Death awaits you all, with nasty, big, pointy teeth!"
Monty Python & the Holy Grail




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: On-Screen Elapsed Time Display?
  2002-10-11 19:32 ` Jeffrey Carter
@ 2002-10-14 21:36   ` Dr Nancy's Sweetie
  2002-10-14 23:05     ` tmoran
  2002-10-15 19:23   ` Dr Nancy's Sweetie
  1 sibling, 1 reply; 6+ messages in thread
From: Dr Nancy's Sweetie @ 2002-10-14 21:36 UTC (permalink / raw)



In a previous article, I mentioned a game (in progress) for which there
needs to be an on-screen time display.  I wanted to (a) get the time,
and (b) get an interrupt every second or so to draw the new time on the
screen.  I'd come up with ways to do this by importing time() and
setitimer(), but that felt a lot like writing C instead of using Ada.

Jeffrey Carter suggested using "Ada.Calendar" and a separate task which
uses a "delay until".  That gives me two processes writing to the screen
at the same time, so some protecting needs to go on.

It works, so far as I can tell correctly, and so, for the benefit of the
next person who does a search at Google on some of the keywords that
appear in this post, here is what I came up with:


with Semaphores   ;
with Ada.Calendar ; use Ada.Calendar
-- other stuff deleted to get the guts of this post

   Screen_Semaphore : Semaphores.Binary_Semaphore_Type(True);

   task Timer_Task is -- for on-screen clock
      entry Start;
   end Timer_Task;
   task body Timer_Task is
      Game_Start  : Time;
      Now         : Time;
   begin

      accept Start; -- wait for screen to be painted first time

      Debug.Print("Timer Started");

      Game_Start := Clock;
      Timer_Started := True;
      loop
         exit when Timer_Stopped;

         Now := Clock;
         Area.Time := Integer(Now - Game_Start);
         Time_String := Make_Time_String(Area.Time);

         Screen_Semaphore.Wait;
         Set_Time_Window(Time_String);
         Screen_Semaphore.Signal;

         Update_Screen;

         delay 0.9; -- try to make sure the counter never skips
      end loop;
   end Timer_Task;


The thing which paints the screen doesn't start the timer until after
the screen is fully painted (that wouldn't be fair).  "Make_Time_String"
turns a number of seconds in 00:00:00 format, and "Set_Time_Window"
actually puts it in the right place on the screen.

"Area.Time" is an integer value in the player's data structure for how
long the game was in progress.  When the player wins, this will be
compared against the best times recorded by other players (as soon as I
write that part 8-).


Thanks for the help, and hopefully this may help the next person.


Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
"I use not only all the brains I have, but all I can borrow as well."
                                                     -- Woodrow Wilson



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: On-Screen Elapsed Time Display?
  2002-10-14 21:36   ` Dr Nancy's Sweetie
@ 2002-10-14 23:05     ` tmoran
  2002-10-16  1:45       ` Dr Nancy's Sweetie
  0 siblings, 1 reply; 6+ messages in thread
From: tmoran @ 2002-10-14 23:05 UTC (permalink / raw)


Some comments:
  Look into using a "protected type" instead of semaphores.  It may
be more efficient and it's certainly safer.  For instance, consider
what would happen in your program if Set_Time_Window(Time_String);
raised, but didn't handle, an exception.
  Area.Time is a variable accessed by two different tasks.  Could that
cause any problems, say if one task updated Area.Time in the middle of
the other task's usage of it?  Possibly access to Area.Time also needs
to be controlled via a protected type.
  You said Set_Time_Window updates the screen with the new time.
What then does Update_Screen do?
  It's a good idea to have the "single file" sections as short as
possible.  Every place your program writes to the screen will have to
be surrounded by semaphores (or use the protected type).  It's simpler,
and less prone to error, if the synchronization is done inside the
write-to-screen routines, rather than by each of their callers.



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: On-Screen Elapsed Time Display?
  2002-10-11 19:32 ` Jeffrey Carter
  2002-10-14 21:36   ` Dr Nancy's Sweetie
@ 2002-10-15 19:23   ` Dr Nancy's Sweetie
  1 sibling, 0 replies; 6+ messages in thread
From: Dr Nancy's Sweetie @ 2002-10-15 19:23 UTC (permalink / raw)



In a previous article, I mentioned a game (in progress) for which there
needs to be an on-screen time display.  I wanted to (a) get the time,
and (b) get an interrupt every second or so to draw the new time on the
screen.  I'd come up with ways to do this by importing time() and
setitimer(), but that felt a lot like writing C instead of using Ada.

Jeffrey Carter suggested using "Ada.Calendar" and a separate task which
uses a "delay until".  That gives me two processes writing to the screen
at the same time, so some protecting needs to go on.

It works, so far as I can tell correctly, and so, for the benefit of the
next person who does a search at Google on some of the keywords that
appear in this post, here is what I came up with:


with Semaphores   ;
with Ada.Calendar ; use Ada.Calendar
-- other stuff deleted to get the guts of this post

   Screen_Semaphore : Semaphores.Binary_Semaphore_Type(True);

   task Timer_Task is -- for on-screen clock
      entry Start;
   end Timer_Task;
   task body Timer_Task is
      Game_Start  : Time;
      Now         : Time;
   begin

      accept Start; -- wait for screen to be painted first time

      Debug.Print("Timer Started");

      Game_Start := Clock;
      Timer_Started := True;
      loop
         exit when Timer_Stopped;

         Now := Clock;
         Area.Time := Integer(Now - Game_Start);
         Time_String := Make_Time_String(Area.Time);

         Screen_Semaphore.Wait;
         Set_Time_Window(Time_String);
         Screen_Semaphore.Signal;

         Update_Screen;

         delay 0.9; -- try to make sure the counter never skips
      end loop;
   end Timer_Task;


The thing which paints the screen doesn't start the timer until after
the screen is fully painted (that wouldn't be fair).  "Make_Time_String"
turns a number of seconds in 00:00:00 format, and "Set_Time_Window"
actually puts it in the right place on the screen.

"Area.Time" is an integer value in the player's data structure for how
long the game was in progress.  When the player wins, this will be
compared against the best times recorded by other players (as soon as I
write that part 8-).


Thanks for the help, and hopefully this may help the next person.


Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
"I use not only all the brains I have, but all I can borrow as well."
                                                     -- Woodrow Wilson



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: On-Screen Elapsed Time Display?
  2002-10-14 23:05     ` tmoran
@ 2002-10-16  1:45       ` Dr Nancy's Sweetie
  0 siblings, 0 replies; 6+ messages in thread
From: Dr Nancy's Sweetie @ 2002-10-16  1:45 UTC (permalink / raw)



[ Hmm, well, it seems to have posted the same article twice.  Here's the
  right one, I hope. ]

tmoran@acm.org wrote:
:   Look into using a "protected type" instead of semaphores.  It may
: be more efficient and it's certainly safer.  For instance, consider
: what would happen in your program if Set_Time_Window(Time_String);
: raised, but didn't handle, an exception.

Oooh, hadn't thought of that.  I'm essentially an Ada newbie.  As with
anyone learning a new language, I still speak with an accent. 8-)  I'm
still waiting for the day when I accidentally type in the Spaceship
Operator for an Ada program.


:   Area.Time is a variable accessed by two different tasks.  Could that
: cause any problems, say if one task updated Area.Time in the middle of
: the other task's usage of it?  Possibly access to Area.Time also needs
: to be controlled via a protected type.

This one I've thought of; Area.Time gets initialized to zero,
incremented only by the timer, and then read outside the timer only
after the game is over (and the timer is stopped).  But the program is
still a work in progress (you can see the "Debug.Print" calls in the
hunk I came up with).


:   You said Set_Time_Window updates the screen with the new time.
: What then does Update_Screen do?

Update_Screen is from the Ada binding for ncurses; it is what
actually makes the physical screen look like the screen in memory.
Set_Time_Window sets the logical window with how it should look, and
then the call to Update_Screen makes ncurses actually update what
the user can see.


:   It's a good idea to have the "single file" sections as short as
: possible.  Every place your program writes to the screen will have to
: be surrounded by semaphores (or use the protected type).  It's simpler,
: and less prone to error, if the synchronization is done inside the
: write-to-screen routines, rather than by each of their callers.

I had sort of started to discover this myself. 8-)


Thanks,
Darren

Darren Provine ! kilroy@elvis.rowan.edu ! http://www.rowan.edu/~kilroy
"It is wonderful to be here in the great state of Chicago." -- Dan Quayle



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-10-16  1:45 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-10-11 18:54 On-Screen Elapsed Time Display? Dr Nancy's Sweetie
2002-10-11 19:32 ` Jeffrey Carter
2002-10-14 21:36   ` Dr Nancy's Sweetie
2002-10-14 23:05     ` tmoran
2002-10-16  1:45       ` Dr Nancy's Sweetie
2002-10-15 19:23   ` Dr Nancy's Sweetie

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox