Do more than one thing at the same time?

This is a discussion on Do more than one thing at the same time? within the C Programming forums, part of the General Programming Boards category; I'm testing my skills by writing a snake clone. It's pretty much finished but I'm stuck with one major problem; ...

  1. #1
    Mad OnionKnight's Avatar
    Join Date
    Jan 2005
    Location
    Umeň, Sweden
    Posts
    555

    Do more than one thing at the same time?

    I'm testing my skills by writing a snake clone. It's pretty much finished but I'm stuck with one major problem; I can't get it to both listen for a keypress and move the snake forward.
    Right now the function I use for getting a keypress looks like this.

    Code:
    void getkey(void)
    {
        key = getch();
        if (key == 0)
            key = getch() + 256;
        switch (key) {
            case LEFT:
            case RIGHT:
            case UP:
            case DOWN:
            dir[1] = dir[0];
            dir[0] = key;
            break;
        }
        if ((dir[1] == RIGHT && dir[0] == LEFT) || (dir[1] == LEFT && dir[0] == RIGHT) || (dir[1] == UP && dir[0] == DOWN) || (dir[1] == DOWN && dir[0] == UP))
            dir[0] = dir[1];
    }
    And whenever it gets there, it will wait for a keypress and not do anything else till you do so.
    A friend mentioned something called "threads" but didn't know much about it, Google isn't being helpful either because searching for "threads" will result in links to various message boards.

  2. #2
    return 0;
    Join Date
    Jan 2005
    Location
    Netherlands
    Posts
    89
    You could use the _beginthread function, it's used like this:

    _beginthread(manageKeys,0,NULL);

    The manageKeys function would have to look like this:

    void manageKeys(void *p);

    When calling the _beginthread function, it creates a new thread and executes the manageKeys function in it. Your program should look something like:

    Code:
    void manageKeys(void *p);
    
    int dir[1000]; // this is the dir array you used in your sample code, don't know if it's the right type and stuff, doesn't matter too much
    
    
    
    int main() {
      // initial code
    
      _beginthread(manageKeys,0,NULL);
    
      while(1) {
         // Move the snake here
      }
    
      return 0;
    }
    
    void manageKeys(void *p) {
      while(1)
        getkey();
    
      _endthread();
    }

  3. #3
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,505
    Which OS and compiler are you using?

    http://faq.cprogramming.com/cgi-bin/...&id=1043284392
    This FAQ has some suggestions on testing to see if there is any keyboard input without stopping your program.
    Basically, you do
    Code:
    while ( 1 ) {
      if ( keypressed() ) {
        read_key();
        change_direction();
      }
      move_snake();
      draw_snake();
      detect_collisions();
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  4. #4
    Mad OnionKnight's Avatar
    Join Date
    Jan 2005
    Location
    Umeň, Sweden
    Posts
    555
    I'm using Borland C++ on Windows.

    When I tried _beginthread() I got "Call to function '_beginthread' with no prototype in function main" and the second one I didn't really understand, isn't that what I'm already using?

  5. #5
    return 0;
    Join Date
    Jan 2005
    Location
    Netherlands
    Posts
    89
    In Salem's solution you should use kbhit() (which is defined in conio.h). kbhit() will check wether a key is pressed, if so it will return 1, otherwhise it will return 0. So it should be something like

    Code:
    if(kbhit()) {
      int key = getch();
      // change direction
    }
    
    // move snake

  6. #6
    Mad OnionKnight's Avatar
    Join Date
    Jan 2005
    Location
    Umeň, Sweden
    Posts
    555
    That worked, but not like I wanted it to. It only gets the key before it starts waiting a second, and only then. So you had to hold down a arrow key and hope it got caught by kbhit().

  7. #7
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    If this is for a DOS program you will need to write an int 09h handler for your keyboard to work correctly.

    The default BIOS handler pretty much sucks at everything related to low-latency ease-of-use multi-key detection compatible stuff.

    But you must be in DOS to do it and yes, it does work on XP.

    Code:
    #ifdef __cplusplus
      #define __CPPARGS ...
    #else
      #define __CPPARGS
    #endif
    
    #include <dos.h>
    
    #define TRUE 1
    #define FALSE 0
    
    int HandlerInstalled;
    
    void interrupt (*OldHandler)(__CPPARGS);
    int keys[255];
    
    void interrupt NewHandler(__CPPARGS)
    {
      int keypress=inportb(0x60);
      
      if (keypress>127)
     {
        keys[keypress & 0x7F]=0;
     } else keys[keypress]=1;
    
      //Send EOI to PIC
      outportb(0x20,0x20);
    }
    
    void InstallHandler(void)
    {
      
      atexit(UnInstallHandler);
      OldHandler=getvect(0x09);
    
      setvect(0x09,NewHandler);
      HandlerInstalled=TRUE;
    }
    
    void UnInstallHandler(void)
    {
       if (HandlerInstalled)
      {
        setvect(0x09,OldHandler);
        HandlerInstalled=FALSE;
      }
    }
    
    int GetKeyState(int scancode)
    {
      //No checking to see if scancode is valid or in range
      return keys[scancode];
    }
    There is another version of this that uses 0x96 to retrieve the key, but I left it out.
    I hope there are not any errors in this....but if this is for DOS this code will do what you want.

    Call InstallHandler to install the keyboard handler.

    Don't press CTRL-BRK during debug...the new handler will be not be uninstalled - and hence you will have to reboot.

    Call UnInstallHandler to remove it from the interrupt vector table and restore the IVT.

    This code registers UnInstallHandler with atexit() so on a normal exit the handler will be correctly uninstalled.

  8. #8
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,528
    Quote Originally Posted by OnionKnight
    And whenever it gets there, it will wait for a keypress and not do anything else till you do so.
    A friend mentioned something called "threads" but didn't know much about it, Google isn't being helpful either because searching for "threads" will result in links to various message boards.
    You can find out more on posix threads here.
    Ditch the win32 search term and you will yield a lot more information on the subject as well.

    ~/

  9. #9
    Mad OnionKnight's Avatar
    Join Date
    Jan 2005
    Location
    Umeň, Sweden
    Posts
    555
    The if (kbhit()) actually worked, problem was that I had the sleep() function after it, instead of before it.

    A little off topic: I'm stuck with sleep(). Why won't delay() work? According to my googling around, it should be there in my version of Borland C++ (version 5.5.1). When I look in dos.h, there is no prototype for it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Execution Time - Rijandael encryption
    By gamer4life687 in forum C++ Programming
    Replies: 5
    Last Post: 09-20-2008, 09:25 PM
  2. The new FAQ
    By Hammer in forum A Brief History of Cprogramming.com
    Replies: 34
    Last Post: 08-30-2006, 10:05 AM
  3. Read and set\change system time
    By Hexxx in forum C++ Programming
    Replies: 9
    Last Post: 01-02-2006, 06:11 AM
  4. calculating user time and time elapsed
    By Neildadon in forum C++ Programming
    Replies: 0
    Last Post: 02-10-2003, 05:00 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21