Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Newcomers DBPro Corner / [Tutorial] Let's make a tower defense clone!

Author
Message
Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 5th Jul 2007 03:31 Edited at: 11th Jan 2008 06:53


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.

indi
20
Years of Service
User Offline
Joined: 26th Aug 2002
Location: Earth, Brisbane, Australia
Posted: 5th Jul 2007 07:24
Duke Wintermaul would be proud of you

MartinS
16
Years of Service
User Offline
Joined: 15th Dec 2005
Location: Rochester, NY
Posted: 5th Jul 2007 10:34
Good job. It was an easy read - nicely written. Finally, some A*!

G2L

Coming soon...
Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 6th Jul 2007 06:25
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

Kieran
16
Years of Service
User Offline
Joined: 6th Aug 2006
Location: Hamilton, New Zealand
Posted: 7th Jul 2007 11:52
very nice! keep it up.

Senkan
16
Years of Service
User Offline
Joined: 7th Jun 2006
Location: Somewhere in the frozen Finland.
Posted: 7th Jul 2007 16:18
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
Code Dragon
16
Years of Service
User Offline
Joined: 21st Aug 2006
Location: Everywhere
Posted: 7th Jul 2007 17:31 Edited at: 8th Jul 2007 05:25
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



with



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.
Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 7th Jul 2007 23:40
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.

Code Dragon
16
Years of Service
User Offline
Joined: 21st Aug 2006
Location: Everywhere
Posted: 8th Jul 2007 02:10
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.
Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 8th Jul 2007 04:36
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.

Roxas
17
Years of Service
User Offline
Joined: 11th Nov 2005
Location: http://forum.thegamecreators.com
Posted: 8th Jul 2007 05:31
Wow! This tutorial is really good indeed. Must show it to my friend


[B] - LINKIN PARK - [/B]
Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 8th Jul 2007 07:07 Edited at: 8th Jul 2007 07:11
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.



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.



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.



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

Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 11th Jul 2007 00:57 Edited at: 11th Jul 2007 01:03
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.



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.



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.



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.

Darth Vader
17
Years of Service
User Offline
Joined: 10th May 2005
Location: Adelaide SA, I am the only DB user here!
Posted: 11th Jul 2007 10:20
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!


Sixty Squares
16
Years of Service
User Offline
Joined: 7th Jun 2006
Location: Somewhere in the world
Posted: 12th Jul 2007 00:04
This tutorial is looking great When it's done I'd like to see the end result

Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 14th Jul 2007 00:57 Edited at: 16th Aug 2007 04:22
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.



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



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:



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.



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.



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

Prancer
17
Years of Service
User Offline
Joined: 6th Feb 2005
Location: Idaho, US
Posted: 16th Aug 2007 04:40 Edited at: 16th Aug 2007 04:40
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!

Login to post a reply

Server time is: 2022-12-01 10:17:37
Your offset time is: 2022-12-01 10:17:37