0
\$\begingroup\$

I am looking up tutorials on how to make 2D games, and I can just copy and paste their code but I would rather know what it means and how to do it.

Suppose you have a 2D game window that has a map width of 64, how do you actually repeat the tiles when you go out of range when scrolling?

In this render method what line of code is actually allowing the game to repeat the tiles when you go out of range?

From the below code this line stands out to me:

int tileIndex = (xTile &(MAP_WIDTH_MASK)) + (yTile &(MAP_WIDTH_MASK))* MAP_WIDTH;

As this line gives you the X and Y coordinates of which tile you are on, it seems like the bitwise & operator is repeating the tiles, please correct me if I am wrong and also explain to me what the & operator is doing?

Code Example:

 public static final int MAP_WIDTH= 64;
 public static final int MAP_WIDTH_MASK= MAP_WIDTH - 1;
 public static final int PIXEL_SIZE= 8;
 public static final int PIXEL_SIZE_MASK= MAP_WIDTH - 1;
 public int[] tiles = new int[MAP_WIDTH*MAP_WIDTH];
 public int[] colours = new int[MAP_WIDTH*MAP_WIDTH*4];
 public int xOffset = 0;
 public int yOffset = 0;

 public void render(int[] pixels, int offset, int row) {
        for(int yTile = (0 + yOffset) >> 3; yTile<=(height + yOffset) >> 3; yTile++) { 
            int yMin = (yTile * PIXEL_SIZE) - yOffset; 
            int yMax = yMin + PIXEL_SIZE; 
            if (yMin<0) yMin=0;
            if (yMax>height) yMax = height; 
            for(int xTile = (0 + xOffset) >> 3; xTile<=(width + xOffset) >> 3; xTile++) {
                int xMin = (xTile * PIXEL_SIZE) - xOffset;
                int xMax = xMin + PIXEL_SIZE;
                if(xMin<0) xMin=0;
                if (xMax>width) xMax = width;
                int tileIndex = (xTile &(MAP_WIDTH_MASK)) + (yTile &(MAP_WIDTH_MASK))* MAP_WIDTH;
                for (int y = yMin; y < yMax; y++){
                    int sheetPixel = ((y + yOffset) & PIXEL_SIZE_MASK)*sheet.width + ((xMin + xOffset)& PIXEL_SIZE_MASK);
                    int tilePixel = offset + xMin + y * row;
                    for(int x = xMin; x< xMax; x++) {
                        int colour = tileIndex * 4 + sheet.pixels[sheetPixel++];
                        pixels[tilePixel++] = colours[colour];
                    }
                }
            }
        }
```
\$\endgroup\$
3
  • 2
    \$\begingroup\$ I would recommend finding a different source to learn from. Setting pixel colours one-by-one as this code does is not what I would call a best practice. If you don't want to just copy-paste code, don't. Instead, start by following a beginner Java game development tutorial - even if it's for a different kind of game than the one you want to make - so that you learn the meaning of every step in the process. Once you're fluent in the language and in the basic building blocks of a game, then you'll be ready to make the game you want, without needing to ask strangers how to modify copy-paste code. \$\endgroup\$
    – DMGregory
    Mar 12, 2020 at 16:43
  • \$\begingroup\$ i totally agree - it seems a slight overkill to me to shift an Image - instead use two images and draw them only partly... \$\endgroup\$ Mar 13, 2020 at 6:52
  • \$\begingroup\$ Especially when you talk about tiles i think it would be better to just draw a bit over the peer \$\endgroup\$ Mar 13, 2020 at 12:50

1 Answer 1

1
\$\begingroup\$

If you have a grid that is xSize x ySize in size and it is stored in a one-dimensional array, then a way of finding the index in that array for a given (x, y) coordinate is:

int index = x + y * xSize;

Each increment to the y-axis advances the index by the entire width of the grid, and each increment to the x-axis increments along that row.

In your example this is basically what happens if we remove the & (MAP_WIDTH_MASK) :

int tileIndex = (xTile) + (yTile)* MAP_WIDTH;

The reason your example is applying the bit-wise and-operator, &, is to wrap around the coordinates.

Since a x-coordinate greater than the width of the grid has no meaning, your code uses the & to clamp the x-coordinate to the range [x- MAP_WIDTH] since it effectively removes the part of the number that is greater than MAP_WIDTH

With the MAP_WIDTH set to 64 the MAP_WIDTH_MASK is 63, or in binary

0000 0000 0011 1111

By applying a bit-wise and between that mask and any number, you're zeroing all the bits of the number that isn't matched by a one in the mask.

So the answer is the & operator is used to wrap the coordinates, and it does this by removing/zeroing the part of the number that is greater than the width.

\$\endgroup\$

You must log in to answer this question.

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