python - 如何在pygame中创建再次播放按钮
问题描述
所以我用 pygame 创建了太空入侵者,并想在玩家死亡时创建一个退出并再次播放按钮。退出按钮有效,但再次播放按钮无效。我没有为按钮使用 def,而是在代码中制作了它。这是我的代码:
import pygame
import random
import math
pygame.init()
screen = pygame.display.set_mode((800, 600)) # CREATING SCREEN
background = pygame.image.load('background.jpg')
pygame.display.set_caption("Space invaders") # Title of the game
icon = pygame.image.load('spaceship.png') # A variable for the icon of the game
pygame.display.set_icon(icon) # to display the icon
player_icon = pygame.image.load('space-invaders.png') # A variable for player's icon
playerX = 365 # X coordinate
playerY = 500 # Y coordinate
playerX_change = 0
def player(x, y):
screen.blit(player_icon,(x, y)) # Function to display player_icon {there is supposed to be a comma after image name}
enemy_icon = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change =[]
num_of_enemies = 5
for i in range(num_of_enemies):
enemy_icon.append(pygame.image.load('alien.png')) # A variable for enemy's's icon
enemyX.append(random.randint(0,736)) # X coordinate
enemyY.append(random.randint(50 ,150)) # Y coordinate
enemyX_change.append(2)
enemyY_change.append(40)
def enemy(x, y, i):
screen.blit(enemy_icon[i], (x, y)) # Function to display enemy_icon {there is supposed to be a comma after image name}
bullet_icon = pygame.image.load('bullet.png') # A variable for enemy's's icon
bulletX = 0 # X coordinate
bulletY = 480 # Y coordinate
bulletX_change = 0
bulletY_change = 5
bullet_state = "ready"
score_value = 0
font = pygame.font.Font('freesansbold.ttf',32)
textX = 10
textY = 10
red = (200, 0, 0)
brigth_red = (255,0 ,0)
green = (0, 200, 0)
brigth_green = (0, 255, 0)
blue = (0, 0, 255)
white = (255,255,255)
black = (0, 0 ,0)
def show_score(x,y):
score = font.render('Score: ' + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
over_text = pygame.font.Font('freesansbold.ttf',128)
def game_over_text():
over_text = font.render('GAME OVER !!' , True, (255, 255, 255))
screen.blit(over_text, (300, 150))
def on_button(x,y,text =''):
button_text = pygame.font.Font('freesansbold.ttf', 5)
button_text = font.render(text, True, (black))
screen.blit(button_text, ((x + 5), (y + 5)))
def bullet(x, y):
screen.blit(bullet_icon, (x, y)) # Function to display enemy_icon {there is supposed to be a comma after image name}
def fire_bullet(x,y):
global bullet_state
bullet_state = "fire"
screen.blit(bullet_icon, (x+19, y+10))
def iscoalision(bulletX,bulletY,enemyX,enemyY):
distance = math.sqrt(math.pow(enemyX - bulletX,2) + math.pow(enemyY-bulletY,2))
if distance < 25:
return True
else:
return False
running = True
game_state = "not working"
while running :
screen.fill((0, 0, 0)) # to fill the screen with some color RGB = (red,green,blue)
screen.blit(background, (0,0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
round = 11
if event.type == pygame.KEYDOWN: # If arrow key is pressed change value of playerX_change
if event.key == pygame.K_LEFT:
playerX_change = -3
if event.key == pygame.K_RIGHT:
playerX_change = 3
if event.key == pygame.K_SPACE:
if bullet_state is "ready":
bulletX = playerX
fire_bullet(bulletX,bulletY)
if event.type == pygame.KEYUP: # If arrow key is released stop changing value of playerX_change
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
playerX += playerX_change #player movement
if playerX <= 0: #(The boundary)
playerX = 0
elif playerX >= 736: #( " )
playerX = 736
for i in range(num_of_enemies):
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if 100 + 200 > mouse[0] > 100 and 300 + 50 > mouse[1] > 300: # This is where i try to make play again button
pygame.draw.rect(screen, brigth_green, (100, 300, 200, 50)) # inside the bracket(x-axis , y-axis , width, hieght)
if click[0] == 1: #the tuple for clicks is (0,0,0) [0] = left click ,[1]= middle click. if clicked [0] or [1] or [2] = 1
pass
else:
pygame.draw.rect(screen, green, (100, 300, 200, 50))
on_button(100,300,'play again?')
if 500+ 200 >mouse[0] > 500 and 300 +50 >mouse[1] > 300:
pygame.draw.rect(screen, brigth_red, (500, 300, 200, 50))
if click[0] == 1:
running = False
break
else:
pygame.draw.rect(screen, red, (500, 300, 200, 50))
on_button((500 + 50),(300 + 5),"I QUIT")
enemyX[i] += enemyX_change[i] #enemy movement
if enemyX[i] <= 0: #(The boundary two and fro movement)
enemyX_change[i] = 2
enemyY[i] += enemyY_change[i]
elif enemyX[i] >= 736: #( " )
enemyX_change[i] = -2
enemyY[i] += enemyY_change[i]
coalision = iscoalision(bulletX, bulletY, enemyX[i], enemyY[i])
if coalision:
bullet_state = "ready"
bulletY = 480
score_value += 1
enemyX[i] = random.randint(0, 736)
enemyY[i] = random.randint(50, 150)
enemy(enemyX[i], enemyY[i], i)
if bulletY <= 0:
bullet_state = "ready"
bulletY = 480
if bullet_state is "fire":
fire_bullet(bulletX,bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(textX, textY)
pygame.display.update()
到现在为止,我已经尝试将整个 while 循环放在一个 if 条件中,如果条件满足,然后运行 while 循环,但这不起作用。我还尝试将整个代码放入 def 中,并在我需要再次播放时调出 def 并且有效,但这使子弹出现错误,我无法修复。这是播放 agin 按钮和功能。
for i in range(num_of_enemies):
if enemyY[i] > 440:
for j in range(num_of_enemies):
enemyY[j] = 2000
game_over_text()
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if 100 + 200 > mouse[0] > 100 and 300 + 50 > mouse[1] > 300:
pygame.draw.rect(screen, brigth_green, (100, 300, 200, 50))
if click[0] == 1:
pass
现在我用pass填充了按钮功能的位置。希望这么多信息有帮助。
解决方案
首先,使您的代码面向对象。如果你不知道那是什么,youtube上有很多教程,但是看看你的代码,我可以看到如果你继续不使用任何类型的课程,你将来会遇到一堆头痛和对象。您应该为玩家、敌人和子弹创建一个类,然后定义它们的属性并调用它们的方法,例如 move() 或 draw()。
要回答您的问题,您可以创建一个简单的按钮类:
class Buttons(object):
def __init__(self, x, y, width, height, colour1, text='', func=None, arg=None): # pink buttons
self.x = x
self.y = y
self.width = width
self.height = height
self.colour1 = colour1
self.text = text
self.func = func
self.arg = arg
def draw(self, win): # draws centralised buttons and text
font = pygame.font.SysFont('comicsans', 30, True)
text = font.render(self.text, 1, colours["black"])
pygame.draw.rect(win, self.colour1,
(int(self.x - self.width // 2), int(self.y - self.height // 2), int(self.width), int(self.height)))
win.blit(text, (int(self.x - text.get_width() // 2), int(self.y - text.get_height() // 2)))
def isover(self, pos): # detects if mouse positions is above buttons'
if self.x < pos[0] < (self.x + self.width) and self.y < pos[1] < (self.y + self.height):
return True
return False
def isclicked(self, pos): # pos here is mouse position
if self.isover(pos):
if self.arg is not None:
self.func(*self.arg):
else:
self.func():
def quit(your_quit_args):
# this is your quit function. You might want to close any files, etc before quitting
def play_again(your_play_again_args):
# here, you should reset all values, clear queues, lists etc
然后,要创建一个按钮,您只需创建一个新的按钮对象:
# use the x, y, width, height, colour and text you want
btn_play_again = Button(x, y, width, height, colour, text=your_text, func=quit, args=your_quit_args)
btn_quit = Button(x, y, width, height, colour, text=your_text, func=play_again, args=your_play_again_args)
以上将创建按钮对象,但您必须实际绘制它们并检查它们是否被单击,您应该在主循环中执行此操作:
while running:
# everything else
btn_quit.draw(screen)
btn_play_again.draw(screen)
pos = pygame.mouse.get_pos()
btn_quit.isclicked(pos)
btn_play_Again.draw(pos)
pygame.display.update()
请注意,如果您有很多按钮,可能值得将它们全部放在一个按钮列表中并遍历它以避免重复代码。
推荐阅读
- ruby-on-rails - 从路由名称查找路由的定义位置
- android - 实现共享位置地点选择器,与没有地点选择器的 WhatsApp 相同,因为它已被弃用
- vagrant - 运行厨房测试时无法接受许可证
- c# - 如何查找数字(在最小-最大范围内)和等于数字总和=一个数字的所有序列
- android - AzureSpatialAnchors 基本演示不保存
- javascript - 如何在没有引导程序的情况下使图像在较低分辨率上正确定位?
- r - 当一些文件包含错误时并行处理运行多个文件
- python - 如何将自定义字段添加到 ModelView (flask-appbuild)
- reactjs - 如何使用 yup 和 formik 有条件地验证
- fork - FORK 不适用于 root 用户以外的用户