More Power to the Numbers Data Sequences and Arrays

This chapter extends the subjects of variable data types and looping processes, which were covered in previous chapters, bringing them together in a new light. As you will learn in more detail shortly, data sequences allow you to add data directly to a program without loading that data from a file or other means, which can be very useful in a game. Whereas a complete game might use data files to store information about the objects in the game (such as characters, places, ships, weapons, monsters, and so on), this type of data can be inserted into the game right from the start using data sequences. This can be very useful when you are designing an initial prototype of a game or game engine and you don't want to spend time creating game editors to design your game worlds, characters, and such.

Arrays work hand-in-hand with data sequences and even more with looping commands, with which they are able to iterate through long lists of information quickly and efficiently. While looping with variables or functions allows you to perform repeat processes easily, looping with data sequences allows you to read and apply custom values to your game. For example, suppose you are writing your own roleplaying game with a character that explores dungeons and fights against monsters. The character and the monsters will have traits, such as strength, endurance, hit points, and so on. Storing monster names along with traits in a data sequence is quick and easy and allows you to make changes to the traits right inside the source code at any time. For larger projects, you would want to store traits in data files, but a data sequence will work just as well in smaller projects.

Introduction to Data Sequences and Arrays

A data sequence can store any data in sequential order. Data is read one item at a time, like an assembly line. A stack is another way of describing a data sequence. A stack keeps track of data in a first in, last out order. Alternatively, this can be described as last in, first out. Figure 7.1 illustrates a commonplace example of a stack, in which plates coming from the dishwasher are added to the stack and immediately removed for service. The first plate added to the stack might never even be used!

click to expand
Figure 7.1: A software stack works like a stack of plates at a buffet, where the last plate added is the first plate removed—first in, last out or last in, first out.

Keeping Track of Data

Comparing a data sequence to a stack is not entirely accurate because you can't add new items to the data sequence after the program starts running (during the run time); you can only add new items when you are editing the source code (during the design time). However, if you type in the data statements in a data sequence in order, it does resemble a design-time stack, so I thought this analogy would help you visualize how data sequences work.

Another example that is perhaps more accurate is comparing a data sequence to a sequential disk file. Chapter 15, "Loading and Saving Information Using Files," explains how to work with files, so I won't get into them in detail here other than to summarize how they work. There are two basic types of files—sequential and random-access. Sequential files are like text files that you can edit with Notepad. A program settings file, such as win.ini, is also a sequential text file that you can read with Notepad. Another type of sequential file is a binary file that stores bytes or other types of numbers. Random-access files are structured files that read and write records of data rather than a single character at a time. DarkBASIC does not support structured files because it knows how to read most game-related files natively (such as 3D Studio Max files, wave files, texture files, and so on).

The difference between a sequential file and a stack is that you must read and interpret a file using number or string variables, and you must keep track of file numbers, names, lengths, and so on. Data sequences are much easier to use! Just think of a data sequence as a simple kind of sequential file.

Storing Data Efficiently

All things being equal, data sequences are really only effective for limited amounts of data. When the data in a data sequence becomes too large, it is difficult to maintain the data in your source code file. One way around the problem of lengthy source code listings is to use the #INCLUDE command to include one or more source code files in your main program file. You can then move the data sequences over to a separate file and keep your main program listing more tidy.

What types of data can you imagine storing in a data sequence inside your program? I can think of many.

  • Character traits and attributes in a role-playing game
  • Spaceship names and traits in a space shooter game
  • Weapon names and attack values in a first-person shooter game
  • Height map data for the 3D terrain in each level of a game
  • Power-ups that can be gathered
  • Maps and levels for a real-time strategy game

The one drawback to using a data sequence instead of a disk file is that when the game is finished, compiled, and put up for sale or into the public domain, there won't be any way to add new levels and missions or monsters to the game later. Mission packs, add-ons, and modifications ("mods") are very popular in the gaming community. If even a simple game supports player-made levels, it will generate a fan following. Players enjoy creating their own levels and add-ons for games and then sharing their work with others. It involves a little fame, a little prestige, and a lot of fun overall.

