How hard is it to make an isometric random map?

Get help using Construct 2

Post » Sun Jul 06, 2014 6:25 pm

This is something I've been thinking about for a while since I'm getting started on making the actual levels for my game which is an isometric turn-based rpg.

There are two ways I could do it. One is to create the map by hand, placing the sprites where I want them. It would just be a matter of making the sprites and marking off where I want the solid borders to be for pathfinding. Nothing too difficult there. The main advantage here is complete control over the visual elements so I could make a better looking game. The downside is that the level will always be the same, save for random enemy placement and difficulty.

The other option is to randomly generate a map. The advantage to this would be having a different layout each time. The downsides are that it's harder to make it look nice. I can't place "filler" sprites to cover weak areas or to add in detail as easily since they would need to be placed in the proper location. I also have to make sure the map "works" and is still interesting. The major issue I've had is placing structures such as a long wall, a river, a long cliff, anything that is not just one sprite but a group of sprites that need to line up or make sense.

Here are a couple different examples.

Image

Image

The first is from Age of Empires II, and the second is from Baldur's Gate II.

I can adapt the game to work with either type of map. I would lean more towards the Baldur's Gate style map since this is an RPG after all.

The AoE map is probably easier to make. It is more open and would only need correct sprite placement so that it looks nice. If I add water, I would have to worry about islands I can't reach or whatnot. If I add trees, I would want them in groups preferably but not blocking paths either. I would have to create some sprites to indicate shorelines for each side and some corner pieces and place them correctly, which seems like it would be tricky.

The Baldur's Gate style maps rely more on paths and rooms. The biggest challenge is how to make the walls have proper corner pieces, be the proper thickness (as you can see in the picture some rooms are very close together, and others have more space around them.) Even if I set up some sort of code to randomly place rooms and hallways, I would still need the textures/sprites to be in the correct place. A wall needs to have an actual end to it and fit in with the corner of the next wall.

All of this is easy with manual placement. I just create some sprites (walls, rocks, etc.) and place them where I want them until the level is built.

I've messed with arrays a little bit, and looked at some random map generators here. I really can't see any way to make a functional world that's both random and isometric and actually works. Placing isometric objects like a tree is not hard, and I could make the ground tiles diagonal or whatever.

But getting walls built around paths and things like that is just really confusing, assuming I could build an isometric hallway to begin with. Has anyone had any success with anything like this?
B
79
S
30
G
35
Posts: 340
Reputation: 22,996

Post » Mon Jul 07, 2014 1:08 am

Forget about isometric for a moment and look at doing it only in 2d. Isometric can be added later easily enough with the only headache being perhaps sorting.

The simplest kind of procedural generation is done on a 2d grid. This can be represented by a 2d array which will provide a value for each grid position. Next you as the designer need to choose what the values mean.

For a continent type you could use say 0 for water and 1 for land. For a dungeon you could use 0 for floor and 1 for walls. It just all depends on what you want to generate. Also there is no reason why you couldn't use 2,3... and so forth for more terrain types, again it depends on what you want to do.

Note at this point we just have a data representation of the map. If we want to get a visual of it we need to loop over the array and create objects at those positions.

For example if each tile is 32x32 pixels and the tile's origin is in the center then you can create the map with an event like so:
Code: Select all
Array: for each xy element
--- Array: current value = 0
------> System create water on layer 0 at (Array.CurX*32+16, Array.CurY*32+16)
--- Array: current value = 1
------> System create ground on layer 0 at (Array.CurX*32+16, Array.CurY*32+16)


Or if your sprites are isometric then you can do this. Note: a 32x32x32 isometric cube will have a 64x64 pixel image.
Code: Select all
Array: for each xy element
--- Array: current value = 0
------> System create water on layer 0 at ((Array.CurX-Array.CurY)*32+320, (Array.CurX+Array.CurY)/2*32+16)
--- Array: current value = 1
------> System create ground on layer 0 at ((Array.CurX-Array.CurY)*32+320, (Array.CurX+Array.CurY)/2*32+16)



