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
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
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
Are you looping it? If you are, then it might be a device problem rather than a coding problem
RE: Game: keyboard input
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
DO
REP$ = ""
REP$ = INKEY$
IF REP$ <> "" THEN PRINT REP$
LOOP UNTIL REP$ = CHR$(13)
RE: Game: keyboard input
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
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
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
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
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
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
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
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
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
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
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
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
RE: Game: keyboard input
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
RE: Game: keyboard input
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
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
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
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
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
RE: Game: keyboard input
I seem to have forgotten to post the assembler routine
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