So, in between lunch breaks, I've made tiny-but-significant progress in my level generation code. It's part of a "bigger picture" thing, and meant to be useful across multiple projects; since I'm kind of digging into proc-gen core gaming. Even this little project is a proof-of-concept of a major undertaking, depending on if I can squish this into tokens available.
The idea here is to take a number of levels "LV" and make each one a 15-plus-one table - the first 15 being a kind of "perlin noise" function used to script "rooms" into the level, and the last being a control variable "BIOME" which influences the level's colors, themed elements, etc. I'm planning on coupling this with horizontal and vertical "targets" - ones to collect, ones to avoid, ones to attack, etc. Well, a "target" can be oriented both vertically and horizontally, and in varying speeds (more on this after my next WIP major chunk of code, "MAKETARGET()").
So MAKELEVEL(3) would generate 3 "output" tables:
LVL1={n1,n2...n15,biome}
LVL2={n1,n2...n15,biome}
LVL3={n1,n2...n15,biome}
...and then these tables will define the 5x3 screen map of each level.
I'll have to add "biome control" in later scripting, depending on the kind of game it generates, after the level generation. The "doorway" table definition occurs BEFORE it runs... for instance, it makes sense for a platformer to limit "doorways" to being {0,4,5,9,10,14}, where in top-down adventure or RPG games, it could be anywhere.
That said... still checking this for proper P8 syntax, and to see if it can be simplified. Being intermediate-level at best, I have the suspicion this can be streamlined a little bit still. Maybe even a lot.
function makelevel(lv or 15) if (lv>15) lv=15 winlevel=lv for lv>0, do "lvl"lv={} level={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,biome} -- create sequence of 16 doors -- we don't have to use them all 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)} ezpath={} hdpath={} d=0 n=1 for n=1 to lv do d+=doorshuf(n) add doorlist (return doorways,d) n+=1 end --each exit makes a short, --high-risk way, then a long --low-risk alternative for n=1 to lv 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 end 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 end end add ezpath {"1","-1","5","-5"} if (#hdpath<3) add hdpath{"1","-1"} --shuffle ezpath/hdpath order shuf(ezpath) shuf(hdpath) --read paths, edit level table local pos=stdoor for i=#hdpath,2,-1 do local step={ -1=(makelevel(pos)+=18,makelevel(pos-1)+=4,pos-=1), 1=(makelevel(pos)+=20,makelevel(pos+1)+=2,pos+=1), -5=(makelevel(pos)+=17,makelevel(pos-5)+=8,pos-=5), 5=(makelevel(pos)+=24,makelevel(pos+5)+=1,pos+=5)} end local pos=stdoor for i=#ezpath,2,-1 do local step={ -1=(makelevel(pos)+=2,makelevel(pos-1)+=4,pos-=1), 1=(makelevel(pos)+=4,makelevel(pos+1)+=2,pos+=1), -5=(makelevel(pos)+=1,makelevel(pos-5)+=8,pos-=5), 5=(makelevel(pos)+=8,makelevel(pos+5)+=1,pos+=5)} end --return generated results as a --list of "lvl1,lvl2" tables... return "lvl"lv{}=level{} end end |
I use a pretty standard LUA shuffle script there, too. And I hope the FOR/DO/LOCAL STEP{..} is effectively equal to a switch/select case statement, because this is where I needed that!
As for the high variables on HDPATH, I'm adding a 16-factor to the typical 4-directional perlin noise, to designate them as "hard path rooms," where harsher penalties for screwups can occur.
WIP P8 file available here: https://app.box.com/s/95hozscthimtty9wsw2febpyfpi0zlw7
Never mind on the "later" part.
function maketarget(obj,scr,x,y,xrange or 0,yrange or 0,speed or 0,loop or 0) --x/y position relative to map xpos=((scr\5)*16+x) ypos=((scr/5)*16+y) --set sine motions to control local xmove=2*sqrt(xrange)*speed local ymove=2*sqrt(yrange)*speed --reverse direction! if (xmove=xrange or xrange<0) xmove*=-1 if (ymove=yrange or yrange<0) ymove*=-1 --diagonals or curves if loop=1 then xmove=xrange elseif loop=-1 then xmove-=xrange end --place object on trajectory --and move accordingly! mset xpos ypos obj obj.x+=xmove obj.y+=ymove end |
[Please log in to post a comment]