Page 2 of 2 FirstFirst 12
Results 11 to 20 of 20

Thread: Procedural world generation - ground and traps seems to not generating.

  1. #11
    [QUOTE=Darkhog;95451]@SilverWarrior: Yeah, I thought so about setting dimensions bu wasn't sure. Will change that bit of code. Also let's say I'd make 2d minecraft (which isn't something I want to do): Grass can only grow on ground, so it is unlikely I'll need to check for other ground tiles, especially in Super Heli Land where it is like 3-4 tiles max./QUOTE]

    Yes I understand that grass can only grow on land.
    But we are talking about gamemap data structure whic would be used in other parts of the game aswell and not only to determine if there should be gras there or not. Si it is good to plan aghead when designing this as you can save yoursel lots of troubles in future.


    And now for the reason why your perlin noise algorithm doesn't alows you to generate infinite maps.
    If you take a look at its initalization procedure you will see that it uses deafult random number generator algorithm which ships with FPC and this algorithmonly accepts one input parameter (seed number).
    If you want to make perlin noise generator which alows making infinite levels you need to integrate different kind of random number generator algorithm into it. This algorithm must be capable of accepting athleast two inputs (Seed number, Offset). As you may recal from one of my previous posts I did some serching for such algorithm in past but hadn't had much luck in finding it.

  2. #12
    PGDCE Developer Carver413's Avatar
    Join Date
    Jun 2010
    Location
    Spokane,WA,Usa
    Posts
    206
    [QUOTE=SilverWarior;95468]
    Quote Originally Posted by Darkhog View Post
    @SilverWarrior: Yeah, I thought so about setting dimensions bu wasn't sure. Will change that bit of code. Also let's say I'd make 2d minecraft (which isn't something I want to do): Grass can only grow on ground, so it is unlikely I'll need to check for other ground tiles, especially in Super Heli Land where it is like 3-4 tiles max./QUOTE]

    Yes I understand that grass can only grow on land.
    But we are talking about gamemap data structure whic would be used in other parts of the game aswell and not only to determine if there should be gras there or not. Si it is good to plan aghead when designing this as you can save yoursel lots of troubles in future.


    And now for the reason why your perlin noise algorithm doesn't alows you to generate infinite maps.
    If you take a look at its initalization procedure you will see that it uses deafult random number generator algorithm which ships with FPC and this algorithmonly accepts one input parameter (seed number).
    If you want to make perlin noise generator which alows making infinite levels you need to integrate different kind of random number generator algorithm into it. This algorithm must be capable of accepting athleast two inputs (Seed number, Offset). As you may recal from one of my previous posts I did some serching for such algorithm in past but hadn't had much luck in finding it.
    you only need to set the seed once. changing the seed will change everything and you will never get the chunks to match;
    Code:
    for y:=0 to height-1 do begin
      for x:=0 to width-1 do begin
        vNoise:=PerlinNoise2d(x+vOffsetX,y+vOffsetY,Persistence,Frequency,Octaves);// Noise is -1 to 1;
        vColor:=NoiseToColor(vNoise); //Clamp Color values to MinMax 0,255 because Noise isn't perfect.
        Map(x,y):=vColor; //do not use multi dementional arrays for bitmaps must be a single block of memory. 
      end;
    end;
    Perlin01.jpg

  3. #13
    Guess that infinite perlin noise should be calculated on the fly for given coordinates and seed rather than fill the predefined buffer with values (like in implementations i've came across)

  4. #14
    [QUOTE=Carver413;95470]
    Quote Originally Posted by SilverWarior View Post

    you only need to set the seed once. changing the seed will change everything and you will never get the chunks to match;
    Code:
    for y:=0 to height-1 do begin
      for x:=0 to width-1 do begin
        vNoise:=PerlinNoise2d(x+vOffsetX,y+vOffsetY,Persistence,Frequency,Octaves);// Noise is -1 to 1;
        vColor:=NoiseToColor(vNoise); //Clamp Color values to MinMax 0,255 because Noise isn't perfect.
        Map(x,y):=vColor; //do not use multi dementional arrays for bitmaps must be a single block of memory. 
      end;
    end;
    Seed is only set once, when creating TWorldGenerator class (which in Create makes TPerlinNoise object and destroys it in Destroy). So perlin itself matches with each other. Problem is that caves don't (_genStepCarving, I think).

    Quote Originally Posted by SilverWarrior
    you need to integrate different kind of random number generator algorithm into it. This algorithm must be capable of accepting athleast two inputs (Seed number, Offset).
    Can you point me to such algorithm?
    Last edited by Darkhog; 03-06-2013 at 06:39 AM.

  5. #15
    Quote Originally Posted by Darkhog View Post
    Can you point me to such algorithm?
    This should do the thing:
    Code:
    function Random2(const seed, offset: cardinal): double; overload;
    var oldSeed: cardinal;
    begin
      oldSeed:=randseed; // Save old seed
      randseed:=seed+offset; // Shouldn't need to check high(cardinal) ranges.
      // Overflowing should still do the math perfectly.
      result:=random();
      randseed:=oldSeed; // Restore it afterwards,
      // So that use of normal Random() outside of this function is not interrupted.
    end;
    
    function Random2(const n: cardinal; const seed, offset: cardinal): cardinal; overload;
    begin
      result:=trunc(Random2(seed, offset)*n);
    end;
    Edited second Random2() result type.
    Last edited by User137; 07-06-2013 at 07:56 PM.

  6. #16
    So this code:

    Code:
    Randseed:= 3;
    Num:=Random(30);
    Num:=Random(30);
    Num:=Random(30);
    will behave same as
    Code:
    Num:=Random2(30; 3, 2);
    right?

  7. #17
    No, Num:=Random2(30, 3, 2); behaves like:
    Code:
    oldSeed:=randseed
    randseed:=3+2;
    Num:=Random(30);
    randseed:=oldSeed;
    If you do
    Code:
    Num1:=Random2(30, 3, 0);
    Num2:=Random2(30, 3, 0);
    Then Num1 = Num2. But if you change offset
    Code:
    Num1:=Random2(30, 3, 0);
    Num2:=Random2(30, 3, 1);
    Then Num1 and Num2 will differ. But you can always replicate those numbers again with same parameters.
    Last edited by User137; 03-06-2013 at 11:51 AM.

  8. #18
    So why following program
    Code:
    program Project1;
    
    {$mode objfpc}{$H+}
    
    uses
      {$IFDEF UNIX}{$IFDEF UseCThreads}
      cthreads,
      {$ENDIF}{$ENDIF}
      Classes, Crt;
      { you can add units after this }
    var
      num:Integer;
      function Random2(const seed, offset: cardinal): double; overload;
      var oldSeed: cardinal;
      begin
        oldSeed:=randseed; // Save old seed
        randseed:=seed+offset; // Shouldn't need to check high(cardinal) ranges.
        // Overflowing should still do the math perfectly.
        result:=random();
        randseed:=oldSeed; // Restore it afterwards,
        // So that use of normal Random() outside of this function is not interrupted.
      end;
    
      function Random2(const n: cardinal; const seed, offset: cardinal): double; overload;
      begin
        result:=trunc(Random2(seed, offset)*n);
      end;
    begin
      RandSeed:=3;
      num:=Random(30);
      writeln(num);
      num:=Random(30);
      writeln(num);
      num:=Trunc(Random2(30,3,0));
      writeln(num);
      num:=Trunc(Random2(30,3,1));
      writeln(num);
      readkey;
    end.
    gives me this output:
    16
    2
    16
    29

    ?

    I need random function which will pass test, e.g. with offset of 1 it'll generate same value like second random.

  9. #19
    Anyway, I've made it working. Instead of putting circles at random, I've used worm algorithm (dunno if it is known one, I've made it on my own). Basically I'm carving map like worm passing through ground would do.

  10. #20
    Quote Originally Posted by Darkhog View Post
    So why following program
    ...
    gives me this output:
    16
    2
    16
    29
    There's only 1 explanation that comes to mind, that normal Random() uses other internal variables for the result, not just seed.

    I also changed the second function result to cardinal, only the first one was designed to return double. See that it uses Trunc in it, then you used it second time afterwards, which i didn't intend. But this doesn't change the outcome, such thing would seem to need a custom made random algorithm.

    edit: No, it's just seed but it can advance the randseed one or 2 times on one call
    Code:
    random := int64((qword(cardinal(genrand_MT19937)) or ((qword(cardinal(genrand_MT19937)) shl 32))) and $7fffffffffffffff);
    genrand_MT19937()-function is used twice in the sentence there. Seems to be well over 99.999% chance for it to call it twice, because chances for first genrand returning 0 is slim.
    Last edited by User137; 07-06-2013 at 08:11 PM.

Page 2 of 2 FirstFirst 12

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •