The Game Creators
The Game Creators Home Online Shop Click to Login
  Hot: Christmas CompetitionNovember NewsletterModel Pack 36DB Pro Pack 2009DGS BonanzaCharacter PackFPS Creator Bonanza;
The Game Creators
DBPro Newcomers / [Tutorial] Let's make a tower defense clone!

Go to the first page of this board Return to the Forum Menu Post Message
17 Messages - Page   of 1   
Bookmark and Share Search the Forum

Author Message
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 4th Jul 2007 19:31     Edited: 10th Jan 2008 23:53     | link | toggle



I've actually finished the tutorial! I decided to write them in a pdf file that you can download from here.

Included in the file is all of the media required and the directory setup too, just unrar the package and open up the pdf.

NOTE: Ignore the parts of the tutorial requesting you to download media files as these are included in this full package.

Hope you all enjoy it! Please feel free to post comments or suggestions. I'll be adding updates in the future with new features for the game.

If you'd like to download the entire game and try it out before you read the tutorial click here.

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
indi

User


Joined: Mon Aug 26th 2002
Location: Earth, Brisbane, Australia
Posted: 4th Jul 2007 23:24           | link | toggle

Duke Wintermaul would be proud of you

Back to top
Report this message as abusive
MartinS

User


Joined: Thu Dec 15th 2005
Location: Rochester, NY
Posted: 5th Jul 2007 02:34           | link | toggle

Good job. It was an easy read - nicely written. Finally, some A*!

G2L

Coming soon...
Back to top
MartinS\' Music
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 5th Jul 2007 22:25           | link | toggle

Thanks, I know it's a bit wordy, but I'm trying to keep the diction as comfortable as possible. I'm updating constantly and hoping some people find this useful

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
Kieran

User


Joined: Sun Aug 6th 2006
Location: Hamilton, New Zealand
Posted: 7th Jul 2007 03:52           | link | toggle

very nice! keep it up.

Back to top
Report this message as abusive
Senkan

User


Joined: Wed Jun 7th 2006
Location: Somewhere in the frozen Finland.
Posted: 7th Jul 2007 08:18           | link | toggle

Very nice tutorial indeed!

The only problem that might occur is in SaveMap function when program asks permission to overwrite file and player types y -letter with Caps Lock on. The program defines that as no answer and doesn't overwrite that file. The solution is to change line
IF s$ = "y" to IF LOWER$(s$) = "y" so the program changes the letter typed into lowercase.

Hope this helps.

"Whatever that was, I don't care."
-Someone from FarCry
Back to top
Report this message as abusive
Code Dragon

User


Joined: Mon Aug 21st 2006
Location: Everywhere
Posted: 7th Jul 2007 09:31     Edited: 7th Jul 2007 21:25     | link | toggle

Great job! I haven't gotten through the whole tutorial yet, but I have some suggestions.

It might be a better idea to use delete objects to flush the objects.

Why not use the select command more often, it could be useful in UpdateGUI() and UpdateCamera()

Because the Icon sprite and image numbers never change, it'd probably be a good idea to make them constants instead of variables. (This is also required if you use them with the select statement)

In UpdateCamera() you seem to have CamY# = CamY#-2 and CamY# = CamY#+2 a lot. This is an oppurtuninty to explain the dec and inc commands to newcomers.

EDIT: In SaveMap(), copying code should never be necessary in the 21st century. Don't you think it would be better to replace

+ Code Snippet
    IF LOWER$(s$) = "y"
        DELETE FILE MapName$+".tdf"
        PRINT "Saving file..."
        OPEN TO WRITE 1,MapName$+".tdf"
        WRITE STRING 1,STR$(MapSizeX)
        WRITE STRING 1,STR$(MapSizeY)
        WRITE STRING 1,STR$(MapSegmentsX)
        WRITE STRING 1,STR$(MapSegmentsY)
        FOR x = 0 to MapSegmentsX-1
            FOR y = 0 to MapSegmentsY - 1
                WRITE STRING 1,STR$(Map(x,y))
            NEXT y
        NEXT x
        CLOSE FILE 1
        PRINT "Done. Press any key to continue..."
        WAIT KEY
    ENDIF