The tradeoff is whether you want to go through the additional work required to load data into your program from disk files, rather than just storing the data inside your program. Perhaps one benefit to a data sequence is that it is like a built-in array, so you don't need to use an additional array to use it. Data stored in a file, however, would probably need to be loaded into an array, at which point it would somewhat resemble a data sequence.


Data Sequences

In this section I will show you how to create a data sequence in a DarkBASIC program. Next I'll show you the various commands for reading the data sequence and putting the data to good use. Finally, I'll show you how to reset the data sequence and start reading it from the beginning again. This might be useful when you want to restart the game, for instance.

The DATA Statement

The DATA statement defines data in a data sequence. It is specifically called a sequence because you can have many DATA statements in your program. In fact, you can insert a DATA command anywhere in your program, but I would recommend keeping all DATA statements at the top of the source code file for clarity. It is very confusing when you have DATA statements strewn all about your program.

One solution that you can employ with multiple data sequences is to label specific data sequences, and then jump to the labels to read them. I'll explain data labels shortly, when I cover the RESTORE statement.

The DATA statement supports strings, integer numbers, and decimal numbers. Here is a sample of a data sequence that includes a last name, first name, and age.

DATA "Jones", "Bob", 34
DATA "Anderson", "Julie", 19
DATA "Smith", "John", 26
DATA "Wells", "Joanne", 8

See how you can design the data sequence any way you want? This data can accommodate numbers and strings, but there is no way to store binary numbers or bytes—the sort of data you would need to store bitmap pixels, for instance.

The READ Command

The READ command reads data stored in a data sequence. The data is read one item at a time (where individual data items are separated by commas) from beginning to end. The READ command is flexible in that it supports integer numbers, decimal numbers, and strings (just like the DATA statement does).

The following code snippet demonstrates how to read the data sequence and print out the information. Note that this code will use the DATA statements that were shown in the previous section.

FOR n = 1 to 4
 READ LastName$, FirstName$, Age
 PRINT FirstName$; ", "; LastName$; ", "; Age
NEXT n

Do you see how the variables are printed out in a different order than they are read? When you have read the data, you can do anything you want with it! Take note also of the FOR loop, which performs the READ command four times. Even though there are 12 items in the data sequence, three of them are read each time through the loop: LastName$, FirstName$, and Age.

Testing Data Sequences The ContactData Program

Now I'll show you a simple program I wrote that uses a data sequence filled with contact information. The data includes the following fields.

  • Last name
  • First name
  • Address
  • City
  • State
  • Zip
  • Phone

I know you aren't particularly interested in databases, but this simple contact program is a great way to demonstrate how data sequences work. Later I'll show you a more interesting program that uses DATA statements and a modified version of the Conditions program from Chapter 6. Figure 7.2 shows the output of the ContactData program.

click to expand
Figure 7.2: The ContactData program demonstrates how to use the DATA statement and the READ command.

Now for the source code for the ContactData program. There are four DATA statements that provide the contact information used by the program. There is also a single DATA statement at the beginning of the sequence that provides the number of records that should be read. This is an important thing to remember! Without some sort of total value, you will have to hard-code the total number of data statements into your code, and then it will be more difficult to add new DATA statements later (something that is fairly common when working with information).

For your convenience, this project is located on the CD-ROM in the SourcesCH07ContactData folder.

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

REM Declare the data sequence
DATA 4
DATA "Jones","Bob","1234 Somewhere St","Oblivion","MD","10023","916-555-1212"
DATA "Smith","John","5678 Super St","Anchorage","WY","33992","414-555-1234"
DATA "Anderson","Julie","9293 Prairie Dr","Orson","MI","83923","212-555-8382"
DATA "Wells","Joanne","3283 Oak Tree Ln","Wichita","KS","22939","623-555-3928"

REM Declare some variables
NumData = 0
FirstName$ = ""
LastName$ = ""
Address$ = ""
City$ = ""
State$ = ""
Zip$ = ""
Phone$ = ""

REM Initialize the program
SYNC ON

REM Read the record count
READ NumData

REM Read and print out the data sequence
FOR n = 1 to NumData
 REM Read the data sequence
 READ LastName$, FirstName$, Address$, City$, State$, Zip$, Phone$

 REM Print the contact information
 PRINT "CONTACT "; n
 PRINT " NAME "; FirstName$; " "; LastName$
 PRINT " ADDRESS "; Address$; ", ";City$; ", "; State$; " "; Zip$
 PRINT " PHONE "; Phone$
 PRINT

 SYNC
