How can I make a scrolling background in python wi

2019-03-06 21:47发布

问题:

I've been trying to make a space shooting game for the past 2 days and I want to make the background scrolling down but i don't know how. Heres my code:

import pygame
import time
pygame.init()

width = 800
height = 600

black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)

ship_width = 35
ship_height = 64

disp = pygame.display.set_mode((width,height))

pygame.display.set_caption("Space Jump")

clock = pygame.time.Clock()

background = pygame.image.load("Space.png").convert()

shipImg = pygame.image.load("Ship.png")

def ship(x,y):
    disp.blit(shipImg, (x,y))

def gameLoop():
    x = (width * 0.45)
    y = (height * 0.8)

x_ch = 0
y_ch = 0

gameExit = False

while not gameExit:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            gameExit = True

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                x_ch = -5
            elif event.key == pygame.K_RIGHT:
                x_ch = 5
            elif event.key == pygame.K_UP:
                y_ch = -5
            elif event.key == pygame.K_DOWN:
                y_ch = 5


        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                x_ch = 0
            if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                y_ch = 0

    x += x_ch
    y += y_ch

    if x > width - ship_width or x < 0:
        x_ch = 0

    if y > height - ship_height or y < 0:
        y_ch = 0
    x_bg = 0
    while True:
        disp.blit(background, (0,x_bg)) # i tried this but when i launch
                                        #a black screen just appears without 
        x_bg -= 1                       #any image
    ship(x,y)

    pygame.display.update()
    clock.tick(60)

gameLoop()
pygame.quit()
quit()

I have a background and i want to make it scrolling down continuously can you help me?

回答1:

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



标签: python pygame