with

+ Code Snippet
IF LOWER$(s$) <> "y" THEN ResetScreen(): EXITFUNCTION


and then change the else to and endif and delete the endif at the bottom of the function

Keep up the good work! And I agree with Games 2 Live, finally some A* pathfinding!

You never really know a person until you look at their google autocomplete entries.
Back to top
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 7th Jul 2007 15:40           | link | toggle

Thanks for checking the tutorial out. I'll definitely add the LOWER$() command to the map editor. I recently found a bug where the map file size must be an even number, otherwise the tile placement doesn't work correctly. How can I go about checking if a number is even?

Code dragon, thank you for the suggestions, I'll be certain to add them. I know, I'm bad about using constants, but I'll edit the code and start using some constants where applicable. Concerning the select command, you are absolutely right. I completely forgot about this, yes, it will be very handy instead of using all those IF statements. I hadn't done any programming in a long time, so about a week ago I decided to get back into it and I made this game while forgetting some very useful commands it appears. By the way, I'm sorry the updates are slow, I'm rewriting the game as I write the tutorial. There are a lot of problems with my completed game that I'm hoping to fix. I agree it would be helpful to explain and use the DEC and INC commands.

By the way, is this simple enough to follow? I'm trying not to assume too much of anyone using this tutorial but I'm also trying to explain what is going on, I hope the code comments are helpful. If not, please inform me and I'll be more diligent in explaining the code.

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
Google Ad
Back to top
 
Code Dragon

User


Joined: Mon Aug 21st 2006
Location: Everywhere
Posted: 7th Jul 2007 18:10           | link | toggle

Quote: "How can I go about checking if a number is even?"

The mod command should help, it divides two numbers and returns the remainder. So x mod 2 = 0 will be true when x is even, false when odd.

I think tutorial is pretty simple, you explain the commands in depth and tell why the code works.

You never really know a person until you look at their google autocomplete entries.
Back to top
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 7th Jul 2007 20:36           | link | toggle

Thanks, Code Dragon, I'll certainly be adding that. For now, if anyone is actually doing this tutorial, just remember to make your maps with even coordinates. Otherwise there'll be some serious issues.

Also, with every post edit, I'm making sure to update the source code in the link at the top of the page if you ever want to jump on board without going through everything. If the link isn't working, be sure to inform me and I'll fix it straight away.

I'm really enjoying rewriting my engine, I missed a lot of important features in Tower Defense my first time through, this time, I'm keeping that in mind. Also, the code seems much cleaner and I think it will turn out a lot better than before.

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
Roxas

User


Joined: Fri Nov 11th 2005
Location: http://forum.thegamecreators.com
Posted: 7th Jul 2007 21:31           | link | toggle

Wow! This tutorial is really good indeed. Must show it to my friend


[B] - LINKIN PARK - [/B]
Back to top
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 7th Jul 2007 23:07     Edited: 7th Jul 2007 23:11     | link | toggle

Tutorial Continued
Update: Changed the tile textures to make it easier to see the edges of individual tiles

Whoops, we mustn't forget to add our UpdateMouse() function to our game loop. Add this function just above the call to the ShowDebugInfo() function in our main game loop.

Ok, it's time we start working on our critter logic (pathfinding, spawning, etc). When we created our map, we made sure to add a single spawn tile and a single finish tile. For our critter logic, we're going to need to know the location of these tiles. Let's add four more members to our Map type to hold these values. Going back to our Map TYPE, add the following four members.

+ Code Snippet
    SpawnX as integer `the x coordinate of the critters' spawn tile
    SpawnZ as integer `the z coordinate of the critters' spawn tile
    GoalX as integer `the x coordinate of the critters' goal tile
    GoalZ as integer `the z coordinate of the critters' goal tile


Ok, now we will need to fill these members with the correct data. Where's the best place to do this? How about the CreateMap() function. Let's hop in there and see what we can do. It appears that we have a loop for texturing every tile in our matrix, this would be the perfect place to check for our spawn point and our goal point. Let's add this code to our CreateMap() function just below the SET MATRIX TILE command.

