Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Game: keyboard input 1

Status
Not open for further replies.

Oak

Programmer
Aug 6, 2000
77
0
0
CA
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
 
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.
 
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
 
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$ <> &quot;&quot; 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
 
Here's a way to make a continuous movement. You have to clear REP$ every loop. Try this code:

DO
REP$ = &quot;&quot;
REP$ = INKEY$
IF REP$ <> &quot;&quot; THEN PRINT REP$
LOOP UNTIL REP$ = CHR$(13)
 
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$ = &quot;N&quot;
CASE CHR$(0) + CHR$(75): NouvCompa$ = &quot;O&quot;
CASE CHR$(0) + CHR$(77): NouvCompa$ = &quot;E&quot;
CASE CHR$(0) + CHR$(80): NouvCompa$ = &quot;S&quot;
CASE CHR$(27): END
END SELECT

Tag = 0
SELECT CASE NouvCompa$
CASE &quot;N&quot;
Pix1 = POINT(CurX - 1, CurY - 2)
Pix2 = POINT(CurX + 13, CurY - 2)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;N&quot;
CurY = CurY - 1
Tag = 1
END IF
CASE &quot;O&quot;
Pix1 = POINT(CurX - 2, CurY - 1)
Pix2 = POINT(CurX - 2, CurY + 13)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;O&quot;
CurX = CurX - 1
Tag = 1
END IF
CASE &quot;E&quot;
Pix1 = POINT(CurX + 14, CurY - 1)
Pix2 = POINT(CurX + 14, CurY + 13)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;E&quot;
CurX = CurX + 1
Tag = 1
END IF
CASE &quot;S&quot;
Pix1 = POINT(CurX - 1, CurY + 14)
Pix2 = POINT(CurX + 13, CurY + 14)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;S&quot;
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$ = &quot;N&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;O&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;E&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;S&quot; THEN : PUT 'PacMan Sprite
CASE 6 TO 10
IF Compa$ = &quot;N&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;O&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;E&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;S&quot; THEN : PUT 'PacMan Sprite
CASE 11 TO 15
IF Compa$ = &quot;N&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;O&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;E&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;S&quot; THEN : PUT 'PacMan Sprite
CASE 16 TO 20
IF Compa$ = &quot;N&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;O&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;E&quot; THEN : PUT 'PacMan Sprite
IF Compa$ = &quot;S&quot; THEN : PUT 'PacMan Sprite
END SELECT

SCREEN 7, 0, 0, 0: PCOPY 2, 0: PCOPY 1, 2
LOOP
 
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.
 
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
 
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
 
Have you considered moving some of your code? Such as:

SELECT CASE Clef$
CASE CHR$(0) + CHR$(72)
NouvCompa$ = &quot;N&quot;
Pix1 = POINT(CurX - 1, CurY - 2)
Pix2 = POINT(CurX + 13, CurY - 2)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;N&quot;
CurY = CurY - 1
Tag = 1
END IF
CASE CHR$(0) + CHR$(75)
NouvCompa$ = &quot;O&quot;
Pix1 = POINT(CurX - 2, CurY - 1)
Pix2 = POINT(CurX - 2, CurY + 13)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;O&quot;
CurX = CurX - 1
Tag = 1
END IF
CASE CHR$(0) + CHR$(77)
NouvCompa$ = &quot;E&quot;
Pix1 = POINT(CurX + 14, CurY - 1)
Pix2 = POINT(CurX + 14, CurY + 13)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;E&quot;
CurX = CurX + 1
Tag = 1
END IF
CASE CHR$(0) + CHR$(80)
NouvCompa$ = &quot;S&quot;
Pix1 = POINT(CurX - 1, CurY + 14)
Pix2 = POINT(CurX + 13, CurY + 14)
IF Pix1 = 0 AND Pix2 = 0 THEN
Compa$ = &quot;S&quot;
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.
 
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
 
If you change the repeat rate in BIOS it works for DOS progs. At least, it does for my old DOS wordprocessor.
 
.
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

 
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
 
It seems to me that the effect that Oak wants to eliminate is the so-called &quot;typematic delay&quot; -- 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 &quot;scan code&quot; of the key you pressed, and then raises an &quot;interrupt request line&quot; on the processor, which causes it to run a little routine called an &quot;interrupt handler&quot; -- 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 &quot;poll&quot; 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.
[tt]
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 &quot;1&quot;;
ELSE
COLOR
7
PRINT &quot;0&quot;;
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
[/tt]
 
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)
Code:
DO while inkey$<>chr$(27)
If inkey$=&quot;t&quot; then print &quot;t&quot;
LOOP
FASTER!!!:

Code:
Kb$=inkey$
Do while Kb$<>chr$(27)
if Kb$=&quot;t&quot; then print &quot;t&quot;
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
 
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.

 
Hello,
I tried accessing the website (also tried 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!
 
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.
 
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
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top