How to get a pixel color out of the screen border in pygame?

1

I know that to get a pixel color in PyGame I use get_at . But I have a huge background image and a good part of it stays outside of the pygame delimited screen area.

For example, a 1000x1000 image inside a 500x500 screen will only have 50% visible, the rest will be "off" the screen. So I need to access this part OUTSIDE the pygame screen.

But if I refer to get_at with a coordinate greater or less than the dimensions of the screen, Pygame gives an error:

  

IndexError: pixel index out of range

import pygame
W = 600
H = 400
pygame.init()
screen = pygame.display.set_mode([W, H])
image = pygame.image.load('huge_background.png').convert_alpha()
screen.blit(image, [-5000, -420])
pygame.display.update()
screen.get_at([100, -5]) # gera o erro "IndexError: pixel index out of range"

Would anyone know how I can access a pixel beyond the visible area of the pygame screen?

This is a simulation of vehicles within a track.

Here is the pygame screen currently visible (1600 x 600). The 3 lines (in magenta) are the collision "detectors":

Andhereisthebackground(track)thatwillscrollaccordingtothepositionofthecar(8000x8000):

Thiswouldbeascreenview(quotedinred)andtheoverallplanewiththebackgroundimage(track):

Thus,collisiondetectorlinesmayexceedthepygame'sscreenboundaries,butmust"read" the outer pixels to detect the collision.

    
asked by anonymous 21.09.2018 / 01:39

1 answer

2

Your screen is the screen, and it only has 500x500 pixels - do not know, and there is 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 stored in the variable image in this case, as well as its screen, in the variable screen , is a Surface of pygame. The .get_at method is a method of the Surface class.

Then all you need to do is keep your image read from the disk in the variable image available, and check the pixel value on it, instead of on the surface - in a complete project, rather than in that demo, the values of will also be in variables, instead of the fixed values there [-5000, -420] -

Let's say you save this value in a tuple, or better yet, in a Vector2:

 offset = pygame.math.Vector2(-5000, -420)

At the time of requesting the value of the "off-screen" pixel, just add in the coordinates of the screen the negative value of that offset - that is, the pixel (0,0) of the screen corresponds to the pixel "5000, 420 "of image - Then just do:

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 to Pygame, available from  of 1.9, if I'm not mistaken - realize that the great advantage of it is that if it is added to or subtracted from with a tuple, or another sequence of two coordinates, it already does the right account 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 worth noting - pygame's .get_at and .set_at methods are good for spot checks - for example, see if a pixel is within a large area of a color, or change a detail well image. However, for both large checks (if you're looking for specific colors in an image area, for example), they're rather slow - why they involve a function call and dynamic creation of multiple Python objects for each call. That is: a call to get_at will return a tuple of 4 integer components - internally, the computer will pick up the numbers in the memory representing the image, take the reference to 4 int objects of Python and create a tuple containing them. This can be 1000 to 10000 times slower than just querying the values in sequence in memory.

So if you're manipulating the image, the ideal is to temporarily transform the manipulated area into a surfarray - this returns an array of numpy , which can access the inplace numbers in memory, tremendously more efficiently.

    
21.09.2018 / 17:09