So I can't figure out why I can't get the images to stay connect and seamless when the regenerate at the top of the display screen. I have them both going back to top (rect.bottom = 0) once the rect.top reaches bottom (600). depending on what my speedy is they do funny things like start apart and then slide together at top of screen or just end up with a consistent space in between them.
Any help would be appreciated or can I put the image in same class and have it repeat 6 times down the screen and move them all so I don't have to do 6 different Road classes.
import pygame
from pygame.locals import *
import sys
import os
W, H = 800, 600
HW, HH = W / 2, H / 2
AREA = W * H
os.environ['SDL_VIDEO_WINDOW_POS'] = "50,50"
FPS = 30
GREEN = (0, 200, 0)
def events():
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
class Road1(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
bkgrnd = pygame.image.load("Images/Road.png").convert_alpha()
self.image = pygame.transform.scale(bkgrnd, (300, 100))
self.rect = self.image.get_rect()
self.rect.x = 100
self.rect.top = 0
self.speedy = 0
def update(self):
self.rect.top += self.speedy
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.speedy += 0.25
if keys[pygame.K_s]:
self.speedy -= 0.25
if self.speedy <= 0:
self.speedy = 0
if self.speedy >= 20:
self.speedy = 20
if self.rect.top >= 600:
self.rect.x = 100
self.rect.bottom = 0
class Road2(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
bkgrnd = pygame.image.load("Images/Road.png").convert_alpha()
self.image = pygame.transform.scale(bkgrnd, (300, 100))
self.rect = self.image.get_rect()
self.rect.x = 100
self.rect.top = 100
self.speedy = 0
def update(self):
self.rect.top += self.speedy
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.speedy += 0.25
if keys[pygame.K_s]:
self.speedy -= 0.25
if self.speedy <= 0:
self.speedy = 0
if self.speedy >= 20:
self.speedy = 20
if self.rect.top >= 600:
self.rect.x = 100
self.rect.bottom = 0
pygame.init()
CLOCK = pygame.time.Clock()
DS = pygame.display.set_mode((W, H))
pygame.display.set_caption("Scrolling")
all_sprites = pygame.sprite.Group()
road = pygame.sprite.Group()
rd1 = Road1()
all_sprites.add(rd1)
road.add(rd1)
rd2 = Road2()
all_sprites.add(rd2)
road.add(rd2)
while True:
CLOCK.tick(FPS)
events()
all_sprites.update()
DS.fill(GREEN)
all_sprites.draw(DS)
pygame.display.flip()
If the "street" is out of the window at the bottom, the it's top position is not exactly 600, it is a bit greater than 600. To keep the alignment of the streets to each other, you have to change the the top of the street by the height of the window:
class Road1(pygame.sprite.Sprite):
# [...]
def update(self):
#[...]
if self.rect.top >= 600:
self.rect.x = 100
self.rect.top = self.rect.top - 600
class Road2(pygame.sprite.Sprite):
# [...]
def update(self):
#[...]
if self.rect.top >= 600:
self.rect.x = 100
self.rect.top = self.rect.top - 600
Further more, it is absolutely a bad design to generate a separate class for each part of the street. Classes have attributes and constructors of classes have parameters. Use them! THe parts of the streets differ only in its initial position. This can be a parameter to the constructor of a class Road
:
class Road(pygame.sprite.Sprite):
def __init__(self, top):
pygame.sprite.Sprite.__init__(self)
bkgrnd = pygame.image.load("Images/Road.png").convert_alpha()
self.image = pygame.transform.scale(bkgrnd, (300, 100))
self.rect = self.image.get_rect()
self.rect.x = 100
self.rect.top = top # parameter top
self.speedy = 0
def update(self):
self.rect.top += self.speedy
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.speedy += 0.25
if keys[pygame.K_s]:
self.speedy -= 0.25
if self.speedy <= 0:
self.speedy = 0
if self.speedy >= 20:
self.speedy = 20
if self.rect.top >= 600:
self.rect.x = 100
self.rect.top = self.rect.top - 600
# [...]
rd1 = Road(0)
# [...]
rd2 = Road(100)
# [...]
For an endless road you'll need 7 elements, where the 1st element is placed at -100. If an element has to be flipped to the begin, its new position is top = top-700
.
Since self.speedy
is a floating point I recommend to add an attribute self.top
, which is synchronized to the integral attribute self.rect.top
. e.g.:
class Road(pygame.sprite.Sprite):
def __init__(self, top):
pygame.sprite.Sprite.__init__(self)
bkgrnd = pygame.image.load("Images/Road.png").convert_alpha()
self.image = pygame.transform.scale(bkgrnd, (300, 100))
self.rect = self.image.get_rect(topleft = (100, top))
self.top = top
self.speedy = 0
def update(self):
self.top += self.speedy
if self.top > 600:
self.top = self.top - 700
self.rect.top = self.top
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
self.speedy = min(20, self.speedy + 0.25)
if keys[pygame.K_s]:
self.speedy = max(0, self.speedy + 0.25)
all_sprites = pygame.sprite.Group()
road = pygame.sprite.Group()
for i in range(7):
rd = Road((i-1) * 100)
all_sprites.add(rd)
road.add(rd)