Older Version Newer Version

Alyce Alyce May 2, 2011

==Sprite Byte Tutorials Lesson Six: User-Controlled Sprite and Computer-Controlled Sprite== //by Alyce Watson// http://alycesrestaurant.com/ [[user:Alyce]] [[toc]] ==Sprites Controlled by User and Computer== In [[sprite4|Lesson Four]] we leaned how to move a sprite with code routines, and in [[sprite5|Lesson Five]] we learned how to move a sprite according to user input. If we put those two methods together, we've got the basis for an arcade game. ==Sprite Location Stored in a Variable== In [[sprite5|Lesson Five]] we stored the location of the user-controlled sprite in variables called SpriteX and SpriteY so that we could change those values easily. We updated the location of the sprite whenever the user pressed one of the arrow keys. It looked like this: [[code format="vbnet"]] 'right arrow = X gets bigger: if asc(right$(Inkey$,1))=39 then spriteX = spriteX + 3 'left arrow = X gets smaller: if asc(right$(Inkey$,1))=37 then spriteX = spriteX - 3 'up arrow = Y gets smaller: if asc(right$(Inkey$,1))=38 then spriteY = spriteY - 3 'down arrow = Y gets bigger: if asc(right$(Inkey$,1))=40 then spriteY = spriteY + 3 'locate sprite at new position and update display #w.g "spritexy guy ";spriteX;" ";spriteY #w.g "drawsprites" [[code]] You can review the methods here: [[sprite5|Sprite Byte Tutorials Lesson Five: User-Controlled Sprite]] [[Computer-Controlled Sprite Location Stored in a Variable]] We'll add a user-controlled sprite just as we did in [[sprite5|Lesson Five]]. We'll also add a computer-controlled sprite. We must first load a bitmap for the sprite image. The crab bitmap is located in the Sprites folder in the Liberty BASIC root directory. [[code format="vbnet"]]format="lb"]] loadbmp "crab", "sprites\crab1.bmp" [[code]] We add the sprite with the **ADDSPRITE** command and give the sprite the name, "enemy", like this: [[code format="vbnet"]] #w.g "addsprite enemy crab" [[code]] We'll call the variables for the location of the crab sprite **crabX** and **crabY**. We issue the **spritexy** command, to locate the crab sprite, then we issue the **drawsprites** command to update the display. //Did you notice how we named the variables to reflect their usage? This is an easy way of documenting our code so that it is easy to understand.// [[code format="vbnet"]] 'variable for location of computer sprite crabX = 360 : crabY = 100 #w.g "spritexy enemy ";crabX;" ";crabY #w.g "drawsprites" 'update screen [[code]] ==Moving Independently== The crab sprite will move at regular intervals because we use a timer to update the crab's location as we did in [[sprite4|Lesson Four]]. The timer command looks like this: [[code format="vbnet"]] 'set up a timer to move crab sprite timer 300, [updateDisplay] [[code]] The crab and the smiley move independently of one another. The routine triggered by the timer moves the crab sprite: [[code format="vbnet"]] [updateDisplay] 'move computer-controlled sprite at timer intervals crabX = crabX - 5 : crabY = crabY + 2 'locate sprites at new positions and update display #w.g "spritexy enemy ";crabX;" ";crabY #w.g "drawsprites" wait [[code]] The routine triggered by the user's keyboard presses moves the smiley sprite: [[code format="vbnet"]] [updatePosition] 'move user-controlled sprite when arrows are pressed '37 = left arrow '38 = up arrow '39 = right arrow '40 = down arrow 'Arrow keys make Inkey$ two characters long, 'so we check the rightmost character with 'the right$() function. 'right arrow = X gets bigger: if asc(right$(Inkey$,1))=39 then spriteX = spriteX + 3 'left arrow = X gets smaller: if asc(right$(Inkey$,1))=37 then spriteX = spriteX - 3 'up arrow = Y gets smaller: if asc(right$(Inkey$,1))=38 then spriteY = spriteY - 3 'down arrow = Y gets bigger: if asc(right$(Inkey$,1))=40 then spriteY = spriteY + 3 #w.g "spritexy guy ";spriteX;" ";spriteY #w.g "drawsprites" wait [[code]] There are two demonstration programs at the end of this lesson. The first one is a very simple program that shows a user-controlled smiley sprite and a computer-controlled crab sprite. ==Boundary Detection== The methods discussed above work well, but if the program runs for a bit, the crab moves off the screen, never to be seen again! We can stop the crab easily by checking its location each time we move it. If it is close to one of the edges, we will change its direction. ==Variables for Amount of Movement== We accomplish boundary detection most easily if we store the amount of X and Y movement in variables, just as we stored the X and Y locations in variables. [[code format="vbnet"]] 'add variable for increment to move crab each time moveCrabX = -5 : moveCrabY = 2 [[code]] ==Stopping at the Edge== Each time we update the location of the crab sprite, we'll test the current location with a series of **if/then** statements. If the crab's X location variable is near the left side, we'll change the incremental X variable to be **5** so that it begins to travel toward the right. If the crab's X location is near the right side, we'll change the incremental X variable to be **-5** so that it begins to travel toward the left. If the crab's Y location is near the top, we'll change the incremental Y variable to be **2** so that it begins to travel downward. If the crab's Y location is near the bottom, we'll change the incremental Y variable to be **-2** so that it begins to travel upward. [[code format="vbnet"]] 'add boundary detection and reverse direction at edges if (crabX > 370) then moveCrabX = -5 if (crabX < 10) then moveCrabX = 5 if (crabY > 270) then moveCrabY = -2 if (crabY < 10) then moveCrabY = 2 [[code]] ==Changing Direction== We've checked to see if the crab is at the edge of the display and we've modified the movement variables if needed. Here's how we use those variables. We add the incremental variables to the location variables then issue a **spritexy** command to update the crab's location on the screen, like this: [[code format="vbnet"]] crabX = crabX + moveCrabX : crabY = crabY + moveCrabY #w.g "spritexy enemy ";crabX;" ";crabY [[code]] ==Review== In Lesson Six, we've used a computer-controlled sprite that moves when a timer event is triggered. We've also used a user-controlled sprite that moves when a user keyboard event is triggered. These actions happen independently of one another. The first demonstration program below includes the complete code. We've also added boundary detection for the computer-controlled sprite. We've stored the amount of movement in the X and Y directions in special variables that we use to incremement the sprite's location each time it moves. This is demonstrated in the second program listed below. ==Demonstration Programs== [[image:smileycrab.png caption="Demonstration Program"]] //The following demonstration programs require bitmaps in your Liberty BASIC sprites folder and they must be run from the Liberty BASIC root directory.// **Demo of Computer-Controlled Sprite and User-Controlled Sprite** [[code format="vbnet"]] 'Add a sprite and locate it at x=10, y=30. 'Allow user to press arrow buttons to move sprite. 'Add a computer-controlled sprite. nomainwin loadbmp "smiley", "sprites\smiley.bmp" loadbmp "crab", "sprites\crab1.bmp" loadbmp "landscape", "sprites\bg1.bmp" WindowHeight = 350 : WindowWidth = 400 graphicbox #w.g, 0, 0, 400, 300 statictext #w.s, "",40,300,100,40 open "User Sprite + Computer Sprite" for window_nf as #w #w "trapclose [quit]" #w.g "down" #w.g "background landscape" #w.g "addsprite guy smiley" 'variable for location of user sprite spriteX = 10 : spriteY = 30 #w.g "spritexy guy ";spriteX;" ";spriteY 'set up event trapping for key presses #w.g "setfocus" 'MUST setfocus to graphicbox #w.g "when characterInput [updatePosition]" 'add computer-controlled crab sprite #w.g "addsprite enemy crab" 'variable for location of computer sprite crabX = 360 : crabY = 100 #w.g "spritexy enemy ";crabX;" ";crabY #w.g "drawsprites" 'update screen 'set up a timer to move crab sprite timer 300, [updateDisplay] wait [updatePosition] 'move user-controlled sprite when arrows are pressed '37 = left arrow '38 = up arrow '39 = right arrow '40 = down arrow 'Arrow keys make Inkey$ two characters long, 'so we check the rightmost character with 'the right$() function. 'right arrow = X gets bigger: if asc(right$(Inkey$,1))=39 then spriteX = spriteX + 3 'left arrow = X gets smaller: if asc(right$(Inkey$,1))=37 then spriteX = spriteX - 3 'up arrow = Y gets smaller: if asc(right$(Inkey$,1))=38 then spriteY = spriteY - 3 'down arrow = Y gets bigger: if asc(right$(Inkey$,1))=40 then spriteY = spriteY + 3 #w.g "spritexy guy ";spriteX;" ";spriteY #w.g "drawsprites" wait [updateDisplay] 'move computer-controlled sprite at timer intervals crabX = crabX - 5 : crabY = crabY + 2 'locate sprites at new positions and update display #w.g "spritexy enemy ";crabX;" ";crabY #w.g "drawsprites" wait [quit] timer 0 unloadbmp "landscape" unloadbmp "smiley" unloadbmp "crab" close #w : end [[code]] **Boundary Detection Added** [[code format="vbnet"]] 'Add a sprite and locate it at x=10, y=30. 'Allow user to press arrow buttons to move sprite. 'Add a computer-controlled sprite. 'Add boundary detection. nomainwin loadbmp "smiley", "sprites\smiley.bmp" loadbmp "crab", "sprites\crab1.bmp" loadbmp "landscape", "sprites\bg1.bmp" WindowHeight = 350 : WindowWidth = 400 graphicbox #w.g, 0, 0, 400, 300 statictext #w.s, "",40,300,100,40 open "User Sprite + Computer Sprite" for window_nf as #w #w "trapclose [quit]" #w.g "down" #w.g "background landscape" #w.g "addsprite guy smiley" spriteX = 10 : spriteY = 30 #w.g "spritexy guy ";spriteX;" ";spriteY 'set up event trapping for key presses #w.g "setfocus" 'MUST setfocus to graphicbox #w.g "when characterInput [updatePosition]" 'add computer-controlled crab sprite #w.g "addsprite enemy crab" 'original location of crab crabX = 360 : crabY = 100 'add variable for increment to move crab each time moveCrabX = -5 : moveCrabY = 2 #w.g "spritexy enemy ";crabX;" ";crabY #w.g "drawsprites" 'update screen 'set up a timer to move crab sprite timer 100, [updateDisplay] wait [updatePosition] 'move user-controlled sprite when arrows are pressed '37 = left arrow '38 = up arrow '39 = right arrow '40 = down arrow 'Arrow keys make Inkey$ two characters long, 'so we check the rightmost character with 'the right$() function. 'right arrow = X gets bigger: if asc(right$(Inkey$,1))=39 then spriteX = spriteX + 3 'left arrow = X gets smaller: if asc(right$(Inkey$,1))=37 then spriteX = spriteX - 3 'up arrow = Y gets smaller: if asc(right$(Inkey$,1))=38 then spriteY = spriteY - 3 'down arrow = Y gets bigger: if asc(right$(Inkey$,1))=40 then spriteY = spriteY + 3 #w.g "spritexy guy ";spriteX;" ";spriteY #w.g "drawsprites" wait [updateDisplay] 'locate sprites at new positions and update display 'add boundary detection and reverse direction at edges if (crabX > 370) then moveCrabX = -5 if (crabX < 10) then moveCrabX = 5 if (crabY > 270) then moveCrabY = -2 if (crabY < 10) then moveCrabY = 2 'move computer-controlled sprite at timer intervals crabX = crabX + moveCrabX : crabY = crabY + moveCrabY #w.g "spritexy enemy ";crabX;" ";crabY #w.g "drawsprites" wait [quit] timer 0 unloadbmp "landscape" unloadbmp "smiley" unloadbmp "crab" close #w : end [[code]] ==Challenges== * challenge: make the crab go in a random direction or speed after it encounters an edge. * challenge: give the crab multiple images so it appears to be walking realistically. * challenge: prevent the user-controlled sprite from going off the edge. * challenge: use different images to change the look of this program. ---- [[toc]]