Can't get pseudo random to work with tilemap generation

I have tried long and hard at this, but just can’t seem to get anywhere.

I’m trying to make my 2d top-down background tilemap randomized either 1 - on. or 0 - off. 16 times across and 8 times down in a grid. Each tile based on its x and y position + the camera offset is input into the randomSeed() function.
However no matter how I set it up i can never get random values. Its either all repeating patterns or not random at all.

void draw_background(){
  for (int by=0; by<64; by+=8){
    for (int bx=0; bx<128; bx+=8){
      seed = ceil(camx / 8) + ((bx + by) / 8);

      if (random() % 2 > 0){
        Sprites::drawOverwrite(bx - (camx % 8), by - (camy % 8), Images::background, 0);

I appreciate if anybody could either help, or point me in the direction of some useful reference.

You should only be setting randomSeed once in the program or when you need to explicitly reset the random sequence to a known pattern. Each subsequent call to random() will give a new random value that should be poorly correlated with the previous one.


right, but then how would I make sure each tile in the grid always has the same value. Im only drawing the tiles in the camera view. and the camera can move indefinitely.

so tile x1, y1 always = r0; but if my camera move x+1; now x0, y1 should = r0. and x1,y1 should = r1;
“r” meaning known random value.

but if x1, y1 is off my screen. I don’t render it at all. So I would need to skip that iteration if i just used a random() sequence. ( at least how I understand it).

ah! You’re wanting to use a PRNG as the data source and have the same x,y always produce the same value. What you really want here is a good hash function, not a PRNG. There’s some useful pointers at c - What integer hash function are good that accepts an integer hash key? - Stack Overflow. You probably want to first make a larger number from the X and Y and salt values, then hash that with sampling of one of the inner bits.

1 Like

You can use an LFSR (Linear Feedback Shift Register) to get a pseudo random numbers.

Here’s an example from some unfinished game of mine:

uint16_t rnd; // global var

uint8_t getRandom(uint8_t min, uint8_t max)
  uint16_t r = rnd /* ^ TCNT0 */; //uncomment for some extra randomness
  (r & 1) ? r = (r >> 1) ^ 0xB400 : r >>= 1;
  rnd = r;
  return r % (max - min) + min;

It returns a minimum value of min and a maximum value of max-1

in your draw_background function replace


rnd = seed;

but put it at the beginning of the function outside the for loops.
also replace


if (getRandom(0,2)) {

Note. Make sure rnd is not set to 0 or else it only produces 0s

1 Like

That code looks super familiar.

1 Like

It would be helpful if you told us more about the actual reasoning behind why you want to do this/what effect you’re trying to achieve to avoid the XY problem.

It sounds like what you really want is to have some kind of procedurally generated map or pattern, but we don’t really know enough to be able to suggest something that’ll actually be useful for what you want.

You’re asking us about rendering a map, but I suspect what you actually want is to be able to generate the map, not merely to render it.

If, however, you’re only generating a background pattern and it’s only decoration, then you might find something like this useful:

Right. I suppose I’m more asking about generating a map. But because it’s infinite I can’t generate the whole thing.
So because I render everything I have generated I guess it’s combined. Altho maybe there is a better way of doing that instead.
I could generate chunks but I’d still need to generate them the same way.
As of right now it’s purely decoration, but the plan was to use the same method for generating trees and stuff.

Basically a top down version of Minecraft.

Damn, this forum has more connection to Minecraft than I’d ever thought.

If you’re expecting the player to be able to modify the map you’re going to struggle because the Arduboy has a very small amount of RAM (over 1,048,576 times less than your average desktop/laptop/smartphone) so there’s a limit to the number of modifications you can track. You’ll likely only be able to save a very small number of modifications, so the map will be constantly resetting itself to its original state.

Theoretically you could save off-screen chunks onto the FX chip if you’re writing this for the Arduboy FX, but that’s easier said than done.

If you don’t need the player to modify the map then life gets a heck of a lot easier, depending on what your other limitations are (e.g. whether the player should be able to interact with the map, e.g. colliding with trees and the like).

Infinite without repetition is going to be effectively impossible on the Arduboy because of its constraints.

Depending on your other constraints you can likely manage ‘large enough that nobody will notice that the map repeats’, but not ‘truly infinite without repetition’.

Depending on what kind of pattern you’re expecting/hoping for that’s also easier said than done.

One thing to note here is that you likely don’t want true/pure randomness. If you’re attempting to create a world then you probably want some kind of pattern because natural terrain does form patterns (e.g. rivers, height levels, trees growing in clusters).

With some good use of algorithms you can likely take a hash function as input and produce some convincing infinite terrain without too much CPU strain or memory usage, which would be fine if you’re happy for the terrain to be read-only, but needing to modify it would be an issue.

Some other code examples that may be of interest…

Generation of terrain using ‘noise’ and turbulance:

(A result of this old thread, particularly the culmination of the work here. You may want to skim that, particularly the parts about hash functions.)

Generation of a pseudo-infinite background:

(A result of this old thread.)

1 Like