NEXT n

REM Wait for key press
WAIT KEY

REM End the program
END

Have you noticed that I always include a variable declarations section in the sample programs? Although DarkBASIC doesn't require it, I highly recommend that you include a section at the top of your program for important variables so you can identify them more easily. It can be very confusing when variables are declared at random throughout the source code. This is a good programming practice rather than a requirement of DarkBASIC. Most programming languages require you to declare variables anyway, so it's a good habit to acquire.

The RESTORE Command

The RESTORE command moves the internal data sequence position to the beginning of the list where the first DATA statement is located, so the next READ command will pick up the first item of data again. The RESTORE command also supports data labels that allow you to group related items of data.

You can call the RESTORE command on its own, in which case the data sequence position will move to the top of the list. If you want to move the position to a data label, just add the name of the label after the RESTORE command. The syntax of this command is RESTORE data label.

Using the RESTORE Command: The MonsterList Program

The RESTORE command might be simple, but it is actually a very powerful command that can give your programs some interesting capabilities. I have written a program called MonsterList that demonstrates using the RESTORE command with data labels. Figure 7.3 shows the output from the MonsterList program.

click to expand
Figure 7.3: The MonsterList program demonstrates how to use the RESTORE statement with data labels.

The source code for the MonsterList program follows. Pay attention to the placement of the labels (shown in bold) and also the first DATA statement, which just includes the name of the program. This is a filler data item to demonstrate how the RESTORE command will jump to a label rather than starting from the top if you use it in that manner. It is just a coincidence that there are four monsters and four heroes in the program; feel free to add more data to the list to see how the program easily supports additional data. Just be sure to update the NumData value to reflect the number of data records used.

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

REM Misc data
DATA "Monster List Program"

REM Hero data
heroes:
DATA 4
DATA "Warrior", 15, 12, 10
DATA "Archer", 8, 8, 15
DATA "Valkyrie", 14, 13, 12
DATA "Wizard", 4, 3, 8

REM Monster data
monsters:
DATA 4
DATA "Troll", 18, 16, 3
DATA "Goblin", 5, 5, 5
DATA "Ghost", 10, 13, 6
DATA "Berserker", 16, 2, 8

REM Declare some variables
NumData = 0
Name$ = ""
Attack = 0
Defend = 0
Speed = 0

REM Initialize the program
SYNC ON
PRINT "NAME, ATTACK, DEFEND, SPEED"
PRINT

REM Print out the monsters
PRINT "MONSTERS"
RESTORE monsters
PrintData

REM Print out the heroes
PRINT "HEROES"
RESTORE heroes
PrintData

REM Wait for key press
WAIT KEY

REM End the program
END

FUNCTION PrintData()
 REM Read the record count
 READ NumData

 REM Read and print out the data sequence
 FOR n = 1 to NumData
 REM Read the data sequence
 READ Name$, Attack, Defend, Speed

 REM Print the information
 PRINT Name$; ", ";
 PRINT Attack; ", ";
 PRINT Defend; ", ";
 PRINT Speed

 SYNC
 NEXT n
 PRINT
ENDFUNCTION


Arrays

Wouldn't you agree that data sequences are fun and an interesting way to add information to a game? I can certainly appreciate the number of uses for data statements and commands that DarkBASIC provides. This section is related to data sequences, although arrays are more focused on real-time data and are more useful when reading data from disk files. In this section, I'll show you what arrays can do and how you can use them to improve your programs’ capabilities. The last demonstration program in this chapter is called BouncingBalls—I'll leave what the program does to your imagination.

What Is an Array?

An array is a sequential list of values with the same data type, such as integer, decimal, or string. Unlike data sequences, in which you can mix and match data, arrays must be filled with the same kind of data. When creating the array, you must use the dollar sign or pound sign to specify a string or decimal array, respectively. You don't use any character to specify the default integer data type for the elements of the array.

Given enough memory, there is no set maximum number of elements you can allocate in an array. It is perfectly legal to create an array with a hundred million elements! However, you will want to make sure enough memory is available before allocating a huge array, by using the memory function SYSTEM TMEM AVAILABLE or SYSTEM SMEM AVAILABLE.

