Programming the Keyboard, Mouse, and Joystick

This chapter is dedicated to the subject of input—specifically, taking control of the computer's input devices with DarkBASIC. DarkBASIC includes numerous commands for handling input events from the keyboard, mouse, and joystick. It also includes features such as force feedback that are available with many joysticks.

Introduction to User Input

Every device, from a TV to a microwave oven, requires some sort of control device to use it. A TV requires a remote to change channels, and a microwave has a front control panel for programming the temperature and the time to cook a meal. In fact, most consumer electronics devices require some sort of user input. User input is what makes the difference between a technical demo and a game. Reading the input from a control allows the game to ascertain what the player would like to do, and then perform that task.

Every game console, from the Atari 2600 to the Xbox, has some form of user input. The user input is relayed to the console via some form of controller. Figure 12.1 shows a collection of different controllers for user input.

click to expand
Figure 12.1: A collection of game input controllers

DarkBASIC uses the DirectInput library to get all of its input. If you are familiar with DirectInput, you will recognize some of the functions in DarkBASIC, as well as how they correspond to their DirectInput counterparts.

DarkBASIC supports three different basic types of controllers—the keyboard, mouse, and joystick. Most PC users have one or more of these devices. These days, it is hard to imagine a computer without at least a keyboard and a mouse. However, it was not long ago that PC games only had one type of input—the keyboard.

Keyboard Basics

The keyboard is the most basic form of user input to which you will have access. Every computer has a keyboard. However, this was not always the case. The keyboard itself has been around since 1868, when an inventor by the name of Christopher Lathem Sholes took out a patent on the first typewriter. Computers in their present form were not even around then. In fact, some of the earliest computers did not use keyboards; they used punch cards, on which the computer instructions were punched and then fed into the computer.

In 1964, MIT, Bell Labs, and General Electric designed the first computer that used a keyboard. It was called the Mutlics. It was nothing more than a collection of monitors and keyboards (called dumb terminals) hooked up to a larger system, but since that moment every computer has used a keyboard.

A keyboard has many different keys, but most keyboards are laid out in the QWERTY format. The QWERTY format, also invented by Christopher Lathem Sholes, specifies the layout of the keys on the keyboard. Q, W, E, R, T, and Y are the first six letters in the top row of letter keys on the QWERTY keyboard. Figure 12.2 shows a picture of a QWERTY keyboard.

click to expand
Figure 12.2: A QWERTY keyboard gets its name from the position of the QWERTY keys.

Many keyboards have 101 to 104 keys. Most of the older keyboards have 101 keys, and the newer keyboards have 104 or more keys. To help visualize the keyboard as a control device, you must view each key as a button (like on a joystick, which I will cover in the "Joystick Commands" section later in this chapter). Each button has three different states: UP, DOWN, and PRESSED. Although it might seem a little odd that there are three different states, it's really quite simple. If a key has not been pressed, it is in the UP state. If a key is being pressed currently, it is in the DOWN state. If a key is currently in the UP state but was previously in the DOWN state, it is in the PRESSED state. Figure 12.3 illustrates this point.

click to expand
Figure 12.3: The three different states of a key

Most game applications use four main keys for movement. They traditionally are the up, down, left, and right arrows. The A, W, S, and D keys are sometimes used for movement, but this is rather uncommon. In that case, W is used for up, A is used for left, S is used for down, and D is used for right. Generally, there is one key used for fire in a game; this is usually the Ctrl key. Other keys commonly used in games are the Enter key, the Alt key, and the spacebar.

Although the keyboard is the largest control that is hooked up to the computer, it is not the only common controller. Almost all computers have a mouse attached to them; at $10 for a cheap mouse, who can't own one?

Mouse Basics

It is hard to imagine a computer without a mouse; they feel unusable without one. However, the mouse has not always been part of the computer. In 1964, a man by the name of Douglas C. Engelbart created the first mouse. He patented this mouse as an X-Y position indicator, but he nicknamed it the "mouse" because it had a tail coming out the back of it. His original mouse was nothing more then a wooden box with two roller balls inside. In 1998, Douglas Engelbart was inducted into the National Inventors Hall of Fame. I think he most richly deserves that induction for inventing the most well-loved and oft-used input device since the keyboard.

Mouse devices come in all different shapes and sizes, from a traditional ball-and-wheel mouse to a more complex optical mouse to a trackball. Each mouse, though unique in style, has the same basic function—to indicate an X-Y position. In the Windows and Macintosh operating systems, the mouse controls your cursor. In DarkBASIC you might have a cursor that looks slightly different but serves the same function as the Windows or Macintosh cursor. You might be wondering about games such as Quake III or Doom 2. They don't have a cursor, right? You are correct, but they still read the mouse information and convert the X-Y position into a useful user control. Figures 12.4 and 12.5 show mouse movement and the corresponding results.

click to expand
Figure 12.4: A mouse moving left or right

click to expand
Figure 12.5: A mouse moving up or down

The mouse has one other feature that makes it a popular gaming control—buttons. Most mouse devices have two or more buttons (unless you have a Macintosh mouse, in which case you only have one button). These buttons can each be assigned to a different aspect of a program. Windows uses the buttons to select, execute, and control different files. Just as the keyboard keys have different states, so do the mouse buttons. However, there are four different states for a mouse button—UP, DOWN, CLICKED, and DOUBLE CLICKED.

The UP state is just like the keyboard UP state—the mouse button has not been clicked. The DOWN state is just like the keyboard DOWN state, but with one unique difference. In most applications, the mouse button DOWN state is used to drag a box around a collection of items. This is the most common use of the DOWN state, but it does not always have to be the case. The CLICKED state is the same as the keyboard PRESSED state. The DOUBLE CLICKED state is nothing more than the mouse being in the CLICKED state twice in a row. Figure 12.6 shows an example of the different states of the mouse.

click to expand
Figure 12.6: The different mouse button states

There is one more aspect of the mouse that I need to cover. Most new mouse devices have a wheel, which allows the user to scroll up and down. This feature is usually used to scroll between weapons in a game or to scroll up and down on a Web page without using the side scroll bar.

Although the mouse is a wildly popular input device for PC games (I would almost venture to say that it is the most popular for PC games), it is not the only gaming input device. There is also the joystick, which is almost as popular as the mouse for most computer-or console-based games.

Joystick Basics

The joystick is the most common user input device for any console or console-based game. The Atari 2600 had a basic one-button controller, while the GameCube has a more complex control. They all serve the same function: To allow human input into a game in the most convenient manner possible. Figure 12.7 shows a collection of different joysticks.

click to expand
Figure 12.7: Different joystick controllers

Although I cannot pinpoint the exact inventor of the joystick, I know that joysticks have been hooked to computers since 1964, when the first computer game (Space War) was written. The standard for joystick connection to the PC did not come until much later, however. The game port is the most common type of connection for a joystick. Also known as the joystick port, the game port is generally connected like a traditional mouse and is found on most sound cards. You can use a Y splitter to connect two joysticks to a game port at once.

The USB port is becoming a wildly popular connection for the joystick. I think this is a great idea because USB ports support faster communications between the joystick and the computer, which allows greater precision in the joystick.

Precision is the accuracy of a controller. The more precise a joystick or mouse is, the better the input that the game will receive from it.

The joystick is a lot like the mouse in that it is an X-Y indicator. Most joysticks have some form of X and Y input. What makes a joystick different than a mouse is that the X and Y input can be separated on a joystick, whereas they cannot on the mouse. A prime example of this is a driving wheel. The wheel portion of the joystick is the X input, and the pedals are considered the Y input. Figure 12.8 shows a joystick with combined X and Y axes, and Figure 12.9 shows a joystick with separated X and Y axes.

click to expand
Figure 12.8: A controller with combined X and Y axes

click to expand
Figure 12.9: A controller with separated X and Y axes

