×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Game: keyboard input

Game: keyboard input

Game: keyboard input

(OP)
I everybody!
I've got a problem about keyboard's INKEY simpling rate.
I'm on old video games projects; Mr.Do and PacMan likes.

My problem stand while I try to make a change in the character direction. Even if I keep a key down(arrow-up for exemple) my character wont turn every time I tell him.

The only way to make him execute command on every time is to interrupt the program execution each time the instruction pointer pass on the INKEY$ statement(slowing the video refreshing rate to a critical point - to not say unacceptable)

I've tried the ON KEY() statement but get a similar interruption rate.

I think that question's a particuliary point of interest for Qbasic game programming which the keyboard's a important input device.

Can you help?
Thanks
Oak

RE: Game: keyboard input

Not sure what you are after, but it sounds like it's a coding problem since the character won't turn accordingly.

Can you post some code of the area that is giving you problems?

--MiggyD

Never be afraid to try something new. Remember that amateurs built the Ark. Professionals built the Titanic.

RE: Game: keyboard input

It sounds like he's saying that the code doesn't always pick up the input for INKEY$.

Are you looping it?  If you are, then it might be a device problem rather than a coding problem

RE: Game: keyboard input

(OP)
Cool. First, Thanks for your interest!

I difficulty could print my codes here. I'm not a professionnal and I write my code a way that is for many of you, a messy way.

But lets consider that-­­>

SCREEN 7,0,1,1
'Putting the background code here
DO
SCREEN 7,0,2,0: PCOPY 1,2
<INKEY$'s here>
'PacMan's sprite is calculated and displayed here
'Phantom's sprites are calculated and displayed here
SCREEN 7,0,0,0: PCOPY 2,0: PCOPY 1,2
LOOP

The problem result in the fact that the INKEY$ function isn't fast enough->

 Int  |  -        -   -   -   -   -   -   -   -
      |
      |
      --------------------------------------------->
      0s                0.01s                    t

To explain this, I've tried a pretty simple program->

SCREEN 9: CLS
DO
REP$ = INKEY$
IF REP$ <> "" THEN PRINT REP$
LOOP UNTIL REP$ = CHR$(13)
END

If you run this simple, you would notice that even if you HOLD a key, the result will not end in a continuous output on the screen. It will take the form I've wrote on the graphic above.

I hope that I've been a little more clearer this time for you to understand. Notice me if I really have to put my code here.

Oak

RE: Game: keyboard input

Here's a way to make a continuous movement.  You have to clear REP$ every loop.  Try this code:

DO
REP$ = ""
REP$ = INKEY$
IF REP$ <> "" THEN PRINT REP$
LOOP UNTIL REP$ = CHR$(13)

RE: Game: keyboard input

(OP)
Well, I guess it would help if I get the code there.:)

I've proceded this way-­>

First, I use SCREEN 7,0,1,1 for the background display.
Then I went into a LOOP for the game playing->
  - I first treat the keyboard input:
    ¤ I used 2 variables: NouvCompa$ and Compa$. NouvCompa$
      is use as a temporary variable and Compa$ stand for
      the real moving processing.
    ¤ The input keys go into NouvCompa$ then I use SELECT
      CASE for treating the validity of the move. The last
      thing I want is to watch my sweet sprite crashing
      against walls on ALL input.:)
    ¤ I use a pixel check for defining if the sprite can
      make a change in a direction and detecting walls. If
      so, then I put NouvCompa$ into Compa$ for the move
      processing. If not, then I keep my old Compa$ value
      for keeping the sprite to travel the same way that it
      does.
  - After that, I switch page and PUT sprites over the
    maze. TicTac stand for the PacMan animation ->
    Mouth = Close-> Open-> WideOpen-> Open
  - Few!!

Well, I hope you'll enjoy!:) If ever of you got a better way to proceed, I'll be very happy to read your ideas!

Thanks,
Oak

------------------------------------------------------------
SCREEN 7,0,1,1
'Displaying the background maze