Creating an Array with DIM

You use the DIM command to create an array variable. This is a keyword in DarkBASIC that you might recognize if you have ever used Visual Basic (which uses DIM for all variables, not just arrays). The DIM statement syntax is DIM VariableName(Number of Elements).

VariableName can be any name of your choosing; it is similar to any ordinary variable name. The number of elements in the array is the parameter that goes inside the parentheses. DarkBASIC is a forgiving language in that the starting number for arrays can be 0 or 1, and the upper range of the array is still the number you specified. In most programming languages, the Number of Elements value for an array can mean 1 to 30 or 0 to 29. In other words, there are exactly 30 elements to the array. However, DarkBASIC always allocates one extra index for the array, so you can use 0 or 1 and still go up to the value you specified for the upper limit.

Since DarkBASIC is lenient in this way, take care to be consistent in how you use arrays. If you treat the first element of the array as 0, then stick to it throughout your program to avoid confusion. If you prefer 1, then stick to that.

Deleting an Array with UNDIM

If for any reason you need to delete an array after you have created it with DIM, you can use the UNDIM command to remove the array from memory. This statement is provided so you can recreate the array with DIM. There are some cases in which this might be useful, such as when you are restarting the game, but I personally avoid using UNDIM and prefer to use an array throughout the program or create additional arrays when needed. One possible benefit to the UNDIM command is in a situation in which you no longer need an array and you want to free up memory to improve your game's performance. If you created a really big array and you no longer need it at some point in the program, go ahead and delete it with UNDIM. However, you don't need to delete any arrays at the end of the program because DarkBASIC will de-allocate memory automatically; you don't need to worry about memory in DarkBASIC.

Testing Arrays The BouncingBall Program

To fully demonstrate how arrays work and how you can use them to their greatest potential, I have written a program called BouncingBalls. This program starts by creating several arrays with the DIM command to keep track of the position and speed of 30 balls on the screen. It then creates the balls, each with a random position, speed, and diameter. The main part of the program moves and draws all 30 balls over and over, resulting in a more advanced version of the Conditions program that you saw in Chapter 6.

Testing the Program

The BouncingBalls program creates 30 balls on the screen by keeping track of each ball in an array. It then uses a loop to draw each ball before updating the screen. The result is a high-speed demonstration of balls bouncing off the edges of the screen. Each ball is a different size—some are very small and some are very large. Figure 7.4 shows the program running at standard resolution, and Figure 7.5 is a tweaked version running at 16001200.

click to expand
Figure 7.4: The BouncingBalls program demonstrates the use of arrays to store the position and velocity of balls on the screen.

click to expand
Figure 7.5: The BouncingBalls program running at 16001200.

Writing the Source Code

The source code for the BouncingBalls program follows. I have bolded the section of code that actually creates the arrays, as well as the section that animates the balls on the screen (further down in the listing). This program is similar to the Conditions program from Chapter 6, but I have moved the logic that bounces the balls off each of the four edges of the screen into a function.

I have also added a new function called DrawRect, which draws the border around the screen using LINE commands. The most important function in the program is MoveBall, which has a Num parameter that identifies the elements of the ball arrays that should be used to draw the balls on the screen.

  Tip

To really see what this program can do, go through the code and replace the 30-element arrays with some larger number, such as 1,000, and see what happens!

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

REM Create some variables
DIM BallX(30)
DIM BallY(30)
DIM BallSize(30)
DIM SpeedX(30)
DIM Speedy(30)
DIM Color(30)

REM Initialize the program
SET DISPLAY MODE 640, 480, 32
SYNC ON

REM Initialize the balls
InitializeBalls

REM Start the main loop
DO
 REM Clear the screen
 CLS

 REM Set the border color
 INK RGB(255,255,255), 0

 REM Draw the screen border
 DrawRect(0,0,639,479)
 REM Move and draw the balls
 FOR n = 1 TO 30
 MoveBall(n)
 NEXT n

 REM Redraw the screen
 SYNC
LOOP

REM End program
END

