I know that to get a pixel color in Pygame I use get_at
. But I need to get a pixel that is outside my screen, ie, I have an image already blitted with just a portion visible.
For example, a 1000x1000 image inside a 500,500 screen will only have 50% visible, the rest will be "off" the screen. So I need to access the portion off the screen.
But if I reference get_at
with a coordinate greater or less then the screen dimensions, Pygame stops with an error:
IndexError: pixel index out of range
import pygame
W = 1600
H = 600
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]) # generates "IndexError: pixel index out of range"
How can I get the background image pixel color outside the screen dimensions?
Here is the currently visible pygame screen (1600 x 600). The 3 lines (in magenta) are the collision "detectors":
And here is the background that will scroll (8000 x 8000):
So here is an idea of the scenario:
So, the collision detector lines might exceed the pygame screen limits but need to "read" the outside pixels to detect the collision.
Here's a stand-alone example that tracks the position of the view/camera on a larger background.
import pygame
W = 600
H = 400
pygame.init()
# generate repeated KEYDOWN events when a key is held
pygame.key.set_repeat(500, 50)
screen = pygame.display.set_mode([W, H])
# image = pygame.image.load('huge_bkgnd.png').convert_alpha()
#create a large bkgnd image
bkgnd = pygame.Surface((W*10, H*10))
# draw a rainbow on the bkgnd surface
colours = ["red", "orange", "yellow", "green", "lightblue1", "blue", "purple"]
bar_width = bkgnd.get_width() // (10 * len(colours))
for x in range(0, bkgnd.get_width() // bar_width):
rect = [x*bar_width, 0, bar_width, bkgnd.get_height()]
bkgnd.fill(pygame.Color(colours[x % len(colours)]), rect)
position = [0, 0]
clock = pygame.time.Clock() #for limiting FPS
finished = False
while not finished:
for event in pygame.event.get():
if event.type == pygame.QUIT:
finished = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
position[0] -= 100
if event.key == pygame.K_RIGHT:
position[0] += 100
if event.key == pygame.K_UP:
position[1] -= 100
if event.key == pygame.K_DOWN:
position[1] += 100
# for all key movement clamp position to size of background
position[0] = max(0, min(position[0], bkgnd.get_width() - W))
position[1] = max(0, min(position[1], bkgnd.get_height() - H))
try:
x = position[0] + W*2 # just look at what's to the right
y = position[1]
print(f"At {position}: Heading for ({x},{y}) {bkgnd.get_at((x, y))}")
except IndexError:
print(f"Heading for the edge! {bkgnd.get_width() - position[0]} to go!")
# copy bkgnd to screen
view_rect = (*position, W, H)
screen.blit(bkgnd.subsurface(view_rect), (0,0))
# update the screen
pygame.display.update()
clock.tick(60) # limit FPS
pygame.quit()
Ignore the hacky-bit at the start to generate a rainbow background image so horizontal movement is obvious.
The program moves the position based on arrow key presses. Using pygame.key.set_repeat()
it allows for the arrow keys to be held down.
There's a little bit of house-keeping in the event loop to ensure the view can't move outside the boundary of the background. Then it prints the colour of a pixel in the distance.
After the events are processed, a section of the background is drawn to the screen, based on the current position.
Let me know if you'd like any clarification.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.