+ Code Snippet
            IF Map(x,y) = 4
                Map.SpawnX = x `Store the X coordinate of the spawn tile
                Map.SpawnZ = y `Store the Z coordinate of the spawn tile
            ENDIF
            IF Map(x,y) = 5
                Map.GoalX = x `Store the X coordinate of the goal tile
                Map.GoalZ = y `Store the Z coordinate of the goal tile
            ENDIF


Remember, this code must be inside our FOR loop. All this does is check if the current tile is a 4 (spawn) tile or a 5 (goal) tile and then stores the current x and y values of our FOR loop into our Map members.

Ok, to confirm that this works, let's add these four lines of code to our ShowDebugInfo() function in our Main.dba source file.

+ Code Snippet
    TEXT 0,30,"Map.SpawnX: "+STR$(Map.SpawnX) `Show the X value of the tile our critters spawn at
    TEXT 0,40,"Map.SpawnZ: "+STR$(Map.SpawnZ) `Show the Z value of the tile our critters spawn at
    TEXT 0,50,"Map.GoalX: "+STR$(Map.GoalX) `Show the X value of the tile our critters go to
    TEXT 0,60,"Map.GoalZ: "+STR$(Map.GoalZ) `Show the Z value of the tile our critters go to


Double check the coordinates with your MouseTileX and MouseTileZ variables to ensure we did everything correctly. Did it work?

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 10th Jul 2007 16:57     Edited: 10th Jul 2007 17:03     | link | toggle

Update: Added pathfinding!

Ok, I'm a little bummed out cause I just added a huge amount of tutorial as an edit to my last post but it completely lost it . I'll just add it to this post.

First, before we get any further into our pathfinding, we need to download an A* library. Go to this link. Scroll down a bit and download the zip file. Extract the zip file and copy the MapAndSearch.dba file to your project directory. Include this file with your project.

Now for an important lesson for any coder. Do not rewrite what has already been written. As long as you can find something that is efficient and suits your purpose there is no other reason to write what has been written. Unless you just want to learn. I'd love to write a tutorial on how to do pathfinding but that would have to be a tutorial all on its own. For now, we're making a game and IanM has supplied the DarkBasic community with this little gem. A* pathfinding is type of pathfinding that is used in all sorts of RTS games. Please google it or search these forums for more information, but in basics, it creates a tree of possible routes and, based on a simple point system, finds the least costly route to get to the destination.

Ok, now let me show you all of the functions we will be adding to our Critter.dba file. Here's they are. Add these to your Critter.dba source file.

