Infinite persistant world generation

Discussion in 'Advanced Programming Discussion' started by lolslayer, May 2, 2017.

  1. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    Video game worlds are getting big. But it can even be bigger.

    With random generation you can make incredibly big worlds. Randomly generating a world is really easy. You just need to put random objects at random locations and you're done.

    But there comes the problem.

    Computers can only handle a limited amount of objects. So if you want to go on "infinitely" finding new objects, you need to only generate the objects that are close to you, and get rid of the ones that fall behind.

    So what you of course want to do, is to generate new objects whenever you enter an area. As simple as that.

    But now we got another problem.

    If you go back to a place you visited before, and you randomly place objects, they of course don't share the same location as the objects did when you visited that place the first time.

    You can't fix this by saving all objects you generated before, and loading them in when you get in the area where they are present. Because the memory is limited aswell.



    For these problems we need to find a way to combine infinite generation, but every object being persistant in locations and properties when you generate them and every time you regenerate them.

    One simple solution I created was by dividing the world in equally-sized chuncks. Every chunck gets an unique number based on his location, because the location is the only property you can find out without storing any data of the chunck.
    When you generate the objects of one chunck, you'll set the random generation seed to the unique number of the chunck. This way every chunck will generate excactly the same content whenever you enter and re-enter it.

    The script I used create an unique number for every chunck based on it's location, goes like this:
    Code:
    ///position_to_seed(chunckx,chuncky);
    //creates a seed based on a position, every position gives an unique seed
    
    var cx = argument[0];
    var cy = argument[1];
    
    if (cx == 0 && cy == 0){
        return 0;
    }
    else{
        var maxc = max(abs(cx),abs(cy));
       
        var minseed = sqr((maxc-1)*2+1);
       
        if cy == maxc*-1{//top
            return (minseed + cx+maxc);
        }
        else{
            if cy == maxc{//bottom
                return (minseed + maxc*2+1 + (maxc*2-1)*2 + cx+maxc);
            }
            else{
                if cx == maxc*-1{//left side
                    return (minseed + maxc*2+1 + (cy+maxc-1)*2);
                }
                else{//right side
                    return (minseed + maxc*2+1 + (cy+maxc-1)*2 + 1);
                }
            }
        }
    }
    This script uses rounded numbers as input. They can be positive or negative.

    The way it calculates it seed is fairly abstract. But you can see the chuncks as having a middle chunck, and around that middle chunck there are an infinite amount of layers, as you can see in this picture (with the first 3 layers shown):
    layers generation.png
    Layer 0 is the middle chunck.

    I think the best way to explain the seed distribution, is by giving an example. In the example I include the middle chunck and the 2 layers of chuncks around it. The middle chunck has the seed 0:
    Code:
    09 10 11 12 13
    14 01 02 03 15
    16 04 00 05 17
    18 06 07 08 19
    20 21 22 23 24
    For every layer you get farther away from the middle, the bigger the seed number will get. The seed number will grow exponentially because every new layer contains more chuncks than the last.

    Of course, variables also have a limited lenght, so you can't get an infinite big number. But because of that the biggest seed numbers are at the most outer layers of chuncks, you won't surpass the maximum variable length soon.
    (My tests went as far as layer 1.000.000.000.000, and even when I reached that number the limit wasn't reached so you can bet that your worlds will be big with this system).



    There are a few things that are worth discussing with this topic:
    -How can you create an infinite room where you generate and destroy objects dynamically?
    -Can the system I've shown here be improved by making the chunck layers circular instead of rectangular (if that's a word)? And how can you implement such a system?
    -Is this system fast enough, or should it be optimized? (@Misu probably has something to say here)



    Here is an example project of my system in use, you can switch chuncks by pressing the up, down, left and right keys:
    http://www.mediafire.com/file/jam7vr1ta0a2qai/infinitite_persistant_generation.gmz
     
    Last edited: May 2, 2017
    Zerb Games, Wraithious and slojanko like this.
  2. Misu

    Misu The forum's immigrant

    Joined:
    Jun 20, 2016
    Posts:
    585
    Seems interesting. This is more of a generator than a chunk system TBH. I can tell that this script can make a good alternative for generating maps and static objects. Although the problem here is that no matter what you do, this script will return you the same generation results (when starting the game) no matter what. Its not bad for a game that aims to make a specific kind of map but its bad for those who want a different map during creation of a world. Unless you save a separate generation seed that will apply to the generation code within the script and save that seed in memory, then you could probably get different results for every time you start the game without each visited room changing.

    Also it runs fast just because it is generating every time once you enter a room. There is no real process going on after that. So it is fast as it is. The other main problem here is that this script cannot help you out on updating dynamic stuff or certain changes because its just a generator script for static entities. The only way to do that is by storing information of certain chunks into the system and read out from it whenever it is possible (an actual chunk system).

    Now, based upon my knowledge, you can actually achieve actual chunk system with buffers by having each buffer index represent a chunk and storing your value or entity within a linear data structure in it. After fully generating the chunk, you save it outside the game (externally) and only load it when you meet in close range to such boundary (indicated on filename).


    Your aim seems more on generating a huge space at once. In reality, that would cost lot of loading time when it comes to updating in realtime. Of course, updatting a 1000x1000 (at least) size world map will possibly crash your game or take some time to load before making the next drawing update. That is why I use buffers so the best way is to generate them by smaller fragments (chunk by chunk) as you move along since buffers is fast enough to go through all that without noticing any lag or problem.


    In Minecraft for example generates new smaller chunks as it moves along the world map. What made this possible is that the game saves group of chunks into one external file. The filenames are specified as “r.n1.n2” where n1 is the x index of the chunk and n2 is the y index of the chunk (similar to 2D arrays). The game loads up a chunk base upon a position in the world map. Reading the name of the file, it picks up the position of the chunk in the world map base on that.


    Example:

    Lets say the chunk size in 2D is 32x32…

    r.-1.-1 = this would mean location [-32,-32]

    r.3.-2 = this would be [96,-64].


    Well just note that Minecraft chunks are 16x16x256 and each file has more than one chunk.


    Anyway, the game only uses the chunks that are visible in range and whenever there is a chunk out of view, it deletes the buffer and loads up the new one that is in range. This avoids having too much memory used in-game. Just take in note that the memory will increase externally as files. This allows to bypass the limit on world size but it depends on hardware’s memory. You can actually generate 4 million pixel size with this (possibly way more).

    This is all relied on memory usage, you need to manage that properly.

    When it comes to 2D, this would work perfectly since it relies only on x and y coordinates (unless you doing something experimental and use an additional depth value) so it should run super fast.
     
    Last edited: May 2, 2017
  3. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    Yeah you're right, the system I gave as an example is only used for static objects. Every change will not be saved.

    But if we combine the system I explained with your theory of chuncks, you can make the game dynamic aswell.

    What you can do for example, is for every change that happens in a chunck, you save it in a file (Like in the way that minecraft does where the name explains the chunck location). Whenever you get in a chunck, you first generate it using my system. After doing that you check if there is a file about that chunck in existance, when that's the case, it will load that file in and read what changes you made in the past to that chunck.

    This way you can save a lot of data because most of the world is still generted and nowhere saved, but the world is still dynamic.



    Another problem you mentioned about only being able to generate one map is indeed a problem. I was thinking about one giant universe you could explore when I thought up my system, you didn't need other worlds there. I should give it a look once, if I can make a double-seed system.
     
  4. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    756
    One of the factors here that is really interesting to me is that hypothetically, this system results in every possible seed being used. That means that every countably infinite possible room will be created. If you imagine shifting the seed used by a randomized offset, then all you really did is offset where the player spawns in the world. It's like the library of babal sort of, except is procedurally generated, not totally random, so it's even cooler.

    So if you use a double-seed system, it has to work in a way that basically randomizes the order that the rooms are placed, not just which seed is used. Since you still need to keep track of all of the seeds used for each chunk it's sort of more difficult to randomize the order, since it needs to be known before-hand in order to create the chunks in the first place. I suppose you'd do it the same way you did with each chunk separately: save the seed itself and then regenerate the order of the chunks each time you started the game itself.

    Another possibility I was considering, possibly combined with the one above, would be to randomize the generation script itself. For example, if you wrote 5 different scripts that could potential generate a world and then randomized which one was used by the global seed, then you could have more variations of rooms. A variation of this that would not require different scripts would be to randomly adjust each chance used. Like, if there was a 1/50 chance for a tree to spawn, that could be randomly adjusted by the global seed to be anywhere from 45 to 65 for each room. That would make sure that each world spawned would be extremely generate, and increase the variation from room to room, because the chances of certain things happening is actually changed.

    ---

    As for an infinite room, I can imagine it's possible to create a room the size of 3 chunks and then when the player moved towards on at the top, everything in the room slides down to create space for a new chunk at the top and the chunk at the bottom is removed. It'd be hard to make it seamless, but not impossible. The other possibility of course, is to not bother, and just separate everything into multiple rooms. This probably would be fine if the loading time is pretty small.

    ---

    Finally, I was thinking about the storage issue. Because, as was mentioned before, the final limit of this system is that eventually it runs out of memory to store the saved chunk information, no matter how compressed and efficient it is. It would probably be possible to store the chunk information on a server, that could have much more memory than the computer playing the game. Obviously expensive and inefficient though. However, this led me to think about using this concept instead for an MMO game of sorts, sort of like No Man's Sky, and use one server to store a nearly infinite universe to explore.
     
    SnotWaffle Studios likes this.
  5. Misu

    Misu The forum's immigrant

    Joined:
    Jun 20, 2016
    Posts:
    585
    Dude, that only applies when using the RAM to store memory. My idea was basically storing it "externally" as a separate outside resource. Same technique that Minecraft uses and Minecraft can generate a world size bigger than 2 billion voxels (possibly way more). This relies on a saved memory not putting them to use in RAM except very few of them. As you update the system, it changes memory by freeing the ones that are out of range and adding the new ones in range. This keeps a steady, stabilize RAM usage which is good. In fact, let me provide explaination.

    Basically you create a buffer and bake up a premade chunks at start with some values in them (can range from 0 to 65535 or more but that depends on how you want it to be)

    Code:
    ////THIS JUST AN EXPLANATORY EXAMPLE!
    var xx = 0;
    var yy = 0;
    var zz = 0;
    var ww = 16; //x size of chunk
    var hh = 16; //y size of chunk
    var dd = 256 //z size of chunk (yes, this is an example with 3D but same principle applies to 2D)
    global.CHUNK[0,0] = buffer_create(ww*hh*dd,buffer_fixed,4)
    
    repeat(dd)
    {
     repeat(hh)
     {
      repeat(ww)
      {
       var ii = ((yy*ww)+(xx mod ww))+(zz*(ww*hh));
       buffer_seek(global.CHUNK[0,0],buffer_seek_start,ii);
       buffer_write(global.CHUNK[0,0],buffer_u32,value);
       chunk_spawn(0,0,xx,yy,value);//depending on value result, spawn something to world map
       xx++
      }
      xx=0; yy++
     }
     yy=0; zz++
    }
    NOTE: This explains how to load them by iterating both x and y coordinates. Its possible to apply generations base upon within relative position only. I just prefer it this way, not sure why though.

    Now for an updater, you want to recursively apply a new chunk around the player's boundary and store them into a 2D array that specifies the x and y index of the player's close boundary for loading chunks. You can understand what I mean with explanatory image below:

    [​IMG]

    Each spawn represents a chunk loaded around the player. Of course, in 2D we want them to be visible within the room. well you can adjust that by indicating the cell size you want and how many cells to scatter around the player. Now for this entire group of chunks, you want to verify if the chunks are fully loaded and if so, set two type of variables that check for the width and height of the boundary, equivalent to its number of pixel spaces of every chunk size needed.

    After that we move can check on the system to update for whenever a character move into a new sector or if the chunks have move from one boundary position to another...

    Code:
    ///This is to update chunks but this code block is a small fragment my actual code.
    ///This time im using an example for 2D
    var xc = 5; //amount of chunks around player's position in x axis
    var yc = 5; //amount of chunks around player's position in y axis
    var wc = 256;//each chunk width
    var hc =  256;//each chunk height
    var dx = 1; //this is to divide the generation process into 1 fragment to only load a few to then load more on the next step
    var dy = 1; //same above; you can actually change this to any number to divide your chunks properly.
    
    if (floor(x/wc)!=global.CHUNK_C1)||(floor(y/hc)!=global.CHUNK_C2)//check to see if any chunks have moved to new position
    {
       var xx = 0;
       var yy = 0;
       repeat(yc)
       {
        repeat(xc)
        {
         chunk_free(global.CHUNK[xx,yy]) /// typically its buffer_delete :P
        var xn = floor( x/wc )+(xx-floor(xc/2));
         var yn = floor( y/hc )+(yy-floor(yc/2));
        if file_exists(working_directory+"r_"+string(xn)+"_"+string(yn)+".misu") ///load chunks that already exist outside the games memory
         {global.CHUNK[xx,yy]=chunk_load(working_directory+"r_"+string(xn)+"_"+string(yn)+".misu");}//this is basically buffer_load in case you wonder :P
        else
        {
         /// generate new chunks
         global.INCOMPLETE = 1;///entire group in general has incomplete chunks
         global.INC[xx,yy] = 1; ///chunk index that is incomplete
         if (wc<=dx)&&(hc<=dy) {global.INCOMPLETE=0; global.INC[xx,yy]=0}
         global.CHUNK[xx,yy] = chunk_generate(wc/dx,hc/dy,1,value);//Script is basically the same you use to generate premade chunks at start (see previous code)
         chunk_save(global.CHUNK[xx,yy],working_directory+"r_"+string(xn)+"_"+string(yn)+".misu");//typically its buffer_save :P
        }
         xx++
        }
       xx=0
       yy++
       }
      global.CHUNK_C1=floor(x/wc);
      global.CHUNK_C2=floor(y/hc);
    }
    
    This would update everything within the boundary of the player. It runs fast and smooth. This is just a blueprint idea I provided. My actual scripts are more complex than this.

    That is true. Servers can pack up large memories compared to your average computer but its lot of budget on your wallet that will fly out the window. Plus your game will need to rely on being online always ( this is a down side for offline modes).
     
    Cloaked Games likes this.
  6. Cloaked Games

    Cloaked Games Member

    Joined:
    Jul 4, 2016
    Posts:
    756
    Oh yes, that makes sense. Thanks for the explanation. To clarify though, I did know you were talking about storing them externally, but it appears that the storage limits are not a huge concern in this situation.

    Yeah, a server would be very expensive and requires online mode (something I really dislike personally). Although you could probably allow offline and online play as separate options.

    Either way, that is why I started thinking about its use for an MMO game instead. With infinite world generation, if it's interesting terrain, you could store a massive universe on some server players connected to. They could basically explore forever. If you had systems for procedurally generating new enemies, new items, new dungeons or whatever. But at this point we just made no man's sky, and this one is only 2D.
     
  7. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    I don't have much time to write a big well thought answer to both of you right now (Still studying for my finals :p), but I have one idea to make up for the fact that you can't generate different worlds each time.

    What you can do, is changing your spawning position. Atm Always spawn in the middle of the map, but because it is so gigantic, you could for example choose a chunck that's between x&y in a range of -1.000.000.000 and 1.000.000.000

    Even if you generate so far away from the middle of the map, you still have a lot to explore in all directions. To put it into perspective, you aren't even at 1% of how far you can get to the world border.

    Of course, if you're unlucky you could spawn at a place that is close to your last, but most of the times this would work well enough.

    Just a fun little visualization, everything that's white is the place that you can spawn in if you spawn in a range of -1.000.000.000 and 1.000.000.000, and everything that's black is so far I know the surrounding space where you can't spawn. (Can you see that little white spot? :p)
    visualization of world map.png
     
    Last edited: May 4, 2017
    Cloaked Games likes this.
  8. Wraithious

    Wraithious Member

    Joined:
    Jun 24, 2016
    Posts:
    1,166
    Hi, very interesting topic! I have an idea that might help with going back to previous "rooms" that were generated and saving the states of the objects and/or conditions present in the previous rooms upon leaving them, without technically saving anything extra to memory, my idea is this, as you said, each chunck has a unique number assigned to it when it is created, so let's take this number and make it a string instead of a number, then append to the beginning of it a string of numbers describing the states of anything that might be in the room, you'd only have to append a string of numbers equal to the number of conditions you allow in the game to append (propend? is that a more accurate term for placing something before the original string?). in any case you would want them first so you can easily find the room identifier number (it will always be at the same position in the string) . So what I mean by all that is, say in your game you have 4 possibilities that can happen such as: you can meet an npc and have a conversation with it, you can open a treasure, you can solve a puzzle, and there can be doors that are locked or unlocked. so what you would do is add 4 numbers before the room identifier number to save the states and so room 1's id would start off as "00000". The numbers after position 4 in the string identifying the room will be parsed upon returning to the room and will never be changed, but the first 4 numbers in the string you will change each time you leave that same room, and upon re entering the room you will parse the first 4 numbers to identify the state of gameplay for that room. For example if there's no npc generated or the player didnt talk to it the first number stays 0, if there is an npc there and the player talked to it the first number is 1, if the player completed the conversation to it or completed a request from it the first number is 2 etc.. if no treasure 2nd number is 0, treasure locked 2nd number is 1, treasure has been opened 2nd number is 2 etc.. same setup for the next 2 things that could have happened.
    Hopefully this idea can help with that part of the infinite problem
     
  9. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    Well, I'm not sure how to save it without extra memory.

    The thing is, with the system I've shown, none of the numbers are saved anywhere, but they can't be changed aswell.

    For your system you need to save the change in numbers, if you want to use it again when getting back to the room.

    It is a system that uses small amounts of memory though to save changes, but you still need to save it somewhere.

    Correct me if I'm wrong though.
     
    Wraithious likes this.
  10. Wraithious

    Wraithious Member

    Joined:
    Jun 24, 2016
    Posts:
    1,166
    I see what you mean, I was thinking the room number was being saved somewhere, and didnt realize the way it's set up that it cant be changed. It could be possible to save them to a text file and reference it through the non changing room id and when the text file's size limit is reached it could make another text file, but as mentioned that would get huge on the users computer with, for example, just one galaxy full of stars.
     
  11. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    That system could work.

    But another system that's possible is by giving every chunck an unique file to save the changes in when a change is made. The problem with one single file storing all the information of the changes is that you need to load information in that you don't need at the moment.
    But one thing that is better with one big file is that you use less data. Files on the computer Always need to store at least a certain amount of data, if only little changes are made, the data stored is so small that the file size is enlarged to fit that minimum amount of data. If you get this with a lot of files, you store a lot of unused data.
    If you use global files storing data, you'll have this problem a lot less or even not at all.

    So it definitely is something to research.
     
    Wraithious likes this.
  12. Wraithious

    Wraithious Member

    Joined:
    Jun 24, 2016
    Posts:
    1,166
    yes definitely and I think maybe a solution is like you said have one big file, (that could turn into more files if the max file size is reached) and since you know what room you are trying to check (and what file if there's more than 1) you won't have to use file_text_readln to get all the way down to the line you need and can just access it directly with one shot

    But i dont know if theres a way to bypass file_text_readln? If you could just do file_text_readln(room_number) that would be awesome but i don't know if thats possible
     
    Last edited: May 11, 2017
  13. renex

    renex Member

    Joined:
    Jun 23, 2016
    Posts:
    506
    One time i experimented with a chunk system. But the limit in coordinates creates the problem that eventually you run out of space and your world generator overflows. A solution i thought about for that was to have recursive chunking - regions of the map would be made of chunks, and each region was also a chunk in itself. This way you can adjust the seeds for your noise generator to avoid repetition and also have true infinite worlds, just add more chunk layers until the player virtually can't ever reach the edges.

    Here's an illustration:

    upload_2017-5-11_15-19-34.png

    Another thing that is specially useful in world generation like this is perlin noise, since it's consistent across chunks, so your chunk edges can match. I haven't ever implemented an engine like this but i experimented extensively with perlin noise for realtime texture generation. You can also write a shader to render the noise - pulling data from a surface is probably way faster than generating it in gml.

    I believe chunks are the way to go since they're extremely convenient.

    As for saving, buffer files definitely. If your chunks are small enough, you can discriminate between altered and pristine chunks (a chunk whose contents were never changed by the player) and only save the changed chunks. The unaltered chunks can simply be regenerated upon reentry. This saves a lot of storage space.

    I've played around with world generation quite a few times but unfortunately i lost some of my old studio 1.2 project files in a hard drive crash so i don't have any examples of my techniques. I also used a different method for quickly generating walking surfaces using simple sum of sine waves, and it's pretty good for side scrolling games like runners and physics racers.
     
  14. Strawbry_jam

    Strawbry_jam Member

    Joined:
    Jun 20, 2016
    Posts:
    217
    The biggest limitation would be the dynamic features - saving changes. While saving these changes in chunks will be near infinite, storage space is still limited. One way around this could be factoring in time. It really depends on what the dynamic features are but say for instance a town burned down. Over a set amount of time, the changes could transition back to being unchanged from the initial random generation. At first the building are destroyed, then they are slowly being rebuilt, then they are back to normal. The chunk for this part can be deleted at that point. Same with simply talking to an npc. Over time, if you haven't talked to them in awhile, they could forget they talked to you. Or treasure chests could be filled once more.

    Another thing about factoring in time, the random generation could use this to cause a town to be burned down when generated.
     
  15. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    Sorry for not answering in a long time, I was busy with exams and after it was finished I forgot about it :')

    Today I'm busy too, but when I have some more time on hands I'll give a proper respond to all
     
  16. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,164
    A popular pattern for chunk indexing is the Hilbert Spiral.
    It keeps groups of chunks with close indices, but still results in smaller indices closer to the origin.
    This improves average cache performances, without ending up with massive indexes close to the origin.

    If your world is then truely massive, you can store those chunks in pages on disk, and use a Btree as a parse index.
    This of course is way overkill for a simple video game.
    You could simply go with a linear parse index, and paging.

    The advantage of using a single value index over using pairs of numbers (x and y) is that its is always going to be easily sortable, making your lookup that much faster.
    The advantage of pages is that you can load entire pages at once, and keep them in memory for a while: with a pattern like the hilbert spiral, it is likely that the next loaded chunk will be on the same page.
    Remember the slowest part of this operation is loading data from disk, So its well worth minimising the number of disk operations you do.
     
    Morne and renex like this.
  17. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    I still don't have much time on hand, but somebody named Kit made another script that's interesting to use and it uses way less code, it looks like this:
    Code:
    var cx = argument[0];
    var cy  argument[0];
    
    var ring=max(abs(cx),abs(cy));
    var degrees=point_direction(0,0,cx,cy)%360;
    
    return max(0,round((8*(ring-1))+(8*ring)-(8*ring)*(degrees/360)));
    I modified it to work with gamemaker but I didn't test it yet, if it doesn't work, please tell me, if you need to find out quick what doesn't work about it, here is the code he sent me:
    Code:
    def pos_id(x,y):
        import math
        ring=max(abs(x),abs(y))
        degrees=math.degrees(math.atan2(x,y))%360
        return max(0,int(round((8*(ring-1))+(8*ring)-(8*ring)*(degrees/360))))
    The seed distribution looks like this:
    Code:
    TEST POS_ID
    ###  -05-04-03-02-01+00+01+02+03+04+05
          |  |  |  |  |  |  |  |  |  |  |
    -05 __47 48 49 50 51 52 53 54 55 56 57
    -04 __46 36 37 38 39 40 41 42 43 44 58
    -03 __45 35 25 26 27 28 29 30 31 45 59
    -02 __44 34 24 14 15 16 17 18 32 46 60
    -01 __43 33 23 13 03 04 05 19 33 47 61
    +00 __42 32 22 12 02 00 06 20 34 48 62
    +01 __41 31 21 11 01 08 07 21 35 49 63
    +02 __40 30 20 10 09 24 23 22 36 50 64
    +03 __39 29 19 18 17 40 39 38 37 51 65
    +04 __38 28 27 26 25 56 55 54 53 52 66
    +05 __37 36 35 34 33 72 71 70 69 68 67
     
    Wraithious and renex like this.
  18. Wraithious

    Wraithious Member

    Joined:
    Jun 24, 2016
    Posts:
    1,166
    I made a quick setup to test it, this is what I came up with
    Script matrixMap:
    Code:
    var cx = argument0;
    var cy = argument1;
    var ring=max(abs(cx),abs(cy));
    var degrees=point_direction(0,0,cx,cy)%360;
    return max(0,round((8*(ring-1))+(8*ring)-(8*ring)*(degrees/360)));
    press space:
    Code:
    //vars a,b declared in create event, for drawing text
    a = round(random(200))-round(random(200));
    b = round(random(200))-round(random(200));
    getpos=matrixMap(a,b);
    Draw:
    Code:
    draw_set_color(c_yellow);
    draw_text(200,200,"X,Y: "+string(a)+","+string(b));
    draw_set_color(c_white);
    draw_text(200,214,"#Result- "+string(getpos));
     
  19. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    Did it work? :)
     
    Wraithious likes this.
  20. Wraithious

    Wraithious Member

    Joined:
    Jun 24, 2016
    Posts:
    1,166
    Yes it does, with - or + values it outputs a single + value from the inputted x and y values, which of course can be fed to it when leaving a chunk, or area in a room thus providing a 'chunk id' so to speak, or whatever you want to do with it, For testing purposes I just set up a random x and y input that could have - and + value possibilities. I learned something tho, I didn't know you could use the % symbol as a math operator in gml, but the code works so I guess you can!
     
    Kuro likes this.
  21. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    Nice :)

    And yeah, the % is the modulus, you should look it up if you don't know yet what it does ;)
     
  22. Wraithious

    Wraithious Member

    Joined:
    Jun 24, 2016
    Posts:
    1,166
    ahh I didn't know that, I'v allways used if variable mod some_integer = some_integer { do stuff }
     
  23. lolslayer

    lolslayer Member

    Joined:
    Jun 23, 2016
    Posts:
    642
    The more you know :p
     
    Kuro and Wraithious like this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice