1
\$\begingroup\$

I am a novice programmer.

In my program, I can render a 5000 x 500 map, but it renders incorrectly, instead of this :

,,~,,,,~,,,,,~,~,,,,,~~,,,~,,,~,,,~,,~~~,~~~,,,~,,,,~,~,,,~~,~,,~,~,~~,~,,,,,~,,~~,,~,,,,,,~,,,,,~,,~~,~,,,,,,,~,,,,~,~~,,,~,,,~,~~~,,~~~,,,,,,,,~,~~,,,,,~,,,,,~~,,,~,,~~,~~~,,,~,,~,~,,~,,,~~,~~,~,,~~~~~,~,,,,,~,~,~,~,,,,~~,,~,,,,,~,,,~,,~,,~,,,,~~,,,~,,,,,,,~,~,,,,,~,,,,~,~~,~,,,,,,,~,~~,,,,,~~,,,,,,~,~~~~,,~,,~,,,,~~,,,,~~,~~~,,~,~,,~~~~,,,~,,~,,,,~~,~,,,,,,,,,,,~,,~~,,~,~,~,,,,~~,,,,,,,,,~,,,~,,,,~~~,,,~,,~,,,,,~,,~,~~,,~~,,,,~,,~,,,,,,,,,,,,~~,,,,,,,,~,,~~,,,,~,,,~,,,,~,,,,~,,,,,,~,,,,,,~,~,,,,,,,~,,~~~,~~~~,,~~,~,~,~,,,~,~,,~,~~,~,,,,,,~,~,~,,,,~,,,~,,~,,~,,,,,~~~~,,,,,~,,,~~,,,~,,,,~~,~,~~,~,~~,~,~,~~~~,,,~,,,,,,~,,,,,,,~,,,,,~~,~~~,,~~,~~,~,,~,,~~~,,,,,,~~,~,~,,,,~,,,,,,,,,,~~,,,,~,,~,,~~,,,~,,,,~,~,,~,~,,,~~~~,~,,,,,,~~~,,~,,~~~,~~~,~,,~,,,~,,,,,,~~,,,,~,,,~~~,,~,~,,,,~~,~,,,,,,~,~,,~~~,,~~,,,~,,,,~,,~,~,,,,,,,,,~~,,,,,,~~,~~,,,~~~,,~,~,~,,,~~,,~,,,,,,,,,~,~,,~,,,,,,,~,,~,,~~~,~~,~,,,,~,~,,,,,,~,,,~,,,,,,,,,~,,~~~~,,,~~,,~,~,,~,,,,,,~~~~~~,,,~,,,,,~,,,,,,~,~,,,~~~,~,,~,~,,,,,,~,~,~,,,,,,~,,,~~,~,,,,,~~,~,~,,~,~~,,~,,,~,,,~~~,,,,,~,,~,~,,,~,~,,~~~~~~,,,,~,,,,,,,,,~,,,~,~~,,,,,,,,~,~~,,,,,~,,~~,,~,~~,,,,,~,,,~,,~~,~,,~,,,,,,,,,~~,~~,~,,,~,,~~,~~,,,~~,,~~~~,,,,,,,,~,,,,,~,~,,

which was generated using a random coin flip

it renders the tiles in weird lines like this:

~.~.~.~.
~.~.~.~.
~.~.~.~.

Here is the link to the source code

Here is the rendering code:

    // Tile Renderer. 

    let screen_w_in_tiles: f32 = ceilf(screen_width() / 32.0);
    let screen_h_in_tiles: f32 = ceilf(screen_height() / 32.0);

    let center_tile_x = ((screen_width() / 2.0) - worldx as f32) / 32.0;
    let center_tile_y = ((screen_height() / 2.0) - worldy as f32) / 32.0;

    let lo_tile_x = floorf(center_tile_x - screen_w_in_tiles / 2.0); 
    let hi_tile_x = floorf(center_tile_x + screen_w_in_tiles / 2.0 + 2.0); 

    let lo_tile_y = ceilf(center_tile_y - screen_h_in_tiles / 2.0 - 2.0); 
    let hi_tile_y = ceilf(center_tile_y + screen_h_in_tiles / 2.0); 

    for i in lo_tile_x as usize..hi_tile_x as usize {
        for j in lo_tile_y as usize..hi_tile_y as usize {
            match world_data[i] {
                ','=> tile = grass,
                '*'=> tile = sand,
                '~'=> tile = water,
                '/'=> tile = ice,
                _=>   tile = unknown,
            }
            blit(tile, i as isize * 32 + worldx, j as isize * 32 + worldy, 32, 32);
        }
    }