FUNCTION InitializeBalls()
 FOR n = 1 TO 30
 BallX(n) = RND(640)
 BallY(n) = RND(480)
 BallSize(n) = RND(20) + 5
 SpeedX(n) = RND(12) - 6
 SpeedY(n) = RND(12) - 6
 Color(n) = RGB(RND(256), RND(256), RND(256))
 NEXT n
ENDFUNCTION

FUNCTION MoveBall(Num)
 REM Move the ball
 BallX(Num) = BallX(Num) + SpeedX(Num)
 BallY(Num) = BallY(Num) + SpeedY(Num)

 REM Check conditions for the BallX
 IF BallX(Num) > 640 - BallSize(Num)
 BallX(Num) = 640 - BallSize(Num)
 SpeedX(Num) = SpeedX(Num) * -1
 ELSE
 IF BallX(Num) < BallSize(Num)
 BallX(Num) = BallSize(Num)
 SpeedX(Num) = SpeedX(Num) * -1
 ENDIF
 ENDIF

 REM Check conditions for BallY
 IF BallY(Num) > 480 - BallSize(Num)
 BallY(Num) = 480 - BallSize(Num)
 SpeedY(Num) = SpeedY(Num) * -1
 ELSE
 IF BallY(Num) < BallSize(Num)
 BallY(Num) = BallSize(Num)
 SpeedY(Num) = SpeedY(Num) * -1
 ENDIF
 ENDIF

 REM Draw the ball
 INK Color(Num), 0
 CIRCLE BallX(Num), BallY(Num), BallSize(Num)
ENDFUNCTION

FUNCTION DrawRect(Left,Top,Right,Bottom)
 LINE Left, Top, Right, top
 LINE Right, Top, Right, Bottom
 LINE Right, Bottom, Left, Bottom
 LINE Left, Bottom, Left, Top
ENDFUNCTION


Summary

This chapter explained the benefits and uses for data sequences and arrays in DarkBASIC. You learned how to add items of data to your programs using the DATA and READ commands, including the ability to use data labels to group related data items. You also learned all about arrays and how to use them. Several sample programs graced the pages of this chapter, including the ContactData and MonsterList programs, which showed you how to use data sequences.

The BouncingBalls program was a great demonstration of using arrays. Although you might not have realized it at the time, the program very closely resembles a real game! Later chapters on bitmaps and sprite animation will take this to another level, but this chapter provided you with a taste of what is to come. If you found the BouncingBalls program intriguing, then you will really enjoy Chapter 9, "Basic Graphics Commands," which goes into detail about how to use all of the 2D drawing commands supported by DarkBASIC.


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 or statement is used to declare a data sequence?

  1. READ
  2. UNDIM
  3. DATA
  4. DIM

d

2.

How does the READ command read a data sequence?

  1. Sequentially
  2. Randomly
  3. Telepathically
  4. Structurally

a

3.

Which command can be used to move the pointer in a data sequence back to the beginning?

  1. READ
  2. DIM
  3. INPUT
  4. RESTORE

d

4.

What is a list of related data stored in sequential order within the source code called?

  1. Array
  2. Data sequence
  3. Disk file
  4. Structured

b

5.

If an array is created with DIM A(10), how many elements are usable in the array?

  1. 10
  2. 9
  3. 1
  4. 11

a

6.

What types of data can you store inside a data sequence or an array?

  1. Integers, variables, and arrays
  2. Integers, decimals, and strings
  3. Numbers, strings, and constants
  4. Bytes, binary numbers, and currency

b

7.

Arrays can't store strings, just integers or decimals.

  1. True
  2. False

b

8.

What is the largest number of elements that you can allocate in an array?

  1. 32
  2. 4,096
  3. 16,384
  4. Limited only by the available memory

d

9.

Which command did the BouncingBalls program use to draw each ball?

  1. INK
  2. LINE
  3. CIRCLE
  4. ELLIPSE

c

10.

What does the RESTORE monsters command accomplish in the MonsterList program?

  1. Rejuvenates all slain monsters in the game
  2. Moves all monsters back to their starting positions
  3. Moves the DATA pointer to the first data item following the monsters label
  4. Tells all of the monsters to attack the heroes

c

Answers

1.

D

2.

A

3.

D

4.

B

5.

A

6.

B

7.

B

8.

D

9.

C

10.

C




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