Just like the keyboard and mouse, the joystick also has buttons. (This seems to be a common theme among controllers, doesn't it?) Joysticks generally have between two and ten buttons, a mouse usually has two to five buttons, and a keyboard has approximately 104 buttons.) Each button again has three different states—UP, DOWN, and PRESSED. The UP state for the joystick is just like the UP state for the mouse and keyboard—the button has not been pressed. The DOWN state is the same as well, but most games use the DOWN state for rapid fire functions. The PRESSED state is also the same as for the keyboard and mouse, and it is usually used for single fire. Figure 12.10 shows the different states of joystick buttons.

click to expand
Figure 12.10: Various states of a joystick button

Now that you have covered the three major input devices for a PC game, it is time to cover them in detail, from concepts to commands. Each device has a unique set of commands assigned to it to make it function with DarkBASIC. I will start with the keyboard and work through the mouse and the joystick.


Keyboard Commands

The keyboard commands in DarkBASIC are pretty easy to use. There are commands for reading entire strings as well as for reading one character. You have used many of the commands in previous chapters without knowing exactly what they are or what they do.

Reading Text Input

The most fundamental requirement of basic input commands is reading a string or number input. You need to read a string to gather information such as the player's name or his favorite color. Although you can create your own string input routine with the key-press commands, DarkBASIC provides a command to read strings for you.

The INPUT Command

The INPUT command is one of the oldest commands in any BASIC language. In fact, it is as old and widely used as the PRINT command. The INPUT command can take two forms. The first format of the command is a simple INPUT string$, where keyboard keys are read and the keys are stored in string$. The second format of the INPUT command is INPUT string$, variable$, where the keyboard input is read and placed in string$, and variable$ is printed on the string. This form is a little more useful because it will print something right before the location where the user will input text.

The following program (aptly named KeyboardInput) demonstrates how to use the INPUT command. Figure 12.11 shows you the output of the program.

click to expand
Figure 12.11: The KeyboardInput program demonstrates the use of the INPUT command.

'-----------------------------
'Beginner's Guide To DarkBASIC Game Programming
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - KeyboardInput program
'-----------------------------

'create some variables
name$ = ""
age = 0
color$ = ""

'initialize the program
CLS
HIDE MOUSE
'ask user for some personal info
PRINT
INPUT "What is your name? ", name$
INPUT "What is your age? ", age
INPUT "What is your favorite color? ", color$

'display the delay message
PRINT
PRINT "Calculating what I know about you";

'delay for 2 seconds
SLEEP 500
PRINT ".";
SLEEP 500
PRINT ".";
SLEEP 500
PRINT ".";
SLEEP 500
PRINT ".";
PRINT

'display the info on the screen
PRINT
PRINT "What I know about you:"
PRINT "Your name is " + name$ + "."
PRINT "Your name backwards is " + StringBackwards$(name$)
PRINT "Your age is " + STR$(age)
PRINT "Your age backwards is "+StringBackwards$(STR$(age))
PRINT "Your favorite color is " + color$
PRINT "Your favorite color backwards is " + StringBackwards$(color$)

'pause and then end
WAIT KEY
END

FUNCTION StringBackwards$(A$)
 newstring$ = ""
 FOR N = LEN(A$) TO 1 STEP -1
 newstring$ = newstring$ + MID$(A$, N)
 NEXT N
ENDFUNCTION newstring$

I must tell you about one important drawback to the INPUT command. Although it is a useful command for reading entire strings, it might not always be the best command for game programming because it is a blocking command, which means that it will not allow any other commands to run until it is finished. INPUT is a good command to use if you do not need to process anything else while you are waiting for the user to type something. At the end of the keyboard section, I will show you how to write a non-blocking INPUT command.

Reading Key Presses

The INPUT command is not the only keyboard command that DarkBASIC supports. DarkBASIC can also use the keyboard as a series of buttons. Remember, the keyboard has three states for its keys: UP, DOWN, and PRESSED. The following commands will help you determine these states accurately.

The WAIT KEY and SUSPEND FOR KEY Commands

The WAIT KEY command waits for any key to be pressed. This command takes no parameters. Like INPUT, it is a blocking command. This command is good for holding title screens and winning screens. The SUSPEND FOR KEY command performs the same function. These commands will wait for any key to be in the PRESSED state before continuing.

The INKEY$( ) Command

The INKEY$() command is one my favorites. It tells you which key is currently being pressed. It is a non-blocking command, so you can use it in loops without stalling the program. The INKEY$() command takes no parameters, but it returns a single character that represents the key that is currently being pressed. Note that INKEY$() only returns one letter (or chr$). You can only read one key at a time in the DOWN state with this command.

You can use INKEY$() to detect the three different states of each key on the keyboard. To detect the DOWN state of a key, just check to see whether INKEY$() is equal to the value of that key. To detect the UP state, check to see whether INKEY$() is not equal to that key's value. To detect the PRESSED state, check to see whether INKEY$() is equal to, and then not equal to, the value of that key.

The following game, called TextBlast, uses the INKEY$() function to scan for all three states. It detects when a key is in the DOWN state and sets a flag for that key (DIM charhit). The flag indicates that the key was pressed. When you release the key (previously in the DOWN state and flagged as such), the program processes that key as being in the PRESSED state. When the program finishes processing the key in the PRESSED state, it resets the flag for that key, and the key is returned to the UP state.

The object of TextBlast is simple. Just type the key that corresponds to the letters or numbers falling down the screen to destroy them. Each character falls at a different speed, so your reflexes will have to be fast. Figure 12.12 shows the output of the TextBlast program, which you will find on the CD in the SourcesChapter12TextBlast folder.

click to expand
Figure 12.12: The TextBlast game demonstrates a practical use of the INKEY$() command.


REMSTART
---------------------------------
Beginner's Guide To Game Programming With DarkBASIC
Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
Chapter 12 - Taking Control: Programming the Input Devices
---------------------------------

REMEND
CLS
DIM char$(100)
DIM charx(100)
DIM chary(100)
DIM charspeed(100)
DIM charhit(100)
DIM hitschars(1)
DIM CharCount(1)

SYNC ON
SYNC RATE 30

RndCounter = 0

White = RGB(255,255,255)
Black = RGB(0,0,0)

' This will set a random seed
SET TEXT OPAQUE
WHILE INKEY$()<>" "
 RndCounter = RND(1000)
 INK White,Black
 CENTER TEXT 320,240,"Text Blast"
 RndColor = RGB(rnd(100)+150,rnd(100)+150,rnd(100)+150)
 INK RndColor,Black
 CENTER TEXT 320,260,"Press Space to Continue"
 SYNC
ENDWHILE
RANDOMIZE RndCounter

SET TEXT TRANSPARENT
InitChars()
hitschars(1) = 0
CharCount(1) = 1

' Loop until 100 chars have passed
WHILE CharCount(1) < 100
 INK 0,0
 BOX 0,0,639,479
 IF NoneFalling()=1 THEN StartNewFalling()
 ProcessText()
 DisplayScoreLine()
 SYNC
ENDWHILE

CLS
INK White,Black
TempString$ = "You have hit "+STR$(hitschars(1))+" out of "+STR$(100)+"!"
CENTER TEXT 320,240,TempString$
WAIT KEY
END

' Intialize all the characters for falling
FUNCTION InitChars()
 FOR x = 1 TO 100
 charnum = RND(92)+33
 char$(x) = CHR$(charnum)
 charx(x) = RND(600)+20
 chary(x) = -1
 charhit(x) = 0
 charspeed(x) = RND(6)+1
 NEXT x
ENDFUNCTION

' Are any characters falling
FUNCTION NoneFalling()
 Flag = 1
 FOR x = 1 TO 100
 IF chary(x) >= 0 AND chary(x) < 450 THEN EXITFUNCTION 0
 NEXT x
ENDFUNCTION Flag
' Set some new characters falling
FUNCTION StartNewFalling()
 FOR x = 1 to 4
 chary(x+CharCount(1)) = 0
 NEXT x
 CharCount(1) = CharCount(1) + 4
ENDFUNCTION

' Check the keyboard to see if any of the falling
' Characters have been hit..
FUNCTION ProcessText()
 White = RGB(255,255,255)
 Black = RGB(0,0,0)
 Red = RGB(255,0,0)
 FOR x = 1 TO 100
 IF chary(x) >= 0 AND chary(x)<450
 IF INKEY$() = char$(x)
 INK Red,Black
 charhit(x) = 1
 chary(x) = chary(x) + charspeed(x)
 LINE 0,479,charx(x),chary(x)
 LINE 0,0,charx(x),chary(x)
 LINE 639,0,charx(x),chary(x)
 LINE 639,479,charx(x),chary(x)
 ELSE
 INK White,Black
 IF charhit(x) = 1
 chary(x) = 490
 hitschars(1) = hitschars(1) + 1
 ELSE
 chary(x) = chary(x)+ charspeed(x)
 ENDIF
 ENDIF
 TEXT charx(x),chary(x),char$(x)
 ENDIF
 NEXT x
ENDFUNCTION

' Display the Score line...
FUNCTION DisplayScoreLine()
 WHITE = RGB(255,255,255)
 BLACK = RGB(0,0,0)

 INK WHITE,BLACK
 STRING$ = "You have hit "+str$(hitschars(1))+"!"
 TEXT 10,465,string$
ENDFUNCTION

There are two other things to note about the INKEY$() command. First, INKEY$() will detect the difference between uppercase and lowercase letters, so the p and P keys are two different things in the INKEY$() command. When you are detecting whether the P key is pressed, you should look for both the P and p keys. You can also take the input of INKEY$() and pass it to the UPPER$ command to convert it to uppercase automatically.

Second, the INKEY$() command can return more than just the letters on the keyboard. It can also return the ASCII value of whatever key is currently pressed. Remember the CHR$(value) command? This is where it comes in handy because you can now detect different keys being pressed. For example, to detect whether the Enter key has been pressed, check to see whether INKEY$() = CHR$ (13). Appendix C, "ASCII Chart" contains a complete listing of all the ASCII values and the corresponding keys. Table 12.1 shows some of the most common keys and their ASCII values.

Table 12.1: Common ASCII values

Value

Key

8

Tab

9

Backspace

13

Enter

27

Esc

32

Spacebar

Reading Special Keys

In addition to reading any key with the INKEY$() command, DarkBASIC also supports the reading of special keys, such as the up, down, left, and right arrows. There are a total of nine special keys that DarkBASIC exclusively reads. Figure 12.13 shows a keyboard with the special keys highlighted. These special keys are detailed in the following sections.

click to expand
Figure 12.13: A keyboard illustration showing the special keys that DarkBASIC reads.

The UPKEY() Command

The UPKEY() command reads whether the up arrow is in the UP or DOWN state. It takes no parameters and returns a 0 if the up arrow is in the UP state and a 1 if it is in the DOWN state. To detect whether the up arrow is in the PRESSED state, look for it to be in the DOWN state (1), and then in the UP state (0). The up arrow is most commonly used to move a character upward in a keyboard-based game.

The DOWNKEY Command

The DOWNKEY() command reads whether the down arrow is in the UP or DOWN state. It returns a 0 if the down arrow is in the UP state and a 1 if it is in the DOWN state. The down arrow is most commonly used to move a character downward in a keyboardbased game.

The LEFTKEY Command

The LEFTKEY() command reads whether the left arrow is in the UP or DOWN state. It returns a 0 if the left arrow is in the UP state and a 1 if it is in the DOWN state. The left arrow is most commonly used to move a character left in a keyboard-based game.

The RIGHTKEY Command

The RIGHTKEY() command reads whether the right arrow is in the UP or DOWN state. It returns a 0 if the right arrow is in the UP state and a 1 if it is in the DOWN state. The right arrow is most commonly used to move a character right in a keyboard-based game.

The CONTROLKEY Command

The CONTROLKEY() command reads whether the Ctrl key is in the UP or DOWN state. This command returns a 0 if the Ctrl key is in the UP state and a 1 if it is in the DOWN state. The Ctrl key is most commonly used to fire weapons in a keyboard-based game. This command does not tell you whether the left or right Ctrl key was hit; it just lets you know that one was hit.

The SHIFTKEY Command

The SHIFTKEY() command reads whether the Shift key is in the UP or DOWN state. It returns a 0 if the Shift key is in the UP state and a 1 if it is in the DOWN state. This command does not tell you whether the left or right Shift key was hit; it just lets you know that one was hit.

The SPACEKEY Command

The SPACEKEY() command reads whether the spacebar is in the UP or DOWN state. It returns a 0 if the spacebar is in the UP state and a 1 if it is in the DOWN state. The spacebar is most commonly used to either fire or jump in a keyboard-based game.

The RETURNKEY Command

The RETURNKEY() command reads whether the Return key is in the UP or DOWN state. The Return key is generally labeled Enter on the keyboard; it can be found above the right Shift key. Do not confuse this key with the Return key on the number pad (which is sometimes labeled Enter as well). Although the Return key on the number pad returns the same ASCII value in INKEY$() as the Enter key above the Shift key, the RETURNKEY() command only detects the Enter key above the Shift key. It returns a 0 if the Enter key is in the UP state and a 1 if it is in the DOWN state. The Enter key is most commonly used to perform an action in a keyboard-based game, which can range from opening a door to talking to another character.

The ESCAPEKEY Command

The ESCAPEKEY command returns whether the Esc key is in the UP or DOWN state. This command returns a 0 if the Esc key is in the UP state and a 1 if it is in the DOWN state. The Esc key is most commonly used to quit a game.

Summing Up the Special Key Commands

There are nine special key commands for the common keys used in a game. DarkBASIC uses a different set of commands for reading the rest of the keys on the keyboard simultaneously, as you will see in the next section. Table 12.2 sums up the nine special key commands.

Table 12.2: Special Key Commands

Command

Key

UPKEY Up

arrow

DOWNKEY

Down arrow

LEFTKEY

Left arrow

RIGHTKEY

Right arrow

CONTROLKEY

Ctrl

SHIFTKEY

Shift

SPACEKEY

Spacebar

RETURNKEY

Enter (not the number pad Enter)

ESCAPEKEY

Esc

Reading Multiple Keys and Scan Codes

Sometimes reading one key is just not enough. There are times when you need to read multiple keys. Although you can use all of the special functions at the same time, sometimes that is not enough. For example, you might want to move upward while firing your guns at the same time. This works fine if the fire command is attached to the Ctrl key and the up command is attached to the up arrow. But what if the fire command is attached to the P key and the up command is attached to the W key?

DarkBASIC provides a few commands that will detect whether multiple keys are pressed. To detect multiple key presses, you must understand scan codes, which are different from ASCII values. A scan code is the raw number that the keyboard assigned to a key before sending it to the computer. Usually scan codes are assigned from the upper-left of the keyboard to the lower-right.

A scan code is the value assigned by the keyboard (not Windows, ASCII, or anyone else) to a specific key. The keyboard actually has a small microcontroller inside of it that handles all the key presses and complexities of the keyboard's operation. This controller is programmed with a standard set of scan codes for PC-AT 101 keyboards, and is the ultimate source of keyboard information for the computer.

The SCANCODE Command

Although it only returns the value of one key, the SCANCODE() command is useful for determining what scan code is assigned to each key. This command takes no parameters, but it returns the scan code of the key currently being pressed.

The KEYSTATE Command

The KEYSTATE() command takes one parameter—the scan code of the key you are looking for—and returns whether the key is up or down. The UP state of the key returns a 0, and the DOWN state returns a 1.

Using KEYSTATE and SCANCODE: The VirtualKeyboard Program

The following program uses the KEYSTATE and SCANCODE commands to mimic the UP and DOWN states of the keys on the screen. You must press Esc and Enter to quit this program. If you run this program within the DarkBASIC environment, you can also escape from the program by pressing F12. Figure 12.14 shows the output of this program.

click to expand
Figure 12.14: The VirtualKeyboard program, demonstrating the use of the KEYSTATE() command


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - VirtualKeyboard Program
'---------------------------------

DIM KEY$(256)
DIM KEYX(256)
DIM KEYY(256)

' Key State Data
DATA 1,"Esc",30,43
DATA 59,"F1",93,43
DATA 60,"F2",137,43
DATA 61,"F3",178,43
DATA 62,"F4",218,43
DATA 63,"F5",262,43
DATA 64,"F6",303,43
DATA 65,"F7",343,43
DATA 66,"F8",385,43
DATA 67,"F9",425,43
DATA 68,"F10",467,43
DATA 87,"F11",507,43
DATA 88,"F12",551,43
DATA 41,"'",26,92
DATA 2,"1",85,92
DATA 3,"2",126,92
DATA 4,"3",172,92
DATA 5,"4",210,92
DATA 6,"5",254,92
DATA 7,"6",297,92
DATA 8,"7",340,92
DATA 9,"8",383,92
DATA 10,"9",428,92
DATA 11,"0",469,92
DATA 12,"-",513,92
DATA 13,"=",555,92
DATA 14,"Back",593,92
DATA 15,"TAB",26,130
DATA 16,"Q",85,130
DATA 17,"W",126,130
DATA 18,"E",172,130
DATA 19,"R",210,130
DATA 20,"T",254,130
DATA 21,"Y",297,130
DATA 22,"U",340,130
DATA 23,"I",383,130
DATA 24,"O",426,130
DATA 25,"P",469,130
DATA 26,"[",513,130
DATA 27,"]",555,130
DATA 43,"",580,130
DATA 58,"CAPS",26,164
DATA 30,"A",85,164
DATA 31,"S",126,164
DATA 32,"D",172,164
DATA 33,"F",210,164
DATA 34,"G",254,164
DATA 35,"H",297,164
DATA 36,"J",340,164
DATA 37,"K",383,164
DATA 38,"L",426,164
DATA 39,";",469,164
DATA 40,"’",513,164
DATA 28,"ENTER",555,164
DATA 42,"LSHFT",26,195
DATA 44,"Z",85,195
DATA 45,"X",126,195
DATA 46,"C",172,195
DATA 47,"V",210,195
DATA 48,"B",254,195
DATA 49,"N",297,195
DATA 50,"M",340,195
DATA 51,"<",383,195
DATA 52,">",426,195
DATA 53,"/",469,195
DATA 54,"RSHIFT",513,195
DATA 29,"LCTRL",48,240
DATA 219,"LWIN",120,240
DATA 56,"LALT",187,240
DATA 57,"SPACE",262,240
DATA 184,"RALT",335,240
DATA 220,"RWIN",404,240
DATA 221,"APP",475,240
DATA 157,"RCTRL",547,240
DATA 200,"UP",290,279
DATA 203,"LT",246,317
DATA 208,"DN",285,317
DATA 205,"RT",323,317
DATA 183,"SYSRC",0,0
DATA 70,"SCRLOCK",0,0
DATA 210,"INS",20,279
DATA 199,"HOME",71,279
DATA 201,"PGUP",125,279
DATA 211,"DEL",20,315
DATA 207,"END",71,315
DATA 209,"PGDN",125,315
' Keypad keys
DATA 69,"NUM",436,280
DATA 181,"/",486,280
DATA 55,"*",531,280
DATA 74,"-",574,280
DATA 71,"7",436,309
DATA 72,"8",486,309
DATA 73,"9",531,309
DATA 75,"4",436,340
DATA 76,"5",486,340
DATA 77,"6",531,340
DATA 78,"+",574,326
DATA 79,"1",436,368
DATA 80,"2",481,368
DATA 81,"3",531,368
DATA 82,"0",462,396
DATA 83,".",522,387
DATA 156,"E",574,382

DISABLE ESCAPEKEY

LOAD BITMAP " keyboard.bmp",1

SET TEXT TRANSPARENT
SYNC ON
SYNC RATE 30

ReadKeyboardData()

' Scan for all the keys being hit.
WHILE ESCAPEKEY()=0 OR RETURNKEY()=0
 COPY BITMAP 1,0
 SET TEXT TRANSPARENT
 DisplayKeyboard()
 SET TEXT OPAQUE
 LastScanCode = SCANCODE()
 IF LastScanCode < 10 AND LastScanCode >=0
 tempstring$ = "Last Scan Code = 00"+STR$(LastScanCode)
 ENDIF
 IF LastScanCode < 100 AND LastScanCode >=10
 tempstring$ = "Last Scan Code = 0"+STR$(LastScanCode)
 ENDIF
 IF LastScanCode < 1000 AND LastScanCode >=100
 tempstring$ = "Last Scan Code = "+STR$(LastScanCode)
 ENDIF
 TEXT 10,440, tempstring$
 SYNC
ENDWHILE
DELETE BITMAP 1
END

' Displays the keys and
' highlights the ones that are hit.
FUNCTION DisplayKeyboard()
 White = RGB(255,255,255)
 Black = RGB(0,0,0)
 Red = RGB(255,0,0)
 INK White, Black
 FOR x = 1 to 256
 IF KEYX(x) <> 0
 StateOfKey = KEYSTATE(x)
 IF StateOfKey = 0
 TEXT KEYX(x), KEYY(x), KEY$(x)
 ELSE
 INK Red, Black
 TEXT KEYX(x), KEYY(x), KEY$(x)
 INK White, Black
 ENDIF
 ENDIF
 NEXT x
ENDFUNCTION

' Loads all the DIM values with
' the DATA values
FUNCTION ReadKeyboardData()
 FOR x = 1 to 256
 KeyX(x) = 0
 NEXT x
 FOR x = 1 TO 256
 READ KeyValue
 READ KeyName$
 READ KeyXpos
 READ KeyYPos
 KEY$(KeyValue) = KeyName$
 KEYX(KeyValue) = KeyXpos
 KEYY(KeyValue) = KeyYpos
 NEXT x
ENDFUNCTION

A Non Blocking Input Command

The ENTRY$() and the CLEAR ENTRY BUFFER commands in DarkBASIC make nonblocking input a simple task. These two commands use the Windows keyboard buffer to track what has been typed on the keyboard without having to keep track of every key (as would be the case with an INKEY$() based non-blocking input).

The ENTRY$() command reads whatever string is stored in the Windows keyboard buffer at the time it is called. The Windows keyboard buffer stores every key typed on the keyboard until CLEAR ENTRY BUFFER is called. The CLEAR ENTRY BUFFER command clears the Windows keyboard buffer so a new string can be read.

The NonBlocking program shows you how to use the ENTRY$() and CLEAR ENTRY BUFFER commands in conjunction with the INKEY$() command to keep track of input while other processes are running. There is a clock in the upper-left corner. It changes as you are typing in your text. Change the program to use INPUT$ instead, and notice the difference. Figure 12.15 also shows the output of the NonBlocking example.

click to expand
Figure 12.15: The NonBlocking program demonstrates the use of the ENTRY$() and CLEAR ENTRY BUFFER commands.


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - NonBlocking program
'---------------------------------
CLS
SYNC ON
SYNC RATE 30

White = RGB(255,255,255)
Black = RGB(0,0,0)
SET TEXT TRANSPARENT

InputString$ = ""
StaticString$ = ""
INK White,Black
CLEAR ENTRY BUFFER
' Process clock and keys until ESC is pressed.
WHILE ESCAPEKEY()=0
 INK 0,0
 BOX 0,0,639,479
 INK White,Black
 TEXT 10,10, GET TIME$()
 TEXT 10,370, "Type your string here, and notice the clock still changes:"

 charhit$ = INKEY$()
 IF charhit$ = CHR$(8)
 StaticString$ = StaticString$ + ENTRY$()
 NewLen = LEN(StaticString$)-1
 StaticString$ = LEFT$(StaticString$,NewLen)
 CLEAR ENTRY BUFFER
 ENDIF

 InputString$ = StaticString$ + ENTRY$()
 TEXT 10,400, InputString$
 SYNC
ENDWHILE
END


Mouse Commands

Next to the keyboard, the mouse is the most popular input device for the PC. Almost any program requires a mouse. Mouse devices come in all shapes, colors, and sizes. However, they all have one thing in common: They move the cursor on the screen. There are 10 different DarkBASIC commands that control the mouse.

The HIDE MOUSE Command

The HIDE MOUSE command gets rid of that pesky mouse cursor. The mouse cursor is cute, but sometimes it can be annoying when it follows your mouse. The two most annoying examples I can think of are in a flight-simulator-type game, where the mouse cursor should not be seen, and in a game where you need a custom mouse cursor, such as a targeting game. The command takes no parameters and returns nothing.

The SHOW MOUSE Command

The SHOW MOUSE command does just the opposite of the HIDE MOUSE command. It returns the cute, lovable mouse cursor. The command takes no parameters and returns nothing.

Mouse Position

Perhaps the most important data received from the mouse is the cursor's X and Y position on the screen. A game programmer translates this information into useful data for movement of characters, sprites, or 3D objects. The X and Y positions of the mouse start from the upper-left corner of the screen and work toward the lower-right corner. The mouse cursor moves further right the more positive the X value is, and further down the more positive the Y value is. Figure 12.16 will help you to visualize this concept.

click to expand
Figure 12.16: The X-Y relative positions of the mouse

There is a third position of the mouse that DarkBASIC reads—the Z position. It is hard to visualize a mouse with three positions because there is only a left-right, up-down orientation on a mouse pad. Most often, the Z position of the mouse refers to the wheel located in the center of the mouse. It is a little misleading, but it makes sense after you have used it. Figure 12.17 demonstrates the concept of the mouse wheel and how it relates to a Z value.

click to expand
Figure 12.17: The mouse wheel and corresponding Z values

The MOUSEX Command

The MOUSEX() command returns the X position of the mouse cursor on the screen. This command takes no parameters but returns the X value of the cursor, which is between 0 and the width of the screen in pixels minus 1. The maximum value is the screen width minus 1 because the minimum position starts at 0.

The MOUSEY Command

The MOUSEY() command returns the Y position of the mouse cursor on the screen. It takes no parameters but returns the Y value of the cursor, which is between 0 and the height of the screen in pixels minus 1. The maximum value is the screen height minus 1 because the minimum position starts at 0.

The MOUSEZ Command

The MOUSEZ() command returns the value of the mouse wheel, which ranges from 0 to 100. It takes no parameters.

The POSITION MOUSE Command

The POSITION MOUSE command positions the mouse cursor on the screen. It takes two parameters (X position and Y position) and returns nothing.

Using the Mouse Position Commands: The MousePositon Program

The MousePosition program demonstrates the use of the mouse position commands. It displays the X, Y, and Z positions of the mouse on the screen and shows the mouse cursor. It also uses the keyboard to move the mouse using the POSITION MOUSE command. Figure 12.18 shows the results of this program.

click to expand
Figure 12.18: The MousePosition program demonstrates the use of the mouse commands.

'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - MousePosition Program
'---------------------------------
CLS
SYNC ON
SYNC RATE 30
White = RGB(255,255,255)
Black = RGB(0,0,0)
WHILE ESCAPEKEY()=0
 INK 0,0
 BOX 0,0,639,479
 INK White,Black
 tempstring$ = "Mouse X pos: "+STR$(MOUSEX())
 TEXT 10,10, tempstring$
 tempstring$ = "Mouse Y pos: "+STR$(MOUSEY())
 TEXT 10,22, tempstring$
 tempstring$ = "Mouse Z pos: "+STR$(MOUSEZ())
 TEXT 10,34, tempstring$
 tempstring$ = "Press R to Reset the mouse"
 TEXT 10,400, tempstring$
 IF INKEY$()="R" OR INKEY$()="r"
 POSITION MOUSE 0,0
 ENDIF
 SYNC
ENDWHILE

Mouse Movement

Now that you know how to use the mouse position commands, you can read the difference between the mouse positions. The oldest way of knowing how far the mouse moved is by using the following formulas: dx = x2−x1, dy = y2−y1, dz = z2−z1. dx, dy, and dz are all delta values. In other words, they are the difference between the last mouse position and the current mouse position. DarkBASIC provides some mouse movement commands so that it is not necessary to calculate dx, dy, and dz. Figure 12.19 better illustrates the concept of mouse movement.

click to expand
Figure 12.19: Mouse position versus mouse movement

The MOUSEMOVEX Command

The MOUSEMOVEX command tells you the distance between the current MOUSEX() and the last MOUSEX(). It is the same as the dx = x2–x1 formula. This command takes no parameters and returns the distance in the x position.

The MOUSEMOVEY Command

The MOUSEMOVEY command tells you the distance between the current MOUSEY() and the last MOUSEY(). It is the same as the dy = y2–y1 formula. This command takes no parameters and returns the distance in the y position.

The MOUSEMOVEZ Command

The MOUSEMOVEZ command tells you the distance between the current MOUSEZ() and the last MOUSEZ(). It is the same as the dz = z2−z1 formula. This command takes no parameters and returns the distance the mouse wheel has moved.

Using the Mouse Movement Commands

The MouseMove program demonstrates the uses of the mouse movement commands. It scales a bitmap based on the movement of the mouse. To quit the program, just press the Esc key. Figure 12.20 shows the output of the MouseMove example.

click to expand
Figure 12.20: The MouseMove program demonstrates the use of the mouse-movement commands.


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - MouseMove Program
'---------------------------------
LOAD BITMAP " graphic.bmp", 1

HIDE MOUSE
SYNC ON
SYNC RATE 30
White = RGB(255,255,255)
Black = RGB(0,0,0)
SIZEX = 100
SIZEY = 100
SET CURRENT BITMAP 0
' Size the picture until Esc is hit.
WHILE ESCAPEKEY()=0
 INK 0,0
 BOX 0,0,639,479
 INK White,Black
 sizex = sizex + (MOUSEMOVEX()/10)
 sizey = sizey + (MOUSEMOVEY()/10)
 IF sizex > 100 THEN sizex = 100
 IF sizex < 1 THEN sizex = 0

 IF sizey > 100 THEN sizey = 100
 IF sizey < 1 THEN sizey = 0

 x1 = 0
 x2 = (638*sizex)/100+1
 y1 = 0
 y2 = (478*sizey)/100+1
 COPY BITMAP 1,0,0,639,479,0,x1,y1,x2,y2
 tempstring$ = "Move the mouse to scale the picture"
 TEXT 10,460,tempstring$
 SYNC
ENDWHILE

Mouse Buttons

Now that you can determine the position and movement of the mouse, there is one more item that must be read—the state of the mouse button. A given mouse button has four states: UP, DOWN, CLICKED, and DOUBLE CLICKED. The CLICKED and DOUBLE CLICKED states are derived from the UP and DOWN states.

The MOUSECLICK Command

The MOUSECLICK() command returns which button on the mouse is currently pressed. This command takes no input but returns a value that indicates which button is being pressed.

The left mouse button is a value of 1; the right mouse button is a value of 2. If there are more than two buttons, the third and fourth buttons are valued at 4 and 8, respectively. This way, you can determine which buttons are being pressed at one time. The MOUSECLICK() command adds the values of the buttons that are being clicked, so if the left and right mouse buttons are pressed, the value is 3. Table 12.3 shows the return values for MOUSECLICK() and what they mean.

Table 12.3: Return Values of MOUSECLICK

Value

Buttons Pressed

0

None

1

Left

2

Right

3

Left and right

4

Third

5

Third and left

6

Third and right

7

Third, left, and right

8

Fourth

9

Fourth and left

10

Fourth and right

11

Fourth, left, and right

12

Fourth and third

13

Fourth, third, and left

14

Fourth, third, and right

15

Fourth, third, left, and right

Determining CLICKED versus DOUBLE CLICKED

Determining CLICKED and DOUBLE CLICKED states is not that hard. For the CLICKED state, you simply detect when the button is pressed. At that point, you wait until the mouse button is up: MOUSECLICK() = 0. You now have a button in a CLICKED state.

The DOUBLE CLICKED state is a little trickier. You must determine that the button is in a CLICKED state two times within a given timeframe. The Click States program shows an example of the CLICKED and DOUBLE CLICKED states. Figure 12.21 shows the output of the program.

click to expand
Figure 12.21: The Click States program demonstrates the use of the MOUSECLICK() command.

'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - Click States Program
'---------------------------------
CLS
SYNC ON
SYNC RATE 30

' This is to color the box
' Click types are as follows
' 0 = No click
' 1 = Mouse Down
' 2 = Mouse Click
' 3 = Mouse Double Clicked
ClickType = 0
Dclick = 0

Red = RGB(255,0,0)
Green = RGB(0,255,0)
White = RGB(255,255,255)
Blue = RGB(0,0,255)
Black = RGB(0,0,0)

SYNC ON
SYNC RATE 30
' Run this program until Escape is hit.
WHILE ESCAPEKEY()=0
 IF ClickType = 0 THEN INK Blue,Black
 IF ClickType = 1 THEN INK Red,Black
 IF ClickType = 2 THEN INK White,Black
 IF ClickType = 3 THEN INK Green,Black
 IF DClick > 0 THEN DClick = DClick - 1
 IF DClick = 0 THEN DClick = -1
 BOX 0,0,100,100
 INK White,Black
 TEXT 10,400,"Click or Double Click in the box to change the color!"
 IF MOUSECLICK()=1
 IF MOUSEX()<=100 AND MOUSEY() <=100
 IF Dclick > 0 OR Dclick = -3
 Dclick = -3
 ClickType = 1
 ELSE
 ClickType = 1
 Dclick = -2
 ENDIF
 ELSE
 ClickType = 0
 Dclick = -1
 ENDIF
 ENDIF
 IF MOUSECLICK()=0 AND Dclick = -2
 IF ClickType = 1
 ClickType = 2
 Dclick = 50
 ENDIF
 ENDIF
 IF MOUSECLICK()=0 AND Dclick = -3
 IF ClickType = 1
 ClickType = 3
 Dclick = -1
 ENDIF
 ENDIF
 SYNC
ENDWHILE

The Mouse Handler

The mouse handler is a concept that works well with game programming. It is nothing more than a function that is created to handle all mouse-related input. Every stage of a game can contain a different mouse handler, but placing all of the mouse-related input into a function will make it easier to control items with the mouse.

The ShootingGallery program is a simple shooting gallery game. It uses most of the mouse commands that I have covered in this chapter. The mouse handler is clearly defined. To destroy the targets, move the cursor over the target and left-click on it. Figure 12.22 shows the output of the ShootingGallery program.

click to expand
Figure 12.22: Output of the ShootingGallery program


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - ShootingGallery program
'---------------------------------

SYNC ON
SYNC RATE 30
DIM SpriteHit(20)
DIM SpriteTimer(1)
HIDE MOUSE
SpriteTimer(1) = 0
LOAD IMAGE "crosshair.bmp",25
LoadTargetAnims()
' Initialize all the sprites
FOR x = 2 TO 20
 SPRITE X,-100,68,5
 SET SPRITE x,1,1
 SpriteHit(x) = 0
NEXT X
' Set th mouse cursor spite
SPRITE 1,320,240,1
SET SPRITE 1,1,1
' Seting up the lines in the background
SET CURRENT BITMAP 0
Green = RGB(0,255,0)
Red = RGB(255,0,0)
Black = RGB(0,0,0)
White = RGB(255,255,255)
INK Green,Black
BOX 0,98,639,102
INK Red,Black
BOX 0,100,639,100
INK White,Black
inum = 5
TEXT 10,400,"Click on the target to destroy it!"
' Play the game until the Escape key is hit.
WHILE ESCAPEKEY()=0
 ProcessSprites()
 ControllerHandler()
 SYNC
ENDWHILE

END

' This moves the crosshairs to where the mouse is.
FUNCTION ControllerHandler()
 SPRITE 1, MOUSEX(), MOUSEY(), 25
 IF MOUSECLICK()=1
 FOR X = 2 TO 20
 IF SPRITE COLLISION(1,X)
 SpriteHit(X) = 1
 ENDIF
 NEXT X
 ENDIF
ENDFUNCTION

' This does all the Sprite Collision processing.
FUNCTION ProcessSprites()
 SpriteTimer(1) = SpriteTimer(1) - 1
 IF SpriteTimer(1) <= 0 THEN MoveNewSprite()
 FOR X = 2 TO 20
 IF SPRITE X(X) > 704
 SPRITE X,-100,68,5
 ENDIF
 IF SpriteHit(X)
 SPRITE X,SPRITE X(x)+5,SPRITE Y(X), SPRITE IMAGE(X)+1
 IF SPRITE IMAGE(X) >= 15
 SPRITE X,-100,68,5
 SpriteHit(X) = 0
 ENDIF
 ELSE
 IF SPRITE X(X) >= -64
 SPRITE X,SPRITE X(x)+5,SPRITE Y(X), 5
 ENDIF
 ENDIF
 NEXT X
ENDFUNCTION

' Moves out a new sprite
FUNCTION MoveNewSprite()
 FOR X = 2 TO 20
 IF SPRITE X(X) <= -100
 SPRITE X , -64, SPRITE Y(X), 5
 X = 21
 ENDIF
 NEXT X
 SpriteTimer(1) = 30
ENDFUNCTION

' Loads are the Target Animations.
FUNCTION LoadTargetAnims()
 LOAD BITMAP "target.bmp",1
 inum = 5
 fadestep = 100
 SET CURRENT BITMAP 1
 FOR X = 0 TO 10
 FADE BITMAP 1,90
 GET IMAGE inum,0,0,64,64
 inum = inum + 1
 NEXT X
 DELETE BITMAP 1
 SET CURRENT BITMAP 0
ENDFUNCTION


Joystick Commands

What do all gaming consoles have in common? Their joysticks! Every gaming console has the potential to have a joystick. From the Atari 2600 to the modern PC, the joystick is the choice of most game developers for input. DarkBASIC has a wide selection of commands to control the joystick.

Analog versus Digital Input

Before you get into the wonderful world of DarkBASIC joystick commands, you need a little understanding of how a joystick works. There are two different types of joysticks—digital and analog. Each type works with a PC, but they generate the data in completely different ways.

An analog joystick is like most old-school mouse devices. It consists of two rollers that, when moved, calculate the distance and report the information to the computer. All older joysticks generate this analog input. When the input is generated, it is converted to a digital signal for the computer to use. The problem with analog input is that the joystick has a tendency to drift because of slight movements.

Digital joysticks read differently than analog joysticks. Instead of having two rollers to read the distance between movements, digital joysticks use an optical or light sensor that converts user movements into a digital signal. This gives you a much more accurate reading of the user input without the drifting problems. A common digital joystick (the one I use) is the Microsoft Sidewinder 3D.

Joystick Position

Like the mouse, the joystick has two common positions—X and Y. Unlike the mouse, however, you do not have to move the joystick around a large pad to get your X and Y position readings. You just move your hand up while holding the joystick, and the Y position decreases. Move your hand left to decrease the X position.

Some joysticks also contain a third position—the Z position. This is very much like the mouse wheel. Figure 12.23 shows the three positions and how they correspond to the joystick.

click to expand
Figure 12.23: The three axes of a joystick

The JOYSTICK X Command

The JOYSTICK X() command returns the X position of the joystick, which ranges from −1000 to +1000. The joystick is in the center of the X axis when the X position is equal to 0.

The JOYSTICK Y Command

The JOYSTICK Y() command returns the Y position of the joystick, which also ranges from −1000 to +1000. The joystick is in the center of the Y axis when the Y position is equal to 0.

The JOYSTICK Z Command

The JOYSTICK Z() command returns the Z position of the joystick, which also ranges from −1000 to +1000. The joystick is in the center of the Z axis when the Z position is equal to 0.

Recycling an Old Program

To demonstrate the X, Y, and Z joystick commands, I have rewritten the mouse movement command to read the joystick. Notice that there is no joystick position command because you cannot reposition the joystick. Figure 12.24 shows the output of the JoystickPosition program.

click to expand
Figure 12.24: Output of the JoystickPosition program


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - JoystickPosition Program
'---------------------------------
CLS
SYNC ON
SYNC RATE 30
White = RGB(255,255,255)
Black = RGB(0,0,0)
' Reads the Joystick position until
' the escape key is hit..
WHILE ESCAPEKEY()=0
 INK 0,0
 BOX 0,0,639,479
 INK White,Black
 tempstring$ = "Joystick X pos: "+STR$(JOYSTICK X())
 TEXT 10,10,tempstring$
 string$ = "Joystick Y pos: "+STR$(JOYSTICK Y())
 TEXT 10,22,tempstring$
 string$ = "Joystick Z pos: "+STRr$(JOYSTICK Z())
 TEXT 10,34,tempstring$
 SYNC
ENDWHILE

Joystick Movement

The joystick movement commands are not like the mouse movement commands. They do not give you the distance that the joystick moves; rather, they tell you what direction the joystick is moving.

The JOYSTICK UP Command

The JOYSTICK UP() command tells you whether the joystick is moving upward. This command takes no parameters and returns a 1 if the joystick is moving up. If the joystick is moving downward, this command returns a 0.

The JOYSTICK DOWN Command

The JOYSTICK DOWN() command tells you whether the joystick is moving downward. This command takes no parameters and returns a 1 if the joystick is moving down. If the joystick is moving upward, this command returns a 0.

The JOYSTICK LEFT Command

The JOYSTICK LEFT() command tells you whether the joystick is moving left. This command takes no parameters and returns a 1 if the joystick is moving to the left. If the joystick is moving right, this command returns a 0.

The JOYSTICK RIGHT Command

The JOYSTICK RIGHT() command tells you whether the joystick is moving right. This command takes no parameters and returns a 1 if the joystick is moving to the right. If the joystick is moving left, this command returns a 0.

Recycling Yet Another Old Program

The MouseMove program scaled a bitmap with the mouse. You are now going to recycle that code and scale the picture with the joystick. Notice that the JOYSTICK UP() value is subtracted from the scalex value, and JOYSTICK DOWN() is added. This is different than the code for the MouseMove program, in which you just added one value, because neither JOYSTICK UP() nor JOYSTICK DOWN() returns a negative number. Therefore, you just create the negative value. The same is true with JOYSTICK LEFT() and JOYSTICK RIGHT(). Figure 12.25 shows the output of the JoystickMove program.

click to expand
Figure 12.25: Output of the JoystickMove program


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - JoystickMove Program
'---------------------------------
CLS
LOAD BITMAP " graphic.bmp", 1

HIDE MOUSE
SYNC ON
SYNC RATE 30
White = RGB(255,255,255)
Black = RGB(0,0,0)
SIZEX = 100
SIZEY = 100
SET CURRENT BITMAP 0
' Scales with Joystick movement
' until the escape key is pressed
WHILE ESCAPEKEY()=0
 INK 0,0
 BOX 0,0,639,479
 INK White,Black
 sizex = sizex - JOYSTICK UP()
 sizex = sizex + JOYSTICK DOWN()
 sizey = sizey - JOYSTICK LEFT()
 sizey = sizey + JOYSTICK RIGHT()
 IF sizex > 100 THEN sizex = 100
 IF sizex < 1 THEN sizex = 0

 IF sizey > 100 THEN sizey = 100
 IF sizey < 1 THEN sizey = 0
 x1 = 0
 x2 = (638*sizex)/100+1
 y1 = 0
 y2 = (478*sizey)/100+1
 COPY BITMAP 1,0,0,639,479,0,x1,y1,x2,y2
 tempstring$ = "Move the JoyStick to scale the picture"
 TEXT 10,460,tempstring$
 SYNC
ENDWHILE

Joystick Buttons

Just like the mouse, the joystick has buttons. Some joysticks have lots of buttons (such as for the Xbox, GameCube, and PlayStation 2), while other joysticks have one button (such as for the Atari 2600). However, each button has one thing in common—it provides a game with user input. Each button is assigned to a specific action or series of actions. In Super Mario Brothers, for example, one button is used to jump, and the other button is used to fire. DarkBASIC provides commands to read these buttons from the joystick and use them in your game.

The JOYSTICK FIRE A Command

The JOYSTICK FIRE A() command lets you know when the primary button on the joystick has been pressed. This is commonly used for firing at objects in most firstperson shooters. The command takes no parameters, but it returns a 0 if the primary button is in the UP state and a 1 if it is in the DOWN state.

The JOYSTICK FIRE B Command

The JOYSTICK FIRE B() command lets you know when the secondary button on the joystick has been pressed. This is commonly used for a secondary firing function in most first-person shooters. The command takes no parameters, but it returns a 0 if the secondary button is in the UP state and a 1 if it is in the DOWN state.

The JOYSTICK FIRE C Command

The JOYSTICK FIRE C() command lets you know when the third button on the joystick has been pressed. This is commonly used to check status or perform actions in some first-person shooters. The command takes no parameters, but it returns a 0 if the third button is in the UP state and a 1 if it is in the DOWN state.

The JOYSTICK FIRE D Command

The JOYSTICK FIRE D() command lets you know when the fourth button on the joystick has been pressed. This is not commonly used in first-person shooters, but it can be assigned to change things in the display. The command takes no parameters, but it returns a 0 if the fourth button is in the UP state and a 1 if it is in the DOWN state.

Joystick Sliders

Some joysticks, both analog and digital, have sliders on them, much like you would see in the cockpit of a spaceship or on top of a soundboard. DarkBASIC provides a means to read these sliders as well.

The JOYSTICK SLIDER A Command

The JOYSTICK SLIDER A() command returns the value of the primary slider on a joystick. I usually use this slider to control my thrust in a space flight simulation. The command takes no input, but returns a value between 0 and 65535. This is much more precise than JOYSTICK X() and JOYSTICK Y(), so you can get more precision out of a slider.

  Note

The number 65535 will show up frequently when you are programming devices. This is because it has 16 bits and is a computer-friendly number (because it is based on a power of 2).

The JOYSTICK SLIDER B Command

The JOYSTICK SLIDER B() command returns the value of a secondary slider on a joystick. The command also takes no input, but it returns a value between 0 and 65535. I have never had a joystick with two sliders before, but I'm sure it is a great combination of control and style.

Additional Joystick Commands

There are four other joystick commands that I need to address. These commands cover some of the unconventional aspects of joysticks. However, DarkBASIC would not be complete without them.

The JOYSTICK TWIST X Command

The JOYSTICK TWIST X() command reads the twist of the X position of the joystick. It takes no parameters but returns the value of the joystick twisted in the X direction. This value is between 0 and 65535.

The JOYSTICK TWIST Y Command

The JOYSTICK TWIST Y() command reads the twist of the Y position of the joystick. It takes no parameters but returns the value of the joystick twisted in the Y direction. This value is between 0 and 65535.

The JOYSTICK TWIST Z Command

The JOYSTICK TWIST Z() command reads the twist of the Z position of the joystick. It takes no parameters but returns the value of the joystick twisted in the Z direction. This value is between 0 and 65535.

The JOYSTICK HAT ANGLE Command

The JOYSTICK HAT ANGLE command returns the degrees of the hat controller on your joystick. Some joysticks have more than one hat, so this command takes one parameter—the number of the hat. It supports up to four different hats, and returns the angle at which the hat is pointing in tenths of a degree. The value of the angle ranges from 0 to 3600. Table 12.4 lists the most common hat directions.

Table 12.4: Hat Directions

Direction

Angle (in Tenths of a Degree)

North

0

East

900

South

1800

West

2700

A hat is a multidirectional button on a joystick. You simply press down most buttons, but you press a hat button in a particular direction.

Revising the ShootingGallery Program

Now that you know all the joystick commands, it is time to revisit the ShootingGallery program. This time you will replace the mouse commands with joystick commands. Because of the way the program was written, you only need to change one function—the mouse handler. The following source code lists the changes you need to make to enable the ShootingGallery program to use the joystick. You can find the full source code for the JoystickShootingGallery program on the CD in the Chapter 12 directory.

Place the following source code after the SYNC RATE 30 command in the original ShootingGallery program.

DIM XPos(1)
DIM YPos(1)
XPos(1) = SCREEN WIDTH() /2
YPos(1) = SCREEN HEIGHT() /2

Now replace the ControllerHandler() section with this new section, which uses the JOYSTICK commands.

FUNCTION ControllerHandler()
 IF JOYSTICK UP() = 1 THEN YPos(1) = YPos(1) - 3
 IF JOYSTICK DOWN() = 1 THEN YPos(1) = YPos(1) + 3
 IF JOYSTICK LEFT() = 1 THEN XPos(1) = XPos(1) - 3
 IF JOYSTICK RIGHT() = 1 THEN XPos(1) = XPos(1) + 3
 IF XPos(1) < 0 THEN XPos(1) = 0
 IF YPos(1) < 0 THEN YPos(1) = 0
 IF XPos(1) > SCREEN WIDTH()-1 THEN XPos(1) = SCREEN WIDTH()-1
 IF YPos(1) > SCREEN HEIGHT()-1 THEN YPos(1) = SCREEN HEIGHT()-1
 SPRITE 1, XPos(1), YPos(1) , 25
 IF JOYSTICK FIRE A()=1
 FOR X = 2 TO 20
 IF SPRITE COLLISION(1,X)
 SPRITEHIT(X) = 1
 ENDIF
 NEXT X
 ENDIF
ENDFUNCTION


Defining Control Devices

Before you move on to the final capabilities of the joystick, you need to take a side trip. This trip takes you down the path of control devices. Some computers have more than one control device, which can be just about any human input device. Some examples are joysticks, head-mounted trackers, and driving wheels. The next set of commands tells DarkBASIC which one of those control devices to use and sets the default control devices.

The PERFORM CHECKLIST FOR CONTROL DEVICES Command

The PERFORM CHECKLIST FOR CONTROL DEVICES command fills up the check list information with all the available control devices. Each device gets its own space within the checklist. The name of the device is returned in CHECKLIST STRING$(). If the device supports force feedback, CHECKLIST VALUE A() returns a 1; otherwise, it returns a 0.

The SET CONTROL DEVICE Command

After you have listed the control devices, you need to set the default control device using the SET CONTROL DEVICE command. This command takes one parameter, which is a string with the name of the device. If PERFORM CHECKLIST FOR CONTROL DEVICES returns more than one control device, you should ask the user which device to use and then pass the string for that device to this command.

The CONTROL DEVICE NAME$ Command

The CONTROL DEVICE NAME$ command returns the string name of the control device. This is very useful because you will not have to keep track of the current control device; you can just read its name from CONTROL DEVICE NAME$. This command takes no parameters, but returns a string with the control device's name.

The CONTROL DEVICE X Command

The CONTROL DEVICE X command returns the X value of the current controller. This is exactly like the JOYSTICK X() command, but it works for any control device specified.

The CONTROL DEVICE Y Command

The CONTROL DEVICE Y command returns the Y value of the current controller. This is exactly like the JOYSTICK Y() command, but it works for any control device specified.

The CONTROL DEVICE Z Command

The CONTROL DEVICE Z command returns the Z value of the current controller. This is exactly like the JOYSTICK Z() command, but it works for any control device specified.

Selecting the Current Control Device

The SetControlDevice program provides a simple example of how to detect and set the current control device. It contains a function that you will use in quite a few other programs to determine which control device to use. Figure 12.26 shows the output of the SetControlDevice program.

click to expand
Figure 12.26: Output of the SetControlDevice program


'---------------------------------
'Beginner's Guide To Game Programming With DarkBASIC
'Copyright (C)2002 Jonathan S. Harbour and Joshua R. Smith
'Chapter 12 - SetControlDevice Program
'---------------------------------
SYNC ON
SYNC RATE 30

SetControlDevice()
PRINT CONTROL DEVICE NAME$()

END

' Sets the current control device
FUNCTION SetControlDevice()
 PERFORM CHECKLIST FOR CONTROL DEVICES
 IF CHECKLIST QUANTITY() = 1
 SET CONTROL DEVICE CHECKLIST STRING$(1)
 EXITFUNCTION CHECKLIST STRING$(1)
 ENDIF
 CLS
 PRINT "Please Select Control Device"
 FOR X = 1 TO CHECKLIST QUANTITY()
 tempstring$ = STR$(X)+": "+CHECKLIST STRING$(X)
 PRINT tempstring$
 NEXT X
 INPUT ConDev
 SET CONTROL DEVICE CHECKLIST STRING$(ConDev)
ENDFUNCTION CHECKLIST STRING$(ConDev)

One special thing to note about this function is that is there is only one control device—the function does not list the devices, it just picks that one control device. This is useful for keeping the flow of a program going. Also, if there are no control devices available, this function returns a string of "none." That way, you can check up front to see whether there are any control devices.


Force Feedback

Now that you have learned about the control devices, I will cover force feedback, which includes more than just the standard joystick. Driving wheels and other control devices (including some mouse devices) also support force feedback.

What is force feedback? It is a tactile sensation returned to the gamer by the control device he is using. An example would be a gamer playing a boxing game. In real boxing, when your opponent hits you, you feel the hit on your face. In the gaming world, you really don't want to be hit in the face, but you would like some other feedback to let you know you've been hit. Thus your joystick will rumble or move to one side as your opponent strikes you. That is why it is called force feedback—the joystick is forcing you to feel some feedback. The joystick or input device accomplishes this with small motors and sensors that are built into it.

Programming Force Feedback

Programming force feedback in DarkBASIC does not take a rocket scientist. When I finish explaining the command, you will add some source code to the ShootingGallery program to add force feedback.

Before activating any of the force-feedback commands, you must first determine whether the device supports it. Remember that the checklist created by PERFORM CHECKLIST FOR CONTROL DEVICES stores a value of 1 in CHECKLIST VALUE A() if the device supports force feedback. Your program will fail if you attempt to use force feedback on a device that does not support it.

You can split the force-feedback commands into two groups—the standard commands and the special commands. Each group of commands takes similar input. At least one of their parameters (unless otherwise specified) takes a magnitude value.

Magnitude value is the extent of the force-feedback effect. This value ranges from 0 to 100, where 0 is no effect and 100 is the largest possible effect.

Standard Force Feedback Commands

The standard force-feedback commands allow you to create your own force-feedback effects. They give you the ability to move the joystick in any direction you want. The commands are FORCE ANGLE, FORCE UP, FORCE DOWN, FORCE LEFT, FORCE RIGHT, FORCE AUTO CENTER ON, FORCE AUTO CENTER OFF, and FORCE NO EFFECT.

The FORCE ANGLE Command

FORCE ANGLE is the most versatile of the standard force-feedback commands. It takes three parameters and returns none. The first parameter is the magnitude of the force. The second value is the angle at which you want to put the force-feedback device. The third value is the time for which you want to leave the device at that angle, measured in milliseconds.

The FORCE UP Command

The FORCE UP command forces the joystick into the up position. It provides resistance if you are trying to pull down on the joystick. The command takes one parameter, which is the magnitude of the force, and returns nothing.

The FORCE DOWN Command

The FORCE DOWN command forces the joystick into the down position. It provides resistance if you are trying to pull up on the joystick. The command takes one parameter, which is the magnitude of the force, and returns nothing.

The FORCE LEFT Command

The FORCE LEFT command forces the joystick into the left position. It provides resistance if you are trying to pull the joystick right. The command takes one parameter, which is the magnitude of the force, and returns nothing.

The FORCE RIGHT Command

The FORCE RIGHT command forces the joystick into the right position. It provides resistance if you are trying to pull the joystick left. The command takes one parameter, which is the magnitude of the force, and returns nothing.

The FORCE AUTO CENTER ON Command

The FORCE AUTO CENTER ON command forces the joystick to always return to the center, instead of forcing left, right, up, or down. This command is great for stiffing the joystick. It takes no parameter, and it returns nothing.

The FORCE AUTO CENTER OFF Command

The FORCE AUTO CENTER OFF command frees the joystick to stay in whatever position it is in. This command is great for loosening the joystick. It takes no parameter, and it returns nothing.

The FORCE NO EFFECT Command

The FORCE NO EFFECT command is the last of the standard commands, and it affects both the standard and the special force-feedback commands. This command cancels all force feedback applied to the joystick. It takes no parameters and returns nothing.

Special Force Feedback Commands

Sometimes just moving the joystick up, down, left, and right is not enough. DarkBASIC provides commands to do more than just standard stuff. These are special case commands that perform more complex actions. DarkBASIC supports four special commands: FORCE CHAINSAW, FORCE SHOOT, FORCE IMPACT, and FORCE WATER EFFECT.

The FORCE CHAINSAW Command

The FORCE CHAINSAW command creates a chainsaw effect within the control device. Imagine revving up a chainsaw and keeping it running. That's what this command simulates. It takes two parameters. The first is the magnitude value, and the second is the duration of the effect. Like all force-feedback effect commands, the duration is measured in milliseconds.

The FORCE SHOOT Command

The FORCE SHOOT command emulates the kickback from a pistol. The kickback occurs when you pull the trigger—your hand moves back and the bullet moves forward. This command takes two parameters. The first is the magnitude value, and the second is the duration value.

The FORCE IMPACT Command

The FORCE IMPACT command is probably the most versatile of the special force-feedback commands. You can use it for hitting walls, hitting people, or getting hit.

I think this might be my favorite special force-feedback command. It takes two parameters. The first is the magnitude value, and the second is the duration value.

The FORCE WATER EFFECT Command

FORCE WATER EFFECT is an interesting command. It creates the sensation of walking through water. This command takes two parameters. The first is the magnitude value, and the second is the duration value.

Revising the ShootingGallery Program Again

This is your last visit to the ShootingGallery program. This time you will add special force-feedback commands to the program. You will add two new commands, change the control handler, and modify the main portion of the program. You can find the full source code for this program on the CD in the Chapter 12 directory, under ForceShootingGallery.

First, add the following source code after the SYNC RATE 30 section. This code checks the force-feedback capabilities of the joystick. You will enter SETCONTROLDEVICE() in a little while.

DIM SupportsForceFeedBack(1)
SupportsForceFeedBack(1) = 0
SetControlDevice()

Add the following source code after inum = 5. These are the instructions to activate the force-feedback commands if the joystick supports them.

IF SupportsForceFeedBack(1) = 1
 TEXT 10,292,"C - Chain Saw Effect"
 TEXT 10,304,"V - Water Effect"
 TEXT 10,316,"W - Force UP"
 TEXT 10,328,"S - Force DOWN"
 TEXT 10,340,"A - Force LEFT"
 TEXT 10,352,"D - Force RIGHT"
 TEXT 10,364,"O - Auto Center On"
 TEXT 10,376,"P - Auto Center Off"
ENDIF

Add the following line of code after ControllerHandler(). This processes the other force-feedback effects.

 DoOtherEffects()

Next, replace the existing ControllerHandler() function with the following ControllerHandler() function.

FUNCTION ControllerHandler()
 IF JOYSTICK UP() = 1 THEN YPos(1) = YPos(1) - 3
 IF JOYSTICK DOWN() = 1 THEN YPos(1) = YPos(1) + 3
 IF JOYSTICK LEFT() = 1 THEN XPos(1) = XPos(1) - 3
 IF JOYSTICK RIGHT() = 1 THEN XPos(1) = XPos(1) + 3
 IF XPos(1) < 0 THEN XPos(1) = 0
 IF YPos(1) < 0 THEN YPos(1) = 0
 IF XPos(1) > SCREEN WIDTH()-1 THEN XPos(1) = SCREEN WIDTH()-1
 IF YPos(1) > SCREEN HEIGHT()-1 THEN YPos(1) = SCREEN HEIGHT()-1
 SPRITE 1, XPos(1), YPos(1) , 25
 IF JOYSTICK FIRE A()=1
 IF SupportsForceFeedBack(1) <> 0 THEN FORCE SHOOT 50,25
 FOR x = 2 TO 20
 IF SPRITE COLLISION(1,x)
 IF SupportsForceFeedBack(1) <> 0
 FORCE IMPACT 50,25
 ENDIF
 SpriteHit(x) = 1
 ENDIF
 NEXT x
 ENDIF
ENDFUNCTION

Now add the following two functions to the end of your program, and you will have force-feedback capability in your ShootingGallery program.

FUNCTION SetControlDevice()
 PERFORM CHECKLIST FOR CONTROL DEVICES
 IF CHECKLIST QUANTITY() = 0
 EXITFUNCTION "NONE"
 ENDIF
 IF CHECKLIST QUANTITY() = 1
 SET CONTROL DEVICE CHECKLIST STRING$(1)
 SupportsForceFeedBack(1) = CHECKLIST VALUE A(1)
 EXITFUNCTION CHECKLIST STRING$(1)
 ENDIF
 CLS
 PRINT "Plese Select Control Device"
 FOR x = 1 TO CHECKLIST QUANTITY()
 tempstring$ = STR$(x)+": "+CHECKLIST STRING$(x)
 PRINT tempstring$
 NEXT X
 INPUT ConDev
 SupportsForceFeedBack(1) = CHECKLIST VALUE A(X)
 SET CONTROL DEVICE CHECKLIST STRING$(ConDev)
ENDFUNCTION CHECKLIST STRING$(ConDev)

FUNCTION DoOtherEffects()
 IF SupportsForceFeedBack(1) =0 THEN EXITFUNCTION
 KeyPress$ = UPPER$(INKEY$())
 IF KeyPress$ = "" THEN EXITFUNCTION
 IF KeyPress$ = "C" THEN FORCE CHAINSAW 50,1000
 IF KeyPress$ = "V" THEN FORCE WATER EFFECT 50,1000
 IF KeyPress$ = "W" THEN FORCE UP 50
 IF KeyPress$ = "S" THEN FORCE DOWN 50
 IF KeyPress$ = "A" THEN FORCE LEFT 50
 IF KeyPress$ = "D" THEN FORCE RIGHT 50
 IF KeyPress$ = "O" THEN FORCE AUTO CENTER ON
 IF KeyPress$ = "P" THEN FORCE AUTO CENTER OFF
ENDFUNCTION


Summary

Wow, there are a lot of commands to take control of input devices. This chapter explained all of the commands and how to execute them. User input devices make a technical demo a game. The ShootingGallery program is an excellent example of using input devices. Someday, I hope to see someone take that program and add sounds, high scores, and plenty of bells and whistles.


Quiz

The chapter quiz will help you retain the information that was covered in this chapter, as well as give you an idea about how well you're doing at understanding the subjects. You will find the answers for this quiz in Appendix A, "Answers to the Chapter Quizzes."

1.

Which command is used to read a string or number entered from the keyboard?

  1. INPUT
  2. OUTPUT
  3. MOUSE BUTTON()
  4. PRINT

a

2.

What does the INKEY$() command do?

  1. Returns the key currently being pressed
  2. Returns a random key
  3. Returns a string of all the keys being pressed
  4. Returns nothing

a

3.

Which command returns 1 when the spacebar is pressed?

  1. SPACEBARKEY()
  2. ESCAPEKEY()
  3. RETURNKEY()
  4. INKEY$()

a

4.

What is the value of mouseclick() when the left and right mouse buttons are both pressed?

  1. 1
  2. 2
  3. 3
  4. 0

c

5.

When a mouse is located at x = 100, y = 300, which command returns 100?

  1. MOUSEMOVEX()
  2. MOUSEMOVEY()
  3. MOUSEX()
  4. MOUSEY()

c

6.

How many joystick hats does DarkBASIC support?

  1. 3
  2. 4
  3. 7
  4. 2

b

7.

Which checklist value returned from PERFORM CHECKLIST FOR CONTROL DEVICES returns whether the device supports force feedback?

  1. CHECKLIST STRING$()
  2. CHECKLIST VALUE A()
  3. CHECKLIST VALUE B()
  4. CHECKLIST VALUE C()

b

8.

Which command cancels all force-feedback effects on a joystick?

  1. FORCE NO EFFECT
  2. FORCE UP
  3. FORCE WATER EFFECT
  4. FORCE STOP

c

9.

Which command returns the scan code of the key currently being pressed?

  1. SCANCODE
  2. CODESCAN
  3. KEYSTATE
  4. INKEY$()

a

10.

ESCAPEKEY() = 1 means the Esc key is being held down.

  1. True
  2. False

a

Answers

1.

A

2.

A

3.

A

4.

C

5.

C

6.

B

7.

B

8.

C

9.

A

10.

A




Beginner's Guide to DarkBASIC Game Programming
Beginners Guide to DarkBASIC Game Programming (Premier Press Game Development)
ISBN: 1592000096
EAN: 2147483647
Year: 2002
Pages: 203

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net