Pong - 当任一玩家达到分数阈值时崩溃而不是重置游戏
Pong - crashes instead of resetting the game when either player reached a score threshold
问题是每次显示获胜者文本后游戏都会崩溃(如果任一玩家的分数达到 10 或更高)并且未能重新调用 main() 函数,正如我所说的那样从我下面的代码中看到。因此,当它显示获胜者文本时,它应该暂停游戏 5 秒,然后跳出 while 循环并调用 main(),但它在显示获胜者文本后立即崩溃(见下面的屏幕截图)。获胜文本的逻辑在我的 main() 函数的顶部附近。
不确定根本原因是什么,因为我在程序顶部调用了 pygame.init()。任何帮助将不胜感激!完整的代码在下面...如果有人可以 运行 它并让我知道它崩溃的根本原因是什么,那就太好了。提前致谢!
import pygame
pygame.init()
WIDTH, HEIGHT = 750, 500
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG")
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 75])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.paddle_speed = 4
self.points = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 10])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.speed = 2
self.dx = 1
self.dy = 1
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
def redraw():
WINDOW.fill(BLACK)
font = pygame.font.SysFont("Consolas", 35)
text = font.render("---[PONG]---", 1, YELLOW)
textRect = text.get_rect()
textRect.center = (WIDTH//2, 25)
WINDOW.blit(text, textRect)
#Player 1 score
p1_score = font.render(str([paddle1.points]), 1, WHITE)
p1Rect = p1_score.get_rect()
p1Rect.center = (50, 50)
WINDOW.blit(p1_score, p1Rect)
#Player 2 score
p2_score = font.render(str([paddle2.points]), 1, WHITE)
p2Rect = p2_score.get_rect()
p2Rect.center = (700, 50)
WINDOW.blit(p2_score, p2Rect)
all_sprites.draw(WINDOW)
pygame.display.update()
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WINDOW.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT//2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(5000)
def main():
run = True
while run:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
winner_text = ""
if paddle1.points >= 10:
winner_text = "Blue Wins!"
if paddle2.points >= 10:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
# Paddle movement
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddle1.rect.y -= paddle1.paddle_speed
if key[pygame.K_s]:
paddle1.rect.y += paddle1.paddle_speed
if key[pygame.K_UP]:
paddle2.rect.y -= paddle2.paddle_speed
if key[pygame.K_DOWN]:
paddle2.rect.y += paddle2.paddle_speed
# Ensures paddles never move off the screen
if paddle1.rect.y < 0:
paddle1.rect.y = 0
if paddle1.rect.y > 425:
paddle1.rect.y = 425
if paddle2.rect.y < 0:
paddle2.rect.y = 0
if paddle2.rect.y > 425:
paddle2.rect.y = 425
# Ball movement
ball.rect.x += ball.speed * ball.dx
ball.rect.y += ball.speed * ball.dy
# Setting up collision detection with the walls by changing ball's direction
if ball.rect.y > 490:
ball.dy = -1
if ball.rect.x > 740:
ball.rect.x, ball.rect.y = 375, 250
paddle1.points += 1
if ball.rect.y < 10:
ball.dy = 1
if ball.rect.x < 10:
ball.rect.x, ball.rect.y = 375, 250
paddle2.points += 1
# Setting up collision detection with the paddles
if paddle1.rect.colliderect(ball.rect):
ball.dx = 1
if paddle2.rect.colliderect(ball.rect):
ball.dx = -1
redraw()
main()
if __name__ == "__main__":
main()
切勿递归调用应用程序循环,切勿在应用程序循环中“等待”。参见 How to wait some time in pygame? and 。
创建一个 init
函数来初始化所有游戏状态:
def init():
global paddle1, paddle2, ball, all_sprites
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
需要重启游戏时调用init
函数:
def main():
run = True
while run:
# [...]
if winner_text != "":
draw_winner(winner_text)
init()
# [...]
# main() <--- DELETE
添加一个game_over
状态并使用pygame.time.get_ticks()
to get the number of milliseconds since pygame.init()
被调用。当游戏结束时,设置状态game_over
并计算必须重新开始游戏的时间。到时候,重置 game_over
并调用 init
。根据game_over
绘制场景:
def main():
init()
winner_text = ""
restart_time = 0
game_over = False
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
current_time = pygame.time.get_ticks()
# [...]
if not game_over:
if paddle1.points >= 10:
winner_text = "Blue Wins!"
restart_time = current_time + 5000
game_over = True
if paddle2.points >= 10:
winner_text = "Red Wins!"
restart_time = current_time + 5000
game_over = True
if game_over:
draw_winner(winner_text)
if current_time > restart_time:
init()
game_over = False
else:
continue
# [...]
使用pygame.time.Clock
控制每秒帧数,从而控制游戏速度。
方法tick()
of a pygame.time.Clock
object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick()
:
This method should be called once per frame.
这意味着循环:
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
每秒运行 100 次。
完整示例:
import pygame
pygame.init()
WIDTH, HEIGHT = 750, 500
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG")
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 75])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.paddle_speed = 4
self.points = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 10])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.speed = 2
self.dx = 1
self.dy = 1
def init():
global paddle1, paddle2, ball, all_sprites
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
def redraw():
WINDOW.fill(BLACK)
font = pygame.font.SysFont("Consolas", 35)
text = font.render("---[PONG]---", 1, YELLOW)
textRect = text.get_rect()
textRect.center = (WIDTH//2, 25)
WINDOW.blit(text, textRect)
#Player 1 score
p1_score = font.render(str([paddle1.points]), 1, WHITE)
p1Rect = p1_score.get_rect()
p1Rect.center = (50, 50)
WINDOW.blit(p1_score, p1Rect)
#Player 2 score
p2_score = font.render(str([paddle2.points]), 1, WHITE)
p2Rect = p2_score.get_rect()
p2Rect.center = (700, 50)
WINDOW.blit(p2_score, p2Rect)
all_sprites.draw(WINDOW)
pygame.display.update()
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WINDOW.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT//2 - draw_text.get_height()/2))
pygame.display.update()
def main():
init()
winner_text = ""
restart_time = 0
game_over = False
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
if not game_over:
if paddle1.points >= 10:
winner_text = "Blue Wins!"
restart_time = current_time + 5000
game_over = True
if paddle2.points >= 10:
winner_text = "Red Wins!"
restart_time = current_time + 5000
game_over = True
if game_over:
draw_winner(winner_text)
if current_time > restart_time:
init()
game_over = False
else:
continue
# Paddle movement
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddle1.rect.y -= paddle1.paddle_speed
if key[pygame.K_s]:
paddle1.rect.y += paddle1.paddle_speed
if key[pygame.K_UP]:
paddle2.rect.y -= paddle2.paddle_speed
if key[pygame.K_DOWN]:
paddle2.rect.y += paddle2.paddle_speed
# Ensures paddles never move off the screen
if paddle1.rect.y < 0:
paddle1.rect.y = 0
if paddle1.rect.y > 425:
paddle1.rect.y = 425
if paddle2.rect.y < 0:
paddle2.rect.y = 0
if paddle2.rect.y > 425:
paddle2.rect.y = 425
# Ball movement
ball.rect.x += ball.speed * ball.dx
ball.rect.y += ball.speed * ball.dy
# Setting up collision detection with the walls by changing ball's direction
if ball.rect.y > 490:
ball.dy = -1
if ball.rect.x > 740:
ball.rect.x, ball.rect.y = 375, 250
paddle1.points += 1
if ball.rect.y < 10:
ball.dy = 1
if ball.rect.x < 10:
ball.rect.x, ball.rect.y = 375, 250
paddle2.points += 1
# Setting up collision detection with the paddles
if paddle1.rect.colliderect(ball.rect):
ball.dx = 1
if paddle2.rect.colliderect(ball.rect):
ball.dx = -1
redraw()
if __name__ == "__main__":
main()
首先让我们深入了解一下您的 main()
函数:
def main():
run = True
while run:
#[...]some part of code here
if winner_text != "":
draw_winner(winner_text)
break
#[...]some part of code here
main()
现在只要有人赢了 paddle1.points
= 10 或 paddle2.points
= 10
if paddle1.points >= 10:
winner_text = "Blue Wins!"
if paddle2.points >= 10:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
现在,一旦有人获胜,您的这部分代码就会被执行:
if winner_text != "":
draw_winner(winner_text)
break
因此,您只是显示“蓝色获胜”或“红色获胜”之类的文本,然后跳出 while 循环并再次调用 main()
函数,但您并未重置paddle1.points
和 paddle2.points
各为 0。
所以您的 main()
函数应该类似于:
def main():
run = True
paddle1.points = 0
paddle2.points = 0
while run:
#[...]while loop here
这是完整的工作代码:
import pygame,sys
pygame.init()
WIDTH, HEIGHT = 750, 500
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG")
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 75])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.paddle_speed = 4
self.points = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 10])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.speed = 2
self.dx = 1
self.dy = 1
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
def redraw():
WINDOW.fill(BLACK)
font = pygame.font.SysFont("Consolas", 35)
text = font.render("---[PONG]---", 1, YELLOW)
textRect = text.get_rect()
textRect.center = (WIDTH//2, 25)
WINDOW.blit(text, textRect)
#Player 1 score
p1_score = font.render(str([paddle1.points]), 1, WHITE)
p1Rect = p1_score.get_rect()
p1Rect.center = (50, 50)
WINDOW.blit(p1_score, p1Rect)
#Player 2 score
p2_score = font.render(str([paddle2.points]), 1, WHITE)
p2Rect = p2_score.get_rect()
p2Rect.center = (700, 50)
WINDOW.blit(p2_score, p2Rect)
all_sprites.draw(WINDOW)
pygame.display.update()
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WINDOW.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT//2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(5000)
def main():
run = True
paddle1.points = 0
paddle2.points = 0
while run:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
winner_text = ""
if paddle1.points >= 1:
winner_text = "Blue Wins!"
if paddle2.points >= 1:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
# Paddle movement
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddle1.rect.y -= paddle1.paddle_speed
if key[pygame.K_s]:
paddle1.rect.y += paddle1.paddle_speed
if key[pygame.K_UP]:
paddle2.rect.y -= paddle2.paddle_speed
if key[pygame.K_DOWN]:
paddle2.rect.y += paddle2.paddle_speed
# Ensures paddles never move off the screen
if paddle1.rect.y < 0:
paddle1.rect.y = 0
if paddle1.rect.y > 425:
paddle1.rect.y = 425
if paddle2.rect.y < 0:
paddle2.rect.y = 0
if paddle2.rect.y > 425:
paddle2.rect.y = 425
# Ball movement
ball.rect.x += ball.speed * ball.dx
ball.rect.y += ball.speed * ball.dy
# Setting up collision detection with the walls by changing ball's direction
if ball.rect.y > 490:
ball.dy = -1
if ball.rect.x > 740:
ball.rect.x, ball.rect.y = 375, 250
paddle1.points += 1
if ball.rect.y < 10:
ball.dy = 1
if ball.rect.x < 10:
ball.rect.x, ball.rect.y = 375, 250
paddle2.points += 1
# Setting up collision detection with the paddles
if paddle1.rect.colliderect(ball.rect):
ball.dx = 1
if paddle2.rect.colliderect(ball.rect):
ball.dx = -1
redraw()
main()
if __name__ == "__main__":
main()
虽然这可行,但我建议您按照@Rabbid76 所说的去做,因为递归调用应用程序循环从来都不是一个好的做法
问题是每次显示获胜者文本后游戏都会崩溃(如果任一玩家的分数达到 10 或更高)并且未能重新调用 main() 函数,正如我所说的那样从我下面的代码中看到。因此,当它显示获胜者文本时,它应该暂停游戏 5 秒,然后跳出 while 循环并调用 main(),但它在显示获胜者文本后立即崩溃(见下面的屏幕截图)。获胜文本的逻辑在我的 main() 函数的顶部附近。
不确定根本原因是什么,因为我在程序顶部调用了 pygame.init()。任何帮助将不胜感激!完整的代码在下面...如果有人可以 运行 它并让我知道它崩溃的根本原因是什么,那就太好了。提前致谢!
import pygame
pygame.init()
WIDTH, HEIGHT = 750, 500
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG")
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 75])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.paddle_speed = 4
self.points = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 10])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.speed = 2
self.dx = 1
self.dy = 1
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
def redraw():
WINDOW.fill(BLACK)
font = pygame.font.SysFont("Consolas", 35)
text = font.render("---[PONG]---", 1, YELLOW)
textRect = text.get_rect()
textRect.center = (WIDTH//2, 25)
WINDOW.blit(text, textRect)
#Player 1 score
p1_score = font.render(str([paddle1.points]), 1, WHITE)
p1Rect = p1_score.get_rect()
p1Rect.center = (50, 50)
WINDOW.blit(p1_score, p1Rect)
#Player 2 score
p2_score = font.render(str([paddle2.points]), 1, WHITE)
p2Rect = p2_score.get_rect()
p2Rect.center = (700, 50)
WINDOW.blit(p2_score, p2Rect)
all_sprites.draw(WINDOW)
pygame.display.update()
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WINDOW.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT//2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(5000)
def main():
run = True
while run:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
winner_text = ""
if paddle1.points >= 10:
winner_text = "Blue Wins!"
if paddle2.points >= 10:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
# Paddle movement
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddle1.rect.y -= paddle1.paddle_speed
if key[pygame.K_s]:
paddle1.rect.y += paddle1.paddle_speed
if key[pygame.K_UP]:
paddle2.rect.y -= paddle2.paddle_speed
if key[pygame.K_DOWN]:
paddle2.rect.y += paddle2.paddle_speed
# Ensures paddles never move off the screen
if paddle1.rect.y < 0:
paddle1.rect.y = 0
if paddle1.rect.y > 425:
paddle1.rect.y = 425
if paddle2.rect.y < 0:
paddle2.rect.y = 0
if paddle2.rect.y > 425:
paddle2.rect.y = 425
# Ball movement
ball.rect.x += ball.speed * ball.dx
ball.rect.y += ball.speed * ball.dy
# Setting up collision detection with the walls by changing ball's direction
if ball.rect.y > 490:
ball.dy = -1
if ball.rect.x > 740:
ball.rect.x, ball.rect.y = 375, 250
paddle1.points += 1
if ball.rect.y < 10:
ball.dy = 1
if ball.rect.x < 10:
ball.rect.x, ball.rect.y = 375, 250
paddle2.points += 1
# Setting up collision detection with the paddles
if paddle1.rect.colliderect(ball.rect):
ball.dx = 1
if paddle2.rect.colliderect(ball.rect):
ball.dx = -1
redraw()
main()
if __name__ == "__main__":
main()
切勿递归调用应用程序循环,切勿在应用程序循环中“等待”。参见 How to wait some time in pygame? and
创建一个 init
函数来初始化所有游戏状态:
def init():
global paddle1, paddle2, ball, all_sprites
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
需要重启游戏时调用init
函数:
def main():
run = True
while run:
# [...]
if winner_text != "":
draw_winner(winner_text)
init()
# [...]
# main() <--- DELETE
添加一个game_over
状态并使用pygame.time.get_ticks()
to get the number of milliseconds since pygame.init()
被调用。当游戏结束时,设置状态game_over
并计算必须重新开始游戏的时间。到时候,重置 game_over
并调用 init
。根据game_over
绘制场景:
def main():
init()
winner_text = ""
restart_time = 0
game_over = False
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
current_time = pygame.time.get_ticks()
# [...]
if not game_over:
if paddle1.points >= 10:
winner_text = "Blue Wins!"
restart_time = current_time + 5000
game_over = True
if paddle2.points >= 10:
winner_text = "Red Wins!"
restart_time = current_time + 5000
game_over = True
if game_over:
draw_winner(winner_text)
if current_time > restart_time:
init()
game_over = False
else:
continue
# [...]
使用pygame.time.Clock
控制每秒帧数,从而控制游戏速度。
方法tick()
of a pygame.time.Clock
object, delays the game in that way, that every iteration of the loop consumes the same period of time. See pygame.time.Clock.tick()
:
This method should be called once per frame.
这意味着循环:
clock = pygame.time.Clock() run = True while run: clock.tick(100)
每秒运行 100 次。
完整示例:
import pygame
pygame.init()
WIDTH, HEIGHT = 750, 500
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG")
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 75])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.paddle_speed = 4
self.points = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 10])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.speed = 2
self.dx = 1
self.dy = 1
def init():
global paddle1, paddle2, ball, all_sprites
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
def redraw():
WINDOW.fill(BLACK)
font = pygame.font.SysFont("Consolas", 35)
text = font.render("---[PONG]---", 1, YELLOW)
textRect = text.get_rect()
textRect.center = (WIDTH//2, 25)
WINDOW.blit(text, textRect)
#Player 1 score
p1_score = font.render(str([paddle1.points]), 1, WHITE)
p1Rect = p1_score.get_rect()
p1Rect.center = (50, 50)
WINDOW.blit(p1_score, p1Rect)
#Player 2 score
p2_score = font.render(str([paddle2.points]), 1, WHITE)
p2Rect = p2_score.get_rect()
p2Rect.center = (700, 50)
WINDOW.blit(p2_score, p2Rect)
all_sprites.draw(WINDOW)
pygame.display.update()
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WINDOW.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT//2 - draw_text.get_height()/2))
pygame.display.update()
def main():
init()
winner_text = ""
restart_time = 0
game_over = False
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.quit()
if not game_over:
if paddle1.points >= 10:
winner_text = "Blue Wins!"
restart_time = current_time + 5000
game_over = True
if paddle2.points >= 10:
winner_text = "Red Wins!"
restart_time = current_time + 5000
game_over = True
if game_over:
draw_winner(winner_text)
if current_time > restart_time:
init()
game_over = False
else:
continue
# Paddle movement
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddle1.rect.y -= paddle1.paddle_speed
if key[pygame.K_s]:
paddle1.rect.y += paddle1.paddle_speed
if key[pygame.K_UP]:
paddle2.rect.y -= paddle2.paddle_speed
if key[pygame.K_DOWN]:
paddle2.rect.y += paddle2.paddle_speed
# Ensures paddles never move off the screen
if paddle1.rect.y < 0:
paddle1.rect.y = 0
if paddle1.rect.y > 425:
paddle1.rect.y = 425
if paddle2.rect.y < 0:
paddle2.rect.y = 0
if paddle2.rect.y > 425:
paddle2.rect.y = 425
# Ball movement
ball.rect.x += ball.speed * ball.dx
ball.rect.y += ball.speed * ball.dy
# Setting up collision detection with the walls by changing ball's direction
if ball.rect.y > 490:
ball.dy = -1
if ball.rect.x > 740:
ball.rect.x, ball.rect.y = 375, 250
paddle1.points += 1
if ball.rect.y < 10:
ball.dy = 1
if ball.rect.x < 10:
ball.rect.x, ball.rect.y = 375, 250
paddle2.points += 1
# Setting up collision detection with the paddles
if paddle1.rect.colliderect(ball.rect):
ball.dx = 1
if paddle2.rect.colliderect(ball.rect):
ball.dx = -1
redraw()
if __name__ == "__main__":
main()
首先让我们深入了解一下您的 main()
函数:
def main():
run = True
while run:
#[...]some part of code here
if winner_text != "":
draw_winner(winner_text)
break
#[...]some part of code here
main()
现在只要有人赢了 paddle1.points
= 10 或 paddle2.points
= 10
if paddle1.points >= 10:
winner_text = "Blue Wins!"
if paddle2.points >= 10:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
现在,一旦有人获胜,您的这部分代码就会被执行:
if winner_text != "":
draw_winner(winner_text)
break
因此,您只是显示“蓝色获胜”或“红色获胜”之类的文本,然后跳出 while 循环并再次调用 main()
函数,但您并未重置paddle1.points
和 paddle2.points
各为 0。
所以您的 main()
函数应该类似于:
def main():
run = True
paddle1.points = 0
paddle2.points = 0
while run:
#[...]while loop here
这是完整的工作代码:
import pygame,sys
pygame.init()
WIDTH, HEIGHT = 750, 500
WINDOW = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("PONG")
WINNER_FONT = pygame.font.SysFont('comicsans', 100)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
class Paddle(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 75])
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.paddle_speed = 4
self.points = 0
class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface([10, 10])
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.speed = 2
self.dx = 1
self.dy = 1
paddle1 = Paddle()
paddle1.image.fill(BLUE)
paddle1.rect.x = 25
paddle1.rect.y = 225
paddle2 = Paddle()
paddle2.image.fill(RED)
paddle2.rect.x = 715
paddle2.rect.y = 225
ball = Ball()
ball.rect.x = 375
ball.rect.y = 250
all_sprites = pygame.sprite.Group()
all_sprites.add(paddle1, paddle2, ball)
def redraw():
WINDOW.fill(BLACK)
font = pygame.font.SysFont("Consolas", 35)
text = font.render("---[PONG]---", 1, YELLOW)
textRect = text.get_rect()
textRect.center = (WIDTH//2, 25)
WINDOW.blit(text, textRect)
#Player 1 score
p1_score = font.render(str([paddle1.points]), 1, WHITE)
p1Rect = p1_score.get_rect()
p1Rect.center = (50, 50)
WINDOW.blit(p1_score, p1Rect)
#Player 2 score
p2_score = font.render(str([paddle2.points]), 1, WHITE)
p2Rect = p2_score.get_rect()
p2Rect.center = (700, 50)
WINDOW.blit(p2_score, p2Rect)
all_sprites.draw(WINDOW)
pygame.display.update()
def draw_winner(text):
draw_text = WINNER_FONT.render(text, 1, WHITE)
WINDOW.blit(draw_text, (WIDTH//2 - draw_text.get_width()/2, HEIGHT//2 - draw_text.get_height()/2))
pygame.display.update()
pygame.time.delay(5000)
def main():
run = True
paddle1.points = 0
paddle2.points = 0
while run:
pygame.time.delay(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
winner_text = ""
if paddle1.points >= 1:
winner_text = "Blue Wins!"
if paddle2.points >= 1:
winner_text = "Red Wins!"
if winner_text != "":
draw_winner(winner_text)
break
# Paddle movement
key = pygame.key.get_pressed()
if key[pygame.K_w]:
paddle1.rect.y -= paddle1.paddle_speed
if key[pygame.K_s]:
paddle1.rect.y += paddle1.paddle_speed
if key[pygame.K_UP]:
paddle2.rect.y -= paddle2.paddle_speed
if key[pygame.K_DOWN]:
paddle2.rect.y += paddle2.paddle_speed
# Ensures paddles never move off the screen
if paddle1.rect.y < 0:
paddle1.rect.y = 0
if paddle1.rect.y > 425:
paddle1.rect.y = 425
if paddle2.rect.y < 0:
paddle2.rect.y = 0
if paddle2.rect.y > 425:
paddle2.rect.y = 425
# Ball movement
ball.rect.x += ball.speed * ball.dx
ball.rect.y += ball.speed * ball.dy
# Setting up collision detection with the walls by changing ball's direction
if ball.rect.y > 490:
ball.dy = -1
if ball.rect.x > 740:
ball.rect.x, ball.rect.y = 375, 250
paddle1.points += 1
if ball.rect.y < 10:
ball.dy = 1
if ball.rect.x < 10:
ball.rect.x, ball.rect.y = 375, 250
paddle2.points += 1
# Setting up collision detection with the paddles
if paddle1.rect.colliderect(ball.rect):
ball.dx = 1
if paddle2.rect.colliderect(ball.rect):
ball.dx = -1
redraw()
main()
if __name__ == "__main__":
main()
虽然这可行,但我建议您按照@Rabbid76 所说的去做,因为递归调用应用程序循环从来都不是一个好的做法