Well... trying to make some dynamic level generation script - it's a thing I've been digging into, lately... and kind of fuzzy on implementing it.
So, the idea is that the main playmap area is 3 screens tall, 5 screens across; and ultimately, represented as a table like:
LVL1={/leveltype,scr1,scr2,scr3,scr4...scr15} (where scr1 for instance, is a perlin noise variable that indicates where it joins with other screens... so if it were "4," it would open to the right (up=1, left=2, right=4, down=8). LVL1-LVL15 each do this.
I have a table called DOORWAYS={1,6,11,5,10,15} ...these are the screen IDs that can contain doorways. And then one that's DOORSHUF={RND(1,6),RND(1,5),RND(1,5)...} - the idea is that the starting door from level 1 is the first variable, and it references "DOORWAYS" to place the appropriate door - then every door thereafter is made by adding the next "n" of DOORSHUF to the previous one, and if need be, subtracting 6 from it until the table finishes, and returning those values to a DOORLIST table that should end up looking like either (16 values of 1 through 6, to reference DOORWAYS) or (16 values of DOORWAYS that always alternate).
From there, I'm aiming at taking THAT table, and having each of 15 levels take that sequence, and concoct a "fast road" that's high risk, rewarding, but very direct toward the next door; and a "slow road" that's safer but winding (at least 7 "screens" in sequence)... the two paths can cross, too. The path generation basically adds the appropriate openings to scr1, scr2, etc. (and doesn't really matter which way it generates, since that's just the openings on the screens); and calculates via +/-1s and +/-5s (trying to devise a way to prevent calculative wrapping... so "5 to 6" has to do a "+5" and 4 "-1s" rather than a +1... so that too)...
Anybody else here mess with this kind of thing and get it to work right, by chance?
In progress:
DOORWAYS={1,6,11,5,10,15} FUNCTION MAKELEVEL(BIOME,SCR1=0,SCR2=0,SCR3=0,SCR4=0,SCR5=0,SCR6=0,SCR7=0,SCR8=0,SCR9=0,SCR10=0,SCR11=0,SCR12=0,SCR13=0,SCR14=0,SCR15=0) --CREATE SEQUENCE OF 16 DOORS DOORSHUF={RND(1,6),RND(1,5),RND(1,5)...} D=0 N=1 FOR N=1 TO 15 DO D+=DOORSHUF(N) ADD DOORLIST (RETURN DOORWAYS,D) N+=1 NEXT |
Now working on the pathbuilding... basically trying to make constraints that if scr(n)\5 = 0, it can't +1, and if scr(n)\5 = 1, it can't -1... and then if scr(n) / 5 <= 1, it can't -5 and then if scr(n) /5 >2, it can't +5... (easy enough); but then having the pathways calculate as a result of the correct amount of +/-1s and +/-5s (this should take screen(n.previous + variable) and give the new "next" screen - then depending on the operator involved, it'll add the appropriate Perlin values to each of the scr1...scr15 variables in that level's table...
...but that's still tricky to take from "idea" to successfully implemented code, isn't it! 'XD
PS: Can anybody tell I come from OOP shit? I think half of this question/post is "am I syntaxing correctly here?"
Tony, if you're going to add data, instead of marking in your code all the doors and special features, why not use the PIXEL space in the tiles for 2-dimensional data ?
Then you won't have to remember all the coordinates of the special items; they are right there in your pixel-data.
At one point, I, too, would store important script locations via raw locations as part of my source code.
But have found it much more effective to use a data table outside the program, whether it's a text file that contains additional definition and mapping data, or you want to carry speech and scripts of the sprite.
Work it in data outside the source I say.
He isn't working out how to store locations - he wants to programmatically generate them.
After eventually wrapping my mind around what you've got so far, I feel like thinking in terms of that linear data structure is getting in the way of how you'll algorithmatize it all. Not that you should change the structure, just ignore it for the design part.
So find some basic path/maze generation algos, run a straighter one and a windier one, then worry about serializing it into your level table.
At least that's my initial take on it all.
Is the map different each time is it run, Tyroney ? Like a random world generator ? That's what is confusing me about this ATM when you say algorithmatize. Which I don't think is a word, but it oughta be. :)
What I'm doing:
[01][02][03][04][05]
[06][07][08][09][10]
[11][12][13][14][15]
^ These are each a "screen" of data/positions.
-Make a sequence of "doors" that all alternate, and are all in: 01, 06, 11, 05, 10, 15. When the player moves from the start door to the finish door, the finish door becomes the "start door," and this rewrites the map to the next sequence. So a sequence of 16 doors will write 15 "levels" - one between each of them.
-Short/long paths are all made up of 4 things: "+1" "-1" "+5" "-5" THESE edit a level-specific table made up of perlin noise checks. So 10 doing a "-1" will take the tenth entry of the level and "add 2" (which represents left) and takes the ninth entry and and "add 4" (which represents right). The result of this is that each of the screens in that table will have a sum that controls which direction they're open. The "hard path" does an "add 16" - which then just places obstacles with more consequences for missing them. The "easy path" can converge or cross the "hard path," and really... having one or two "challenging screens" in it doesn't make the "easy path" not easier overall. Junctions can allow the player to take half of one and half of the other, too.
-Each level then generates by referencing the appropriate level's table, which then points to data that controls the positions where "things" generate. A lot of these things are horizontal/vertical-oriented obstructions (widgets/timing gates, breadcrumb trails, etc.). These "things" are also determined by the biome of the level, so you'll see some recurring themes - but as the level goes up, the consequences for misses gets more brutal and the margin of error gets smaller.
-The "screen data" looks up the perlin noise info: If n>16, marks "hard" true and subtracts 16; then whatever's left will reference one of 15 sprites/tables regarding obstacle placement, based on which sides are "open" or not. The "biome" keyword tells it what colors to make the terrain, and which obstacles to place.
The idea is to converge "random pathing" with "deliberately designed." ;)
And the "doors" aren't for specific door locations - it's just a chart that tells the game which SCREEN to put the doorway in; the data referenced by that will give the game a specific location to place it within that screen. A start/finish screen may use a widget for fun; but are generally "safe spaces" where you aren't going to die.
Hopefully the outcome is a game where as you make it to one exit, it will do a short transition that immediately writes the new level in place of the old one on the fly, while rewarding you for reaching the end of that level. I also plan to couple that with a 9000-frame timer (300 seconds, which means 5 minutes) to complete the whole thing within, and awards a bonus on completion.
Not-really-spoiler-alert: The top and bottom are sometimes on different sides (normally top left/bottom right), but the middle row interprets the data backwards (right to left), so that the vertical shafts line up above/below it... so that in those areas, the vertical areas have an intrisic "back and forth" to them instead of being strictly up/down. But in some biomes, it IS up/down!
I'm also thinking of interpreting one biome like:
[01][02][03]
[04][05][06]
[07][08][09]
[10][11][12]
[13][14][15]
...but since this requires a restructruing of things, this is left in "feature creep" territory. Gotta see how this plays out with tokens/space first. The left/right current structure of doors is nicer for testing/playing than the top/bottom there too, or the way-too-short possible "short paths" that left/right would do in that setup.
You know ... reading ... pondering ... I think what you want is something like ROGUE. It's a popular type of adventure game where the maze changes each time.
I wrote some test code like this a few months back. Watch how it builds rooms and see if this will help you.
Notice how all rooms can be reached despite their random placement.
https://www.dropbox.com/s/whbhm6h5uukp9f8/Rogue%20Map%20Maker.zip?dl=0
The original rogue comes from 1980 on the Apple computer in a game called "Beneath Apple Manor" and the concept behind it is still quite popular even today.
Well, I'm pretty good at this sort of thing. What problems in your code are you having now ? Maybe I can help as this is directly my field of interest. Turn-based RPGs and adventure games.
It's mostly syntaxing. Coming from VB/C#/XNA/GML... I'm not sure if I'm doing LUA right here.
*"doorways" here is a table it's referring to above, that's ={1,6,11,5,10,15}
function makelevel(biome,scr1=0,scr2=0,scr3=0,scr4=0,scr5=0,scr6=0,scr7=0,scr8=0,scr9=0,scr10=0,scr11=0,scr12=0,scr13=0,scr14=0,scr15=0) --create sequence of 16 doors doorshuf={rnd(1,6),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5),rnd(1,5)} d=0 n=1 for n=1 to 15 do d+=doorshuf(n) add doorlist (return doorways,d) n+=1 next --each exit makes a short, --high-risk way, then a long --low-risk alternative for n=1 to 15 do stdoor=doorlist(n) endoor=doorlist(n+1) --vertical paths? vstep=(stdoor/5)-(endoor/5) if (vstep<0) vstep*=-1 --horizontal paths? hstep=(stdoor\5)-(endoor\5) if (hstep<0) hstep*=-1 --add values to paths for n=vstep to 0 do if (stdoor/5)<(endoor/5) then add ezpath "5" add hdpath "5" else add ezpath "-5" add hdpath "-5" vstep-=1 next for n=hstep to 0 do if (stdoor\5)<(endoor\5) then add ezpath "1" add hdpath "1" else add ezpath "-1" add hdpath "-1" hstep-=1 next add ezpath {"1","-1","5","-5"} --finish this next |
Still a WIP, but the idea is that "ezpath" and "hdpath" will be populated with an appropriate sequence of 1s, 5s, and inversions of them, so that it will always make an equation that connects "stdoor" to "endoor;" and then it just shuffles the order of them in the next step. Then it applies the values relative to "stdoor" to build the path... which then adds the perlin factors to the level table.
The result is a level layout that is a table; and then the table just builds the gameplay data. I'm also using way too many tokens here. Or maybe that's just me being overly cautious of token usage. (I'm at about 500 altogether, but that's counting plenty of other sections.) The extra line just makes the easy path "longer" than the hard path by adding one extra "move up/down/left/right" to the table...which would still give the same equation/solution!
"ezpath" and "hdpath" are tables containing a collection of pennies and nickels (+/- 1s and +/- 5s) that when added to "stdoor" will total "endoor." Without breaking the sides (conditional stuff there)
The step I'm working on now (??) Is to shuffle their order, then use them to "walk through" the map, adding level shape values to the level's "screen table."
I'm thinking I need to post my chaos maze. It sounds similar to what you are doing and may help. I'll do so once I finalize my pico notepad.
So... usually in C#/XNA, I'd be able to use a shuffle_array kind of function to shuffle the resulting ezlist/hdlist, but I'm not finding the LUA command for it...
Is there one, or do I need to make a function for it?
[Please log in to post a comment]