DO
Clef$ = INKEY$
SELECT CASE Clef$
  CASE CHR$(0) + CHR$(72): NouvCompa$ = "N"
  CASE CHR$(0) + CHR$(75): NouvCompa$ = "O"
  CASE CHR$(0) + CHR$(77): NouvCompa$ = "E"
  CASE CHR$(0) + CHR$(80): NouvCompa$ = "S"
  CASE CHR$(27): END
END SELECT
 
Tag = 0
SELECT CASE NouvCompa$
  CASE "N"
    Pix1 = POINT(CurX - 1, CurY - 2)
    Pix2 = POINT(CurX + 13, CurY - 2)
    IF Pix1 = 0 AND Pix2 = 0 THEN
      Compa$ = "N"
      CurY = CurY - 1
      Tag = 1
    END IF
  CASE "O"
    Pix1 = POINT(CurX - 2, CurY - 1)
    Pix2 = POINT(CurX - 2, CurY + 13)
    IF Pix1 = 0 AND Pix2 = 0 THEN
      Compa$ = "O"
      CurX = CurX - 1
      Tag = 1
    END IF
  CASE "E"
    Pix1 = POINT(CurX + 14, CurY - 1)
    Pix2 = POINT(CurX + 14, CurY + 13)
    IF Pix1 = 0 AND Pix2 = 0 THEN
      Compa$ = "E"
      CurX = CurX + 1
      Tag = 1
    END IF
  CASE "S"
    Pix1 = POINT(CurX - 1, CurY + 14)
    Pix2 = POINT(CurX + 13, CurY + 14)
    IF Pix1 = 0 AND Pix2 = 0 THEN
      Compa$ = "S"
      CurY = CurY + 1
      Tag = 1
    END IF
END SELECT
IF Tag = 0 THEN NouvCompa$ = Compa$

SCREEN 7, 0, 2, 0: PCOPY 1, 2
 
IF TicTac = 20 THEN TicTac = 0
  TicTac = TicTac + 1
  SELECT CASE TicTac
    CASE 1 TO 5
      IF Compa$ = "N" THEN : PUT 'PacMan Sprite
      IF Compa$ = "O" THEN : PUT 'PacMan Sprite
      IF Compa$ = "E" THEN : PUT 'PacMan Sprite
      IF Compa$ = "S" THEN : PUT 'PacMan Sprite
    CASE 6 TO 10
      IF Compa$ = "N" THEN : PUT 'PacMan Sprite
      IF Compa$ = "O" THEN : PUT 'PacMan Sprite
      IF Compa$ = "E" THEN : PUT 'PacMan Sprite
      IF Compa$ = "S" THEN : PUT 'PacMan Sprite
    CASE 11 TO 15
      IF Compa$ = "N" THEN : PUT 'PacMan Sprite
      IF Compa$ = "O" THEN : PUT 'PacMan Sprite
      IF Compa$ = "E" THEN : PUT 'PacMan Sprite
      IF Compa$ = "S" THEN : PUT 'PacMan Sprite
    CASE 16 TO 20
      IF Compa$ = "N" THEN : PUT 'PacMan Sprite
      IF Compa$ = "O" THEN : PUT 'PacMan Sprite
      IF Compa$ = "E" THEN : PUT 'PacMan Sprite
      IF Compa$ = "S" THEN : PUT 'PacMan Sprite
  END SELECT
  
SCREEN 7, 0, 0, 0: PCOPY 2, 0: PCOPY 1, 2
LOOP

RE: Game: keyboard input

If you still want to Cut/Paste your code...

Save your code as (Text - readable by other programs).
Then change the file's extension from BAS to TXT.
and you're all done. (now you can use EDIT [from DOS] or NOTEPAD [from WINs] to read it.)

If you want to use QB again you can open the file directly as it is named (.txt) or reverse the above process.

Also, if your code's a bit messy, not to fret.  That's part of being a programmer...create something, test, then revise it, test again, then revise that, test again [vicious isn't it?].

I'll try working on what you have posted so far and see where that leads and get back to you.

--MiggyD

Never be afraid to try something new. Remember that amateurs built the Ark. Professionals built the Titanic.

RE: Game: keyboard input

(OP)
Well, I think that it will be difficult to send you more; the rest of the code stands about sprites itself.
  Like- Put (curX,CurY),PacEastWideOpen%,XOR
and it will be a little bit hard to send you my .SPR files that contains drawing of Pacman.

I'm not at home now but I'll try anyway later.:)

