Your screen is the screen, and it only has 500x500 pixels - you don’t know, and there’s nothing outside it.
However, to draw the background image, you load it on the line:
image = pygame.image.load('huge_background.png').convert_alpha()
The object saved in the variable image in this case, as well as your screen, in the variable screen, is a Surface pygame. The method .get_at is a Surface class method.
So all you need is to keep your disk image read in variable image available, and check the pixel value on it, instead of in Surface - in a complete project, instead of in this demonstration, the background image offset values will also be in variables, instead of the fixed values there [-5000, -420] -
Let’s say you keep that amount in a tuple, or better yet, in a Vector2:
offset = pygame.math.Vector2(-5000, -420)
When asking for the value of the pixel "off-screen", just add in the coordinates of the screen, the negative value of this displacement - that is, the pixel (0,0) of the screen corresponds to the pixel "5000,420" of image - So just do it:
offset = pygame.math.Vector2(-5000, -420)
...
# No corpo do código do jogo, mantenha o "offset" atualizado
# se mudar a posição do fundo
...
color = image.get_at([100, -5] - offset)
# (em vez de screen.get_at([100, -5]) )
The Vector2 class is relatively new in Pygame, it is available from
of 1.9, if I’m not mistaken - realize that its great advantage is that if it’s summed or subtracted a with a tuple, or another sequence of two coordinates, it already does the right number for each component of the coordinate.
If offset was a normal tuple instead of a Vector2, the code would have to be:
color = image.get_at([100 - offset[0], -5 - offset[1])
Important
Another thing of note - the methods .get_at and .set_at pygame surfaces are good for spot checks - for example, seeing if a pixel is within an extensive area of a color, or changing a very small detail on an image. However, both for larger checks (if you are looking for specific colors in an area of the image, for example), they are quite slow - because they involve a function call and dynamic creation of several objects in Python for each call. That is to say:
a call to get_at returns a tuple of 4 whole components - internally, the computer will take the numbers in the memory representing the image, take the reference to 4 objects int Python and create a tuple containing them. This can be 1000 to 10000 times slower than just checking the values in sequence in memory.
So if you’re manipulating the image, the ideal is to turn the manipulated area temporariametne into a surfarray - this returns an array of the numpy, that can access the "inplace" numbers in memory, tremendously more efficiently.
Thank you so much for the excellent explanation! Little by little I’ll get acquainted with the concepts of pygame. I understood that the concept of Surface, where the background image is a Surface and the screen as well and can be manipulated independently.
– Rogério Dec
I edited the original question and added some images and explanations. I understand that I can use the
get_atindependently on the background image and not on the screen. But in addition to the background image, there may be OTHER CARS and other previously 'blighted' objects. That is, it would be a composition of the background image with other objects on top. How to treat the collision in this case' composite'?– Rogério Dec
the collision with other cars has to be compared with the coordinates of the other cars in the game, not with respect to their pixels on the screen - for this we will use the concept of Sprites and groups, and the collision functions embedded in the pygame. I suggest you unfold the question, and make the doubt in the above comment another question here in stackoverflow - since they will be distinct concepts. I or someone else will answer.
– jsbueno