PC Games
• Orb Tutorials
• 2D shoot 'em up Latest Updates
SDL2 Versus game tutorial
Download keys for SDL2 tutorials on itch.io
The Legend of Edgar 1.37
SDL2 Santa game tutorial 🎅
SDL2 Shooter 3 tutorial
Tags • android (3) • battle-for-the-solar-system (10) • blob-wars (10) • brexit (1) • code (6) • edgar (9) • games (43) • lasagne-monsters (1) • making-of (5) • match3 (1) • numberblocksonline (1) • orb (2) • site (1) • tanx (4) • three-guys (3) • three-guys-apocalypse (3) • tutorials (17) • water-closet (4) Books The Honour of the Knights (Second Edition) (Battle for the Solar System, #1) When starfighter pilot Simon Dodds is enrolled in a top secret military project, he and his wingmates begin to suspect that there is a lot more to the theft of a legendary battleship and the Mitikas Empire's civil war than the Helios Confederation is willing to let on. Somewhere out there the Pandoran army is gathering, preparing to bring ruin to all the galaxy... |
— Simple 2D adventure game — Note: this tutorial assumes knowledge of C, as well as prior tutorials.
Introduction Now we can move around our map and be constrined by the tiles (cannot cross holes or walls), it's time we worked with a proper map. The best map we have up to this point contains just random scatters of holes and walls. Loading map data from a file is easy, as it's a list of number, enough to fill our map array. Extract the archive, run cmake CMakeLists.txt, followed by make, and then use ./adventure03 to run the code. You will see a window open like the one above, showing the prisoner on a tiled background. Use WASD to move around. You will find this map more interesting to explore, as it's more maze-like in nature. Close the window to exit. Inspecting the code Only two files have changed in this update: map.c and player.c. Before we look at those changes, let's take a look at the map data itself: 1 1 1 1 1 40 40 1 1 1 1 40 0 40 40 40 40 40 40 0 0 0 0 40 40 40 1 1 40 0 0 0 0 0 0 40 40 40 40 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 40 1 1 1 1 40 0 0 0 40 40 1 1 1 1 40 40 40 0 0 0 0 40 1 1 40 40 40 40 1 1 1 1 1 1 1 1 40 40 40 40 40 40 40 1 1 1 40 40 40 40 1 1 1 1 40 0 40 1 1 1 1 40 40 40 40 40 1 1 1 1 1 1 1 40 40 0 0 0 40 1 1 1 1 1 1 1 40 40 40 1 1 1 1 40 0 0 0 0 0 0 1 1 1 40 0 0 40 1 1 1 1 40 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 40 1 40 40 40 40 1 1 40 0 40 1 1 1 1 40 40 40 0 0 0 0 1 1 1 40 0 0 40 40 40 40 40 40 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 40 1 40 40 40 40 1 1 40 0 40 1 1 1 1 1 1 40 40 0 0 0 1 1 1 40 0 0 0 0 0 0 0 0 0 40 1 1 1 1 1 1 40 40 40 40 40 40 1 1 1 1 1 40 0 0 0 40 40 40 40 1 1 1 1 40 0 40 1 1 1 1 1 1 1 40 0 0 0 1 1 1 40 40 40 40 40 40 40 40 40 40 40 1 1 40 1 1 1 40 0 0 0 0 40 1 1 1 1 1 40 0 0 0 0 0 0 40 40 40 40 40 40 0 40 1 1 1 1 1 1 1 40 40 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 1 1 1 40 0 1 1 0 40 1 1 1 1 1 40 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 1 1 1 1 1 1 1 40 40 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 1 1 1 40 0 1 1 0 40 1 1 1 1 1 40 0 40 40 40 40 40 40 40 40 40 40 40 40 40 1 1 40 40 40 40 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 1 1 1 40 0 1 1 0 40 1 1 1 1 1 40 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 40 1 1 1 1 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 1 1 40 40 1 1 1 1 1 40 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 40 40 40 40 40 40 0 0 0 0 0 0 1 1 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 40 40 40 40 40 40 40 1 1 1 1 1 1 1 40 40 0 0 0 0 0 0 0 0 40 0 40 40 40 40 0 1 1 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 0 0 0 40 40 40 40 1 1 1 1 40 0 0 0 40 40 40 40 40 40 40 0 40 1 1 40 0 1 1 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 0 0 0 0 0 0 40 1 1 1 1 40 0 0 0 40 1 1 1 1 1 40 0 40 1 1 40 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 0 0 0 0 0 0 40 1 1 1 1 40 0 0 0 40 1 1 1 1 1 40 0 40 1 1 40 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 40 40 0 0 0 0 0 0 0 0 0 0 40 1 1 1 1 40 0 0 0 40 40 40 1 1 1 40 1 1 1 1 1 1 1 40 40 40 40 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 40 0 0 0 0 0 0 0 0 0 0 0 0 40 1 1 1 1 40 0 0 0 0 0 40 1 1 1 40 1 1 1 1 1 1 1 40 0 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 1 1 1 40 40 40 0 0 0 40 1 1 1 40 1 1 1 1 1 1 1 40 0 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 0 0 0 0 0 0 0 40 40 40 1 1 1 1 1 1 40 0 0 0 40 1 1 1 40 1 1 1 1 1 40 40 40 0 0 0 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 1 40 0 0 0 0 0 40 40 40 40 40 40 40 1 1 1 1 1 1 1 1 40 0 0 0 40 1 1 1 40 40 40 1 1 1 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 40 1 40 40 40 40 40 40 40 1 1 1 1 1 1 1 40 40 40 40 40 40 40 40 0 0 0 40 1 1 1 40 1 1 1 1 1 40 0 0 0 40 40 40 40 40 40 40 40 40 40 40 40 0 0 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 0 0 0 0 0 0 40 1 1 1 40 1 1 1 1 1 40 0 0 0 40 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 40 40 40 0 0 0 40 40 40 40 40 1 1 1 40 1 1 1 1 1 40 0 0 40 40 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 40 1 1 1 1 1 1 1 40 1 1 1 1 1 40 40 40 40 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 40 1 1 40 40 40 40 40 40 40 40 40 40 40 40 40 1 1 1 40 0 0 0 40 40 40 40 40 40 1 1 40 1 1 1 1 1 1 1 1 1 1 40 40 40 40 40 40 40 1 1 1 40 40 0 0 40 40 1 1 40 0 0 0 0 0 0 0 0 0 0 0 40 1 1 1 40 0 0 0 0 0 0 0 0 40 1 1 1 1 1 40 40 1 40 40 1 1 1 40 0 0 0 0 0 40 1 1 1 1 40 40 40 40 1 1 1 40 0 0 0 0 0 0 0 0 0 0 0 40 40 1 1 40 40 0 0 0 0 0 0 0 40 1 1 1 1 1 40 0 1 0 40 1 1 1 1 1 1 1 1 0 40 1 1 1 1 1 1 1 1 1 1 1 40 40 40 40 40 40 40 40 40 0 0 0 0 40 1 1 1 40 0 0 0 0 0 0 0 40 1 1 1 1 1 40 0 1 0 40 1 1 1 40 0 1 1 1 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 40 0 0 0 0 40 1 1 1 40 40 40 40 40 40 40 40 40 1 1 1 1 1 40 0 0 0 40 1 1 1 40 0 1 1 1 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 40 0 0 0 0 40 1 1 1 1 1 1 1 1 1 1 1 1 1 1 As I said, it's just one long list of numbers. In this case, 1710..! Quite a lot, and our map is only 57 x 30. The map for the final dungeon will be bigger. Still, the file size of this map is just under 4kb, so it's not terrible. This map wasn't produced by hand. A simple map editor was rolled to help with creating it. A future tutorial will look into how to make such an editor. Now let's look at the code: Starting with map.c, the initMap function now calls loadMap, to load the map data, before then calling another function called decorateMap to add details:
The loadMap function itself is simple:
We call a function called readFile, to load the map data into a char array, then point another char pointer (p) at the start of the array. Now ready to load our map data, we set up y and x variables to read the data by row and column; so, we'll read all the values on the first row, then the second row, etc., until we have read all the data. We call atoi on p (which will initially be pointing at the first number in our map data), to read the tile value and assign it to the appropriate index in our map. After this, we'll increment the value of p while the character isn't a space, to move onto the next number. Our numbers are space delimited, and so setting up this while loop will jump to the next one. Remember, calling atoi will read the next number found, but won't move the pointer on! If we didn't do this, we would end up reading the same number constantly and never finish. If we told the pointer to move on just one character, numbers composed of more than one digit would cause the data to read incorrectly. Once we're finished reading the data, we free it. Note that that loadMap function assumes there are exactly the right number of values and performs no error checking or correction..! Onto the decorateMap function. This function serves to randomly change the ground and walls tiles:
We're seeding the random with a fixed number, so that the random picks are always the same, and then looping through our map data. If we encounter a ground tile, there's a one in five chance we'll change it. Effectively, this step turns some normal ground tiles into cracked tiles. We know from our atlas that the four cracked tiles follow directly after the regular ground tile, which is why we increment the number by 1-4. Similarly, when we encounter a wall tile we'll randomly add 0-5 to the value. This will either leave the wall as default or change it to one of the other wall image types. There's no real reason for not manually doing this in the map data itself, other than to do away with the repetitive nature of doing so in an editor, where the process could take some time. Moving on to player.c, we've made just some simple adjustment to the player's starting position. Instead of starting at 0,0, we're moving the player over to 14,28. This is just to give them a new starting position to start exploring from.
Before we finish, a quick look at the readFile function, which lives in util.c. This function simlpy reads a file into a char array and returns it. If the file doesn't exist, we print an error and exit the program. Because the data read is malloc'd, need to always free it when we're done using it (as happens in loadMap).
So, there we have it - a basic map loading routine. We'll be using this map for a few more tutorials, but the final dungeon that will form our core game will actually be a few times larger; consider this map to be a test bed for various bits and pieces to come. Next, we'll look at how we can handle interacting with other entities, such as items. Purchase The source code for all parts of this tutorial (including assets) is available for purchase: From itch.io It is also available as part of the SDL2 tutorial bundle: |