Well, then on to more about the generation. The most simple generation other than setting all the array to one value is to set each value to be randomly 0 or 1.
Code: Select all
Start of layout
Array for each xy element
---> Array: set value at (Array.CurX, Array.CurY) to choose(0,1)


Beyond that there are a lot of different ways you can generate the maps.

Instead of set setting individual grids you can set horizontal or vertical lines and filled rectangles by using "for loops".

For terrain you can use the "noise" addon which will give nice perlin noise instead of staic noise. I've also used a smaller separate array and interpolated it onto the larger array for a more globular noise.

For the wall bit do a search for "bitwise" for a method to choose a image based on what's around it. It also can be used for the water shoreline.

To have a land mass that doesn't have any inaccessible areas there are basically two ways to go about it. One is to pick a spot with land and do a "flood fill" there to mark anything connected and then check for values of land that isn't marked. A second method is to only grow from existing land so you always know it's connected.

Another topic to look up is "cellular automata" which can be useful at times.

cheers
B
92
S
32
G
109
Posts: 5,294
Reputation: 70,999

Post » Mon Jul 07, 2014 2:04 am

Thanks. I'll look into what you said.
B
79
S
30
G
35
Posts: 340
Reputation: 22,996

Post » Mon Jul 07, 2014 4:39 am

This might give you some ideas. http://www.vlambeer.com/2013/04/02/rand ... and-kings/
You might also look into how Spelunky generates it's levels. It sort of combines authored content with procedural generation by having a set of pre-made rooms that are stuck together semi-randomly.
B
35
S
9
G
4
Posts: 201
Reputation: 5,170

Post » Tue Jul 08, 2014 6:14 am

Ahr Ech wrote:This might give you some ideas. http://www.vlambeer.com/2013/04/02/rand ... and-kings/
You might also look into how Spelunky generates it's levels. It sort of combines authored content with procedural generation by having a set of pre-made rooms that are stuck together semi-randomly.


That Wasteland Kings example looks very interesting. From what the article said, it looked like the floormaker is a sprite that is spawing floor tiles as it goes, and then each floor tile spawns a wall on one of its corner. It seems like this would generate a lot of overlapping tiles since some would get placed on the same spot. It also looks like the tiles are very simple and blocky without much need for variation. I would rather make mine a little bit better looking since it would fit my game better.

I do like the idea of Wasteland Kings map generation. It will also create areas that are accessible with only a small chance of something going wrong.

I looked up a bit on bitwise map creation as @R0J0hound suggested. It looks like it can be done on an array where it simply checks to see the value of the neighboring elements using something like "array.curX +1". I really can't find many good ways to reference a single element on an array.

Here is an article I found that was useful on bitwise stuff:

http://www.saltgames.com/2010/a-bitwise ... -tilemaps/

I tried to find a way to combine the two methods. The only way I saw to do it was to create a sprite for each tile, put it on the layout in the correct spot, put them in a family, give the family an instance variable, and then have the floormaker piece change that variable when it overlaps them as it moves around the layout. Then, the sprites would modify the value of their corresponding array element, then they would be deleted. Then, after all that, the bitwise part would set in checking values on the array. This is a bit tedious since the layout needs to have one sprite for each array element which is a lot for big maps. I guess I could have used a second animation frame for the sprites as my trigger instead of an instance variable though.

I guess it could be done without sprites if I could move around on an array moving from one element to the next randomly and setting the values to either a 0 or 1 if I want a floor tile or wall tile. I'm not really sure if I know how to do this. It sounds like it would be an easier approach though.

I figure my biggest challenge right now will be to make everything work. It's a party based game, so all 3 heroes need to be spawned correctly and not stuck in a wall. Then, I need to place enemies which shouldn't be too hard. I also need to make sure each part of the map can be accessed if my game goal is to kill all enemies.