Thanks for your interest,
oak

RE: Game: keyboard input

(OP)
I've forget to tell about my computer-
  I'm working on a Pentium 120MHz
Maybe you don't experience what i'm talking about on yours but it doesn't change anything about the code priority like checking the keyboard, resuming to the next statement, and so on...

Maybe input seem to be smooth on most of your PC but i hope that you'll understand that the processing surly be the same but pretty much faster.

Thanks,
oak

RE: Game: keyboard input

Have you considered moving some of your code? Such as:

SELECT CASE Clef$
    CASE CHR$(0) + CHR$(72)
        NouvCompa$ = "N"
        Pix1 = POINT(CurX - 1, CurY - 2)
        Pix2 = POINT(CurX + 13, CurY - 2)
        IF Pix1 = 0 AND Pix2 = 0 THEN
            Compa$ = "N"
            CurY = CurY - 1
            Tag = 1
        END IF
    CASE CHR$(0) + CHR$(75)
        NouvCompa$ = "O"
        Pix1 = POINT(CurX - 2, CurY - 1)
        Pix2 = POINT(CurX - 2, CurY + 13)
        IF Pix1 = 0 AND Pix2 = 0 THEN
            Compa$ = "O"
            CurX = CurX - 1
            Tag = 1
        END IF
    CASE CHR$(0) + CHR$(77)
        NouvCompa$ = "E"
        Pix1 = POINT(CurX + 14, CurY - 1)
        Pix2 = POINT(CurX + 14, CurY + 13)
        IF Pix1 = 0 AND Pix2 = 0 THEN
            Compa$ = "E"
            CurX = CurX + 1
            Tag = 1
        END IF
    CASE CHR$(0) + CHR$(80)
        NouvCompa$ = "S"
        Pix1 = POINT(CurX - 1, CurY + 14)
        Pix2 = POINT(CurX + 13, CurY + 14)
        IF Pix1 = 0 AND Pix2 = 0 THEN
            Compa$ = "S"
            CurY = CurY + 1
            Tag = 1
        END IF
    CASE CHR$(27)
        END
END SELECT


instead?

If you can mail me a compressed/zipped copy of your code files, I'll take a look at them.  Otherwise, I believe the above will help process the keystrokes a little better.

My general box is miggyd2000@yahoo.com.