+ Code Snippet
`**********************
`PrepareCritters()
`**********************
FUNCTION PrepareCritters()
    FOR i = BasicCritterObjectSeed to BasicCritterObjectSeed+MaxCritters `Delete objects if they already exist
        IF OBJECT EXIST(i) = 1
            DELETE OBJECT i
        ENDIF
    NEXT i
    GLOBAL DIM Critters#(MaxCritters,14) `Create our critter array where we will store all the critter data
    SET DIR CurDir$+"Media" `Go to the correct directory
    MAKE OBJECT PLAIN BasicCritterObjectSeed,1,1 `Make a 1x1 plain object
    TEXTURE OBJECT BasicCritterObjectSeed,BasicCritterImage `Texture this object with our Critter Image
    SET OBJECT BasicCritterObjectSeed,1,1,0 `Set transparency on for our object
    XROTATE OBJECT BasicCritterObjectSeed,270 `Rotate the object to be flat against our map
    HIDE OBJECT BasicCritterObjectSeed `Hide the object
    FOR i = 1 to MaxCritters `Clone our object for our game.  We'll make the number of MaxCritters specified.
        CLONE OBJECT BasicCritterObjectSeed+i,BasicCritterObjectSeed `The object number for each critter
        Critters#(i-1,6) = BasicCritterObjectSeed+i `Store the object number for our critter
        HIDE OBJECT BasicCritterObjectSeed+i `Hide our new object
    NEXT i
ENDFUNCTION
`********************
`SpawnCritter()
`********************
FUNCTION SpawnCritter(CritterType)
SELECT CritterType `First, find out what type of critter to spawn
    CASE BasicCritterType `If it's a basic critter
        FOR i = 0 to MaxCritters-1 `Let's cycle through all of the critters
            IF Critters#(i,0) = 0 `If the critter is not currently active
                Critters#(i,0) = 1 `Make it active
                Critters#(i,1) = 10 `Set the health
                Critters#(i,2) = Map.SpawnX `Set the current tile
                Critters#(i,3) = Map.SpawnZ 
                Critters#(i,4) = Map.SpawnX*(Map.X/Map.SegX)+(Map.X/Map.SegX)/2 `Set the new position
                Critters#(i,5) = Map.SpawnZ*(Map.Z/Map.SegZ)+(Map.Z/Map.SegZ)/2
                Critters#(i,9) = 0.05 `Set the critter's speed
                Critters#(i,10) = Critters#(i,4) `Set the target position to the current position so 
                Critters#(i,11) = Critters#(i,5) `the loop will update the pathfinding
                Critters#(i,13) = 0
                POSITION OBJECT Critters#(i,6),Critters#(i,4),0,Critters#(i,5) `Position the object
                SHOW OBJECT Critters#(i,6) `Show the object
                i = MaxCritters `Exit the loop
            ENDIF
        NEXT i
    ENDCASE
ENDSELECT
ENDFUNCTION
`*************************
`UpdateCritters()
`*************************
FUNCTION UpdateCritters
    FOR i = 0 to MaxCritters-1 `Loop through our critters
        IF Critters#(i,0) = 1 `If we find one that is active
            CritterArrayToObject(i) `Store the data in our Object so it's easier to manipulate
            IF Critter.PosX# = Critter.TargetPosX# and Critter.PosZ# = Critter.TargetPosZ# `If the critter hits the target, let's update it's path for the next tile
                UpdateCritterPath() `update the path
            ENDIF
            UpdateCritterMove() `Update the movement
            CritterObjectToArray(i) `Store the data in the array.
        ENDIF
    NEXT i
ENDFUNCTION
`*************************
`UpdateCritterPath()
`*************************
FUNCTION UpdateCritterPath()
    Critter.isBlocked = 0 `Set the critter to currently not blocked
    FOR x = 0 to Map.SegX-1 `loop through our map array
        FOR y = 0 to Map.SegZ-1
            IF Map(x,y) = 3 `If the tile at x,y is a wall
                SetSearchMap(x,y,1) `Set the search map to 1 (ie, can't be crossed)
            ENDIF
            IF TurretMap(x,y) <> 0 `If we have a turret on x,y (TurretMap > 0)
                SetSearchMap(x,y,1) `Set the search map to 1 for this tile (can't be crossed)
            ENDIF
        NEXT y
    NEXT x
    FOR x = 0 to Map.SegX-1
        SetSearchMap(x,Map.SegX,1) `Restrict access to our invisble tiles on the edge of the map
    NEXT x
    FOR y = 0 to Map.SegZ-1
        SetSearchMap(Map.SegZ,y,1) `See above
    NEXT y
    SearchMapAStar8(0,Critter.TileX, Critter.TileZ, Map.GoalX, Map.GoalZ) `Now we create an 8 direction search map (8 directions means diagonal moves are allowed)
    Critter.TargetTileX = GetSearchPathX(0,1) `Set the critter's target tile to the tile determined by the pathfinding function
    Critter.TargetTileZ = GetSearchPathY(0,1) `See above
    IF Critter.TargetTileX = -1 and Critter.TargetTileZ = -1 `The target tile will equal negative one if there is no path available
        Critter.isBlocked = 1 `set the isBlocked to 1
        Critter.TargetTileX = Map.SpawnX `The next goal is going to reset to the spawn
        Critter.TargetTileZ = Map.SpawnZ `See above
        Critter.TargetPosX# = Map.SpawnX*(Map.X/Map.SegX)+(Map.X/Map.SegX)/2 `get position of spawn as target
        Critter.TargetPosZ# = Map.SpawnZ*(Map.Z/Map.SegZ)+(Map.X/Map.SegZ)/2 `See above
    ELSE
        Critter.TargetPosX# = Critter.TargetTileX*(Map.X/Map.SegX)+(Map.X/Map.SegX)/2 `Setup the critter's actual target position to move to (not the tile value, but 3d space coordinate)
        Critter.TargetPosZ# = Critter.TargetTileZ*(Map.Z/Map.SegZ)+(Map.Z/Map.SegZ)/2 `See above
    ENDIF
ENDFUNCTION
`*************************
`UpdateCritterMove()
`*************************
FUNCTION UpdateCritterMove()
    GOALX = Critter.TargetTileX `Rename our variables to cut down on code size
    GOALZ = Critter.TargetTileZ
    GX# = Critter.TargetPosX#
    GZ# = Critter.TargetPosZ#
    CX# = Critter.PosX#
    CZ# = Critter.PosZ#
    IF ABS(CX#-GX#)<0.1 `If the critter's position is pretty close to the target
        CX# = GX# `Make it the target position, this way the UpdateCritterPath() function will be called
    ENDIF
    IF ABS(CZ#-GZ#)<0.1
        CZ# = GZ#
    ENDIF
    IF CZ# <> GZ# and CX# <> GX# `If we need to move on a diaganol
        Speed# = Critter.Speed#/SQRT(2) `The speed is reduced by SQRT(2) because of the diaganol move
        IF Critter.Affliction = 1 `If the critter is currently slowed, divide the speed by two
            Speed# = Speed#/2
        ENDIF
    ELSE
        Speed# = Critter.Speed# `Else, we're not moving in two directions, the speed is the same
        IF Critter.Affliction = 1 `If slowed, divide the speed by tw
            Speed# = Speed#/2
        ENDIF
    ENDIF
    IF CZ# > GZ# `If our critter is above the goal, move it down
        CZ# = CZ#-Speed#
    ENDIF
    IF CZ# < GZ# `If our critter is below the goal, move it up
        CZ# = CZ#+Speed#
    ENDIF
    IF CX# > GX# `If our critter is to the right, let's move him left
        CX# = CX#-Speed# 
    ENDIF
    IF CX# < GX# `If our critter is to the left, let's move him right
        CX# = CX#+Speed#
    ENDIF        
    Critter.PosX# = CX# `Store our new positions
    Critter.PosZ# = CZ# `Store our new positions
    Critter.TileX = int(((Critter.PosX#-MATRIX POSITION X(1))/Map.X)*Map.SegX)
    Critter.TileZ = int(((Critter.PosZ#-MATRIX POSITION Z(1))/Map.Z)*Map.SegZ)
    POSITION OBJECT Critter.ObjectNum,Critter.PosX#,0,Critter.PosZ#
ENDFUNCTION
`*************************
`CritterArrayToObject()
`*************************
FUNCTION CritterArrayToObject(k)
Critter.Alive = Critters#(k,0)
Critter.Health = Critters#(k,1)
Critter.TileX = Critters#(k,2)
Critter.TileZ = Critters#(k,3)
Critter.PosX# = Critters#(k,4)
Critter.PosZ# = Critters#(k,5)
Critter.ObjectNum = Critters#(k,6)
Critter.TargetTileX = Critters#(k,7)
Critter.TargetTileZ = Critters#(k,8)
Critter.Speed# = Critters#(k,9)
Critter.TargetPosX# = Critters#(k,10)
Critter.TargetPosZ# = Critters#(k,11)
Critter.Affliction = Critters#(k,12)
Critter.isBlocked = Critters#(k,13)
ENDFUNCTION
`**************************
`CritterObjectToArray()
`**************************
FUNCTION CritterObjectToArray(k)
Critters#(k,0) = Critter.Alive
Critters#(k,1) = Critter.Health
Critters#(k,2) = Critter.TileX
Critters#(k,3) = Critter.TileZ
Critters#(k,4) = Critter.PosX#
Critters#(k,5) = Critter.PosZ#
Critters#(k,6) = Critter.ObjectNum
Critters#(k,7) = Critter.TargetTileX
Critters#(k,8) = Critter.TargetTileZ
Critters#(k,9) = Critter.Speed#
Critters#(k,10) = Critter.TargetPosX#
Critters#(k,11) = Critter.TargetPosZ#
Critters#(k,12) = Critter.Affliction
Critters#(k,13) = Critter.isBlocked
ENDFUNCTION


Excuse me posting it like this but I don't have time right now to write it how I had it earlier. I'm going to go through each of the functions and explain what they do. First, PrepareCritters() simply loads and creates the physical critter object. Also, it clones this object as many times as we have MaxCritters set to. You'll notice immediately a jump in loading time for our game, that is because loading and clone objects requires some time and memory. Next we have our SpawnCritter() function. This is very important as it positions and actives a fresh critter at the spawn point. Go back to your UpdateSpawnList() function and uncomment the SpawnCritter() line now that we have it written.

Moving on we get to our UpdateCritters() function. This will be called every game loop and updates the positions and pathfinding of each active critter (notice the FOR loop searching for 1 at each (i,0) element). Also important to notice is that we will only be updating our path for each critter when the critter reaches its destination. This will cut down on processor overhead from the pathfinding routines, plus, it's just not necessary to be constantly updating paths.

Our UpdateCritterPath() function is where the real pathfinding magic happens. Look through the comments for explanation on what is going on. Then we have the UpdateCritterMove() function. The code should be easy to understand, read the comments. Essentially we are just adjusting the critter's position based on the difference between it and the target position. The distance that it moves is based on the speed member. The two final functions simply swap data between the type we created and the array storing the critters. You'll notice these are called in our UpdateCritters() function just before any logic is done and then after. That way we can easily manipulate data and then throw it back into our master critter array to store it. Fairly simple.

Ok, let's step back into our Main.dba file to adjust some things and add these new functions to our game loop. First, we added a new member to our Critter type. Go to the critter type and add the following line to it.

+ Code Snippet
    isBlocked as integer `If set to 1, the critter can't move (no path found)


This will keep track of the critter's ability to move. Now replace your current Game Loop Preparation heading and game loop with the following code.

+ Code Snippet
`***************************
`Game Loop Preparation
`***************************
LoadMedia() `This function loads all the media needed for the game
LoadMap() `Load the map file
CreateMap() `This function creates the matrix for our map
PrepareCritters() `Prepare our critters for the game
AppendToSpawnList(BasicCritterType,2,3000)
`***************************
`Pathfinding initialization
`***************************
CreateSearchMap(Map.X, Map.Z)
CreateSearchPathLists(0)
`********************
`GAME LOOP GAME LOOP
`********************
DO
    UpdateMouse() `1. Update the mouse's coordinates and tile values
    UpdateSpawnList()
    UpdateCritters()
    ShowDebugInfo()
    SYNC `Draw the screen
LOOP


We are calling our PrepareCritters() function to load our critter objects and added 2 critters to our queue. Then we are setting up our pathfinding map. And finally we add the update calls to the game loop. Now we are doing plenty of calculations, but our game loop looks nice and tidy. Go ahead and run it, you should see two little critters circling about your map, avoiding the walls (grey tiles) and heading for the goal point. Once they get to the goal point they will return to the spawn and do it all over again. We'll add some logic later to deal with this and simple destroy the critter when they reach the end. Want to make it even more crazy? On your AppendToSpawnList() function, make it spawn more critters with a shorter interval. See how easy it is to adjust settings like these? Eventually this will be controlled by the map file, but, for now, we'll do it manually.

If your code doesn't compile, please check the top link and download the full source code. If you can find any errors in my tutorial, please tell me and I'll fix them as soon as possible. I feel I may be leaving some important code out after messing up my last post.

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
Darth Vader

User


Joined: Tue May 10th 2005
Location: Adelaide SA, I am the only DB user here!
Posted: 11th Jul 2007 02:20           | link | toggle

Hey Prancer. This tutorial looks really great and if it's got A* Pathfinding then that's even better! But since the computer I use for internet is the family computer and not actually my development PC it would make it so much easier of this was a .doc file! Is it possible to put it all in a .zip or .rar?
Thanks!


Back to top
IdealWxrks
Report this message as abusive
Sixty Squares

User


Joined: Wed Jun 7th 2006
Location: Somewhere
Posted: 11th Jul 2007 16:04           | link | toggle

This tutorial is looking great When it's done I'd like to see the end result

Back to top
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 13th Jul 2007 16:57     Edited: 15th Aug 2007 20:22     | link | toggle

Tutorial Continued

Before I continue, I'll be sure to alter my last update to describe every function independently, I just ran out of time.

If you are caught up on the tutorial, hopefully you've noticed that the little critters go to the goal point only to turn around and head back to the spawn in an annoying loop. Our game isn't going to allow such silliness. Any time a critter manages to reach the goal point, the player needs to lose a life. After the player loses all of his lives, then the game is over. So, let's add a player type to our game. Going into our Main.dba source file, add the following underneath your map TYPE.

+ Code Snippet
TYPE Player
    Name$ as string `The player's name (high score list)
    Lives as integer `Number of lives left
    Points as integer `Current number of points
    CurrentLevel as integer `The level the player is on
ENDTYPE


Great, now we need to create an object of this type. Underneath your Create our Types heading, add the following line.

+ Code Snippet
GLOBAL Player as Player


Now we have our new object. It's time to set its default values. Alter the "Set our default map name (for debugging)" heading to this:

+ Code Snippet
`***************************
`Set Default Values (For debugging)
`***************************
Map.Name$ = "Default"
Player.Lives = 10


Now we've given the player ten lives to deal with. Of course, this will be controlled by the map editor during the map creation process, but right now we're working with getting some game logic under our belts before moving on to details.

So, we have our critters happily frolicking about our map in circles between the goal point and the spawn point. Let's add some code to handle what happens when the critter reaches the goal tile. First, jump to the CritterUpdateMove() function in our Critter.dba file. Add the following code to the bottom of this function.

+ Code Snippet
    IF Critter.TileX = Map.GoalX and Critter.TileZ = Map.GoalZ
        Player.Lives = Player.Lives - 1
        DestroyCritter();
    ENDIF


This should be clear as to what is happening. If the critter happens to be on the goal tile, we'll take away one life and destroy that critter. Of course, we still need to add our DestroyCritter() function. Let's do this now. Add the following code to your Critter.dba file.

+ Code Snippet
`*************************
`DestroyCritter()
`*************************
FUNCTION DestroyCritter()
    Critter.Alive = 0
    HIDE OBJECT Critter.ObjectNum
ENDFUNCTION


Again, this is a very small function for the time being, but it serves its purpose. All we have to do to get rid of a critter is simply change the Critter.Alive member variable to 0 and hide the actual object. If you run your code now, you should see the critters disappearing when they reach the goal. Also, using the PICK SCREEN() function, you can see that our critter spawn list is indeed working. After the critter is destroyed at the goal point, its object is reused for the next spawn.

Updates will be added here, soon

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive
Prancer

User


Joined: Sun Feb 6th 2005
Location: Idaho, US
Posted: 15th Aug 2007 20:40     Edited: 15th Aug 2007 20:40     | link | toggle

Sorry there hasn't been an update in a while guys, it has been a busy summer. I'll be updating more often again.

Darth Vader -
I created a .doc file and included it with the current build of the game and the media. I'll be sure to update that file as often as possible. You can grab it here.

Keep checking back for more updates!

Back to top
Prancer\'s World Send AIM user a message
Report this message as abusive

Go to the first page of this board Return to the Forum Menu Post Message
17 Messages - Page   of 1   
Search the Forum

Sorry, but it has been so long since anyone replied to this Thread that it has been automatically locked.
You may read it but not reply.

Forum Search

Enter a word or phrase to search our Forum for:

Thread Subject Search
Search Phrase:
Search Scope: Entire forum
Just this board
 
Google Forum Search
Search Phrase:
 
Apollo v2.02


Dark Game Studio
Privacy Policy AUP Top of Page