I still feel like I will need to sacrifice some graphical detail to get this to work. It's getting late so I need to call it a night. I hope I didn't miss anything with this post.
B
79
S
30
G
35
Posts: 340
Reputation: 22,996

Post » Tue Jul 08, 2014 7:16 pm

@DrewMelton
I'd go for using separate animation frames rather than separate objects.

Here's a bitwise example here that uses the tilemap instead of array, but the concept is about the same.
tilemap-auto-tile-help_p721581?#p721581

I had a bit of a go at making an example in isometric. Art is time consuming for me and I wasn't able to find a free tileset that has all 16 combinations required for the bitwise method. I was able to use a modified approach with what I could find though.
http://opengameart.org/content/cave-tileset
https://dl.dropboxusercontent.com/u/542 ... tile3.capx

I also found a useful general reference on isometric here that may be helpful:
http://gamedevelopment.tutsplus.com/tut ... medev-6511
B
92
S
32
G
109
Posts: 5,294
Reputation: 70,999

Post » Tue Jul 08, 2014 8:26 pm

R0J0hound wrote:@DrewMelton
I'd go for using separate animation frames rather than separate objects.

Here's a bitwise example here that uses the tilemap instead of array, but the concept is about the same.
tilemap-auto-tile-help_p721581?#p721581

I had a bit of a go at making an example in isometric. Art is time consuming for me and I wasn't able to find a free tileset that has all 16 combinations required for the bitwise method. I was able to use a modified approach with what I could find though.
http://opengameart.org/content/cave-tileset
https://dl.dropboxusercontent.com/u/542 ... tile3.capx

I also found a useful general reference on isometric here that may be helpful:
http://gamedevelopment.tutsplus.com/tut ... medev-6511


Thanks for the capx!

I'm going to spend the rest of the evening playing with this. I may implement a sort of Minecraft ability to destroy tiles and look for treasure or to create a path. That way, I won't have to worry about rooms being isolated. If an enemy gets created in an isolated room, I can make him into a monster of some sort rather than human enemy which would look silly.

It might look a tad silly have a mage, fighter, and thief able to use a pickaxe, but it might be fun as well. Plus it would open up more gameplay options and give people more to do than fight.
B
79
S
30
G
35
Posts: 340
Reputation: 22,996

Post » Wed Jul 09, 2014 3:58 am

@R0J0hound or @Ahr Ech or anyone else, can someone have a look at this capx and see what is wrong.

I found an old cap file for construct classic, and I wanted to remake into construct 2 so I could test it. However, it is not working as it should. Some of the logic and terms are different, so maybe something is throwing me off.

Here is the tutorial with the old cap file for reference if you want it. https://dl.dropboxusercontent.com/u/581 ... al.doc.pdf

I have attached my remake. Can someone look at it with fresh eyes and see where the error is? I was trying to follow the example as closely as I could, so maybe something needs to be written differently or maybe I just messed up and didn't realize it.
You do not have the required permissions to view the files attached to this post.
B
79
S
30
G
35
Posts: 340
Reputation: 22,996

Post » Wed Jul 09, 2014 4:43 am

I can't open the capx at the moment but you'll have to tweak your array events slightly.
Construct classic arrays are 1 based so to access the first element you'd use
Array(1)
Array(2) for the second and so on.

C2 uses 0 based arrays, so the expressions to access the first two elements would be:
Array.at(0) and array.at(1)

So I think if you subtract one from the array indexes throughout your capx it should fix it.
B
92
S
32
G
109
Posts: 5,294
Reputation: 70,999

Post » Wed Jul 09, 2014 6:11 am

@R0J0hound Yeah, I made sure to allow for that, though it was still a little off putting, so hopefully I didn't miss any.

I have to call it a day. I'll try again tomorrow. If you get a chance to look at it, let me know. It's probably something simple that I keep glossing over.
B
79
S
30
G
35
Posts: 340
Reputation: 22,996

Next

Return to How do I....?

Who is online

Users browsing this forum: dop2000 and 43 guests