How to scroll the background surface in PyGame?
pygame.Surface.scroll()
doesn't do what you expect. It doesn't seamless roll the surface. See the documentation:
scroll()
Shift the surface image in place[...] Areas of the surface that are not overwritten retain their original pixel values. [...]
You've to write your own scroll functions, which place the part of the surface, which was shifted out, at the other side of thee surface.
e.g. write 2 functions (scrollX
and scrollY
), which can roll along an axis:
def scrollX(screenSurf, offsetX):
width, height = screenSurf.get_size()
copySurf = screenSurf.copy()
screenSurf.blit(copySurf, (offsetX, 0))
if offsetX < 0:
screenSurf.blit(copySurf, (width + offsetX, 0), (0, 0, -offsetX, height))
else:
screenSurf.blit(copySurf, (0, 0), (width - offsetX, 0, offsetX, height))
def scrollY(screenSurf, offsetY):
width, height = screenSurf.get_size()
copySurf = screenSurf.copy()
screenSurf.blit(copySurf, (0, offsetY))
if offsetY < 0:
screenSurf.blit(copySurf, (0, height + offsetY), (0, 0, width, -offsetY))
else:
screenSurf.blit(copySurf, (0, 0), (0, height - offsetY, width, offsetY))
if pressed[pygame.K_UP]:
scrollY(screen, 2)
elif pressed[pygame.K_DOWN]:
scrollY(screen, -2)
elif pressed[pygame.K_LEFT]:
scrollX(screen, 2)
elif pressed[pygame.K_RIGHT]:
scrollX(screen, -2)
How to use pygame.surface.scroll()?
EDIT: Your image
and screen
variables are backwards. That is also causing you some confusion I'm sure..
Your problem may is that you are trying to scroll an all black background. It is probably scrolling, and you just don't know it because the white box you used blit()
to draw on the screen is stationary.
Try using something you can see scroll, like an image file. If you wanna move the white box, you can add a counter as a speed variable. Read this, then run it.
import pygame
from pygame.locals import*
screen=pygame.display.set_mode((1250,720))
pygame.init()
clock=pygame.time.Clock()
boxx=200
boxy=200
image = pygame.Surface([20,20]).convert_alpha()
image.fill((255,255,255))
speed = 5 # larger values will move objects faster
while True :
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT :
pygame.quit()
quit()
image.scroll(10,10)
# I did modulus 720, the surface width, so it doesn't go off screen
screen.blit(image,((boxx + speed) % 720, (boxy + speed) % 720))
pygame.display.update()
clock.tick(60)
I can't say for sure the scroll function is working or not, learn to use an image as your background so you can see it moving first.
How do you make a scrolling background in pygame?
The background moves downwards, so the condition has to be:
if BGY > BG.get_height():
BGY = -BG.get_height()
if BGY2 > BG.get_height():
BGY2 = -BG.get_height()
If the back ground has to move upwards, then you have to decrement BGY
and BGY2
:
BGY -= 2.5
BGY2 -= 2.5
if BGY < BG.get_height() * -1:
BGY = BG.get_height()
if BGY2 < BG.get_height() * -1:
BGY2 = BG.get_height()
How do I make my background scroll as my Sprite moves left and right? Pygame
Here's how I would approach this...
set up a scrolling background as in the tutorial and make sure you can get that working OK by moving the background back & forth instead of the player (just freeze the player's x coordinate in the center and move the background with your left/right keys.
Add some constants into your settings for an edge buffer (the number of x-increments you want the player to avoid the boundaries by
AFTER you get the key input (left or right) set up a conditional statement. For this, you will have to access the player's x-coordinate and compare it to the buffer. Well, either 0+buffer or width-buffer actually and then based on those cases either move the player or the background. See if you can get that working.
Then, you will realize that when you move the background, you are moving the frame of reference for everything else, meaning things like the fireball, so if you are moving the background left or right, you will need to apply those updates to the other objects as well so it looks correct.
If yer stuck, make those updates to code above & message me back in a comment.
How can I make a scrolling background in python with pygame?
Some things first:
- fix your indentation
- your ship function is practically useless
- use the Rect to handle moving
- your real problem is that your code never reaches
pygame.display.update()
because of your second while loop
So, to make an endless scrolling background, and easy way is to do the following:
Blit your background image twice, once at position y
, and once at y + image_width
(replace y
with x
of you want). Then, every iteration of your mainloop, you can substract from y
to create the movement. Once an image moved it's entire height, reset y
to the starting value
Here's a complete example, showing a scrolling background (and how to use sprites, groups, vectors and rects):
import pygame
pygame.init()
SCREEN = pygame.display.set_mode((300, 300))
move_map = {pygame.K_w: pygame.math.Vector2( 0, -1),
pygame.K_s: pygame.math.Vector2( 0, 1),
pygame.K_a: pygame.math.Vector2(-1, 0),
pygame.K_d: pygame.math.Vector2( 1, 0)}
class Actor(pygame.sprite.Sprite):
def __init__(self, group, color, pos, size=(30, 30)):
self.image = pygame.Surface(size)
self.image.fill(color)
self.rect = self.image.get_rect(center=pos)
pygame.sprite.Sprite.__init__(self, group)
class Bullet(Actor):
def __init__(self, *args):
Actor.__init__(self, *args)
self.speed = 10
def update(self):
self.rect.move_ip(self.speed, 0)
if not SCREEN.get_rect().colliderect(self.rect):
self.kill()
class Player(Actor):
def __init__(self, *args):
self._layer = 4
Actor.__init__(self, *args)
self.speed = 4
self.timeout = 0
def update(self):
p = pygame.key.get_pressed()
move_vector = pygame.math.Vector2(0, 0)
for v in [move_map[key] for key in move_map if p[key]]:
move_vector += v
if move_vector:
self.rect.move_ip(*move_vector.normalize() * self.speed)
self.rect.clamp_ip(SCREEN.get_rect())
if self.timeout :
self.timeout -= 1
if p[pygame.K_SPACE] and not self.timeout:
Bullet(self.groups()[0], (130, 200, 77), self.rect.center, (10, 3))
self.timeout = 5
class Background(pygame.sprite.Sprite):
def __init__(self, number, *args):
self.image = pygame.image.load('back.jpg').convert()
self.rect = self.image.get_rect()
self._layer = -10
pygame.sprite.Sprite.__init__(self, *args)
self.moved = 0
self.number = number
self.rect.x = self.rect.width * self.number
def update(self):
self.rect.move_ip(-1, 0)
self.moved += 1
if self.moved >= self.rect.width:
self.rect.x = self.rect.width * self.number
self.moved = 0
group = pygame.sprite.LayeredUpdates()
Player(group, (255, 255, 255), (100, 100))
Background(0, group)
Background(1, group)
clock = pygame.time.Clock()
run = True
while run:
for e in pygame.event.get():
if e.type ==pygame.QUIT:
run = False
SCREEN.fill((0,0,0))
group.update()
group.draw(SCREEN)
pygame.display.flip()
clock.tick(60)
For testing this, you can use this image (save it as back.jpg
):
Related Topics
Start a Function at Given Time
What Is the Easiest Way to Remove All Packages Installed by Pip
How to Verify If One List Is a Subset of Another
Embedding a Matplotlib Figure Inside a Wxpython Panel
Read File from Line 2 or Skip Header Row
Python CSV Error: Line Contains Null Byte
How to Save a Trained Model in Pytorch
Serializing Class Instance to JSON
Merge and Sum of Two Dictionaries
Python MySQLdb: Library Not Loaded: Libmysqlclient.18.Dylib
Python' Is Not Recognized as an Internal or External Command
Why Is It String.Join(List) Instead of List.Join(String)
Generate a Random Date Between Two Other Dates
Pylint "Unable to Import" Error - How to Set Pythonpath
Insert an Element at a Specific Index in a List and Return the Updated List