© Richard G. Ryles, May 2003,
I hope things went well for you last month. If you would like to see my solutions to the problems I left you with, load up and run, in Liberty BASIC, SG1sol.bas and SC1sol.bas. Your sprites will probably be in different locations but you should be able to see all of them on your background.
This month we are going to take on sprite movement. This includes sprites moving automatically, moving sprites with the keyboard and sprites moving with the cursor. Along with movement comes the trapping of sprites (What is that? you ask. We'll be there in a jiffy).
In working with these articles, I've realized that it can get confusing working on two different games at once, so I have broken this article up into two different sections. The first is going to deal with the sub game and the second with the shooting gallery game. Also, this way if you are only interested in one of the games it will be easier to tell the two apart.
I've also shortened up the file names, eight characters or less, so that those using LB version 2 will not have a problem loading the included files.
Without further rambling let's get started.
Moving the Ship
I am going to show you how to get the ship moving in the SubCommand.
Load up your SubCommand1.bas file. From this point on I will refer to this file as SubCom1.bas. Let's save it under a different name since we will be making changes to it. Go to File>>Save As... and give this file the name of SubCom2. Now let's get the ship moving from right to left.
Find the C section of your outline and make the following changes to your initial locations of the sprites:
We place the ship at 500 in X to place it off of the right side of the viewing area. 45 in Y places the ship on top of the water. Change the other sprite's X's to 500 gets them over to the side out of the viewing area.
The point indicated in Figure 2 is the point that will be placed at the location we gave our ship with spritexy. This is the upper left corner of the unmasked sprite. So, anytime you are trying to place a sprite in a certain place on the screen keep this in mind.
Referring to Figure 3, we need to give the "automove" command for the sprite, which is the spritemovexy command. With the spritemovexy command we simply need the name of the sprite and how many pixels we want the sprite to move each time the window is redrawn. Remember, X is first and horizontal and Y is second and vertical. +X moves to the right and –X moves to the left. +Y is moves down and -Y moves up. So, with the -3 we are moving the ship 3 pixels to the left each drawsprites and with the 0 we are not moving the ship up or down, it stays at its current Y position. Add the line from Figure 3 to your code.
Run your program and you should see the ship moving from the right side of the screen to the left. The only other sprite you should see is the green sub. Once the ship has gone off the left side of the screen close the program because it will just keep going and going and going...
Save your work.
Trapping the Ship
Once the ship has moved off of the left side, out of view, we want to return it to the viewing area. We are going to return it to its start location and let it continually cycle across the top of the screen. When we relocate a sprite because of its position we say we are trapping that sprite. We need to add code to two sections of the outline to make this happen.
First to our timer branch:
We need to tell the program to check and see if the ship has gone off the left edge. Since the timer fires the TimerBranch automatically we'll tell it to check where the ship is located each time it fires.
Next we add a new [TrapShip] branch below section X of our outline.
Add the above branch and code. We have a new command here, spritexy?. This command get's the coordinates for ship and places them in the variables x and y. In the next line we check to see if ship has gone off the left edge by comparing it's x with what we feel is far enough to the left, in this case -50. Once the "if" part of the expression is true the "then" part comes into play and simply places the ship back at the start location. You may ask how I got -50. Well I simply guessed at what I thought would give the impression of the ship going completely off the edge and worked from there. If you know the exact width of your sprite you could simply have subtracted that number from zero and gotten it exactly.
Now save and run your program. The ship should move onto the graphicbox from the right and completely off the left side of the graphicbox before starting over again. If this does not happen, take a look at the above changes and make sure you typed everything in correctly.
Moving your Sub with the Keyboard
We will now move the green sub with the number keys.
Add the following lines to the indicated places in the outline:
Above we have moved the wait from under the timer routine to the end of the Mouse and Keyboard events area. If we did not do this then the program would never look for the keyboard or mouse inputs and they would do nothing in our program. To learn more about the setfocus, command refer to the Helpfile under Command Reference and then look at "setfocus". The characterInput command simply says that if there is any keyboard input go to the [MoveSub] branch.
Add the code from Figure 5 to Section IX of your game outline. The [MoveSub] branch actually does the work of moving the sub. First of all we begin by assigning another variable name to Inkey$, just to make things shorter. Then we go around the number pad grouping the number keys based on location. Since 1,4 and 7 are on the left side we set them to move the sub minus 1 pixel each time any of those keys are pressed. sx is a variable name that I have designated to stand for the Sub's X and sy is a variable that I have designated to represent the Sub's Y. Designating variables for the X and Y locations helps to keep the X and Y locations of different entities from getting confused. We then went around and did the same for the other numbers. Notice that 1, 3, 7 and 9 are each listed in two of the statements. This will cause the Sub to move diagonally when one of these keys are pressed. Save you work after these changes and then try it out. Change the trapping numbers and see what happens.
You may wonder if there is an easier way to determine at what point you need to trap a sprite. For the above I commented out the nomainwin command with an apostrophe and put two print commands as seen in Figure 6. This printed my sx and sy values to the main window.
I then ran the program and moved the Sub to the upper left hand location that I wanted it to stop at. I then moved the game window and took the values from the mainwindow and used those values in the trapping code. In Figure 7 you can see where I got my top sy and left sx. I simply moved my sub to that location and used the 1 value for sx and the 55 value for sy.
I then brought the game window and main window back up to the top and moved the Sub to the lower right hand location and got the values for the other two lines of code that keep the sub from going off the bottom and right of the viewing area. After you have set up your trapping code in this manner un-comment your nomainwin command and delete the two extra print commands that are highlighted in Figure 6.
Orientation of the Sub
One last item of business with our Sub sprite, to add a little more realism we need for the sprite to change orientation when it changes direction, in other words when it goes right we want it to point right, when it goes left we want it to point left. The spriteorient command is the command we will use to do this; for a more detailed look at this command look in the Helpfile contents under Sprites>>Sprite Properties. Add the following code in your SubCom2 game:
Since we want more than one thing to happen when certain numbers are pressed we made what we call and if...then block. We could have strung the command together with an "and" but it would have been harder to read and possibly longer than we could view on our monitor without scrolling. To terminate an if...then block you have to end it with the end if command. Alyce Watson explains this the best in her Mastering Liberty BASIC 3 ebook. I quote here with her permission:
"BLOCK IF/THEN - If there are many statements to be considered in the conditional part of an if/then statement or if there are many lines of code to be contained within the statement, it is far easier to use a BLOCK IF/THEN format. The statements from IF up to, and including THEN should appear on one line. Other code may appear on subsequent lines. A statement written in this form MUST have END IF as its last line."
Now that you have inserted the additional statements from Figure 8 into the MoveSub portion of your code, be sure to save your work. Now, when you run the program you should see your sub change directions when you hit a key that is coded to make your Sub move along the X-axis.
My Sub Jumps
In case you didn't notice, (I didn't until I had a student to work through this session) when you press one of the keys that control the sub, the sub jumps up to the upper left hand corner of the limits we set when trapping the sub. What has happened here is that we are using variables for the sub location that we have not previously declared (see Figure 6). So, LB declares them here and gives them a value of zero when we actually need the values of the subs initial location. So the program, when we first press a key, tries to place the sub at 0 0. We will get more into declaring variables next session but let's go ahead and fix this one. First, under "III. Initialize Variables" type in the code from Figure 8b, this is called declaring our variables.
Next we need to use the declared variable in initial location of the sub. Under Section C of your game outline change the initial location values of the sub to those highlighted below in Figure 8c. This will now cause the values associated with the variables to be used for the sub's initial x and y value. There is a space between sub and the quotation mark.
Now that you have completed the above operations and declared the sub's location variables that are to be used throughout the program your sub should now move smoothly from it's initial location and not jump to the upper left hand side when the number keys are first pressed.
Moving the Mine
Moving the Mine is not much different than moving the ship.
Let's first place the mine once again on the viewing area somewhere along the water line since the ship will eventually be dropping the mine into the water. Looking at Figure 9 change the initial location of the mine.
Now we set up the mine to move automatically. Notice in Figure 10 that the ship's X-axis is the axis we move but for the mine we want it to move from top to bottom so we only want the Y-axis to move. Remember that the top of our graphicbox is zero and the bottom is 300 and we want to move from top to bottom. Therefore our movement along the Y-axis is going to be positive (we will be going from a smaller number, 45, to a larger number 320 so we are adding 6 every drawframe command). Add the additional line from Figure 10 into your program.
Trapping the Mine
In this session we are going to have the mine go off the bottom of the graphicbox and reappear at the top continually. In later sessions we will locate the mine's X position relative to the ship's X position.
First we must add a trap branch under the TimerBranch so that the program will check the mines position each drawframe. Add the highlighted line from Figure 11 under part VII of the outline. Next under Section X of the outline add the code that you see in Figure 12.
Figure 12's code causes the mine to start over at it's initial location when the mine's Y is greater than 320. In case you are wondering why I used mineX and mineY for the variable to hold the location of the mine's X and Y it is in an effort to keep the variables from getting mixed up.
Save your work and run the program. The mine should move from along the water line off the bottom and reappear along the water line again. If not check your code to make sure you made no typos or put the code in the wrong place.
If you are curious about where the other sprites are, I've made a demo program that gives you and idea. Load up and run SubCLoc.bas. The Cyan (light blue) area simulates the graphicbox in our program. The black area we do not see. As you will notice, the enemy sub and torpedo are still there but we do not see them in our game because we have placed them outside the graphic box. Also notice that the ship and mine go past the edges to give the full impression that they have passed out of view.
SubCommand Challenges for this Month
This month your challenges for the SubCommand Game will be as follows:
1. Orient the torpedo so that it points up (I've made a new torpedo bitmap so be sure to use it, the old one is now torp.bmp).
2. Set-up the torpedo so that it automatically moves from the bottom of the graphicbox to a point above the top of the graphicbox.
3. Trap the torpedo so that it begins again from it's initial start point
4. Set-up the enemy sub to automatically move from the left of the graphic box to a point beyond the right of the graphicbox.
5. Trap the enemy sub so that once it goes off the right side of the graphicbox it restarts from it's initial location.
Final Remarks on SubCommand
In the next session we will be looking at firing the missile from our sub toward the ship, dropping the mine from the same X location of the ship and possibly collisions between sprites. I'll also give you my solutions to the challenges.
Now open up your ShootGallery1.bas file. Let's save it under a different name. Go to File>>Save As... and give this file the name of SGallery2.bas.
I also have reduced the width of the window and graphic box for this game. I felt that it was a little big for what we are going to do with it. So, change the WindowWidth from 500 to 300 and the graphicbox width from 500 to 300.
I've also moved the bitmaps off of the viewing area; they are still there but just not where we can see them. Modify the initial locations of your sprites so that your code is like that in Figure 13. If you are curious about how things look when you move them off-screen see the Location Demo from the SubCommand game.
Moving the Squirrel
Squirl1.bmp ...................... Squirl2.bmp
In case you have not noticed I have two different bitmaps of the squirrel in the folder. The only difference is that their legs are in different places. We can use this to give the impression that the squirrel is walking or running.
First of all be sure that you have loaded both squirl1 and squirl2 bitmaps as in Figure 14.
Secondly, when we add our sprites to our graphicbox we want to include all of the images that make up that sprite. In this case we want squirrel1 and squirrel2 to make up our sprite called squirrel (see Figure 15).
Before we go any further, let's make the squirrel walk along the top of the counter. We need to change his initial Y location to place him on top of the counter.
Looking at Figure 16 adjust the squirrel's initial location to 200 in X and 205 in Y. This will place him on top of the counter.
We have a new command in Figure 17, cyclesprite. This causes LB to cycle through the bitmap images that we designated when we added squirrel to the graphic box. The number 1 simple tells LB to cycle through the images in the order they were listed. A -1 would have caused it to cycle through the image set in reverse order.
Save your program and run it. If you have a hard time seeing the feet of the squirrel move, you may want to change the fill color of your background to lightgray.
Now that we have the squirrel's feet moving let's move him across the counter. In Figure 6 we moved the squirrel to the top of the counter, now move him to the right out of view. Change the 200 X value to 300. Now if you run your program you should not see your squirrel.
Under section D of the outline add the following highlighted line as shown in Figure 18.
Run your program and you should see the squirrel moving from the right side of the screen to the left. Once the squirrel has gone off the left side of the screen close the program.
Save your work.
Trapping the Squirrel
When the squirrel exits the left side of the screen we would like for him to walk back on from right side.
We want to check the location of the squirrel each time a drawsprites command is issued. So, we place a gosub in the TimerBranch that goes to the code we will write that traps the squirrel. Remember that by trapping we are simply stopping the squirrel at specific point and then placing him in a new location. Add the code from Figure 19 under your TimerBranch section.
In Figure 20 we have added the code under Section X of our outline. The spritexy? command gets the X and Y locations of squirrel and places these values in the variables that we have named. I chose to use SqX and SqY as variable names to help me know that they are values that belong to the squirrel. The if/then statement is the part that actually checks to see if squirrel has gone beyond the limits we have set. If you would like to see a running value of SqX comment out the nomainwin command with an apostrophe and before the return here in Figure 20 place the following command - print SqX. When you run the program now you will see the different values for SqX running by in the main window.
Save your work.
Orientation of the Duck
We now want the duck to move across the graphicbox from left to right, but he is rather small and pointed in the wrong directions. First of all, in order to make the duck larger we use the spritescale command. The number 150 after duck enlarges the duck sprite by 150%. Next we want to turn the duck the other way. For this we use the spriteorient command. The mirror orientation is the one we are using here. Modify your code to look like Figure 21. In the LB Helpfile under Sprites>>Sprite Commands, you can read more about these two commands.
Moving the Duck
Moving the duck is very similar to moving the squirrel. We first of all need to set up the automatic movement of the duck.
Now we want the duck to move from left to right. The duck is starting out at X0 and moving toward X300. To go from 0 to 300 in steps of 4 pixels we would add, so our X value for our spritemovexy command is a positive 4. We want the duck to move straight across so our Y value will remain 0
Trapping the Duck
Add the highlighted line of code from Figure 23 to the VII section of your outline.
This bit of code causes the program to check the whereabouts of the duck each timer cycle.
Now add the code in Figure 24 the the section X of your outline.
Save your work. Run your program. Both the duck and the squirrel should move from one side of the graphicbox to the other. If you have a problem check to make sure you have no typos.
The Balloon - Diagonal Movement
We are now going to make the balloon move from the lower left to the upper right. Much of the following code we have already discussed so I am only going to discuss the parts that are different. Using the following Figures make the necessary additions to your Shooting Gallery code:
The main difference between the balloon and what we have already done is that we are telling the balloon to move in both the X-axis and Y-axis. 4 in X causes the balloon to move to the left while –5 causes it to move up.
Be sure to place the code from Figure 27 under section X of your outline.
Negative 20 gives all of the balloon time to move off the screen before we move it back to it's starting location.
Save your work. If the balloon doesn't move as expected check for typos.
Changing the Cursor
In another effort to add to the realism of the game we are now going to change the cursor from the standard arrow to a crosshair. In LB this is really simple. Under the "I. Window Setup" portion of the outline I usually include this as the last item:
Now save and run your program. You should have a crosshair for a mouse cursor.
Adding the Sight Ring
A sighting ring gives things a "high-tech" feel. So, let's add one. First we must go through the process of adding a new bitmap and sprite to our game. You are familiar with all of this so I'm giving you the code only. These bits of code should be added in their respective sections on the outline (which I have included) after the code of their kind.
Save your work.
Moving the Sight Ring
Now we are going to cause the sight ring to follow the mouse cursor around on the screen.
Add the code from Figure 34 to Section VI of your code. In Figure 34 we have moved the wait from under the timer routine to the end of the Mouse and Keyboard events area. If we did not do this then the program would never look for the keyboard or mouse inputs and they would do nothing in our program. To learn more about the setfocus, command refer to the Helpfile under Command Reference and then look at "setfocus". The mouseMove command simply says that if there is any mouse movement go to the [MoveSight] branch.
Now add the code from Figure 35 to Section IX of your game outline. MouseX and MouseY fetch the coordinates of the mouse. We then take these coordinates, subtract a little from them (to center the sight) and place them in our spritexy command for sight.
Save and run your program. A red circle should follow your cursor around the screen. If not check the code you have added for any mistakes.
Shooting Gallery Challenges for this Month
This month your challenges for the Shooting Gallery Game will be as follows:
1. Add another duck.
2. Cause the second duck to move from the right to the left.
3. Trap the second duck so that he restarts from the right.
4. Cause the target to fall from the top to bottom trapping and restarting it.
Hope you've had fun and learned much. Next session we will be doing some exciting stuff. We will set up a bullet routine to shoot with, a game timer and game scoring.
Until then: Happy Programming!