GM:S 1.4 Procedural generation problem

Discussion in 'Programming' started by Bros Before Giraffes, Jul 17, 2016.

  1. Bros Before Giraffes

    Bros Before Giraffes Member

    Joined:
    Jun 24, 2016
    Posts:
    30
    This question is a bit complicated.
    Basically, I'm trying to make a game where you can explore a randomly generated galaxy, kind of like No Man's Sky, only in 2D and it's more turn based strategy instead of real-time.

    Currently, I have the game randomly place 200 star systems around a map.
    I'm storing the data for each system in an array so I can reference certain properties in other places.
    There are 5 variables for each system that define their name, position, and whether or not you have discovered them.
    Code:
    global.map_seed = random_get_seed();
    /*
    Systems Array 
    0 - System Name
    1 - x
    2 - y
    3 - visited
    4 - seen
    5 - System seed
    */
    //Generate Galaxy (place systems)
    for (i=0 ; i<200 ; i++)
        {
        global.systems[i,0]="System "+string(i);
        global.systems[i,1]=round(random_range(64,4096-64));
        global.systems[i,2]=round(random_range(64,4096-64));
        global.systems[i,3]=false;
        global.systems[i,4]=true;
        }
    
    The 6th variable is the random seed dedicated to the system. When I assign the seed to a system, it will load this seed and generate the same planets in that system every time you go there.
    Code:
    //Set System Generation Seeds
    for (i=0 ; i<200 ; i++)
        {
        randomize();
        global.systems[i,5]=random_get_seed();
        }
    
    random_set_seed(global.map_seed);
    
    All of that happens at the start of the game before anything else.

    After it generates the systems, another object places them in the room using this code:
    Code:
    //Place Systems
    for (i=0 ; i<200 ; i++)
        {
        sys = instance_create(global.systems[i,1],global.systems[i,2],obj_icon_system);
        sys.name=global.systems[i,0];
        sys.discovered=global.systems[i,3];
        sys.sys_id = i;
        sys.seen=global.systems[i,4];
        }
    
    Now, the map screen looks like this:
    [​IMG]
    That arrow represents your ship and you can move around by clicking.
    When you go to a system, it takes you to a different room where it generates the planets inside the system. Before taking you there, it sets a variable global.current_system to the variable sys_id of that system. This way, it will be able to find the correct random seed in the array global.systems.
    Here's the code I'm using to generate the planets. Right now I'm not really sure if I need to use another array for the planets, but whatever.
    Code:
    //Get system Seed
    random_set_seed(global.systems[global.current_system,5]);
    
    //set number of planets
    planet_num = choose(1,2,2,3,3,3,4,4);
    
    /*
    Planet Properties
    0 - Name
    1 - Type 0=terrestrial 1=gas giant
    2 - Landscape 0=forest 1=jungle 2=desert 3=ice 4=volcanic
    3 - radius
    */
    
    //Generate planets
    for (i=0 ; i<planet_num ; i++)
        {
        planets[i,0] = "Planet "+string(global.current_system)+string(i); //name
        planets[i,1] = choose(0,0); //type
        if (planets[i,1]==0) //landscape
        planets[i,2]=choose(0,1,2,3,4);
        planets[i,3]=112+(76*i);
        }
       
    //Place planets
    for (i=0 ; i<planet_num ; i++)
        {
        n = instance_create(obj_sun.x,obj_sun.y,obj_planet);
        n.radius=planets[i,3];
        n.orbit_speed=choose(0.05,0.1,0.12);
        n.dir=round(random(360));
        n.x+=lengthdir_x(n.radius,n.dir);
        n.y+=lengthdir_y(n.radius,n.dir);
        n.image_speed=0;
        //choose image
        if (planets[i,1]==0)
        n.image_index=planets[i,2];
        }
        
    It uses dir to basically pick a random rotation around the sun so the planets don't all spawn in a straight line.
    So after generating the planets, the room would look something like these:
    [​IMG]
    [​IMG]
    So each star system generates a different arrangement of planets, and if you leave one and come back it will generate the same planets it had before.

    Here's where my problem starts.
    Most of the time, it works exactly how I want it to. But sometimes it generates the same planets no matter which system I go to. What happens is I'll run the game, and it will generate everything as expected. After closing and running the game again, every system will generate the same arrangement of planets. After running and ending the game a few more times or clearing the asset compiler cache, it will go back to normal, but it never stays normal.
    Every time this happens it uses the same seed: 2147483648.

    I thought maybe the game was saving the same seed to the array global.systems in the beginning where it generates the system data, so I displayed a list of the seeds on the screen while the game was generating the same system over and over, but all the seeds were different like I expected.
    I also considered the possibility that the game thinks you're trying to go to the same system, so it continues to pick the same seed. But if that's the case, then why would it always pick 2147483648?.

    The most frustrating thing about this is that the game works as expected half the time and the other half it does not.

    So do any of you have any ideas on why this might be happening? I hope I was clear on everything and provided enough information.

    And feel free to constructively criticize my coding techniques. I don't call myself a good programmer and there are probably way simpler ways to do this!
     
  2. johnwo

    johnwo Member

    Joined:
    Jun 20, 2016
    Posts:
    239
    Like it says in the manual:
    ([I might have misunderstood the part above] If the the problem occurs ONLY when this seed is used, then I apoligize. If the seed is the ONLY seed that is used, then I refer to the documentation.)

    Have you tried creating an executable and checking if the results are consistent when using the exe?

    I get what you are trying to do, but I would strongly suggest that you just randomize, generate, then store and load the systems/map from an array or list accordingly.
    Saving/loading the map and systems within the map would get rid of the need to generate them each time you visit them, and it would ensure that the systems/map stays consistent, as the map_seed would be the only factor involved with the generation, and it would only be done once at the start of a new game.

    Cheers!
     
  3. Bros Before Giraffes

    Bros Before Giraffes Member

    Joined:
    Jun 24, 2016
    Posts:
    30
    Thanks for the reply!
    So I have it set up so the first seed that Game Maker uses is used to generate the map (global.map_seed). It's easier to test that way. But then it randomly picks a seed for each of the systems. The problem is that SOMETIMES it only uses that one seed to generate planets instead of the seed assigned to that system, and other times it works properly. So it might work properly when I run the game one time (the game will load the correct seed before generating the planets), but if I exit and restart it might only generate according to 2147483648 (it's always that seed), but it will still use the first seed to generate the map, which is 0 because I did not tell Game Maker to randomize(). What's strange to me is how this happens very inconsistently.

    Generating the planets and then storing them was actually the first thing I tried to do, but when I tried to run the game it instantly crashed with no error. I might have to store them in a .ini or something, but I'd like to figure out why this method isn't working before I rewrite a lot of code.
    I also just tried exporting and running the .exe but that didn't change anything.
     
  4. MasterGrey

    MasterGrey Guest

    You have some nice code there

    Im trying to see if i could try and combine it together with this script

    Code:
    galaxy_radius = 20000;
    num_arms = 6;
    num_stars = 2000;
    
    spiral_tightness = -4; //higher number = more tight, negative reverses direction of spiral
    
    //the nearest any 2 stars can be to each other
    //danger of infinite loop if this number is too high
    min_star_seperation = 5;
    
    //the maximum distance a star can be from its spiral arm
    max_star_displacement = 20;
    
    //how much stars bunch toward center of galaxy
    //lower numbers bunch toward edge, higher toward middle, 0.5 = no bunching
    bunching = 1;
    
    //how much stars bunch toward the spiral arm they are in
    //lower numbers bunch toward edge, higher toward middle, 0.5 = no bunching
    bunching_2 = 5.8;
    
    //no need to touch these
    arm_radial_spacing = 360 / num_arms;
    random_interval = power(galaxy_radius,1/bunching);
    random_interval_2 = power(max_star_displacement,1/bunching_2);
    
    randomize();
    var star_placed, arm, dist, dist2, angle, xx, yy, nearest_star;
    repeat (num_stars)
    {
        star_placed = false
        do
        {
            arm = irandom(num_arms-1);
            dist = power(random(random_interval),bunching);
            angle = (dist + dist) * spiral_tightness + arm * arm_radial_spacing;
          
            xx = random_range(-1,1);
            yy = random_range(-1,1);
            dist2 = power(random(random_interval_2),bunching_2) / point_distance(0,0,xx,yy);
      
            xx = x + lengthdir_x(dist,angle) + xx * dist2;
            yy = y + lengthdir_y(dist,angle) + yy * dist2;
            nearest_star = instance_nearest(xx,yy,object_star_universe_new1);
            if (instance_number(object_star_universe_new) == 0) or (point_distance(xx,yy,nearest_star.x,nearest_star.y) > min_star_seperation)
            {
                instance_create(xx,yy,object_star_universe_new1);
                star_placed = true;
            }
        }
        until (star_placed)
    }

    So what im trying to do is that everytime the player ship moves in the universe he has to discover stars and there will be speical names to them

    So what im trying to do here is that everytime you find a star and click on it it will generate the system and planets .


    If its fine with you can i please use this code...............................


    Plus its a galaxy generation code feel free to use it you only have to ask or so.................

    another plus any help would be nice again i think your on to something here but im trying to see if i could imply it to my own galaxy generation code.
     
    Last edited by a moderator: Mar 1, 2017
  5. Bros Before Giraffes

    Bros Before Giraffes Member

    Joined:
    Jun 24, 2016
    Posts:
    30
    Yeah it's probably a good idea to put it in scripts. I've since decided to basically start from scratch in GMS2 at a later time because basically my entire project is a mess. A lot of the code I used to draw menu screens is inconsistent and should be using scripts to draw similar elements. It was an ambitious project that I know I can do, but it needs more planning and organization. I planned on having turn based combat elements and all kinds of upgrades for your ship and stuff too. I'm working on other stuff now while also figuring out what is going to work for this game, what I need to replace, and what I need to scrap.

    Edit: Also yeah you can use the code. I'm probably going to rewrite it anyway
     
  6. MasterGrey

    MasterGrey Guest

    Do you know how i can add this together with my script because my script generates the galaxy but it dosent store it and it dosent have a name for the stars

    Im working on the planet random terrain but this is confuseing me if you could tell me how i can combine it together it will appreciated.

    my galaxy
    29qGMLZ13131.png
     
  7. Bros Before Giraffes

    Bros Before Giraffes Member

    Joined:
    Jun 24, 2016
    Posts:
    30
    I think you can have each solar system generate a new random seed from the seed used to generate the galaxy. Make sure to store the seed used to generate the galaxy so you can generate the same one again. For star names, you can use a name generator. That's what I planned on doing and there should be a few tutorials on youtube. Then for planet terrain I guess you can basically do the same thing, but one level down.
    Sorry I cant really help you out any more than that.
     
  8. flyingsaucerinvasion

    flyingsaucerinvasion Member

    Joined:
    Jun 20, 2016
    Posts:
    2,163
    Hey, is your gamemaker studio up to date? Because that number 2147483648 was encountered a lot by people when gamemaker used different levels of precision between getting and setting seeds. I believe it was fixed a while ago.
     
  9. Bros Before Giraffes

    Bros Before Giraffes Member

    Joined:
    Jun 24, 2016
    Posts:
    30
    This thread is actually old and I'm pretty sure I fixed the problem. But yeah I'm pretty sure im up to date on the stable version.
     
  10. MasterGrey

    MasterGrey Guest

    Hey Hows it going my man you saved me with that script my man.



    Plus i would love to see how i would implment this with flyingsaucers code he gave me

    Because it would be a random system when you left click with random planets.

    Also sorry for my spelling my good sirs.


    Another plus my galaxy dosent generate on a seed witch is a shame but because flying saucer made this code and im modifying it he would assist.





    But however your code is usefull in the systems area random star systems will be a breeze after i modify it hopefully to my liking.

    But because you only added 1 planet i might need to change it from other planets to just a single planet object.




    Plus i changed it to this

    Code:
    var i
    for (i=0 ; i<script_galaxy_generate();  i++)
        {
        global.systems[i,0]="System "+string(i);
        global.systems[i,1]=round(random_range(64,4096-64));
        global.systems[i,2]=round(random_range(64,4096-64));
        global.systems[i,3]=false;
        global.systems[i,4]=true;
        }
    Another progress report i think i found a way to do this thank you for the code your usefullness has came to a end kiddos goodbye AHAHAHAH.


    Maybe i was too fast to say this but i have a issue with the code it says varible not set before reading

    And this is for global.current_system


    I know what it means but i dont know what code to add to it this isnt my code so im ???????
     
    Last edited by a moderator: Mar 12, 2017

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