Another thing to consider is the KEY REPEAT DELAY rate--normally found in CONTROL PANEL > KEYBOARD.  I have mine on the shortest delay (I've only noticed that it works best with 133MHz or less--with this new sys I have it is virtually imperceptible).

--MiggyD

Never be afraid to try something new. Remember that amateurs built the Ark. Professionals built the Titanic.

RE: Game: keyboard input

Miggyd:
  The key repeat delay is only set for Windows, it does not copy any of the keyboard setup to Qbasic or any other DOS programs

RE: Game: keyboard input

If you change the repeat rate in BIOS it works for DOS progs. At least, it does for my old DOS wordprocessor.

RE: Game: keyboard input

.
Oak,

Try this INKEY$ routine and see if it leads you in the right direction.

Dr. Jon


DEFINT G-Z: DEFSTR A-F
CLEAR : SCREEN 7
a1 = CHR$(0) + CHR$(72)  ' up arrow
a2 = CHR$(0) + CHR$(75)  ' left arrow
a3 = CHR$(0) + CHR$(77)  ' right arrow
a4 = CHR$(0) + CHR$(80)  ' down arrow
a5 = CHR$(27)                  ' escape

LINE (0, 0)-(101, 51), 4, B

x = 50: y = 25: x1 = 2: y1 = 2

a:
a = INKEY$
PSET (x - x1, y - y1), 0 : PSET (x, y), 14
IF a = a1 AND y > 4 THEN y = y - 2: y1 = -2: x1 = 0: GOTO a
IF a = a2 AND x > 4 THEN x = x - 2: x1 = -2: y1 = 0: GOTO a
IF a = a3 AND x < 98 THEN x = x + 2: x1 = 2: y1 = 0: GOTO a
IF a = a4 AND y < 48 THEN y = y + 2: y1 = 2: x1 = 0: GOTO a
IF a = a5 THEN END
GOTO a

RE: Game: keyboard input

(OP)
Thanks for your tips.

Dr.Jon's response has rise an other question that has nothing to do with this current thread, but anyway..

  Is the use of LABEL's correct or not?

I've read that a programmer's rate of efficacity is inversely proportional of is use of LABEL. Hum, but I've begin to learn about assembly language and found that LABEL is a important part(if not vital) of the code. So, if you have any idea about this, maybe an other thread is on the way.

Oak

RE: Game: keyboard input

It seems to me that the effect that Oak wants to eliminate is the so-called "typematic delay" -- the pause between when you press a key and the time it starts repeating. This can only be done by taking keyboard input directly from the keyboard. This is best done with an assembler routine, but it possible to hack something up with QuickBASIC that will work 99.99% of the time or somesuch (but will lose the occasional key -- it is unavoidable).

Here's how the keyboard works: when you press a key, the controller on the motherboard reads the "scan code" of the key you pressed, and then raises an "interrupt request line" on the processor, which causes it to run a little routine called an "interrupt handler" -- in this case, the INT 9 handler. The handler reads the scan code from the controller, as well as a single bit that says whether the key was pressed or released, and then processes the data appropriately. These routines can often be quite tricky to write, depending on into what form you want the information converted. Typical keyboard interrupt handlers convert the scan code into ASCII characters and provide them for input for routines such as INKEY$.

The mechanism whereby the keyboard handler reads the scan codes from the controller is provided in QBASIC as well through the INP() function. The port number is &H60 (some people prefer to use the decimal equivalent, 96). When you read a byte from port &H60, the lower 7 bits of the byte are the scan code and the most significant bit is the status bit. If the status bit is set, then the key is being released; if it is clear, the key is just being pressed.

Armed with this information, and the knowledge that while the keyboard interrupt handler has the interrupt to tell it when to start processing information, you have no idea when it is going to change, it is not too difficult to write a routine which keeps track of which keys are pressed by their scancode. You need an array that stores the status of each key, and you need to very regularly "poll" port &H60 and update the array appropriately. The following code demonstrates this, and can be fairly easily adapted into your program. A listing of scan codes is hidden inside the QBASIC help file; you should be able to find a link to it under the 'KEY' help page.

DIM keyDown%(127) '127 is the maximum scan code

CLS
DO

 updateKeyboardArray 'must be called at least 30 times per second

 LOCATE 1, 1
 FOR i% = 0 TO 127
  IF (i% AND 15) = 0 THEN PRINT
  IF
keyDown%(i%) THEN
   COLOR
15
   PRINT "1";
  ELSE
   COLOR
7
   PRINT "0";
  END IF
 NEXT
i%
LOOP UNTIL keyDown%(1) ' scan code 1 corresponds to the escape key

SUB updateKeyboardArray
SHARED keyDown%()

 byteValue% = INP(&H60)

 status% = (byteValue% AND 128) <> 0
 scanCode% = (byteValue% AND 127)

 keyBeingPressed% = (status% = 0)
 keyDown%(scanCode%) = keyBeingPressed%
END SUB

RE: Game: keyboard input

Hmm, Inkey$ is not the best thing to use ... simply put.. it is terrible, now if you absolutey HAVE to use Inkey$ then the computer responds faster to keyboard commands, if you define Inkey$ as another variable, confused yet ???....

example: (This is slower)

DO while inkey$<>chr$(27)
If inkey$="t" then print "t"
LOOP

FASTER!!!:


Kb$=inkey$
Do while Kb$<>chr$(27)
if Kb$="t" then print "t"
loop

If you are using process heavy routines, and the movement is really!!! slow, you should try the INP(&HA060) routine...
can't be bothered explaining it... read Darkdreads RPG tutorials (even if you AREN'T developing an rpg) at www.qbrps.com

RE: Game: keyboard input