\$\endgroup\$
5
  • \$\begingroup\$ It looks about right to me. I don't know where in the data that is… But you generated alternating grass and water, and you are using the x axis to query over that data. So the y does not matter. The result is columns. What output did you expect or want? \$\endgroup\$
    – Theraot
    Commented Mar 5, 2022 at 18:52
  • \$\begingroup\$ An output more like this: ~,,,~~~,,,,,~~~~~,,,,,~~~~~~~~~~~,,,,,,,,,,,,,,,,,,,,,, \$\endgroup\$ Commented Mar 5, 2022 at 18:53
  • \$\begingroup\$ The output i want is what it looks like from the saved data(i am using .bin files, if that helps) \$\endgroup\$ Commented Mar 5, 2022 at 18:53
  • \$\begingroup\$ Hang on. let me show you the output from the file \$\endgroup\$ Commented Mar 5, 2022 at 18:55
  • \$\begingroup\$ OK, i edited the question, to show you want output i want \$\endgroup\$ Commented Mar 5, 2022 at 18:57

1 Answer 1

1
\$\begingroup\$

I think the code is doing what you are asking it to do. However, I have some idea of what you want. I might be wrong but… Well, you try and tell me.


We have 1D data is world_data, but it is intended to be 2D. So we are going to map a 2D position of the world to a 1D position on world_data. In this particular case I'm going to do it by lines. Because it is simple, be aware that there are other approaches to do this.

Since we know the size of the first dimension (the width of the world) is 5000, we are going to assume we have lines of 5000 elements.

The y coordinate will tell us on which line we are, in other words how many lines we have to skip. The start of the y-th line is 5000 * y. And the x coordinate will tell us the position inside the line. In other words, the position in world_data will be given by 5000 * y + x. Or in you code:

world_data[5000 * j + i]

I'll take the opportunity to suggest storing that 5000 in a variable or constant so you can change it in a single place.


Addendum: I forgot, it is possible that goes out of bounds, so you will want a check, something like this:

for i in lo_tile_x as usize..hi_tile_x as usize {
    for j in lo_tile_y as usize..hi_tile_y as usize {
        let p = 5000 * j + i;
        if p < 0 || p >= world_data.len() {
            // perhaps draw some background here
            continue;
        }
        match world_data[p] {
            /* etc. */
        }
        // …
    }
}

Addendum 2: The above approach does not cut the edges of the world. We could do it with lo_tile_x, lo_tile_y, hi_tile_x, and hi_tile_y instead, by clamping them. I believe this works:

lo_tile_x = fmin(fmax(lo_tile_x, 0.0), 5000.0); # width
hi_tile_x = fmin(fmax(hi_tile_x, 0.0), 5000.0); # width
lo_tile_y = fmin(fmax(lo_tile_y, 0.0), 5000.0); # height
hi_tile_y = fmin(fmax(hi_tile_y, 0.0), 5000.0); # height

I decided to go with libm::fmin and libm:fmax instead of clamp.

Then it should not go out of bounds in the loop. Which means it should work without the fix from the prior addendum.

By the way, you could have the world loop instead. Which would be using the remainder. I hope it works like this:

lo_tile_x = ((lo_tile_x % 5000.0) + 5000.0) % 5000.0; # width
hi_tile_x = ((hi_tile_x % 5000.0) + 5000.0) % 5000.0; # width
lo_tile_y = ((lo_tile_y % 5000.0) + 5000.0) % 5000.0; # height
hi_tile_y = ((hi_tile_y % 5000.0) + 5000.0) % 5000.0; # height

I know that is not pretty, but I can't figure out what is the correct modulo function in rust. Modulo as in modulo arithmetic, not remainder. The result should be positive.


You can, by the way, use division and reminder to find the 2D coordinantes that will match a position from world_data. If do an integer division of the the 1D position by the width of the world, you will get the y coordinate, and x is the remainder of said division. You may find this useful for generating the world, for example if you need to query a 2D noise function.

\$\endgroup\$
15
  • \$\begingroup\$ I sort of understand what you are talking about, but when i run the code, it crashes with a index out of bound error: thread 'main' panicked at 'index out of bounds: the len is 25000000 but the index is 3907021250', src/main.rs:249:23 \$\endgroup\$ Commented Mar 5, 2022 at 19:25
  • \$\begingroup\$ @MachoOnion see addendum. Edit: perhaps you want to draw some background in those out of bounds positions, now that I think about it. \$\endgroup\$
    – Theraot
    Commented Mar 5, 2022 at 19:29
  • \$\begingroup\$ It rendered no tiles when p was set to 5000, but i tweaked the value of from 5000 to 2, and i have gotten closer and closer each time i tweak it \$\endgroup\$ Commented Mar 5, 2022 at 19:38
  • \$\begingroup\$ But, when the value of p is over 30, it renders no tiles \$\endgroup\$ Commented Mar 5, 2022 at 19:44
  • \$\begingroup\$ @MachoOnion Is 30 triggering the bounds check? if you print lo_tile_x, lo_tile_y, hi_tile_x, hi_tile_y what do you get? \$\endgroup\$
    – Theraot
    Commented Mar 5, 2022 at 19:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .