Copy Link
Add to Bookmark
Report
Qbasic Developers Forum issue 1
-=-=-=-=-=-=-=-=-=-=-=-=-=-
= Qbasic =
- Developers -
= Forum =
-=-=-=-=-=-=-=-=-=-=-=-=-=-
Issue I
Qbasic Developers Forum is a FREE newsletter made for Advanced Basic
Programming. BASICA/GW-BASIC, Qbasic, and QuickBasic coding methods
are discussed. It is written by Acidus Software. To obtain membership
Email me at:
LordAcidus@aol.com
************************************
*The FAT (Feature Allocation Table)*
************************************
(editorials)
-From the Acid Pool...
Acidus Software ideals and current projects
(features)
-"Ground Control to Major Tom..."
Modem Communications in Qbasic
-Morphing the Mouse
How to create and use your own mouse icons
-Player too
Supporting multi-player games in Qbasic
(every issue)
-Face Lift
Give speed Computability to your programs
-Quick Tips
Fast solutions to little annoying programming problems
-ABORT
Final Thoughts
-----------------
From the Acid pool
-----------------
Acidus Software is a small computer company that holds the ideal
that any action that can be done in a another computer language can be done
through BASIC. We are currently designing an OS through Qbasic, as well as
a real time war simulation game called Voices of Liberty(tm). A modem turn
based game similar to Masters of Orion is also being created. We also have
created an FULLY-FUNCTIONABLE BBS through GW-BASIC, Which supports Xmodem
Zmodem Uploading and Downloading.
--------------------------------
"Ground Control to Major Tom..."
--------------------------------
THE MODEM. ohhhh, its scary. To most, its a little magic boxes that
opens our computer to the world. In reality, it is very simple to use. The
modem takes bytes of info, turns it into a noise, and sends it over a phone
line. Theoretically, if you could whistle fast enough and at the right
pitches, you could send a file with the sounds you make. See, no voodoo magic
stuff. As for sending files, that's easy to. The modem sends a ASCII character
to tell the other computer it is sending a file. It then breaks up that file
into chunks and sends it in hunks of bytes (128, 1k, it depends). The modem
then waits for a ASCII character from the other computer telling it that all is
well, and to send the next hunk.
Ok, I've had my history lesson now, you say, but how do I do it in
Qbasic? SIMPLE. 4 commands are all you need for simple communications.
They are:
OPEN COM.........Open up the modem to get stuff from BASIC
INPUT$...........Gets stuff from the modem
LOC..............Tells you if the modem has any stuff from an outside source
PRINT #..........Send stuff to the modem
To start work with the modem, you have to open a "path" to it. This
is just like opening a file, except you use the "OPEN COM" statement. Here
is a sample:
OPEN "COM2:2400,N,8,1,RB2048,TB2048" FOR RANDOM AS #1
What the #&*! is that?!?, Just like opening a file he says? BULL!
Well, here is a secret, Opened Devices (Your modem) act just like opened
files.
Don't worry, the only thing you need to worry about is the number
between "COM" and ":" and the number between ":" and ",N". All the other
stuff deals with transmission settings and the RB TB things deal with
Uploading and Downloading. The first Number is COM port number your modem
is on. Because BASIC was created so long ago, you can only access ports 1
and 2. If you modem is not on COM port 1 or 2, there is a way around that,
but it can cause so big time errors with other programs because you manually
switch the memory addresses of the COM ports. Don't worry about that now,
I will go into that in another issue.
The 2nd number is the Baud. BAUD is the speed of the Modem. Qbasic
can't access COM ports at any higher speed than 9600, so if you have a 14.4
Modem, Qbasic can still use it, but it won't go any faster than 9600. Note
this restriction is for GW-BASIC, BASICA, and QBASIC. I don't know if
compiled QuickBasic programs have this restriction but I don't think they do.
To send stuff to your modem, you use the PRINT #n command, where n
is the file number, in this case 1. But there is no point sending stuff like
"Hello Chris" to your modem right now, because you are not connected to
anything. All you have done with the "OPEN COM" statement, is made a little
path from you modem to your program so they can talk to each other.
But you want to talk to an outside source, like a friend or a BBS,
you have to tell the modem to dial a number. To do this you must know that
ALL modems have a set of commands echoed on to their memory chips that make
them do stuff. You can't just say "Hey modem, dial up 770-555-9806", you have
to talk in the modem's language. This isn't as bad as it sounds. All commands
begin with "AT". Here are some common ones:
MODEM SPEECH TRANSLATION
-------------------------------------------
"ATDT###-###-####" | "Hey Modem, dial ###-###-####"
"ATZ" | "Hey Modem, This sucks, hang up the phone"
"ATS0=#" | "Wait until you someone calls and the phone rings
| # number of times, then try to connect modems"
"ATM2H1L#" | "Set your speaker Volume at # (1-3)"
So, if you wanted to call someone first you would use an OPEN COM
statement to ready the modem then you would use an INPUT statement
to get the phone number to dial as a string, than use PRINT #n to talk to the
modem. Here is an example of a simple phone dialer:
(replace COM# with the COM port your modem is on)
CLS
PRINT "Opening a Path to your Modem..."
OPEN "COM2:2400,N,8,1,RB7048,TB7048" FOR RANDOM AS #1
PRINT "Please Enter the Number you wish to Call"
INPUT PhoneNumber$
PRINT "Talking to your modem..."
PRINT #1, "ATDT" ;PhoneNumber$
PRINT "There you go, pick up the phone and talk"
PRINT "Press [ESC] to hang up
DO
LOOP UNTIL INKEY$ = CHR$(27)
PRINT #1, "ATZ"
But here comes the biggest problem of Modem control with Qbasic, HOW
DO I READ WHAT COMES FROM THE MODEM? Well there is a little Function called
LOC that does this. The syntax is:
LOC(n)
n is the file number which if you used my sample, would be 1
LOC tells you where in a file you are. File? I am not accessing a
file! you exclaim. As I said before, files and devices work the same way.
But with a modem, LOC tells if it has received anything. Fine, now you know
if the modem is getting stuff, put how do you know what it is getting? For
that you use the INPUT$(x,y) function.
INPUT$(x ,y)
x is the number of bytes to get from a file/device
y is the number of the opened file/device
"x" Should ALWAYS be 1. I know this means that only 1 character can
be read on each pass, but this way EVERY character is read, and none are
skipped. If you were getting an 11 byte transmission, and "x" was 2, only
the first 10 characters would be read (because it is a multiple of 2) the
last part would be skipped. This is way for NORMAL communications, keep "x"
as 1. I will going into Downloading in a later newsletter, in which "x" is
not 1. One last thing I will talk about is the "ATS0=#" command. You can
use this to wait for a call
Alright, I will put this all together give you a fully commented
communications program. You can use this to call up any BBS and interact
with it. Note I have not included any Downloading Abilities. I will Address
this as well as uploading through Qbasic using the Xmodem and Zmodem
protocols later:
'-------------------------
'Conn-X ver 1.0
CLS
PRINT "Conn-X Ver 1.0 Acidus Software(tm)"
PRINT "What COM port is your Modem on?"
INPUT ">", port$
baud$ = "9600" '9600 should work with most computers. If you have
'an older one use "2400"
'Open up that com port
OPEN "COM" + port$ + ":" + baud$+ ",N,8,1,RB2048,TB2048" FOR RANDOM AS #1
PRINT "You can:"
PRINT "1-Call someone"
PRINT "2-Wait for a call"
PRINT "3-Quit"
DO
a = VAL(INKEY$)
LOOP UNTIL a >= 1 and a <= 3 'Get choice
IF a = 3 THEN CLOSE : SYSTEM
IF a = 2 THEN GOTO wait
PRINT "Number to call?"
INPUT ">", number$
PRINT #1, "ATDT" + number 'tell the modem to dial the number
GOTO chat
wait:
PRINT #1, "ATS0=1" 'tell modem to connect after 1 ring
'When a modem connect it returns "CONNECT ####"
'The next hunk of code waits until the modem connects before moving on
a$ = ""
DO
IF LOC(1) THEN a$ = a$ + INPUT$(1, 1) 'if anything in modem add it to a$
LOOP UNTIL INSTR(a$, "CONNECT") 'Wait until modem have Connected
chat:
'If you where waiting for a call, a lot of ASCII character will be printed
'on the screen. Don't worry, that just the computers getting in sync and
'talking
'You also will not see what you type
CLS
PRINT "Conn-X CHAT, press [ESC] to quit
DO
t$ = INKEY$
IF LEN(t$) THEN PRINT #1, t$ 'if you typed something send it to the modem
'this will be send by the modem to the other
'computer
IF LOC(1) THEN r$ = INPUT$(1, 1)'if the is something to get, get it and save
'it as r$
IF LEN(r$) THEN PRINT r$; 'if r$ <> "" then print it. the ";" means a
'line is not started
LOOP UNTIL t$ = CHR$(27) 'keep doing this until [esc] is pressed
PRINT #1, "ATZ" 'tell the modem to hang up
CLOSE 'close the open com statement
'-------------------------
There you go, a simple communications program through Qbasic that
lets you talk to another computer. As I said Uploading/Downloading will be
discussed in a later newsletter
------------------
MORPHING THE MOUSE
------------------
Qbasic doesn't normal support mouse programming, but through "CALL
ABSOLUTE" the mouse can be accessed. But when you use it, you get an Arrow
looking thing, like in Windows. But in other games, you don't have just one
type of cursor. In "Command & Conquer", You have a wrench cursor to repair
stuff, a bull's eye to attack things, and so on. Even in windows you have
that hour glass.
When I began programming "Voices Of Liberty" for Acidus Software,
(Which is a real-time war simulator, similar to "Command & Conquer"), I
wanted to make it look as professional as possible. So I need a way to make
different cursors other then an arrow. After thinking about it for a very
long time, I realized that answer was so simple. I then spent about 6 hours
programming and perfecting, turning my prototype into a series of "SUBs" that
can be used in any program.
To change the cursor, I had to use "GET" and "PUT" using the mouse's
x and y coordinates. Now, before I go on, you have to know how the mouse
works in Qbasic. First off, the x and y coordinates are for ONE pixel above
the tip of the arrow. Also, the "CALL ABSOLUTE" that is used to access the
mouse returns that the screen is always 640x200. This means modifications
are necessary. "Voices of Liberty" uses Screen 1 because I am writing it
for CGA. Screen 1 is 320x200. when I use CALL ABSOLUTE to get the current
x coordinate, it returns say, 360. To find out where on a 320x200 screen it
is you must divide that by 2 (640/2=320) This converts the x coordinate into
Screen 1 dimensions. Even in Text mode, you have to divide the x
coordinate by 8 to get the column number (640/8=80 columns), and you must
divide the y coordinate by 8 as well to get the correct row (200/8=25 rows).
Here is a slice of code from Acidus Software's "Voices of Liberty"(tm) which
uses custom made pointers
'-------------------------
'POINTER1.BAS
'Prototype ver 3.7 of Voices Of Liberties
'The following are SUB programs that WEREN'T written by Acidus Software
'They simply load the mouse and check it x/y coordinates
DECLARE SUB MouseDriver (ax%, bx%, cx%, dx%)
DECLARE FUNCTION Initialize% ()
DECLARE SUB CursorOff ()
DECLARE SUB cursoron ()
DECLARE SUB GetMouse (lb%, rb%, xMouse%, yMouse%)
DECLARE SUB LocateCursor (x%, y%)
'The following are SUB used to make your own cursor
DECLARE SUB LoadPointer (load$)
DECLARE SUB MovePointer (xM%, yM%)
DIM SHARED PointerX
DIM SHARED PointerY
DIM SHARED DimX 'how many pixels wide the cursor is
DIM SHARED DimY 'how many pixels tall the cusur is
DIM SHARED pointer(100) 'The cursors image
DIM SHARED UnderPointer(100) 'image of what is under the cursor
'The following allows for mouse use in Qbasic. It is NOT written by Acidus
'Software
DIM SHARED Mouse$
Mouse$ = SPACE$(57)
FOR i% = 1 TO 57
READ a$
H$ = CHR$(VAL("&H" + a$))
MID$(Mouse$, i%, 1) = H$
NEXT i%
DATA 55,89,E5,8B,5E,0C,8B,07,50,8B,5E,0A,8B,07,50,8B
DATA 5E,08,8B,0F,8B,5E,06,8B,17,5B,58,1E,07,CD,33,53
DATA 8B,5E,0C,89,07,58,8B,5E,0A,89,07,8B,5E,08,89,0F
DATA 8B,5E,06,89,17,5D,CA,08,00
CLS
ms% = Initialize%
IF NOT ms% THEN
PRINT "Mouse not found"
END
END IF
'GOTO bypass 'UN comment this line after you run the program once
'the following lines of code make a cursor
'I make all my pointers 10x10
SCREEN 1
CLS
FOR y = 1 TO 10
FOR x = 1 TO 10
READ r
PSET (x, y), r
NEXT
NEXT
GET (1, 1)-(10, 10), pointer
DEF SEG = VARSEG(pointer(0))
BSAVE "cursor1.cpf", 0, 100
DATA 3,0,0,0,0,0,0,0,0,3
DATA 0,3,0,0,0,0,0,0,3,0
DATA 0,0,3,0,0,0,0,3,0,0
DATA 0,0,0,3,0,0,3,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,0,0,0,0,0,0,0
DATA 0,0,0,3,0,0,3,0,0,0
DATA 0,0,3,0,0,0,0,3,0,0
DATA 0,3,0,0,0,0,0,0,3,0
DATA 3,0,0,0,0,0,0,0,0,3
ByPass:
SCREEN 1
'This creates a random background for you to move your cursor over:
CLS
RANDOMIZE TIMER
FOR a = 1 TO 100
xx = INT(RND * 300) + 1
yy = INT(RND * 180) + 1
cc = INT(RND * 2) + 1
LINE (xx, yy)-(xx + 20, yy + 20), cc, BF
NEXT
'To call a custom cusur (which I call pointers) you must first load
'it. Be sure to put the correct wide and tall DIMs, because your cursor is
'centered on the tip of the default arrow head.
'You must also always turn off the cursor before loading a custom pointer
DimX = 10 '10 pixels wide
DimY = 10 '10 pixels tall
LoadPointer "Cursor1.cpf"
pointerloop:
DO
x = xMouse%
y = yMouse%
CALL GetMouse(lb%, rb%, xMouse%, yMouse%)
IF x <> xMouse% OR y <> yMouse% THEN MovePointer xMouse%, yMouse%
LOOP UNTIL INKEY$=CHR$(27)
STOP
SUB CursorOff
'Turns off the mouse cursor
ax% = 2
MouseDriver ax%, 0, 0, 0
END SUB
SUB cursoron
'Turn on the mouse cursor
ax% = 1
MouseDriver ax%, 0, 0, 0
END SUB
SUB GetMouse (lb%, rb%, xMouse%, yMouse%)
ax% = 3
MouseDriver ax%, bx%, cx%, dx%
lb% = ((bx% AND 1) <> 0)
rb% = ((bx% AND 2) <> 0)
xMouse% = cx%
yMouse% = dx%
END SUB
FUNCTION Initialize%
ax% = 0
MouseDriver ax%, 0, 0, 0
Initialize% = ax%
END FUNCTION
SUB LoadPointer (load$)
'Load the image of your custom pointer
DEF SEG = VARSEG(pointer(0))
BLOAD load$, 0
DEF SEG
'Find out the current x,y coordinates of the mouse
CALL GetMouse(lb%, rb%, xMouse%, yMouse%)
'The next statements make it so the center of your pointer is the x,y
'coordinates of the mouse by dividing the width and height by 2
'the xMouse%/2 is used to get the x coordinate into Screen 1 dimensions
'PointerX and PointerY are the top left coordinates of the pointers image.
'They are the top left corner because that is where the image must be PUT
'so that the center of the pointer is the returned x,y Mouse coordinates
PointerX = (xMouse% / 2) - INT(DimX / 2)
PointerY = yMouse% - INT(DimY / 2)
LOCATE 1: PRINT PointerX, PointerY
'The following make sure you stay inside the bounds of the screen
'in screen mode 1, the dimensions are 320x200, so change the following
'numbers if you have different dimensions (like 640x200)
IF PointerX < 1 THEN PointerX = 1
IF PointerX > 319 - (DimX) THEN PointerX = 319 - (DimX)
IF PointerY < 1 THEN PointerY = 1
IF PointerY > 199 - DimY THEN PointerY = 199 - DimY
'The next statement saves the image of what will be under your pointer
GET (PointerX, PointerY)-(PointerX + DimX, PointerY + DimY), UnderPointer
'The next statement places your pointer at that location
PUT (PointerX, PointerY), pointer, OR
END SUB
SUB LocateCursor (x%, y%)
'This moves your ax% = 4
cx% = x%
dx% = y%
MouseDriver ax%, 0, cx%, dx%
END SUB
SUB MouseDriver (ax%, bx%, cx%, dx%)
DEF SEG = VARSEG(Mouse$)
Mouse% = SADD(Mouse$)
CALL Absolute(ax%, bx%, cx%, dx%, Mouse%)
END SUB
SUB MovePointer (xM%, yM%)
'This sub is called when the mouse is moved to a new position
'1st replace the background
PUT (PointerX, PointerY), UnderPointer, PSET
'calculate the new location of the top right corner of your pointer
'the xM%/2 is to get the right Dimensions for screen 1
PointerX = (xM% / 2) - INT(DimX / 2)
PointerY = yM% - INT(DimY / 2)
'Make sure PointerX and PointerY are within Screen Dimensions
IF PointerX < 1 THEN PointerX = 1
IF PointerX > 319 - (DimX) THEN PointerX = 319 - (DimX)
IF PointerY < 1 THEN PointerY = 1
IF PointerY > 199 - DimY THEN PointerY = 199 - DimY
'Save the image under the pointer
GET (PointerX, PointerY)-(PointerX + DimX, PointerY + DimY), UnderPointer
'place the pointer
PUT (PointerX, PointerY), pointer, OR
END SUB
'-------------------------
There you go. This method is very useful, and with a little tinkering
you could make it support many different custom cursors.
----------
PLAYER TOO
----------
Games. They pass the time. But think video games. What kind are
a lot of fun? The kind where you play with/against another human player.
Human players add an element of surprise to each game. They learn from
they past mistakes, and adopt new styles. Most Computers have a RANDOM
type feature in them somewhere, no matter how complex the Artificial
Intelligence is. So, to build multi-player, and thus, more enjoy programs,
Game coders MUST learn how to program for to players.
There are only 2 ways to have multi-player games in Qbasic, as on any
computer. One way is to play over a Modem/Network. The other way is to have
both characters play on the same computer.
Many people overlook how hard it is to support 2 players evenly
in Qbasic. A method I always see is both players use the same keyboard. This
method looks good, but doesn't work at all. Look at this example from a never
released Acidus Software game "Fighter's DANCE":
StartOfGameLoop:
...blah...
a$ = UCASE$(INKEY$)
if a$ = "4" THEN 'move player 1 left
if a$ = "6" THEN 'move player 1 right
if a$ = "0" THEN 'player 1 punches
if a$ = "A" THEN 'move player 2 left
if a$ = "D" THEN 'move player 2 right
if a$ = "\" THEN 'player 2 punches
...blah...
...blah...
GOTO StartOfGameLoop
There are BIG TIME flaws to this method. First, only one player can
move only once with ever GameLoop pass. Second, if say, Player 1, holds down
[6], then his character will move and Player 2 doesn't get the chance to do
anything.
The ONLY way to have 2 players play the keyboard is to use a lot of
"ON KEY(n) GOSUB label" statements. Another way to have 2 players play on
the same computer is if you have 2 joysticks. Use the STICK(n) and STRIG(n)
functions. The only way to Avoid the problem of one player hogging the input
such as in "FIGHTERS DANCE", you have to use these 2 methods.
A final way to have multi-player games is to use a Modem/Network.
Now, Networks are hard as #%&* to deal with. Since I don't have one at home
I can fool around with, I will not go into any form of Network programming
right now. Modems, however, I know quite a bit about. If you don't, read the
article entitled "Ground Control to Major Tom..." in this issue.
There are really 2 forms of Multi-player games using a Modem.
1-Real time
This means the same program is running on 2 different machines. Both
players go at the same time, and the Computer constantly talk to each other
updating each players status. This is how almost all the newer games are.
"Warcraft", "Command & Conquer", "Doom", and "Quake" are all examples of
Real-time modem games.
Real-time modem games are fun to play, because you must react
instantly to the other players moves. Real time also makes your game run
slower, because it must often (Normal once through each game loop), send and
receive game information. In complex games, transporting large strings of info
becomes a problem. I talk later on how to compress data, but I am currently
working on saving the game data as a binary file and sending the file across
the modem. I will go more into sending game data in file for in a later issue.
2-Turn based
This means a player does all his moves, then another player does all
his moves.
This is method is a older way of multi-player programming, but is
still quite good in the right situations. It is also faster because the modem
doesn't have to transmit ever second. It is only suited for some games because
you don't see what your opponent did until your next turn. There are 2 ways to
do this method.
2a-Turn based dual action
In this Both player are playing their game at once at there on
separate machines. The players do their stuff then select the end of their
turn. The computers then transmit all the new data. The next turn begins with
both players see what the other did last turn, and react. If one player ends
their turn before another player, they must wait until the other is done
before the new data arrives.
2b-Turn based single action
Each player moves one at a time, and then end their turn. At the end
of the turn, The computers transmit new data, and the next person can go. This
was the first kind of multi-player games, and are very slow because you have
to wait until the other person is done before you can move. This method
is good for games like chess, and other board-game type games. Simple war
games are also programmed using this method.
To transmit game information over a modem, you must have a way to
tell where a number ends, and where it begins. Else "8210" could be a 8 and
210, 82 and 10, or 821 and 0. I don't recommend sending strings of actual
text across a modem, because of the extra time it takes. Now for an
example. Lets say I am playing a racing game and I need to tell send only
my current place, speed, and distance traveled to the other computer. I would
use my system of make all these number 3 digits, so that way since all the
numbers are 3 digits long, the other computer can extract them corrected.
lets say I'm in 3rd place, going 127mph, and I've gone 41 miles so far.
I would make 3 be 003, the speed can stay as is because it is already 3
digits, and distance would become "041"
This FUNCTION returns a string representation of any number pumped
into it as a 3 digit string.
FUNCTION MakeString$(x)
if x>=1000 then
print "Number more than 3 digits"
MakeString$=""
exit function
end if
if x>=100 then '3 digit
MakeString$=mid$(str$(x),2,3) 'the mid$ function is used because when ever
'you convert a number to a string, a space is
'automatically added to the beginning by BASIC
'The mid$ is used to bypass it so your string
'contains only numbers
exit function
end if
if x>=10 then '2 digits
MakeString$="0"+mid$(str$(x),2,2)
exit function
end if
'Must be 1 digit
MakeString$="00"+mid$(str$(x),2,1)
end function
I then would piece these 3 integers into a single string of numbers to
transmit. I would use a code tidbit thing this:
SendMe$=MakeString$(place)+MakeString$(speed)+MakeString$(distance)
Using the numbers I gave before, you would send a string that looked
like this:
"003127041"
You than send it over the modem using PRINT #n,SendMe$. The receiving
computer gets the values you sent by a code hunk similar to the following.
receive$=""
Do
if loc(1) then receive$=input$(loc(1),1)
loop until len(receive$)=9 'wait until all numbers are received
'Extract the values from ,the received string
OtherPlayersPlace=val(mid$(receive$,1,3))
OtherPlayersSpeed=val(mid$(receive$,4,3))
OtherPlayersDistance=val(mid$(receive$,7,3))
There you go, a simple way to transmit game information over the
modem thus created multi-player games.
----------
Face Lift
----------
Don't you hate it when you are playing some game for Basic and
you get a "Enter Speed (1-9000)"-type message. It is SO unprofessional. It
means some where in the program (probably at the end of the main loop) is
a little bit of code such as:
FOR delay = 1 to NumberTheyEnteredForSpeed
NEXT
This is so the program won't go to fast on some computers. Thetas all
well and good, but it is pointless to ask the user when you can do it
yourself. It is like asking the user to seed the RANDOMIZE statement. But,
if you don't ask, then how do you know how long to delay at the end of the
main game loop you may wonder. Well that is easy too, here's what you do:
1-edit you code to this:
...
Opening crap like DECLAREs and ON...GOTOs
...
TIMER ON 'add this
MainGameLoop:
start = TIMER 'add this
...
Your game logic stuff
...
FOR delay = 1 to NumberTheyEnteredForSpeed 'The delay loop
NEXT
LOCATE 1 : PRINT TIMER - start 'add this
GOTO MainGameLoop
2-Run the program many times, and enter a new number for speed each time
until you get a speed that is not to fast and not to slow for the game.
Once you get it, look at top right corner of the screen and write down
the number that keeps appearing there.
(For the example's sake, we are going to say it was .34)
3-Re-edit your code to look like this
...
Opening crap like DECLAREs and ON...GOTOs
...
TIMER ON
MainGameLoop:
start = TIMER
...
Your game logic stuff
...
DO : LOOP UNTIL TIMER - start > .34
GOTO MainGameLoop
Of course, your number probably won't be .34, so replace it with
your number The DO : LOOP waits for .34 seconds from the start of the
MainGameLoop until it makes another pass.
4-How does this work?
Here is an Example:
Bob is playing PACMAN(tm) on an INTEL Pentium II 300mhz
It takes the Pentium .09 seconds to go through the whole game loop.
The program then sits in the DO : LOOP thingy for .25 seconds (.34 - .09=.25)
The program then goes back to the start of the Main Game loop and repeats.
Bill is Playing PACMAN(tm) on a 386sx 33mhz
It takes the 386sx .20 seconds to go through the whole game loop.
The program then sits in the DO : LOOP thingy for .14 seconds (.34 - .20=.14)
The program then goes back to the start of the Main Game loop and repeats.
No matter what Computer is used, the Main Game Loop is only run once every
.34 seconds. What happens if you have a really slow computer?
Dave is poor and has to run a copy of PACMAN(tm) that he stole on a
IBM XT (c. 1984)
It takes the piece-of-s...er...XT .8 seconds to go through the main
game loop Then program hits the DO : LOOP thingy and says "Oh, .8 seconds
have passed, so I don't have to wait at all in the DO : LOOP thingy, because
it took me longer than .34 seconds because I suck. I'll just exit the DO :
LOOP thingy and go back to the start of the main game loop!"
This makes the program look better, and run the same on all computers.
Now, I know you will NEVER come across an old XT, 386s are all but dead,
and 486s are slowly dying; but this is still helpful because a Pentium 75mhz
is much slower then a Pentium MMX 166mhz which is slower than a Pentium II
333Mhz.
----------
Quick Tips
----------
How do I turn off the Keyboard?
This is a wicked trick to do to someone; can be used as a trick
by Compiling this to an EXE and adding it to a AUTOEXEC.BAT; and
makes a great addition to a Security Program if the wrong Password
is entered.
To disable all input from the Keyboard:
DEF SEG = 64
OUT 97, 204
To Re-able the Keyboard:
DEF SEG = 64
OUT 97, 76
******BE CAREFUL********
You can EASILY lock yourself out and have to Reboot to use your keyboard
again
How Do I Reboot a Computer?
There are many way to do this, But I know of 3 that ALWAYS work, and have
been tested on XT's, 386's, 486's, and Pentiums. Here you go:
For a COLD BOOT:
SHELL "ECHO G = FFFF:0000 | DEBUG" 'This only works if DEBUG.EXE is in a
'pathed directory
-or-
The Shell one is slower than the next method. It also leave 2 files behind
with gibberish names that Debug makes.
DEF SEG = &HFFFF 'This is the better one
CALL Absolute(0)
For a WARM BOOT:
DEF SEG = 0
POKE &H473, &H12 'FLAG FOR WARM BOOT
POKE &H472, &H34 'FLAG FOR WARM BOOT
DEF SEG = &HFFFF
CALL Absolute(0)
How do I Center Text?
This is another SUB I use all the time that gives your programs a very
professional look. There are 2 versions of this.
Cen40 is mainly used in SCREEN mode 1, 7, and 13, but it just depends on the
WIDTH setting. Use Cen on 80 WIDTH
'SUB Cen(txt$, row)
LOCATE row, 39 - LEN(txt$) / 2: PRINT txt$
END SUB
'SUB Cen40(txt$, row)
LOCATE row, 19 - LEN(txt$) / 2: PRINT txt$
END SUB
-----
ABORT
-----
Well, that's the first issue of Qbasic Developers Forum. I hope I
was able to help you expand your ability to program, and to create better
programs. If you like what you learned, let me know. My Email address is
LordAcidus@aol.com
or snail mail
Billy Hoffman
c/o Acidus Software
1349 Garrick Way
Marietta GA, 30068
Oh, I have a BBS that runs from 12am until 12pm EST, open to the public
Sept 1, 1998
Hack the planet,
Acidus