如何在pygame中同时执行两个事件?

时间:2018-08-03 08:49:46

标签: python pygame

我正在尝试制作一款游戏,让玩家可以将主精灵(格兰特)向左移动3列,从而避免从天空掉下雷雨云。这两个组件都可以工作,但不能同时使用,所以我可以移动播放器,或者雷云从顶部掉下。请有人帮忙,以便这两个事件可以同时发生

这里有我的代码...

import pygame, sys
import random
import time
from pygame.locals import *

#sets colours for transparency
BLACK = (   0,   0,   0)
#Sets gran sprite
class Sprite_maker(pygame.sprite.Sprite): # This class represents gran it derives from the "Sprite" class in Pygame
    def __init__(self, filename):
        super().__init__() # Call the parent class (Sprite) constructor
        self.image = pygame.image.load(filename).convert()# Create an image loaded from the disk
        self.image.set_colorkey(BLACK)#sets transparrency
        self.rect = self.image.get_rect()# Fetchs the object that has the dimensions of the image
#Initilizes pygame game
pygame.init()
pygame.display.set_caption("2nd try")
#sets background
swidth = 360
sheight = 640
sky = pygame.image.load("sky.png")
screen = pygame.display.set_mode([swidth,sheight])
#This is a list of every sprite
all_sprites_list = pygame.sprite.Group()
#Sets thunder list and creates a new thunder cloud and postions it
tcloud_speed = 10
tc_repeat = 0
thunder_list = [0, 120, 240]
for i in range(1):
    tx = random.choice(thunder_list)
    tcloud = Sprite_maker("thundercloud.png")
    tcloud.rect.x = tx
    tcloud.rect.y = 0
    all_sprites_list.add(tcloud)
#Creates the gran sprite
gran = Sprite_maker("gran.png")
all_sprites_list.add(gran)
gran.rect.x = 120
gran.rect.y = 430
#Movement of gran sprite when left/right pressed
def gran_movement(movex):
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_LEFT and gran.rect.x == 0:
            gran.rect.x = 0
        elif event.key == pygame.K_RIGHT and gran.rect.x == 240:
            gran.rect.x = 240
        elif event.key == pygame.K_LEFT:#left key pressed player moves left 1
            gran.rect.x -= 120
        elif event.key == pygame.K_RIGHT:#right key pressed player moves left 1
            gran.rect.x += 120
    return movex
#Main program loop
game_start = True
while game_start == True:
    for event in pygame.event.get():
        tcloud.rect.y += tcloud_speed
        if event.type == pygame.QUIT: #If user clicked close
            game_start = False #Exits loop
        #Clear the screen and sets background
        screen.blit(sky, [0, 0])
        #Displays all the sprites
        all_sprites_list.draw(screen)
        pygame.display.flip()
        #Moves gran by accessing gran 
        gran_movement(gran.rect.x)
        #Moves cloud down screen
        if tc_repeat == 0:
            tcloud.rect.y = 0
            time.sleep(0.25)
            tc_repeat = 1
        else:
            tcloud.rect.y += tcloud_speed

pygame.quit()

1 个答案:

答案 0 :(得分:1)

我实际上会创建一些pygame.sprite.Sprite子类和子画面组,但是由于您不熟悉它们,因此我只会使用pygame.Rectspygame.Surface

因此,为播放器创建一个rect,并为云创建一个rect列表。 rects用作blit位置(图像/表面在rect.topleft坐标处被blit),还用于碰撞检测(colliderect)。

要移动云,您必须使用for循环遍历cloud_list,并增加每个矩形的y坐标。这将每帧发生一次(while循环的迭代),并且游戏将以每秒30帧的速度运行(由于clock.tick(30))。

玩家移动(在事件循环中)似乎将与云移动同时发生。

import random
import pygame


pygame.init()
# Some replacement images/surfaces.
PLAYER_IMG = pygame.Surface((38, 68))
PLAYER_IMG.fill(pygame.Color('dodgerblue1'))
CLOUD_IMG = pygame.Surface((38, 38))
CLOUD_IMG.fill(pygame.Color('gray70'))


def main():
    screen = pygame.display.set_mode((360, 640))
    clock = pygame.time.Clock()
    # You can create a rect with the `pygame.Surface.get_rect` method
    # and pass the desired coordinates directly as an argument.
    player_rect = PLAYER_IMG.get_rect(topleft=(120, 430))
    # Alternatively create pygame.Rect instances in this way.
    cloud_rect = pygame.Rect(120, 0, 38, 38)
    # The clouds are just pygame.Rects in a list.
    cloud_list = [cloud_rect]

    done = False

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_d:
                    player_rect.x += 120
                elif event.key == pygame.K_a:
                    player_rect.x -= 120

        remaining_clouds = []

        for cloud_rect in cloud_list:
            # Move the cloud downwards.
            cloud_rect.y += 5

            # Collision detection with the player.
            if player_rect.colliderect(cloud_rect):
                print('Collision!')

            # To remove cloud rects that have left the
            # game area, append only the rects above 600 px
            # to the remaining_clouds list.
            if cloud_rect.top < 600:
                remaining_clouds.append(cloud_rect)
            else:
                # I append a new rect to the list when an old one
                # disappears.
                new_rect = pygame.Rect(random.choice((0, 120, 240)), 0, 38, 38)
                remaining_clouds.append(new_rect)

        # Assign the filtered list to the cloud_list variable.
        cloud_list = remaining_clouds

        screen.fill((30, 30, 30))
        # Blit the cloud image at the cloud rects.
        for cloud_rect in cloud_list:
            screen.blit(CLOUD_IMG, cloud_rect)
        screen.blit(PLAYER_IMG, player_rect)

        pygame.display.flip()
        clock.tick(30)


if __name__ == '__main__':
    main()
    pygame.quit()