# Selecting Tiles Correctly With Scroll

I would like to understand the process of selecting the correct tile from a scaled Surface when I have information about the number of tiles on the x and y axes, the length of the Surface, and also considering the scroll factor

Firstly, I have the following variables:

WIDTH = 640
HEIGHT = 320
TILE_SIZE = 32
MAX_COL = WIDTH // TILE_SIZE
MAX_ROW = HEIGHT // TILE_SIZE


Then, I create the base Surface with screen = pg.display.set_mode((WIDTH, HEIGHT), pg.RESIZABLE), and a dummy Surface as follows: dummy = pg.Surface([WIDTH, HEIGHT]).

Next, I create grids using some clever math and a scroll variable (which changes when I press the D button, moving everything backward):

for v in range(MAX_COL):
# vertical / col
pg.draw.line(dummy, (0, 0, 0), (TILE_SIZE * v - scroll_x, 0), (TILE_SIZE * v - scroll_x, HEIGHT))
# horizontal / row
for h in range(MAX_ROW):
pg.draw.line(dummy, (0, 0, 0), (0 - scroll_x, TILE_SIZE * h), (MAX_COL * TILE_SIZE - scroll_x, TILE_SIZE * h))


Finally, I scale it (using tw and th, calculated dimensions to maintain aspect ratio, but for now, it can be anything):

f = pg.transform.scale(s, (tw, th))


Now, I want to choose a tile so that when I click it, it shows on which field I currently am. I achieve this by dividing my mouse X and Y coordinates from pg.mouse.get_pos() with the size of a scaled tile, and the result looks something like this:

Now I can go ahead and print this tile as a tuple - (2, 2)

But the problem comes when I move with my map and everything changes its position:

To select a tile like this, I would normally use my scroll variable and manipulate it (such as adding that information to the mouse x coordinate). However, it seems a bit tricky because when I scale everything, my scroll isn't accurate anymore, at least not for working with a mouse. So, I am wondering if someone knows how to maintain my coordinate system while also considering my scroll factor. For example here Id like to get (2, 2) as well but thats not what I get

You must apply the inverse of the draw operations in reverse order to the mouse position.

(mx,my) = pg.mouse.get_pos()
my -= pad_y # undo blit center offset
mx /= tw
my /= th # undo the scaling

# mx and my is now in dummy space screen coordinates(not scrolled)

# Scroll X and Y are in dummy coordinate space
tile_x = (mx + scroll_x) // TILE_SIZE
tile_y = (my + scroll_y) // TILE_SIZE

# tile_x is equal to the original h value of grid square under the mouse
# tile_v is equal to the original v value of grid square under the mouse


Affine transformations(translations, i.e. +/- on X,Y,Z,W) are non-linear in nature.

You can build a complete transformation matrix for drawing operations and invert the matrix to give a single operation to undo the screen mouse to source space.