首页 > 解决方案 > 如何在pygame中同时执行两个事件?

问题描述

我正在尝试制作一个游戏,玩家可以在 3 列中将主要精灵(gran)向左向右移动,以避免从天空落下的雷云。两个组件都可以工作,但不能同时工作,所以我可以移动玩家或雷云从顶部落下。请有人帮忙,这样这两个事件可以同时发生

这是我的代码...

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

标签: pythonpygame

解决方案


我实际上会创建一些pygame.sprite.Sprite子类和精灵组,但由于您不熟悉它们,我将只使用pygame.Rectspygame.Surfaces。

因此,为玩家创建一个矩形,为云创建一个矩形列表。rects 被用作 blit 位置(图像/表面在rect.topleft坐标处被 blitted),也用于碰撞检测(colliderect)。

要移动云,您必须cloud_list使用 for 循环遍历并增加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()

推荐阅读