;-------------------------------------------------------------------------------
;
; ;-------------------------------;
; ; Variable Collections ;
; ;,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,;
;
; This part is quite large, to say the least.
; So copy and paste as you see fit.
;
;-------------------------------------------------------------------------------
;
; In a lot of games you can carry multiple weapons.
; Each of these weapons would require ammunition of some sort.
; What if you wanted to create such a system?
; You could do it like this:
;
Weapon1_Ammo = 50
Weapon2_Ammo = 0
Weapon3_Ammo = 0
Weapon4_Ammo = 5
;
; There is another solution however; an array.
;
Dim Weapon_Ammo( 4 )
;
Weapon_Ammo( 1 ) = 50
Weapon_Ammo( 2 ) = 0
Weapon_Ammo( 3 ) = 0
Weapon_Ammo( 4 ) = 5
;
; You're probably wondering why anyone wouldn't want to use
; the topmost solution - it does look a lot easier! :)
; Ofcourse it's all up to the programmer.
; But imagine having a huge amount of weapons.
; And you wanted to display the amount of ammo
; for each weapon on the screen.
; For the topmost approach:
;
Print "Weapon 1 ammo: " + Weapon1_Ammo
Print "Weapon 2 ammo: " + Weapon2_Ammo
Print "Weapon 3 ammo: " + Weapon3_Ammo
Print "Weapon 4 ammo: " + Weapon4_Ammo
Print
WaitKey
;
; And for the array:
;
For Weapon_Number = 1 To 4
Print "Weapon " + Weapon_Number + " ammo: " + Weapon_Ammo( Weapon_Number )
Next
Print
WaitKey
;
; E.g. you can easily walk through each element in the array
; instead of copying, pasting and editing every line :)
;
; The For..Next loop you see up there repeats the Print statement 4 times.
; The variable Weapon_Number - which did not exist before that point -
; will be created as integer variable and a value of 1 is added to it
; with each repetition, inside the For..Next.
;
; Here's a couple of alternatives:
;
; Repeat..Until
;
Weapon_Number = 0
Repeat
Weapon_Number = Weapon_Number + 1
Print "Weapon " + Weapon_Number + " ammo: " + Weapon_Ammo( Weapon_Number )
Until Weapon_Number = 4
Print
WaitKey
;
Weapon_Number = 1
Repeat
Print "Weapon " + Weapon_Number + " ammo: " + Weapon_Ammo( Weapon_Number )
Weapon_Number = Weapon_Number + 1
Until Weapon_Number = 5
Print
WaitKey
;
; While..Wend
;
Weapon_Number = 0
While Weapon_Number < 4 ; Keep repeating until Weapon_Number >= 4
Weapon_Number = Weapon_Number + 1
Write "Weapon " ; Use Write if you don't want
Write Weapon_Number ; the cursor to go to
Write " ammo: " ; the next line.
Print Weapon_Ammo( Weapon_Number )
Wend
Print
WaitKey
;
; And there are lots more!
;
;-------------------------------------------------------------------------------
;
; Remember what happens when a variable is used
; or called upon for the first time?
;
A_New_Variable = 0
;
; It is created, declared, initialized; its type is set.
;
Local An_Integer_Variable% = 0
;
; By default, all variables will be set to 0 when created.
; This also applies to arrays.
; So when you write
;
Dim Weapon_Ammo( 4 )
;
; for the first time,
; a number of elements will be created and set to 0.
;
; Did you notice that each element in the array is also of a specific type?
; That's right, the Weapon_Ammo array is an array of integers!
;
Dim Weapon_Ammo%( 4 )
;
; Another thing you see above is that you can redefine an array.
; When you do this, everything inside the array will be set to 0 again.
; And, not only can you erase an entire array, you can even change its size!
;
Dim Weapon_Ammo( 1 )
;
; But wait - there is more :P
; When an array is created it doesn't start counting from 1.
;
Weapon_Ammo( 0 ) = 50
Weapon_Ammo( 1 ) = 5
;
; There are actually 2 elements in it, when you define it with ( 1 ).
; So there's an extra element ( 0 ).
; This is the difference between 0-based and 1-based orientation.
; E.g. start counting from 0 instead of 1.
; It's usually just another case of personal preference :)
;
; Let's take a look at what our Weapon_Ammo array looks like,
; schematically:
;
; | 0 | 1 | - Element (weapon number)
; +-------+-------+
; | | |
; | 50 | 5 | - Contents (ammo amount)
; | | |
; +-------+-------+
; | Array |
; +---------------+
;
; Resizing the array to its original size.
; All contents is lost.
;
Dim Weapon_Ammo( 4 )
;
; | 0 | 1 | 2 | 3 | 4 | - Element
; +-------+-------+-------+-------+-------+
; | | | | | |
; | 0 | 0 | 0 | 0 | 0 | - Contents
; | | | | | |
; +-------+-------+-------+-------+-------+
; | Array |
; +---------------------------------------+
;
; As with normal variables,
; you can't change the type of the elements
; once an array has been declared for the first time.
; So let's take a new array, an array of strings.
; For example, if we want to store the name of each weapon.
;
Dim Weapon_Name$( 4 )
;
Weapon_Name( 1 ) = "Pistol"
Weapon_Name( 2 ) = "Shotgun"
Weapon_Name( 3 ) = "Flame thrower"
Weapon_Name( 4 ) = "Rocket launcher"
;
; Again, as with variables, once arrays are defined,
; you can omit the type identifier ($, #, etc),
; as you can see above.
;
; You can declare arrays of any type.
; Just to recap, here are the available types:
;
; % Integer variable
; # Floating point variable
; $ String variable
; .[Type name] Pointer variable (more about this soon)
;
; If you can remember, variables are used like this:
;
; [Variable name][Variable type]
;
; Arrays are used like this:
;
; [Array name][Type of elements]([Number of elements])
;
; Number of elements is actually the number of elements + 1, as shown before.
;
;-------------------------------------------------------------------------------
;
; Unlike normal variables, normal arrays
; - declared using the Dim keyword -
; are always global.
; So you can use them anywhere in your program.
;
; There is another trick you can do with arrays.
; When you declare an array you use the Dim keyword,
; which is short for dimension.
; Which would indicate that arrays can be multidimensional.
; Is this true?
;
Dim Grid( 6 , 4 )
;
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 4 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; +--+-------+-------+-------+-------+-------+-------+-------+
; | Array |
; +----------------------------------------------------------+
;
; Apparently :P
; In the above example, a 2-dimensional array, like a grid.
; Imagine a maze where you can walk through.
; So you'd want some walls.
; - How?
; Let's say that a value of 0 (all elements currently)
; means that you can walk there.
; And a value of 1 means there's a wall there.
; You can choose any values you want ofcourse,
; it's all up to the programmer :)
;
; Let's place a wall in the center of the map (3,2).
;
Grid( 3 , 2 ) = 1
;
; This code doesn't really convey much
; as you'll read back sometime and wonder what the 1 stands for,
; but we can do something about that :)
;
Const Free = 0
Const Wall = 1
;
Grid( 3 , 2 ) = Wall
;
; You'll probably remember the 'state-of-life'.
; This is a perfect example of those state identifiers.
;
; Now let's place a larger wall section.
; So we'd have to fill a number of places on the grid with the value 1.
; You could do it like this:
;
Grid( 0 , 0 ) = Wall
Grid( 0 , 1 ) = Wall
Grid( 0 , 2 ) = Wall
Grid( 0 , 3 ) = Wall
Grid( 0 , 4 ) = Wall
;
; So you'd get a vertical wall section on the left side of the grid.
; But you could also use a For..Next loop for that.
;
For Y = 0 To 4
Grid( 0 , Y ) = Wall
Next
;
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 2 | 1 | 0 | 0 | 1 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 3 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 4 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
; | | | | | | | |
; +--+-------+-------+-------+-------+-------+-------+-------+
; | Array |
; +----------------------------------------------------------+
;
; Let's try the opposite side.
;
For Y = 0 To 4
Grid( 6 , Y ) = Wall
Next
;
; And if you wanted to complete the box with a couple of
; horizontal wall sections, well..
; I think you'll understand the code below.
;
For X = 0 To 6
Grid( X , 0 ) = Wall
Grid( X , 4 ) = Wall
Next
;
; Yes, we're actually putting a wall in each corner for the second time.
; It doesn't really need to be fixed,
; as it won't cause bugs or slowdowns,
; but here's what we could have done:
;
For X = 1 To 5
Grid( X , 0 ) = Wall
Grid( X , 4 ) = Wall
Next
;
; Now, it may seem pretty obvious what the grid looks like.
;
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 2 | 1 | 0 | 0 | 1 | 0 | 0 | 1 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 3 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
; | | | | | | | |
; ---+-------+-------+-------+-------+-------+-------+-------+
; | | | | | | | |
; 4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
; | | | | | | | |
; +--+-------+-------+-------+-------+-------+-------+-------+
; | Array |
; +----------------------------------------------------------+
;
; But it might not be as obvious
; how to display the grid on the screen.
; (Yes, I know, it doesn't really look like a maze :P)
;
; If we were to walk through each element in our grid,
; how would we do that in code?
; It is very similar to the first For..Next loop in this program.
;
; If you remember,
; we did a couple of combined loops.
; Even an example of a checkerboard.
;
For Y = 0 To 4
For X = 0 To 6
; Grid( X , Y )
Next
Next
;
; And that's all there is to it! :)
; Well, okay, not all, I mean,
; we still have to put it on the screen :P
;
For Y = 0 To 4
For X = 0 To 6
Write Grid( X , Y ) ; Same line.
Next
Print ; Next line.
Next
WaitKey
;
; Note that the X and Y dimensions can be easily mixed-up.
; This can be dangerous to your code's health :)
; So be careful how you order your dimensions.
;
; Here's an example of what might happen:
;
Print
For Y = 0 To 4
For X = 0 To 4 ; Made smaller to stay
; within grid range.
Write Grid( Y , X ) ; Swapped X with Y.
Next
Print
Next
WaitKey
;
; The grid gets rotated 90 degrees!
; Hmm, not exactly what we had in mind :)
;
; I've made the X range smaller
; otherwise Blitz will complain
; that we're trying to access
; an element that lies beyond
; the range of our array.
;
;-------------------------------------------------------------------------------
;
; By the way, the Write and Print commands
; are not exactly graphical commands.
; These, as well as their friends Locate and Input
; are not totally satisfiable. (eh?)
; I'll explain this later.
;
; So let's try some more 'gamey' commands.
; There's some more maths required though.
;
; First, let's CLear the Screen.
;
Cls
;
; And place some Text at a pixel location of our desire.
;
Text 100 , 100 , "<- (100,100)"
WaitKey
;
; Text, hmm?
; Here's the syntax:
;
; Text (Pixel X location) , (Pixel Y location) , (Text)
;
; There are more optional parameters, (say what?)
; but I'll leave those up to you to find out :P
; Parameters, you know?
; Those thingies you put behind a command,
; separated by commas.
;
; If you're inside BlitzBasic,
; you can press F1 when the cursor is on or near a command/keyword,
; and at the bottom of the window you will see the quick help (syntax).
; Pressing F1 again will bring up the full help page.
;
; Let's try a loop with the Text command.
; A vertical display of numbers below (100,100) on screen.
;
For Y = 1 To 5
Text 100 , 100 + Y * 10 , Y
Next
;
; What happens in the loop is
;
; Y = 1 Pixel X Location = 100
; Pixel Y Location = 100 + 1 * 10 ; 100 + 10 = 110
; Text = 1
;
; Y = 2 Pixel X Location = 100
; Pixel Y Location = 100 + 2 * 10 ; 100 + 20 = 120
; Text = 2
;
; Y = 3 Pixel X Location = 100
; Pixel Y Location = 100 + 3 * 10 ; 100 + 30 = 130
; Text = 3
;
; Y = 4 Pixel X Location = 100
; Pixel Y Location = 100 + 4 * 10 ; 100 + 40 = 140
; Text = 4
;
; Y = 5 Pixel X Location = 100
; Pixel Y Location = 100 + 5 * 10 ; 100 + 50 = 150
; Text = 5
;
; So we leave exactly 10 pixels space for each piece of text, vertically.
;
; Let's try something more interesting.
;
For GridY = 0 To 4
For GridX = 0 To 6
ScreenX = GridX * 10 ; Pixel X Location.
ScreenY = GridY * 10 ; Pixel Y Location.
Display = Grid( GridX , GridY ) ; Number to put on screen.
Text ScreenX , ScreenY , Display
Next
Next
WaitKey
;
; - Isn't the result of that (almost) the same as with Write and Print?
; Indeed it is. The point is that Text has advantages over Write and Print.
; - Which advantages?
; I guess you want to know everything, huh? :)
; First, Text is faster.
; And second, Text is more flexible.
; - More flexible? How?
; You can center the text you want to display on a certain coordinate,
; without having to do the maths for it.
; - How?
; Enough questions! :P
; Please read the Blitz help for more..
; Right now we need colors!
;
Color 255 , 0 , 0 ; (eh?)
;
; That is how we can set the current drawing color.
; Syntax:
;
; Color (Red) , (Green) , (Blue)
;
; The combined color components give you a color of your desire.
; You can specify values in the range of 0 and 255,
; where 0 means darkest and 255 means brightest.
;
; So the current drawing color is now; Red.
;
; Some more examples:
;
Color 0 , 255 , 0 ; Green
Color 0 , 0 , 255 ; Blue
Color 255 , 255 , 255 ; White
Color 0 , 0 , 0 ; Black
Color 255 , 255 , 0 ; Yellow
Color 255 , 0 , 255 ; Purple
Color 128 , 128 , 128 ; Gray
Color 255 , 128 , 0 ; Orange
Color 128 , 64 , 0 ; Brown
Color 16 , 96 , 160 ; Creme Blue
;
; So if we start putting something on the screen now,
; it will be... Creme Blue :)
;
Text 0 , 100 , "Creme Blue"
;
; Let's take our old loop and throw in some colors.
;
For GridY = 0 To 4
For GridX = 0 To 6
ScreenX = GridX * 10
ScreenY = GridY * 10
Display = Grid( GridX , GridY )
If Display
Color 0 , 128 , 255
Else
Color 128 , 64 , 0
End If
Text ScreenX , ScreenY , Display
Next
Next
WaitKey
;
; If an element in our grid contains a non-zero value,
; it will be placed on the screen in Light Blue,
; otherwise Brown.
;
; We are actually overwriting our old grid display on the screen.
; That is, if you're running these couple of sections in one go.
;
; Btw, you can also apply some 'glue'
; to get rid of the extra variables.
; Like this:
;
; Text GridX * 10 , GridY * 10 , Grid( GridX , GridY )
;
; It can be harder to read though.
;
; The screen is cleared with the color black by default.
; But you can change that.
;
ClsColor 128 , 64 , 0
;
; The ClsColor command works the same as the Color command.
; But it applies only to the Cls command.
;
Cls
;
; This would clear your screen with the color.. Brown :)
;
;-------------------------------------------------------------------------------
;
; We've been using a 2-dimensional array.
; So it's time for a 3-dimensional array.
;
Dim Grid3D$( 10 , 10 , 1 )
;
; That would be.. 11 * 11 * 2 = 242 elements.
; Kinda like this:
;
; ---+---+---+---+---+---+---+---+---+---+---+---+
; 1 / / / / / / / / / / / /|
; ---+---+---+---+---+---+---+---+---+---+---+---+ +
; 0 / / / / / / / / / / / /|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 0 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 1 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 2 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 3 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 4 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 5 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 6 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 7 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 8 | | | | | | | | | | | |/|/|
; ---+---+---+---+---+---+---+---+---+---+---+---+ + +
; 9 | | | | | | | | | | | |/|/ \
; ---+---+---+---+---+---+---+---+---+---+---+---+ + 1
; 10 | | | | | | | | | | | |/ \
; ---+---+---+---+---+---+---+---+---+---+---+---+ 0
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 \
;
; Or like this:
;
; | 0 | 1 | 2 | 3 | 4 | 5
; ---+---+---+---+---+---+---+---+---+---+---+-- - -
; | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
; 0 |---+---|---+---|---+---|---+---|---+---|-- - -
; | : | : | : | : | : |
; ---+-------+-------+-------+-------+-------+-- - -
; | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
; 1 |---+---|---+---|---+---|---+---|---+---|-- - -
; | : | : | : | : | : |
; ---+-------+-------+-------+-------+-------+-- - -
; | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
; 2 |---+---|---+---|---+---|---+---|---+---|-- - -
; | : | : | : | : | : |
; ---+-------+-------+-------+-------+-------+-- - -
; | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
; 3 |---+---|---+---|---+---|---+---|---+---|-- - -
; | : | : | : | : | : |
; ---+-------+-------+-------+-------+-------+-- - -
; | | | | | |
; 4 : : : : : : etc
;
; So if you would say
;
; Grid3D( 0 , 0 , 1 ) = 6
;
; here's what would happen:
;
; | 0 | 1
; ---+---+---+-- - -
; | 0 | 1 |
; 0 |---+---|-- - -
; | : 6 |
; ---+-------+-- - -
; | |
; 1 : : etc
;
; So now we can store a unique color for each element,
; as well as a unique character (A, z, 0, !, etc).
;
; We'd have to agree on how to store the things again.
; For example, for each element on the grid
; field 0 would contain the color and
; field 1 would contain the character.
;
; You saw I picked an array of strings so it makes
; storing both types (values and text) easier.
;
; Let's use some sort of index selector to
; distinguish color from character. (a what?)
; Just to make the code more clear.
;
Const Grid3D_Color = 0
Const Grid3D_Char = 1
;
; Here's an example:
;
Grid3D( 10 , 10 , Grid3D_Char ) = "A"
;
; Hopefully this would mean that we put a capital A
; in the lower right corner of the grid.
; But we're not there yet.
;
; Let's remove it before anyone notices it :P
;
Grid3D( 10 , 10 , Grid3D_Char ) = ""
;
; We need to know which colors we're gonna use.
; I mean, we only have 1 field to store a color.
; We could increase the number of fields in the array,
; to be able to use 2 new fields,
; so we would have one field for Red,
; one for Green and one for Blue.
; E.g. having an array that looks like this:
;
; Dim Grid3D$( 10 , 10 , 3 )
;
; But let's do it the hard way :P
;
; As before, we can agree on some
; constants for colors we want to use.
;
; Suppose we want simply red, green and blue.
;
Const Color_Red = 0
Const Color_Green = 1
Const Color_Blue = 2
;
; Again, which values they contain doesn't really matter,
; so long as the values are unique.
; You could even use strings if you wanted to,
; as we're using a grid of strings.
;
; Example:
;
; Grid3D( 5 , 5 , Grid3D_Color ) = Color_Red
;
; So this would be a 'state-of-life' again.
; Like in the previous parts.
;
; You're right, this has nothing to do with
; displaying it on the screen, yet :P
;
; By default, the grid is empty, because it's a grid of strings.
; When you store a number, it will be converted to text.
; And if want to get the number back,
; and store it in an integer variable,
; the text will be translated back into a number.
;
; You can imagine a problem when you try to convert
; text that's not a number, into a number.
;
Value = "ABC"
;
; As said before, you cannot store text in an integer variable.
; So the text will be converted to a number.
; If the text is not a number, it will be converted to 0. (eek)
;
; So when the whole grid contains empty strings,
; you will get a grid of zeroes
; when converting each field to a number.
;
; So each color field contains Color_Red (zero)
; after converting it to a number.
; Also there's no need to convert the character field
; so now each character field contains just "" (empty).
;
; But what if we tried to compare a string with a number?
; Like we want to know what color we have stored.
; And currently all color fields contain "" (empty).
;
Value = 0
If Value = "" Then Print "Zero is equal to Empty"
;
; Apparently Blitz doesn't think
; zero is equal to empty.
;
; However, if you really want to,
; you can force a conversion,
; like this:
;
ConvertedValue = ""
If Value = ConvertedValue Then Print "Zero is equal to (converted) Empty"
;
; or like this:
;
If Value = Int ( "" ) Then Print "Zero is equal to (converted) Empty"
;
; These are the available conversion tools:
;
; Integer Int ()
; String Str ()
; Float Float ()
;
; The brackets are optional.
;
If Value = Int "" Then Print "Brackets are optional"
;
; So remember this when you're
; converting, glueing or comparing.
;
; Let's put a blue exclamation mark in the upperleft corner.
; Can you think of how to do that?
;
Grid3D( 0 , 0 , Grid3D_Color ) = Color_Blue
Grid3D( 0 , 0 , Grid3D_Char ) = "!"
;
; Now let's try build a routine to display the grid.
; First, the loops.
;
For Y = 0 To 10
For X = 0 To 10
Next
Next
;
; At the end of these loops, X and Y will both equal 11.
; So I'll just reset X and Y to 0
; to prevent going off the grid
; in the code coming up.
;
X = 0
Y = 0
;
; We have to set the color first,
; and then draw the character.
;
; If we find Color_Red on a spot,
; we have to set.. a red color.
;
If Grid3D( X , Y , Grid3D_Color ) = Color_Red
Color 255 , 0 , 0
End If
;
; If we find Color_Green in a field,
; the current drawing color must be green.
;
If Grid3D( X , Y , Grid3D_Color ) = Color_Green
Color 0 , 255 , 0
End If
;
; And finally for Color_Blue, blue.
;
If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
Color 0 , 0 , 255
End If
;
; Ofcourse we won't find any of these
; since each color field contains "" (empty).
; As comparing a "" with any number
; won't be result in a color change.
;
; Okay, now stack them.
;
If Grid3D( X , Y , Grid3D_Color ) = Color_Red
Color 255 , 0 , 0
End If
If Grid3D( X , Y , Grid3D_Color ) = Color_Green
Color 0 , 255 , 0
End If
If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
Color 0 , 0 , 255
End If
;
; No, not like that.
;
If Grid3D( X , Y , Grid3D_Color ) = Color_Red
Color 255 , 0 , 0
Else If Grid3D( X , Y , Grid3D_Color ) = Color_Green
Color 0 , 255 , 0
Else If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
Color 0 , 0 , 255
End If
;
; Yeah, that's it.
;
; And maybe you recall a Select Case
; technique for doing that as well.
;
Select Grid3D( X , Y , Grid3D_Color )
Case Color_Red
Color 255 , 0 , 0
Case Color_Green
Color 0 , 255 , 0
Case Color_Blue
Color 0 , 0 , 255
End Select
;
; So which character should we display?
;
Char$ = Grid3D( X , Y , Grid3D_Char )
;
; Oooohh.. storing it in a string variable.
; Because if we store it in an integer variable,
; it will be converted to zero if not a number!
;
; Okay, and where should we place the character?
; Hmm.. maths :)
;
; Let's use a distance of 10 pixels for each character.
; Just like before.
;
WhereX = X * 10
WhereY = Y * 10
;
; Maybe not in the upperleft corner of the screen,
; but somewhere more in the middle.
;
WhereX = X * 10 + 100
WhereY = Y * 10 + 100
;
; Text on the screen?
;
Text WhereX , WhereY , Char
;
; Good girl.
;
; Now merge'm.
;
For Y = 0 To 10
For X = 0 To 10
If Grid3D( X , Y , Grid3D_Color ) = Color_Red
Color 255 , 0 , 0
Else If Grid3D( X , Y , Grid3D_Color ) = Color_Green
Color 0 , 255 , 0
Else If Grid3D( X , Y , Grid3D_Color ) = Color_Blue
Color 0 , 0 , 255
End If
Char = Grid3D( X , Y , Grid3D_Char )
WhereX = X * 10 + 100
WhereY = Y * 10 + 100
Text WhereX , WhereY , grid3d(x,y,grid3d_color)
Next
Next
WaitKey
;
; You should see a red liney thingy somewhere,
; which would be the red exclamation mark.
; If not, you probably didn't copy and paste enough code :)
;
; As before, you can get rid of the Char,
; WhereX and WhereY variables.
; It's all up to you :)
;
; Try playing around some more
; with the grid, colors and text.
; Practice makes perfect ;)
;
;-----------------------------------------------------------------------------------------------------------------------
;
; There's a way to easily store a tilemap in your code.
;
.Tilemap
Data 10 , 10 ; Dimensions
Data Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Free , Free , Free , Free , Free , Free , Free , Free , Wall
Data Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall , Wall
;
; Ofcourse you could also use ones and zeroes.
;
; Blitz will store each data element in sequential order;
; from left to right, and from top to bottom:
;
; .Tilemap: 10 -> 10 -> Wall -> Wall -> Wall -> etc..
;
; It's a lot like the Blitz program cursor
; which reads your program from top to bottom.
;
; You can use the Restore command
; to position the data reading cursor
; at the first Data statement
; under the specified Label.
;
Restore Tilemap
;
; By default the data reading cursor
; starts from the top of your program.
;
; You can read data elements using the Read command.
;
; Read Value ; Reads the next value from data.
;
; So you can first read the dimensions of the tilemap.
;
Read Tilemap_SizeX
Read Tilemap_SizeY
;
; Then erase and resize the tilemap
; using these new dimensions.
;
Dim Tilemap( Tilemap_SizeX , Tilemap_SizeY )
;
; Now, if you would use a double loop
; you could read in the entire tilemap.
;
For Y = 1 To Tilemap_SizeY
For X = 1 To Tilemap_SizeX
; Read the next data element
; and put its value in a variable of your choice.
Read Tilemap( X , Y )
Next
Next
;
; I guess you know how to display it on screen :)
;
;-----------------------------------------------------------------------------------------------------------------------
;
; Let's clear the screen and reset the colors
; so we can use some simple commands again
; to go easy on the brain :P
;
ClsColor 0 , 0 , 0
Cls
Color 255 , 255 , 255
;
; To go to the next level, pointanoids,
; we need to go back to the basics.
; And replay all that has passed.
;
; An integer variable.
;
Integer_Variable% = 1000
;
; +---------------+
; | |
; | 1000 <----
; | |
; +---------------+
; | Integer var. |
; +---------------+
;
; A floating point variable.
;
FloatingPoint_Variable# = 1.000
;
; +---------------+
; | |
; | 1.0 <----
; | |
; +---------------+
; | Float var. |
; +---------------+
;
; A string variable.
;
String_Variable$ = "1.000,00"
;
; | | | | | | | |
; v v v v v v v v
; | | | | | | | | |
; | 1 | . | 0 | 0 | 0 | , | 0 | 0 |
; +---+---+---+---+---+---+---+---+-- -
; | String variable
; +------------------------------ -- -
;
; An array of integers.
;
Const NumberOfElements% = 3
;
Dim ArrayOfIntegers%( NumberOfElements )
;
; | | | |
; +----- v -----+----- v -----+----- v -----+----- v -----+
; | | | | |
; | 0 | 0 | 0 | 0 |
; | | | | |
; +---------------+---------------+---------------+---------------+
; | Integer | Integer | Integer | Integer |
; +---------------+---------------+---------------+---------------+
; | Array of integer variables |
; +---------------------------------------------------------------+
;
; An array of floats.
;
Dim ArrayOfFloats#( NumberOfElements )
;
; | | | |
; +----- v -----+----- v -----+----- v -----+----- v -----+
; | | | | |
; | 0.0 | 0.0 | 0.0 | 0.0 |
; | | | | |
; +---------------+---------------+---------------+---------------+
; | Float | Float | Float | Float |
; +---------------+---------------+---------------+---------------+
; | Array of floating point variables |
; +---------------------------------------------------------------+
;
; And finally, an array of strings.
;
Dim ArrayOfStrings$( NumberOfElements )
;
; | | | |
; v v v v
; | | | |
; | | | |
; +---+-- - +---+-- - +---+-- - +---+-- -
; | String | String | String | String
; +-----------+-----------+-----------+-----------+
; | Array of string variables |
; +-----------------------------------------------+
;
; or
;
; +---------------+
; | |
; | String 0 <----
; | |
; +---------------+
; | |
; | String 1 <----
; | |
; +---------------+
; | |
; | String 2 <----
; | |
; +---------------+
; | |
; | String 3 <----
; | |
; +---------------+-----------+
; | Array of string variables |
; +---------------------------+
;
; Remember our array of colors and characters?
;
; Dim Grid3D( X , Y , Index )
;
; You can also look at it like
; each element on the 2D grid (!)
; having multiple fields so to speak:
;
; Color (string)
; Character (string)
;
; So far we were using constants as:
;
; State identifier
;
; Const State = ..
;
; What_Are_We_Doing = State
; Select What_Are_We_Doing
; Case State
; ..
;
; Count identifier
;
; Const Count = ..
;
; NumberOfApples = Count
; Dim Array( Count )
;
; Index identifier
;
; Const Index = ..
;
; Array( Index ) = Value
;
; Each element in an array
; has to be of the same type.
;
; So what if you wanted more
; different types of fields? (err)
;
; Or what if you wanted just
; a player with various attributes?
;
Local PlayerName$
Local PlayerSpeed#
Local PlayerHealth%
;
; And what if you wanted to have more than one player?
;
Local Player1_Name$
Local Player1_Speed#
Local Player1_Health%
Local Player2_Name$
Local Player2_Speed#
Local Player2_Health%
;
; And what if you wanted to walk through
; over 100 players with a For..Next loop?
;
Dim Player_Name$( 100 )
Dim Player_Speed#( 100 )
Dim Player_Health%( 100 )
;
; And what if there could be
; any number of players?
; - You can resize an array.
; Yes, but the contents will be lost
; when you resize it.
; - Use a second array to copy the contents.
; Okay and what if you had 5 players
; and player 3 had to go?
; How would you do that?
; - Manually re-arrange the contents
; of the array by using a sorting algorithm.
; Smart ass :P
;
; There's a far more easier approach
; than all of the above.
;
; Imagine a list containing any number of objects
; where each object contains anything you want.
;
; For each object you can use a mould, a template,
; a structure or a blueprint if you will.
;
; So in the case of our player:
;
Type Player
Field Name$
Field Speed#
Field Health%
End Type
;
; This is like our design plan for one player.
;
; You can create an existing copy of this Type,
; by using the New command.
;
; New Player ; New (Type)
;
; The only problem is,
; we need to stick it in a variable.
; Otherwise we can't do anything with it.
; In fact, Blitz will give you an error
; if you don't to assign it to a variable.
;
; The variable we stick it in has to be
; of the same type as the thing we're creating.
; Blitz is very strict in this,
; unlike strings, integers etc.
;
; To confuse you even further,
; the variable doesn't really contain the thing,
; it just points to the thing,
; so you can modify the thing,
; as well as change its contents.
;
Local PointerToPlayer.Player
;
; Yes, a pointer variable.
; Or to be more precise,
; a pointer to Player variable.
;
; When a pointer variable is first created,
; it actually doesn't point to anything,
; which is called Null.
;
If PointerToPlayer = Null
Print "Yup, nothing there"
End If
;
; If you would create a player object,
; imagine that this is what it would look like:
;
; +---------------+---------------+-------------------+
; | Name (string) | Speed (float) | Health (integer) |
; +---------------+---------------+-------------------+
; | Player object |
; +---------------------------------------------------+
;
; If you compare it with the other schematics
; of the single variables and arrays above,
; you'll see that the arrow is missing.
; It indicates there's no way we can use it, yet.
;
; Here's what our pointer PointerToPlayer currently looks like:
;
; |
; | v |
; +---------------------------------------------------+
; | Player object (Null) |
; +---------------------------------------------------+
;
; The arrow is there,
; but the object is not :P
; E.g. the type is set,
; but it ain't pointing to any object.
;
; So let's make it point to something that exists.
;
PointerToPlayer = New Player ; (Pointer).(Type) = New (Type)
;
; Yes, you don't have to include the type of a variable
; once it has been defined, remember?
; Just like with strings, floats and integers.
;
If PointerToPlayer <> Null
Print "Something's there!"
End If
;
; Now that the pointer is actually pointing to something,
; we can change the contents of what it's pointing to.
; E.g. the contents of the Player object.
;
PointerToPlayer\Name = "Dr. I.M. D'humb"
PointerToPlayer\Speed = 5.1 ; (Pointer).(Type)\(Field) = (Value)
PointerToPlayer\Health = 100
;
; The backslash (\) allows you to access a field.
; And you can use these fields just like
; any other variable (string, float, etc).
;
; | | |
; v v v
; +----- -----+----- -----+------- -------+
; | Name (string) | Speed (float) | Health (integer) |
; +---------------+---------------+-------------------+
; | Player object |
; +---------------------------------------------------+
;
; Well.. for the rest all you can do is..
; Delete it! :P
;
Delete PointerToPlayer ; Delete (Pointer).(Type)
;
; Okay, not very useful at this point,
; but you get the idea.
;
; Note that the player object was deleted, not the pointer.
; E.g. you can't delete variables :)
;
; Also, the pointer variable PointerToPlayer
; is now pointing to.. Null.. again.
;
; |
; | v |
; +---------------------------------------------------+
; | Player object (Null) |
; +---------------------------------------------------+
;
; Blitz keeps track of all objects you created.
; So you don't have to worry (too much)
; when you're not keeping track of every single object yourself.
;
; | | |
; v v v
; +----- -----+ +----- -----+ +----- -----+
; | Player object | | Player object | | Player object |
; +---------------+ +---------------+ +---------------+
;
; Considering that,
; can you tell me what happens
; in the code below?
;
PointerToPlayer = New Player
PointerToPlayer = Null
;
; In the first line
; a new Player object is created,
; and PointerToPlayer is pointing to it.
;
; In the second line
; we manually make the pointer point to
; a non-existing object (Null).
;
; But the object is still floating somewhere.
; And because Blitz keeps track of all objects
; there is a way we can find out exactly where it is.
;
; In fact, you can walk through
; an entire collection of objects,
; using a single pointer variable.
; It's a bit like walking through an array
; using a single integer variable.
;
; |
; v
; +----- -----+
; | Player object |
; +---------------+--+
; | Player object |
; +---------------+--+
; | Player object |
; +---------------+
;
; Also, like with arrays,
; Blitz keeps track of the order of objects.
; For example; the first time we created a player object,
; it would be the first object.
;
; +-+-----+
; | | |
; | | 1 |
; | | |
; +-+-----+
;
; All objects created after it would stack up behind it.
;
; +-+-----+ +-+-----+ +-+-----+
; | | | | | | | | |
; | | 1 | ----> | | 2 | ----> | | 3 |
; | | | | | | | | |
; +-+-----+ +-+-----+ +-+-----+
;
; Now, let's go fishing for our lost player object.
; We can use the First keyword to retrieve
; the first object in the list.
;
PointerToPlayer = First Player ; (Pointer).(Type) = First (Type)
;
; +-+-----+
; | | |
; ---->| 1 |
; | | |
; +-+-----+
;
; Yes, there is also the keyword Last
; to retrieve the last object from the list.
; It works in exactly the same way.
;
; Ofcourse if there is no first or
; last object in the list,
; all you get is Null.
; E.g. the pointer will point to
; a non-existing object.
;
; Let's put this player object to (some) use.
;
PointerToPlayer\Name = "First Player"
PointerToPlayer\Speed = 0
PointerToPlayer\Health = Rand ( 1 , 100 )
;
; Rand () creates random numbers
; in the range of your choice.
; So the player above will have a random amount of health
; ranging somewhere between 0 and 101. (From 1 to 100)
;
; Unfortunately the random numbers generated are not really random.
; In fact, you could say they're completely fake.
; Everytime you ask for a random number
; you get the next number in a certain pattern.
; You can control what this pattern looks like
; with a so called seed value.
;
SeedRnd 0
;
; Here, a seed value of 0, would give you the same
; pattern every time from this point.
; So if you'd put this at the top of your program,
; you would get the same random number order every time.
; What if we wanted different random numbers every time?
;
SeedRnd MilliSecs ()
;
; MilliSecs () will give you
; the number of milliseconds
; since Windows started.
;
; Because you won't be running the program
; on exactly the same millisecond every day,
; it will seem that the random numbers are indeed.. random :)
; E.g. the pattern will be based on the current millisecond.
;
; So now you'll get a (supposedly) fresh random pattern
; every time you run the program.
;
; Okay, allow me to create a bunch of other players
; with some added random values.
;
For PlayerNumber = 2 To 10
PointerToPlayer = New Player
PointerToPlayer\Name = "Player " + PlayerNumber ; (text-glue)
PointerToPlayer\Speed = Rnd ( 1 , 5 )
PointerToPlayer\Health = Rand ( 1 , 100 )
Next
;
; Is that a typo?
; No, Rnd () works similar to Rand ().
; Rand () returns integer values (1, 2, 3, etc).
; And Rnd () returns floating point values (0.73, 1.8651, etc).
;
; You do not *have* to specify a minimum and maximum value.
; You can also do this:
;
Random_Int = Rand ( 10 ) ; In range of 1 and 10.
Random_Float = Rnd ( 10 ) ; Between 0 and 10.
;
; Note that in the above cases
; Rnd () starts at 0 while Rand () starts at 1.
;
; Through all the distractions,
; do you know how many Player objects we have now?
; We still have a player called First Player.
; And we created 9 more players with unique names.
; So we have 10 Player objects.
;
; You can walk through the entire collection of objects
; using a single pointer to Player type variable.
;
; |
; v
; +----- -----+ +---------------+ +---------------+
; - --| Player object |---| Player object |---| Player object |-- -
; +---------------+ +---------------+ +---------------+
;
; Like mentioned before, it is actually very similar to
; looping through an array with one integer variable.
;
; |
; v
; +--- ---+ +-----------+ +-----------+
; - --| Element |---| Element |---| Element |-- -
; +-----------+ +-----------+ +-----------+
;
; And it's also similar to the above loop
; where we used 1 pointer variable to create 9 objects.
;
For PointerToPlayer = Each Player ; For (Pointer).(Type) = Each (Type)
Number = Number + 1
Write Number + ": "
Print PointerToPlayer\Name
Next
WaitKey
;
; You can use the Each keyword to
; walk through all objects of the same type.
;
; E.g. the PointerToPlayer variable will point
; to every object in the list.
;
; So inside the For..Next you can access
; each object, one at a time.
;
; Each next object in the list
; will be fetched for you,
; and PointerToPlayer
; will point to it.
;
; It also possible to do this manually.
; Imagine a simple For..Next loop.
;
; For Element = 1 to 10 : Next
;
; You can also increment by hand.
;
; Element = 1
; Repeat
; Element = Element + 1
; Until Element = 11
;
; Same goes for objects.
; Automatically:
;
; For Pointer = Each Type : Next
;
; Manually:
;
; Pointer = First Type
; Repeat
; Pointer = After Pointer ; (Pointer).(Type) = After (Pointer).(Type)
; Until Pointer = Null
;
; The After keyword can be used to
; go to the next object in the list.
; E.g. the object behind the
; object it's currently pointing to.
;
PointerToPlayer = First Player
Repeat
PointerToPlayer = After PointerToPlayer
Until PointerToPlayer = Null
;
; If there's After, there's also Before.
; So you can do the same thing backwards.
; Let's try that with a While..Wend loop.
;
PointerToPlayer = Last Player
While PointerToPlayer <> Null
PointerToPlayer = Before PointerToPlayer
Wend
;
; Okay, what if you want to move
; objects in the list around?
;
; There is the Insert keyword to assist you.
; There are 10 players currently, right?
; So how do you place the first player (1)
; behind the last player (10)?
;
; Initialize variables.
Local FirstPlayer.Player
Local LastPlayer.Player
; Locate first and last objects in list.
FirstPlayer = First Player
LastPlayer = Last Player
; Place first object behind last object.
Insert FirstPlayer After LastPlayer
;
; It's almost real english :)
; Let's test what our first object is,
; just to be sure.
;
FirstPlayer = First Player
Print
Print "First object name: " + FirstPlayer\Name
;
; Which should give you the name of Player 2 :)
;
; However, you don't always have to assign
; a variable to use an object.
; Sometimes you can combine keywords
; like there's no tomorrow.
;
Insert Last Player Before First Player
;
; Do you know what we just did?
; That's right, we moved player named First Player
; back to its original spot.
;
; You can use Insert also, for example,
; to arrange objects in a certain order.
;
; But you don't always have to rely on
; the keywords First, Last, Before, After etc.
; Pointers will be pointers.
; You can use them in any way you want.
;
;-----------------------------------------------------------------------------------------------------------------------
;
; There are some common cases
; where you'll want to administer
; all your objects by hand.
;
; Imagine a game with players shooting at enemies.
; And enemies shooting at players.
;
; So you'd need players (just like before).
;
; Type Player
; Field Located_Where
; Field Doing_What
; End Type
;
; As well as enemies.
;
; Type Enemy
; Field Located_Where
; Field Doing_What
; End Type
;
; Now, they can shoot,
; so we'd need to store bullets.
;
; Type Bullet
; Field Located_Where
; End Type
;
; All looking good
; but what if players' shots
; would hurt only enemies
; and vise versa?
;
; So you'd have to know
; who's the owner of a bullet.
; A player, or an enemy.
;
; One way is forgetting
; the old Bullet type structure
; and just using 2 separate ones.
; One for each group (players and enemies).
;
; Type Player_Bullet
; Field Located_Where
; End Type
;
; Type Enemy_Bullet
; Field Located_Where
; End Type
;
; Still looking good
; but it's not so funny
; when there's different types of
; players, enemies and bullets.
;
; So we add a field
; to our original Bullet type
; to know who the owner is
; e.g. which group the bullet belongs to.
;
; Const Bullet_Of_Player = 1
; Const Bullet_Of_Enemy = 2
;
; Type Bullet
; Field Of_Whom ; <---
; Field Located_Where
; End Type
;
; Now what if there are thousands of bullets
; and you don't want to loop through all bullets every time
; and still use just one type of bullet.
;
; You can't do this if you rely on Blitz' keywords.
; This may not be something that happens in your game.
; And most (simple) games will only need Blitz' keywords.
; Remember that pointers will be pointers.
; You can use them in any way you want.
;
; So, here's another solution:
;
; Type Bullet
; Field Located_Where
; End Type
;
; Type Player
; Field Located_Where
; Field Doing_What
; Field FirstBullet.Bullet ; <---
; End Type
;
; Type Enemy
; Field Located_Where
; Field Doing_What
; Field FirstBullet.Bullet ; <---
; End Type
;
;-----------------------------------------------------------------------------------------------------------------------
;
; So far we've seen simple variable types as a field
; but you can also place a pointer variable in there.
;
Type Link
Field PointerToNextLink.Link
End Type
;
; Now we can make our own chain of links.
;
FirstLink.Link = New Link
;
; FirstLink
; |
; v
; ,---.
; / \
; (
; \ /
; `---'
;
AnotherLink.Link = New Link
;
; FirstLink
; | AnotherLink
; v |
; ,---. v
; / \ _.---._
; ( (
; \ / `^---^^
; `---'
;
FirstLink\PointerToNextLink = AnotherLink
;
; FirstLink
; | AnotherLink
; v |
; ,---. v
; / _>---._
; ( ( )
; \ ^>---^^
; `---'
;
AnotherLink = Null
;
; FirstLink
; |
; v
; ,---.
; / _>---._
; ( ( )
; \ ^>---^^
; `---'
;
; So long as you keep track of the root
; or your own first link of the chain,
; you will be able to find any link in the chain
; without having to use any of the keywords.
;
; How?
;
AnotherLink = FirstLink\PointerToNextLink
;
; Actually the reversed of what we did before.
; And you can make it really hairy if you wanted to.
;
; FirstLink\PointerToNextLink\PointerToNextLink\PointerToNextLink\ etc..
;
; Let's add another link to the chain,
; using the same pointer variable.
;
AnotherLink = New Link
;
; FirstLink AnotherLink
; | |
; v v
; ,---. ,---.
; / _>---._ / \
; ( ( ) (
; \ ^>---^^ \ /
; `---' `---'
;
FirstLink\PointerToNextLink\PointerToNextLink = AnotherLink
;
; FirstLink AnotherLink
; | |
; v v
; ,---. ,---.
; / _>---<_ \
; ( ( ) ( )
; \ ^>---<^ /
; `---' `---'
;
AnotherLink = Null
;
; FirstLink
; |
; v
; ,---. ,---.
; / _>---<_ \
; ( ( ) ( )
; \ ^>---<^ /
; `---' `---'
;
; You'll probably want to iterate
; through the manual list easily.
; E.g. walk through each object in
; our home made list, one at a time.
;
; So here's an example While..Wend loop to
; demonstrate how you can walk through
; all links in the chain.
;
; This will be our iterator.
Local PointerToLink.Link
; Find our first link.
PointerToLink = FirstLink
While PointerToLink = Null
; Point to next link in chain.
PointerToLink = PointerToLink\PointerToNextLink
Wend
;
; You could add another pointer variable
; to point to the object before the current object
; to make searching through the list faster.
;
; Ofcourse this chain of links contains only a pointer variable
; so there's no real use for this chain of links
; as we can't really put some useful information in each link.
;
;-----------------------------------------------------------------------------------------------------------------------
;
; So let's put a manual linked list to good use
; and add at least one useful field.
;
Type Element
Field pNext.Element
Field iValue%
End Type
;
; Another idea is to use one (or more) letter
; of the variable name to know what type it is.
; Some examples:
;
; iValue ; Integer
; sName ; String
; fSpeed ; Float
; pNext ; Pointer
;
; Now create a random bunch of objects,
; put some random stuff in them
; and rack'em up (link the chain).
;
; Initialize variables.
Local iElementCount%
Local iElement%
Local pRoot.Element
Local pNext.Element
; Create a root element.
pRoot = New Element
pRoot\iValue = Rand ( 100 )
; Place elements behind it.
pNext = pRoot
iElementCount = Rand ( 10 , 20 )
For iElement = 1 To iElementCount
pNext\pNext = New Element
pNext\pNext\iValue = Rand ( 100 )
pNext = pNext\pNext
Next
;
; Let's see what we generated.
;
iElement = 0
pNext = pRoot
While pNext <> Null
iElement = iElement + 1
Print iElement + ": " + pNext\iValue
pNext = pNext\pNext
Wend
Print
WaitKey
;
;-----------------------------------------------------------------------------------------------------------------------
;
; There's one more type of field you can use.
;
Type Inventory
Field Slots[ 10 ]
End Type
;
; It's called a BlitzArray[tm].
; And it works similar to regular arrays.
;
Inv.Inventory = New Inventory
Inv\Slots[ 0 ] = 293 ; (Pointer).(Type)\Array[ Element ] = Value
;
; The major difference is that
; you cannot redimension it
; e.g. you can't change its size
; or instantly free its contents
; so its size has to be constant.
;
Const Amount = 100
;
Type Ship
Field Weapons[ Amount ]
Field Engine
Field Generator
Field Hull
Field Shield
End Type
;
; If you remember normal arrays
; you'll know that we actually created
; an array of integers.
;
; And if I told you that you can use
; any type of field as a regular variable,
; would that also mean you can create
; a BlitzArray[tm] as a regular variable?
;
Local Weapons[ Amount ]
;
; Yes! :)
;
Global Inventory$[ 10 ]
;
; A (global) BlitzArray[tm] of strings.
;
Inventory[ 1 ] = "Gold coin"
;
; Ofcourse BlitzArrays[tm] are most useful
; in scenarios where the size of the array
; remains constant throughout the game.
;
; Otherwise regular arrays will be an excellent choice.
; Even though regular arrays are always Global.
;
;-----------------------------------------------------------------------------------------------------------------------
;
; So you can have arrays of certain types;
; string, float and integer.
; But what about pointers?
;
Type Thing
Field Contents
End Type
;
Dim PointerArray.Thing( 0 ) ; Dim Array.Type( Elements )
;
; Look!
; An array of pointers!
; Do you see that it looks just like
; an array of a different type?
;
Dim StringArray$( 0 )
;
; Let's do something with the first element.
;
PointerArray( 0 ) = New Thing
PointerArray( 0 )\Contents = 2004 ; Array.Type( Element )\Field = Value
;
; Remember what happens when we redimension the array?
; Its contents gets erased.
;
Dim PointerArray( 1 ) ; Contains 2 elements.
;
; But what we have here is an array of pointers.
; So the actual objects were not erased.
;
; If you remember the First keyword
; you'll know how to retrieve the first object.
;
PointerArray( 0 ) = First Thing
;
; So when we display the contents
; it should be 2004, right?
;
Print PointerArray( 0 )\Contents
WaitKey
;
; What about BlitzArrays[tm]?
;
Const Alot = 10000
;
Local BlitzArray_WithPointers.Thing[ Alot ]
;
BlitzArray_WithPointers[ 9999 ] = PointerArray( 0 )
;
; See how you can combine everything with everything?
; Mix and blend as you see fit :)
;
;-----------------------------------------------------------------------------------------------------------------------
;
; Sometimes that can become difficult though.
; Even though Blitz is a very intelligent language,
; it won't always know what you're talking about :P
;
; You'll remember text glue,
;
Print "Where " + "Am " + "I ?"
;
; and how to convert text to a value.
;
TextValue$ = "5000"
; Auto
Value = TextValue
; Manual
Value = Int ( TextValue )
;
; Sometimes you can't rely on automatic
; conversion because Blitz won't understand
; your mysterious ways.
;
Print "-Glue-"
;
Print Value1 + Value2
; /|\
; |
; Number glue
;
Print Value1 + "" + Value2
; /|\ /|\
; | |
; Text glue
;
Print Str ( Value1 ) + Str ( Value2 )
; /|\
; |
; Text glue
;
; And floats with integers.
;
Print "-Conversion-"
;
; Just integers, not accurate.
Value = 10 / 3 * 10
Print Value
;
; Converted to float, accurate.
Value = Float 10 / 3 * 10
Print Value
;
; Using a float instead of integer, accurate.
Value = 10.0 / 3 * 10
Print Value
;
; Changed priority, accurate.
Value = 10 * 10 / 3
Print Value
;
; Actually, you can do the same with pointers.
;
Type Any
Field Thing#
End Type
;
pAny.Any = New Any
pAny\Thing = -3.14
;
; There's the Handle keyword to convert to a number.
;
Value = Handle pAny ; hType = Handle ( Pointer.Type )
Print Value
;
; Technically what you'll get
; is a unique memory address
; for the pointer.
;
; This way you can keep track
; of pointers by storing their address
; instead of just pointers.
;
; The Object keyword converts
; the address back to a pointer.
;
pAny = Object.Any Value ; Pointer.Type = Object.Type ( hType )
;
; I've used hType to indicate
; it's a handle (address, number, value)
; of a pointer of this type.
;
; And pAny would mean
; a pointer to an object of type Any.
; But you probably already knew that :)
;
; You can also use this approach
; to test any number against any type.
;
; So you could for example store
; *different* types of objects
; in a regular array of integers.
;
; Write "It's a"
; If Object.Engine Array( Element ) <> Null
; Print "n engine."
; Else If Object.Generator Array( Element ) <> Null
; Print " generator."
; Else If Object.Weapon Array( Element ) <> Null
; Print " weapon."
; Else If Object.Shield Array( Element ) <> Null
; Print " shield."
; End If
;
; Handle and Object work exactly
; the same as Int, Str and Float.
;
;-----------------------------------------------------------------------------------------------------------------------