首页 > 解决方案 > 当图像在屏幕顶部重新生成时,无法无缝滚动

问题描述

所以我不明白为什么当在显示屏顶部重新生成时,我不能让图像保持连接和无缝。一旦 rect.top 到达底部(600),我让它们都回到顶部(rect.bottom = 0)。取决于我的速度,他们会做一些有趣的事情,比如分开开始,然后在屏幕顶部一起滑动,或者最终在它们之间有一个一致的空间。

任何帮助将不胜感激,或者我可以将图像放在同一个类中并让它在屏幕上重复 6 次并将它们全部移动,这样我就不必做 6 个不同的道路类。

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()

标签: pythonpygamesmooth-scrollingvertical-scrolling

解决方案


如果“街道”在底部的窗口之外,它的顶部位置不完全是 600,它比 600 大一点。要保持街道相互对齐,您必须更改顶部窗户高度的街道:

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

此外,为街道的每个部分生成一个单独的类绝对是一个糟糕的设计。类具有属性,类的构造函数具有参数。使用它们!街道的各个部分仅在其初始位置上有所不同。这可以是类的构造函数的参数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)
# [...]

对于一条无尽的道路,您需要 7 个元素,其中第一个元素位于 -100。如果一个元素必须被翻转到开头,它的新位置是top = top-700
由于self.speedy是浮点数,我建议添加一个属性self.top,该属性与整数属性同步self.rect.top。例如:

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)

推荐阅读