#python #pygame
#python #pygame
Вопрос:
Итак, я некоторое время пытался это сделать. Я хочу, чтобы основной цикл завершился / игра завершилась, как только player
он достиг границы экрана, но, похоже, не могу понять, как я это сделаю. Вот что у меня есть на данный момент:
import pygame
pygame.init()
class Player(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([25, 25])
self.image.fill(color)
self.color = color
self.rect = self.image.get_rect()
def moveRight(self, pixels):
if self.rect.x pixels > 500 - 25:
self.rect.x = 500 - 25
self.rect.x = pixels
def moveLeft(self, pixels):
if self.rect.x - pixels < 0:
self.rect.x = 0
else:
self.rect.x -= pixels
def moveUp(self, pixels):
if self.rect.y - pixels < 0:
self.rect.y = 0
else:
self.rect.y -= pixels
def moveDown(self, pixels):
if self.rect.y pixels > 500 - 25:
self.rect.y = 500 - 25
else:
self.rect.y = pixels
# Color
red = (255, 0, 0)
white = (255, 255, 255)
screen = pygame.display.set_mode([500,500])
# Sprite List
sprite_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
# Player
player = Player(red)
player.rect.x = 250
player.rect.y = 250
sprite_list.add(player)
notDone = True
clock = pygame.time.Clock()
while notDone:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
notDone = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
player.moveLeft(3)
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
player.moveRight(3)
if keys[pygame.K_UP] or keys[pygame.K_w]:
player.moveUp(3)
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
player.moveDown(3)
screen.fill(white)
sprite_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
В моем примере player
спрайт может перемещаться вверх, вниз, влево и вправо. Персонаж также не может перемещаться за границу. Есть ли способ завершить цикл (как если бы игра закончилась), как только спрайт достиг указанной границы?
Ответ №1:
Если вы хотите завершить игру, когда прямая линия игрока коснется края экрана, тогда нет смысла исправлять положение игрока, если игрок выходит за пределы. В любом случае было бы проще использовать Rect.clamp_ip
.
Что касается выхода из игры, самый простой способ — поместить ваш основной цикл в функцию и на всякий return
случай, если вы захотите выйти.
Чтобы проверить, «покидает» ли прямоугольник (например, игрока) другой прямоугольник (например, прямоугольник экрана), вы можете использовать Rect.contains
функцию.
import pygame
class Player(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([25, 25])
self.image.fill(color)
self.rect = self.image.get_rect()
def moveRight(self, pixels):
self.rect.x = pixels
def moveLeft(self, pixels):
self.rect.x -= pixels
def moveUp(self, pixels):
self.rect.y -= pixels
def moveDown(self, pixels):
self.rect.y = pixels
def main():
pygame.init()
screen = pygame.display.set_mode([500,500])
# Sprite List
sprite_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
# Player
player = Player('red')
player.rect.x = 250
player.rect.y = 250
sprite_list.add(player)
clock = pygame.time.Clock()
while True:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
player.moveLeft(3)
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
player.moveRight(3)
if keys[pygame.K_UP] or keys[pygame.K_w]:
player.moveUp(3)
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
player.moveDown(3)
if not screen.get_rect().contains(player.rect):
return
screen.fill('white')
sprite_list.draw(screen)
pygame.display.flip()
clock.tick(60)
main()
Комментарии:
1. Возможно ли это без основного цикла внутри функции? Или это работает только так?
2. Для использования
return
вам придется использовать функцию. Конечно, есть и другие способы прервать основной цикл, например, вы устанавливаете флаг, вызываетеsys.exit
илиquit
и т. Д. Но я предпочитаю способ функции / возврата, потому что он работает с вложенными циклами, гарантирует, что после обработки событий ничего плохого не произойдет (распространенная ошибка, которую вы ежедневно видите на SO, заключается в том, что люди звонятpygame.quit()
, а затем вызывают другие функции pygame после этого), и делает именно то, что он должен делать (завершение основного цикла) безвыход из всего приложения. Но, в конце концов, это зависит от вас.3. Проблема в том, что когда игра «завершается», экран не закрывается. Вместо этого экран полностью зависает, и я ничего не могу сделать, кроме выхода через окно оболочки. (Я использую Python IDLE для этого кода) Это должно произойти?
4. О, неважно. Если я добавлю
pygame.quit()
передreturn
функцией, игра завершится без проблем. Спасибо за вашу помощь.5. Обычно вам не нужно вызывать
pygame.quit()
; ЗА исключением случаев использования IDLE . Я не знаю почему, и я обычно не использую IDLE.
Ответ №2:
Методы move
* Player
класса должны возвращать логическое значение, указывающее, попал ли игрок в стену. Возврат True
, если игрок попадает в стену, False
в противном случае:
class Player(pygame.sprite.Sprite):
# [...]
def moveRight(self, pixels):
if self.rect.x pixels > 500 - 25:
self.rect.x = 500 - 25
return True
self.rect.x = pixels
return False
def moveLeft(self, pixels):
if self.rect.x - pixels < 0:
self.rect.x = 0
return True
self.rect.x -= pixels
return False
def moveUp(self, pixels):
if self.rect.y - pixels < 0:
self.rect.y = 0
return True
self.rect.y -= pixels
return False
def moveDown(self, pixels):
if self.rect.y pixels > 500 - 25:
self.rect.y = 500 - 25
return True
self.rect.y = pixels
return False
Оцените возвращаемое значение в цикле приложения и установите notDone = False
, касается ли проигрыватель стены:
while notDone:
# [...]
hit = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
hit = player.moveLeft(3)
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
hit = player.moveRight(3)
if keys[pygame.K_UP] or keys[pygame.K_w]:
hit = player.moveUp(3)
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
hit = player.moveDown(3)
if hit:
notDone = False
# [...]
Полный пример
import pygame
pygame.init()
class Player(pygame.sprite.Sprite):
def __init__(self, color):
super().__init__()
self.image = pygame.Surface([25, 25])
self.image.fill(color)
self.color = color
self.rect = self.image.get_rect()
def moveRight(self, pixels):
if self.rect.x pixels > 500 - 25:
self.rect.x = 500 - 25
return True
self.rect.x = pixels
return False
def moveLeft(self, pixels):
if self.rect.x - pixels < 0:
self.rect.x = 0
return True
self.rect.x -= pixels
return False
def moveUp(self, pixels):
if self.rect.y - pixels < 0:
self.rect.y = 0
return True
self.rect.y -= pixels
return False
def moveDown(self, pixels):
if self.rect.y pixels > 500 - 25:
self.rect.y = 500 - 25
return True
self.rect.y = pixels
return False
# Color
red = (255, 0, 0)
white = (255, 255, 255)
screen = pygame.display.set_mode([500,500])
# Sprite List
sprite_list = pygame.sprite.Group()
block_list = pygame.sprite.Group()
# Player
player = Player(red)
player.rect.x = 250
player.rect.y = 250
sprite_list.add(player)
notDone = True
clock = pygame.time.Clock()
while notDone:
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
notDone = False
hit = False
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] or keys[pygame.K_a]:
hit = player.moveLeft(3)
if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
hit = player.moveRight(3)
if keys[pygame.K_UP] or keys[pygame.K_w]:
hit = player.moveUp(3)
if keys[pygame.K_DOWN] or keys[pygame.K_s]:
hit = player.moveDown(3)
if hit:
notDone = False
screen.fill(white)
sprite_list.draw(screen)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Комментарии:
1. Я не знаю, что я делаю не так, но по какой-то причине, когда мой проигрыватель достигает границы, он по-прежнему не возвращает true .
2. @Видимо, я добавил полный пример кода к ответу. Пример протестирован и работает нормально.