(OP)
Right on!!

If someone know a reference to others interrupts codes such INP(&h60), don't forget to send us a such precious tips!
 
Special thanks to logiclrb.

RE: Game: keyboard input

Hello,
I tried accessing the website www.qbrps.com ; (also tried www.qbrpg.com just to see if it was a typo) and the link is broken. Anyone know where I can find this RPG tutorial?  I'm curious about this INP(&HA060) routine as well as what else it might have to say.  Thanks!

RE: Game: keyboard input

Again, I am somewhat disappointed that people are not reading the entire post before posting. sandmann999, my post immediately prior to that by Rathgar contains code that uses the INP() method.

RE: Game: keyboard input

(OP)
Is there something special about arrows keys(72,75,77,80)?
Using INP(), all keys are responding PRETTY much faster; but arrows are kind of sticky: when I release them, they still input data so that the program control's over again.

It might have a way to avoid this but I just wanted to know.

Thanks
Oak

RE: Game: keyboard input

Oh come on now. Oak, just read the post I made! It explains it all!

RE: Game: keyboard input

(OP)
logiclrd,
Sorry but I just can't find an answer about ARROWS. They doesn't seem to respond like all other keys. Even in your previous post that contain a program about scan codes, arrows are acting sticky-> when I relaese 'em, the "1" still. I talk about arrows by-themself (not them on the calculator wish respond like all the others).

Oak

RE: Game: keyboard input

Have you tried it on any other keyboards? It could be that your keyboard is sending out the "extended" scan code in the opposite order of most keyboards and so the value returned by INT(&H60) is changing twice rapidly -- first to the actual release code, and then to the 'extended key' release code. Other keyboards send it in the other order -- the actual release code after the extended scan -- and so it works smoothly.

If this is the case, then you will need to use an actual interrupt handler to catch the release code. I have written one in assembler callable from QB with extensive functionality, if you are interested.

RE: Game: keyboard input

(OP)
I didn't try it on other keyboard. Ouah! What a mess! My keyboard COULD do tricky things?? It's sound like I went into something bigger then I though!! Few!!

I tried to make a PacMan game for my REAL first try and got cought into... a sticky problem... FEW!!

Well, I guess it will never be easy!

So, I'm interest in your assembly interrupt handler; I got a base on assembly so I gest it couldn't be worst!

thanks
Oak

RE: Game: keyboard input

I had the same problem with the arrow keys – when I pushed more than one arrow key down at the same time, sometimes one would ‘stick’ and continue telling my program it was pushed down after I lifted the keys up (I'm using logiclrd's code).  I discovered that if you set keyDown(i%) to 0 after reading it, the keys no longer stick.  However, this prevents the computer from scanning for more than one key at a time.  If down and left are pushed, for example, one of the keys is ignored.
An excerpt from the code:

  IF keyDown%(i%) THEN
   COLOR 15
   PRINT "1";
   keyDown%(i%) = 0         'I added this line here
  ELSE
   COLOR 7
   PRINT "0";
  END IF

RE: Game: keyboard input

Another question that I have about this.  If I wanted to press and HOLD two keys at once, even if I use this code that reads two imputs at one time, if I hold the keys down, it will then only repeatedly read the last one to be pressed.
How would I make it so that if I press and HOLD more then one key at a time, it continues to read all the keys that are being held?

RE: Game: keyboard input

sandmann999, just don't use the 'keyDown%(i%) = 0' line that mgh730 proposed. Alternately, you can use an assembler module that implements it properly, as an interrupt service routine, but this throws a spanner into debugging your code, since the IDE no longer receives the keyboard events ^_^

RE: Game: keyboard input

Oak,

I seem to have forgotten to post the assembler routine Good thing this thread got awakened.

I have posted the files, along with an example .BAS file, at the following URL:

http://israel.logiclrd.cx:8080/kbd/

The example .BAS shows how to use the routine. It has many features: it automatically calculates demicardinal direction from the arrow keys, it queues keydown/keyup messages into a buffer 128 entries long, and it keeps track of which keys are down (using an INTEGER for each key, so you can just check the array offset). It shows it all there

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close