[ LiB ] |
The entire chapter has been leading up to "types", as they are a very important and useful part of the Blitz Basic language. Types are simply a set of related data. That may sound like the definition of an array, but with types, you can have different names for each of the variables , as well as different data types (string, integer, and floating point).
Here is an example. Imagine you have a player ship. The computer needs to know where to put the ship. For our example, we are going to put the ship at the coordinates 100, 100 (if you don't understand coordinates, they will be explained soon). You can do something like this:
playerx = 100 playery = 100
Seems pretty easy, eh? What if you want to add a hit counter? You have to create another variable.
playerhits = 3
That's three variables. If you want to make it possible for the ship to move up and down, you need two more variables. That's a total of five unattached variables!
The best way to remedy this problem is to use types. A type can take all of these unorganized variables and attach them to a single type name , like in Figure 3.22. Here is the creation of a ship type:
Type Ship Field x,y ;the ship's location Field hits ;ship's hitpoints End Type
To create a new type, add the keyword Type before the name of the type. Next , create the individual fields. Each field is a separate variable that is part of the type. Each Field variable can be an integer, a floating point, or a string.
Now you have declared the type, and you have to create a variable that can hold this new data type. The procedure to do this is a little different from defining a variable with one of the built-in types (strings, integers, and floats). To create this new variable, or "instance" as it is called, use the following syntax.
player.ship = New ship
Wow, that looks bizarre. Let's break it down piece by piece. The first thing that you see is the word player on the left of the decimal point. This word refers to the name of the variable you are creating. After the decimal point, you see the word ship . This is the type you want the variable associated with. This variable will now have all of the same fields as the ship type, declared above. To finish off the process, we provide the proper fields by setting
player.ship equal to New ship.
This creates the new player ship. You could create an enemy ship by simply changing the name of player to enemy . Creation of a new type almost always uses this base:
instancename.typename = New typename
Now that we have organized all the loose variables by putting them in a type and creating an instance of the type, we now set the field variables.
player\x = 100 player\y = 100 player\hits = 3
Not too bad, huh? To access one of the variables, just use this formula.
instancename\variablename
Now you can create, define, and access types. Let's get to an example and see how this baby works. To write this program, I am going to use the function Text , which is declared as
Text x,y,string$,[centerx],[centery]
Refer to Table 3.3 to see what each parameter means. Text allows you to draw text on the screen, just like Print , but it also provides the ability for the programmer to choose the exact coordinate position that will appear.
Parameter | Description |
---|---|
x | The x coordinate of the text |
y | The y coordinate of the text |
string$ | The string you want printed |
[centerx] | Set to True if you want the text horizontally centered |
[centery] | Set to True if you want the text vertically centered |
For this program, we will use Text to draw the player on the screen and to show his hit points. You will also be able to decrease his hit points and move him around. This is a pretty basic and simple game. Also, the ship will be represented by the characters <-*->. Table 3.4 describes the keys used in this game.
Key | Function |
---|---|
Left Arrow | Moves ship left |
Right Arrow | Moves ship right |
Up Arrow | Moves ship up |
Down Arrow | Moves ship down |
Spacebar | Decreases the ship's hit points by one |
Esc | Exits Game |
;demo03-11.bb - Draw a ship which can be moved and killed Graphics 400,300 ;CONSTANTS Const STARTHITPOINTS = 3 Const SHIP$ = "<-*->" Const ESCKEY = 1, SPACEBAR = 57, UPKEY = 200, LEFTKEY = 203, DOWNKEY = 208, RIGHTKEY = 205 Const STARTX = 200, STARTY = 150
This is the first part of the program. It begins by setting the graphics mode. Next, it designates which variables are constants. Constants, as you remember, are variables whose values don't change throughout the game. If you wish to make a change to any of these variables, feel free to do so. The difference will be reflected throughout the entire program. It probably isn't a good idea to change the key constants (such as ESCKEY , SPACEBAR , and so on) because it'll just cause some problemsyou will have to search for the correct key.
All of the constants are listed in Table 3.5.
Constant | Default Value | Description |
---|---|---|
STARTHITPOINTS | 3 | The number of times you can decrease the hitpoints (by hitting Spacebar) before the game ends. |
SHIP$ | "<-*->" | The characters that make up the player. Because there are no images, the player is simply a text string. Change this value to change how the player looks. |
ESCKEY | 1 | The key code for Esc. |
SPACEBAR | 57 | The key code for Spacebar. |
UPKEY | 200 | The key code for the Up arrow. |
LEFTKEY | 203 | The key code for the Left arrow. |
DOWNKEY | 208 | The key code for the Down arrow. |
RIGHTKEY | 205 | The key code for the Right arrow. |
STARTX | 200 | The starting x position for the ship. |
STARTY | 150 | The starting y position for the ship. |
Okay, let's keep going.
;TYPES Type Ship Field x,y Field hitpoints Field shipstring$ End Type
This section defines all of the types used in the program. Here, only one is defined Ship . The Ship type groups all of the variables necessary to draw the ship on the screen. Table 3.6 lists all of the fields of the Ship type.
Field | Description |
---|---|
x | The x coordinate of the ship. The field is first initialized to the x value given in STARTX . |
y | The y coordinate of the ship. The field is first initialized to the y value given in STARTY . |
hitpoints | The number of hit points remaining on the ship. The field is first initialized to the hit point value given in STARTHITPOINTS . |
shipstring$ | The actual look of the ship. This field is first initialized to the string value SHIP$ . |
Next we move to the initialization of the program.
;INITIALIZATION SECTION Global cont = 1 Global player.ship = New ship player\x = STARTX player\y = STARTY player\hitpoints = STARTHITPOINTS player\shipstring = SHIP$
The initialization section defines all of the variables that will be used in the program. It also initializes the fields of the Ship type. The first variable, cont , is used in the game loop as the continue variable. As long as the user wants to continue, cont is equal to 1.
The line
Global player.ship = New ship
NOTE
CAUTION
Be careful around the (/) operator and the (\) operator. A forward slash (/) indicates division. A backward slash (\) indicates that you are accessing something from a type.
creates an instance of the Ship type with the name player . Therefore, any fields that are in the ship type can now be accessed via player . The rest of the initialization section sets up the player type by assigning its fields to their respective constants.
Next, we move on to the game loop.
;Game loop While cont = 1 Cls Text player\x, player\y, player\shipstring$ TestInput() DrawHUD() Wend ;End of loop
The game loop is short, as it should be. It begins by testing the cont variable. If cont is equal to 1, the game is run; if not, the game exits. After that, the loop clears the screen by calling Cls . Without calling Cls, the screen would exhibit streaks, like in Figure 3.23. After that, the player is drawn to the screen at his given position. The loop then tests the input by calling TestInput() and draws the HUD by calling DrawHUD() .
;TestInput() changes the direction or hitpoints of the player Function TestInput() ;If player presses left, move him left. If KeyHit(LEFTKEY) player\x = player\x - 3 If player\x <= 0 player\x = 10 EndIf EndIf ;If player presses right, move him right. If KeyHit(RIGHTKEY) player\x = player\x + 3 If player\x >= 385 player\x = 380 EndIf EndIf ;If player presses up, move him up. If KeyHit(UPKEY) player\y = player\y - 3 If player\y <= 0 player\y = 10 EndIf EndIf ;If player presses down, move him down. If KeyHit(DOWNKEY) player\y = player\y + 3 If player\y >= 285 player\y = 280 EndIf EndIf ;If player presses spacebar, remove a hitpoint If KeyHit(SPACEBAR) player\hitpoints = p layer\hitpoints - 1 If player\hitpoints <= 0 cont = 0 EndIf EndIf ;If player presses E sc, set cont to 0, and exit the game If KeyHit(ESCKEY) cont = 0 EndIf
The TestInput() function is ver y long, but also ver y simple. It simply tests the keys that the user may have pressed, and updates the variables based on the input. Starting from the top, if the player presses the left arrow , he is moved three pixels to the left. If he happens to move the character too far (off the screen), the position is moved back to the right. If the user hits right, he is moved left a little. The same happens if the user moves the ship too far up or downit is repositioned back on the screen.
If the player presses Spacebar , the hit point counter is decreased by one. The counter is then tested to see if the player has 0 hit points. If so, then cont is set to 0, and the game is exited on the next frame.
The last test checks if the user pressed Esc. If so, cont is set to 0, and the game exits on the next frame.
;DrawHUD() draws user's info in top Right of screen Function DrawHUD() Text 260, 10, "X position: " + player\x Text 260, 20, "Y position: " + player\y Text 260, 30, "Hitpoints: " + player\hitpoints End Function
The final function in the program, DrawHUD() , simply writes out the ship's information to the screen. The x and y coordinate positions and remaining hit points are drawn in the top-right section of the screen.
NOTE
That is because we are running a mini-game without page flipping. Don't worry, I will teach you how to fix this problem in Part Two of this book.
Figure 3.24 shows how the loop works, and Figure 3.25 is a screenshot of the actual program.
I'm going to leave the concept of types for a moment to talk about coordinate points. Coordinates explain where on the screen something is. They are shown in the format of (x,y). For example, something that is at coordinate (314, 13) has an x position of 314 and a y position of 13. The coordinate plane looks like Figure 3.26. The origin, or 0 value, of both the x and y direction is at the top-left corner of the screen. X increases from the origin right, and y increases from the origin down. When you want to get to coordinate position (314, 13), you move from the origin 314 spaces to the right and 13 spaces down.
Each position is a single pixel on the screen. A pixel is the smallest measurement of a computer screen. Each pixel is a different color , and the pixels fitted together create an image. To see the size of a single pixel on your machine, run demo03-12.bb (see Figure 3.27). The tiny white dot in the center is a single pixel. Small, huh?
When you want to plot an object to the screen, you plot it to a certain pixel position. Usually the top-left corner of the object is drawn to that pixel position. So, as in Figure 3.28, if you want to write some text to a certain position, the top-left corner of the text is at the selected pixel. If you write with the Text command, you are also able to center the text.
Types have been specifically designed to work well with loops . In fact, there is a new kind of loop that only works with types. It is called the For Each Next loop.
The For Each Next loop allows you to create sets of types and perform actions on them as a whole. For example, using a For Each Next loop, you could create a set of enemy ships from one call. Using the type:
Type ship Field x,y Field hitpoints End Type
You now create a bunch of enemy shipssay, 100.
SeedRnd MilliSecs() For enemycounter = 0 To 100 enemy.ship = New ship enemy\x = Rand(1,640) ememy\y = Rand (1,480) ememy\hitpoints = 3 Next
Well, we have just created 100 different enemy ships. Now, to test all of the enemies, we need to use the For Each Next loop. This loop tests every member of a certain type; this makes it easy to create a bunch of copies of an enemy and get rid of them when you're done. Refer to Figure 3.29 to see how the For Each Next loop looks in memory. This specific loop tests each enemy's hit points to make sure they are really alive . If not, they are deleted.
NOTE
It may seem like we are creating the same enemy over and over again. In actuali ty, we are creating a whole bunch of enemies with the same name. Using the For Each Next loop, we will be able to quickly and easily test and modify every enemy ship.
For enemyships.ship = Each ship If hitpoints <= 0 Delete enemyships EndIf Next
Pretty easy, if I do say so myself ! This code snippet tests every one of the ships and deletes it if its hit point counter is equal to or less than 0. To see how the For Each Next loop works in memory, check out Figure 3.30.
NOTE
TIP
You may wonder why I checked if the hit point count is equal to or less than 0. Since the ship is always deleted at 0, why test for less than 0? The reason is, sometimes a tiny error leaks through, and a ship could be assigned a 1 hit point count (this might happen if he was hit twice in the same frame). In cases like these, it's better to be safe than sorry. Test for unlikely conditions.
You can easily change this loop to interact with the enemy ships' x and y values. For example, if you add an x or y direction, you can make the enemies move randomly . You might update the type to look something like this:
Type ship Field x,y Field directionx, directiony Field hitpoints End Type
Next, inside the initialization loop, you would randomize the direction values (a positive number for directionx moves him right, and a positive number for directiony moves him down).
NOTE
If you put all this code in a program and watch the enemy ships, you may notice that the ships leave streaks behind them. This is because the previous position of each ship was not deleted. If you wish to fix this problem, simply add the command Cls (clear screen) to the beginning of the game loop.
enemy\directionx = Rand(-3,3) enemy\directiony = Rand(-3,3)
And finally, you would add code in the final loop to move him around:
enemy\x = enemy\x + enemy\directionx enemy\y = enemy\y + enemy\directiony
Congratulations, you have created animation!
[ LiB ] |