如何获得 python/pygame 中条件语句的等待时间
How do you get a wait time for a conditional statement in python/pygame
我是编程新手,这是我玩的第一个真正的游戏 made/making。基本上,游戏让您作为玩家向敌人射击 "bullets"。一些物体在中间移动以试图阻止所有子弹穿过。
感觉玩家发射子弹的速度太快了。所以我做了一些研究,发现了一些有用的东西。 time.sleep(秒)。当我使用它时,整个游戏会停止并等待时间延迟结束。
当玩家按下鼠标按钮发射子弹时,我在主程序循环中使用了 time.sleep(sec)。这反过来会影响整个游戏,使所有游戏延迟 5 秒。
那我怎么让它等不影响整个游戏呢?
这是我的游戏代码:
import pygame
import random
import time
enemy_speed = 5
running = 1
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
# --- Classes
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("enemy.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update(self):
self.rect.x += 7
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update(self):
self.rect.y = 300
self.rect.x += 5
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand2(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand2.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 100
self.rect.x -= 5
if self.rect.x <= 90:
self.rect.x = random.randrange(50,610)
class Hand3(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand3.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 200
self.rect.x += 3
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand4(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand4.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 50
self.rect.x += 3
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand5(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand5.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 350
self.rect.x -= 3
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("player.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update(self):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.rect.x -= 4
if event.key == pygame.K_RIGHT:
self.rect.x += 4
if self.rect.x <= 50:
self.rect.x = 60
if self.rect.x >= 610:
self.rect.x = 600
class Pellet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([4,10])
self.image.fill(RED)
self.rect = self.image.get_rect()
def update(self):
speed_p = -3
self.rect.y -= speed_p
class Bullet(pygame.sprite.Sprite):
""" This class represents the bullet . """
def __init__(self):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([4, 10])
self.image.fill(BLUE)
self.rect = self.image.get_rect()
def update(self):
""" Move the bullet. """
speed_b = 3
self.rect.y -= speed_b
# --- Create the window
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Cannon Battle")
all_sprites_list = pygame.sprite.Group()
enemy_list = pygame.sprite.Group()
player_list = pygame.sprite.Group()
hand_list = pygame.sprite.Group()
hand2_list = pygame.sprite.Group()
hand3_list = pygame.sprite.Group()
hand4_list = pygame.sprite.Group()
hand5_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
pellet_list = pygame.sprite.Group()
enemy = Enemy()
enemy_list.add(enemy)
all_sprites_list.add(enemy_list)
hand = Hand()
hand_list.add(hand)
all_sprites_list.add(hand_list)
hand2 = Hand2()
hand2_list.add(hand2)
all_sprites_list.add(hand2)
hand3 = Hand3()
hand3_list.add(hand3)
all_sprites_list.add(hand3)
hand4 = Hand4()
hand4_list.add(hand4)
all_sprites_list.add(hand4)
hand5 = Hand5()
hand5_list.add(hand5)
all_sprites_list.add(hand5)
player = Player()
player_list.add(player)
all_sprites_list.add(player_list)
done = False
clock = pygame.time.Clock()
player.rect.y = 370
behind = pygame.image.load("grassland.png").convert()
# -------- Main Program Loop
while not done:
screen.blit(behind, [0,0])
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
time.sleep(5)
elif event.type == pygame.MOUSEBUTTONUP:
pellet = Pellet()
pellet.rect.x = enemy.rect.x
pellet.rect.y = enemy.rect.y
all_sprites_list.add(pellet)
pellet_list.add(pellet)
# --- Game logic
# Call the update() method on all the sprites
all_sprites_list.update()
for pellet in pellet_list:
player_hit_list = pygame.sprite.spritecollide(pellet,player_list,True)
if pellet.rect.y >= 510:
pellet_list.remove(pellet)
all_sprites_list.remove(pellet)
for player in player_hit_list:
done = True
print("You Lost!")
print("But thanks for playing!")
print("Made by Oankar Studios")
for bullet in bullet_list:
enemy_hit_list = pygame.sprite.spritecollide(bullet,enemy_list,True)
if bullet.rect.y <= -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand2.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand3.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand4.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand5.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
for enemy in enemy_hit_list:
done = True
print("You Won!")
print("Made by Oankar Studios")
# Clear the screen
# Draw all the spites
all_sprites_list.draw(screen)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 20 frames per second
clock.tick(60)
pygame.quit()
这里是我使用time.sleep(sec)的地方,它在主程序循环中:
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
time.sleep(5)
您可以存储最后一发子弹的时间,并忽略所有按键,直到 5 秒过去。
所以,在顶部
last_bullet_shot_time = None
然后
elif event.type == pygame.MOUSEBUTTONDOWN:
if last_bullet_shot_time is None or
time.now() - last_bullet_shot_time > datetime.timedelta(seconds = 5):
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
last_bullet_shot_time = time.now()
正如您已经发现的那样,time.sleep() 会暂停整个程序(或确切地说是线程),这通常不是您想要的。一种可能的解决方案是比较 @maniexx 提到的时间。
当您使用 pygame 时,我建议您以基本相同的方式使用 pygame.time.get_ticks(),如 this 答案中所述。
您可以使用 pygame 基于计时器生成事件的功能以及唯一的用户定义事件,让它在经过所需时间后创建通知事件。以下是您需要进行的更改:
# globals
TIMEOUT_EXPIRED = pygame.USEREVENT+1
shooting_allowed = True
然后在游戏正文中:
# in the event processing loop
elif event.type == pygame.MOUSEBUTTONDOWN:
if shooting_allowed:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
# disable shooting for 5 seconds
shooting_allowed = False
pygame.time.set_timer(TIMEOUT_EXPIRED, 5000)
elif event.type == TIMEOUT_EXPIRED:
# re-enable shooting
shooting_allowed = True
pygame.time.set_timer(TIMEOUT_EXPIRED, 0) # stop generation of event
我是编程新手,这是我玩的第一个真正的游戏 made/making。基本上,游戏让您作为玩家向敌人射击 "bullets"。一些物体在中间移动以试图阻止所有子弹穿过。
感觉玩家发射子弹的速度太快了。所以我做了一些研究,发现了一些有用的东西。 time.sleep(秒)。当我使用它时,整个游戏会停止并等待时间延迟结束。
当玩家按下鼠标按钮发射子弹时,我在主程序循环中使用了 time.sleep(sec)。这反过来会影响整个游戏,使所有游戏延迟 5 秒。
那我怎么让它等不影响整个游戏呢?
这是我的游戏代码:
import pygame
import random
import time
enemy_speed = 5
running = 1
# Define some colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
# --- Classes
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("enemy.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update(self):
self.rect.x += 7
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update(self):
self.rect.y = 300
self.rect.x += 5
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand2(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand2.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 100
self.rect.x -= 5
if self.rect.x <= 90:
self.rect.x = random.randrange(50,610)
class Hand3(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand3.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 200
self.rect.x += 3
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand4(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand4.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 50
self.rect.x += 3
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Hand5(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("hand5.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update (self):
self.rect.y = 350
self.rect.x -= 3
if self.rect.x >= 610:
self.rect.x = random.randrange(50,610)
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.image.load("player.png").convert()
self.rect = self.image.get_rect()
self.image.set_colorkey(WHITE)
def update(self):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.rect.x -= 4
if event.key == pygame.K_RIGHT:
self.rect.x += 4
if self.rect.x <= 50:
self.rect.x = 60
if self.rect.x >= 610:
self.rect.x = 600
class Pellet(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface([4,10])
self.image.fill(RED)
self.rect = self.image.get_rect()
def update(self):
speed_p = -3
self.rect.y -= speed_p
class Bullet(pygame.sprite.Sprite):
""" This class represents the bullet . """
def __init__(self):
# Call the parent class (Sprite) constructor
super().__init__()
self.image = pygame.Surface([4, 10])
self.image.fill(BLUE)
self.rect = self.image.get_rect()
def update(self):
""" Move the bullet. """
speed_b = 3
self.rect.y -= speed_b
# --- Create the window
# Initialize Pygame
pygame.init()
# Set the height and width of the screen
screen_width = 700
screen_height = 400
screen = pygame.display.set_mode([screen_width, screen_height])
pygame.display.set_caption("Cannon Battle")
all_sprites_list = pygame.sprite.Group()
enemy_list = pygame.sprite.Group()
player_list = pygame.sprite.Group()
hand_list = pygame.sprite.Group()
hand2_list = pygame.sprite.Group()
hand3_list = pygame.sprite.Group()
hand4_list = pygame.sprite.Group()
hand5_list = pygame.sprite.Group()
bullet_list = pygame.sprite.Group()
pellet_list = pygame.sprite.Group()
enemy = Enemy()
enemy_list.add(enemy)
all_sprites_list.add(enemy_list)
hand = Hand()
hand_list.add(hand)
all_sprites_list.add(hand_list)
hand2 = Hand2()
hand2_list.add(hand2)
all_sprites_list.add(hand2)
hand3 = Hand3()
hand3_list.add(hand3)
all_sprites_list.add(hand3)
hand4 = Hand4()
hand4_list.add(hand4)
all_sprites_list.add(hand4)
hand5 = Hand5()
hand5_list.add(hand5)
all_sprites_list.add(hand5)
player = Player()
player_list.add(player)
all_sprites_list.add(player_list)
done = False
clock = pygame.time.Clock()
player.rect.y = 370
behind = pygame.image.load("grassland.png").convert()
# -------- Main Program Loop
while not done:
screen.blit(behind, [0,0])
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
time.sleep(5)
elif event.type == pygame.MOUSEBUTTONUP:
pellet = Pellet()
pellet.rect.x = enemy.rect.x
pellet.rect.y = enemy.rect.y
all_sprites_list.add(pellet)
pellet_list.add(pellet)
# --- Game logic
# Call the update() method on all the sprites
all_sprites_list.update()
for pellet in pellet_list:
player_hit_list = pygame.sprite.spritecollide(pellet,player_list,True)
if pellet.rect.y >= 510:
pellet_list.remove(pellet)
all_sprites_list.remove(pellet)
for player in player_hit_list:
done = True
print("You Lost!")
print("But thanks for playing!")
print("Made by Oankar Studios")
for bullet in bullet_list:
enemy_hit_list = pygame.sprite.spritecollide(bullet,enemy_list,True)
if bullet.rect.y <= -10:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand2.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand3.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand4.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
if bullet.rect.x == hand5.rect.x:
bullet_list.remove(bullet)
all_sprites_list.remove(bullet)
for enemy in enemy_hit_list:
done = True
print("You Won!")
print("Made by Oankar Studios")
# Clear the screen
# Draw all the spites
all_sprites_list.draw(screen)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# --- Limit to 20 frames per second
clock.tick(60)
pygame.quit()
这里是我使用time.sleep(sec)的地方,它在主程序循环中:
elif event.type == pygame.MOUSEBUTTONDOWN:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
time.sleep(5)
您可以存储最后一发子弹的时间,并忽略所有按键,直到 5 秒过去。 所以,在顶部
last_bullet_shot_time = None
然后
elif event.type == pygame.MOUSEBUTTONDOWN:
if last_bullet_shot_time is None or
time.now() - last_bullet_shot_time > datetime.timedelta(seconds = 5):
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
last_bullet_shot_time = time.now()
正如您已经发现的那样,time.sleep() 会暂停整个程序(或确切地说是线程),这通常不是您想要的。一种可能的解决方案是比较 @maniexx 提到的时间。
当您使用 pygame 时,我建议您以基本相同的方式使用 pygame.time.get_ticks(),如 this 答案中所述。
您可以使用 pygame 基于计时器生成事件的功能以及唯一的用户定义事件,让它在经过所需时间后创建通知事件。以下是您需要进行的更改:
# globals
TIMEOUT_EXPIRED = pygame.USEREVENT+1
shooting_allowed = True
然后在游戏正文中:
# in the event processing loop
elif event.type == pygame.MOUSEBUTTONDOWN:
if shooting_allowed:
bullet = Bullet()
bullet.rect.x = player.rect.x
bullet.rect.y = player.rect.y
all_sprites_list.add(bullet)
bullet_list.add(bullet)
# disable shooting for 5 seconds
shooting_allowed = False
pygame.time.set_timer(TIMEOUT_EXPIRED, 5000)
elif event.type == TIMEOUT_EXPIRED:
# re-enable shooting
shooting_allowed = True
pygame.time.set_timer(TIMEOUT_EXPIRED, 0) # stop generation of event