python - 为什么在单击“开始”按钮后主循环(此代码中的“运行”)没有响应?
问题描述
我正在创建一个基本游戏。我主要有两个代码:(i)菜单(ii)基本游戏。单击“开始”按钮后,我想运行“while game_over”循环。但是我点击“开始”按钮后代码没有响应。
import pygame
import random
import sys
pygame.init()
w=800
h=600
yellow=(255,255,0)
player_size=25
player_pos=[w/2,h-(2*player_size)]
enemy_size=25
enemy_pos=[random.randint(0,w-enemy_size),0]
enemy_list=[ ]
Menu_bg_color=(34,139,34)
red=(255,0,0)
blue=(0,0,125)
bright_blue=(0,0,255)
font_size=35
b1_pos=[w/2-50,h/2]
b1_size=[105,50]
bg_color=(0,0,0)
screen=pygame.display.set_mode((w,h))
speed=10
score=0
clock=pygame.time.Clock()
myFont=pygame.font.SysFont("monospace",font_size)
Menu_myFont=pygame.font.SysFont("freesansbold.tff",font_size)
running=True
Menu_running=True
#GAME CODE
def GameCode():
global game_over
global score
global speed
global player_pos
def set_level(score,speed):
if score<10:
speed=5
elif score<20:
speed=6
elif score<30:
speed=8
elif score<40:
speed=10
elif score<50:
speed=13
elif score<200:
speed=15
else:
speed=20
return speed
def drop_enemies(enemy_list):
delay=random.random()
if len(enemy_list)<6 and delay<0.1:
x_pos=random.randint(0,w-enemy_size)
y_pos=0
enemy_list.append([x_pos,y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pygame.draw.rect(screen,blue, (enemy_pos[0],enemy_pos[1],enemy_size,enemy_size))
def update_enemy_pos(enemy_list,score):
for idx,enemy_pos in enumerate(enemy_list):
if enemy_pos[1]>=0 and enemy_pos[1]<h:
enemy_pos[1]+=speed
else:
enemy_list.pop(idx)
score+=1
return score
def detect_collision(player_pos,enemy_pos):
p_x=player_pos[0]
p_y=player_pos[1]
e_x=enemy_pos[0]
e_y=enemy_pos[1]
if (e_x>=p_x and e_x<(p_x+player_size)) or (p_x>=e_x and p_x<(e_x+enemy_size)):
if (e_y>=p_y and e_y<(p_y+player_size)) or (p_y>=e_y and p_y<(e_y+enemy_size)):
return True
return False
def collision_check(enemy_list,player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos,player_pos):
return True
return False
while game_over==False:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
if event.type==pygame.KEYDOWN:
x=player_pos[0]
y=player_pos[1]
if event.key==pygame.K_LEFT:
x-=player_size
elif event.key==pygame.K_UP:
y-=player_size
elif event.key==pygame.K_RIGHT:
x+=player_size
elif event.key==pygame.K_DOWN:
y+=player_size
player_pos=[x,y]
screen.fill(bg_color)
#screen.blit(road,(0,0))
drop_enemies(enemy_list)
score=update_enemy_pos(enemy_list,score)
speed=set_level(score,speed)
text='Your Score is:' + str(score)
label=myFont.render(text,1,yellow)
screen.blit(label,(w/2,h-40))
if collision_check(enemy_list,player_pos):
game_over=True
break
draw_enemies(enemy_list)
pygame.draw.rect(screen,red,(player_pos[0],player_pos[1],player_size,player_size))
clock.tick(30)
pygame.display.update()
pygame.display.flip()
#MENU CODE
def MenuCode():
global game_over
def button(b1_pos,b1_size):
mouse_pos=pygame.mouse.get_pos()
click=pygame.mouse.get_pressed()
if (b1_pos[0]<mouse_pos[0]<(b1_pos[0]+b1_size[0])) and (b1_pos[1]<mouse_pos[1]<(b1_pos[1]+b1_size[1])):
pygame.draw.rect(screen,bright_blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
if click[0]==1:
game_over=False
else:
pygame.draw.rect(screen,blue,(b1_pos[0],b1_pos[1],b1_size[0],b1_size[1]))
text='START'
label=Menu_myFont.render(text,1,red)
screen.blit(label,(w/2-38,h/2+5))
Menu_running=True
while Menu_running:
for event in pygame.event.get():
if event.type==pygame.QUIT:
sys.exit()
screen.fill(Menu_bg_color)
button(b1_pos,b1_size)
#button(b1_pos,b1_size,'quit')
pygame.display.update()
clock.tick(30)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
break;
screen.fill(bg_color)
if MenuCode():
if game_over==False:
GameCode()
clock.tick(30)
pygame.display.update()
解决方案
这是您的代码的实质性修改版本,没有问题。我已经修改了代码,使其紧密地遵循PEP 8 - Python 代码样式指南指南,并且还通过将它们设置为使用它们的函数的本地变量来消除您拥有的许多全局变量。
我所做的主要装饰性事情之一是确定哪些全局变量是不变的常量,哪些是其值实际发生变化的变量。之后,我将常量名称更改为全部大写(根据 PEP 8),并将具有不同值的名称移到实际使用它们的函数内部。
对菜单处理功能(现在命名)进行了最广泛的更改,menu_code()
这可能是您问题的主要来源。为了便于重写,我添加了一个MenuButton
类来在很大程度上封装它们的行为并减少重复代码。
请注意,该函数可能存在问题,game_code()
因为我没有尝试优化、测试或调试它。
希望这将为您进一步开发游戏提供良好的基础。我强烈建议您阅读并开始关注 PEP 8。
import random
import pygame as pyg
W, H = 800, 600
RED = (255, 0, 0)
BLUE = (0, 0, 125)
BRIGHT_BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
PLAYER_SIZE = 25
ENEMY_SIZE = 25
FONT_SIZE = 35
BG_COLOR = BLACK
FPS = 30
START, QUIT = 0, 1 # Button selection codes returned by menu_code()
pyg.init()
screen = pyg.display.set_mode((W, H))
pyg.display.set_caption('Basic Game')
clock = pyg.time.Clock()
game_font = pyg.font.SysFont("monospace", FONT_SIZE)
menu_font = pyg.font.SysFont("freesansbold.ttf", FONT_SIZE)
def game_code():
enemy_pos = [random.randint(0, W-ENEMY_SIZE), 0]
enemy_list = []
game_over = False
player_pos = [W/2, H - 2*PLAYER_SIZE]
score = 0
speed = 10
def get_speed(score):
if score < 10:
speed = 5
elif score < 20:
speed = 6
elif score < 30:
speed = 8
elif score < 40:
speed = 10
elif score < 50:
speed = 13
elif score < 200:
speed = 15
else:
speed = 20
return speed
def drop_enemies(enemy_list):
delay = random.random()
if len(enemy_list) < 6 and delay < 0.1:
x_pos = random.randint(0, W-ENEMY_SIZE)
y_pos = 0
enemy_list.append([x_pos, y_pos])
def draw_enemies(enemy_list):
for enemy_pos in enemy_list:
pyg.draw.rect(screen, BLUE,
(enemy_pos[0], enemy_pos[1], ENEMY_SIZE, ENEMY_SIZE))
def update_enemy_pos(enemy_list, score):
for idx, enemy_pos in enumerate(enemy_list):
if enemy_pos[1] >= 0 and enemy_pos[1] < H:
enemy_pos[1] += speed
else:
enemy_list.pop(idx)
score += 1
return score
def detect_collision(player_pos, enemy_pos):
p_x, p_y = player_pos
e_x, e_y = enemy_pos
if ((e_x >= p_x and e_x < (p_x + PLAYER_SIZE))
or (p_x >= e_x and p_x < (e_x + ENEMY_SIZE))):
if ((e_y >= p_y and e_y < (p_y+PLAYER_SIZE))
or (p_y >= e_y and p_y < (e_y + ENEMY_SIZE))):
return True
return False
def collision_check(enemy_list, player_pos):
for enemy_pos in enemy_list:
if detect_collision(enemy_pos, player_pos):
return True
return False
while not game_over:
for event in pyg.event.get():
if event.type == pyg.QUIT:
game_over = True
break
if event.type == pyg.KEYDOWN:
x = player_pos[0]
y = player_pos[1]
if event.key == pyg.K_LEFT:
x -= PLAYER_SIZE
elif event.key == pyg.K_UP:
y -= PLAYER_SIZE
elif event.key == pyg.K_RIGHT:
x += PLAYER_SIZE
elif event.key == pyg.K_DOWN:
y += PLAYER_SIZE
player_pos = [x, y]
screen.fill(BG_COLOR)
drop_enemies(enemy_list)
score = update_enemy_pos(enemy_list, score)
speed = get_speed(score)
text = 'Your Score is:' + str(score)
label = game_font.render(text, 1, YELLOW)
screen.blit(label, (W/2, H-40))
if collision_check(enemy_list, player_pos):
game_over = True
break
draw_enemies(enemy_list)
pyg.draw.rect(screen, RED,
(player_pos[0], player_pos[1], PLAYER_SIZE, PLAYER_SIZE))
clock.tick(FPS)
pyg.display.update()
# pyg.display.flip() # Don't do both update() and flip().
class MenuButton:
def __init__(self, text, value, rect):
self.text = text
self.value = value
self.rect = rect
def draw(self):
# Background color determined by whether mouse is positioned over label.
mouse_pos = pyg.mouse.get_pos()
fg_color = RED
bg_color = BRIGHT_BLUE if self.rect.collidepoint(mouse_pos) else BLUE
pyg.draw.rect(screen, bg_color, self.rect)
pyg.draw.rect(screen, YELLOW, self.rect, 1) # Draw a border.
label = menu_font.render(self.text, 1, fg_color)
# Center lable text inside its rectangle.
txw, txh = menu_font.size(self.text)
screen.blit(label, (self.rect.left + txw/2, self.rect.top + txh/2))
def menu_code():
MENU_BG_COLOR = (34, 139, 34)
LABEL_SIZE = LABEL_WIDTH, LABEL_HEIGHT = (105, 50)
B1_RECT = pyg.Rect((W/2 - LABEL_WIDTH/2, H/2 - LABEL_HEIGHT/2), LABEL_SIZE)
B2_RECT = pyg.Rect((W/2 - LABEL_WIDTH/2, H/2 + LABEL_HEIGHT/2), LABEL_SIZE)
MENU_BUTTONS = [MenuButton('Start', START, B1_RECT),
MenuButton('Quit', QUIT, B2_RECT)]
choice = None
while choice is None:
screen.fill(MENU_BG_COLOR)
for button in MENU_BUTTONS:
button.draw()
for event in pyg.event.get():
if event.type == pyg.QUIT:
choice = QUIT
# Handle left mouse button clicks.
if event.type == pyg.MOUSEBUTTONDOWN and event.button == 1:
for button in MENU_BUTTONS:
if button.rect.collidepoint(event.pos):
choice = button.value
break
pyg.display.update()
clock.tick(FPS)
return choice
# Main loop.
running = True
while running:
for event in pyg.event.get():
if event.type == pyg.QUIT:
running = False
break;
screen.fill(BG_COLOR)
choice = menu_code()
if choice == START:
game_code()
if choice == QUIT:
running = False
pyg.display.update()
clock.tick(FPS)
推荐阅读
- c# - 如何重置 ASP.NET MVC 中验证属性的格式化错误消息?
- ruby-on-rails - 从数组数据创建反应组件
- apache-flink - 如何在 Flink 中实现键控窗口超时?
- scrapy - 如何使用scrapy仅提取每个标签的一个元素?
- html - html 自动输入检测和重定向
- azure - 在 azure 数据工厂中创建通用/参数化触发器
- node.js - socket.io - 需要 socket.io 时在严格模式下使用 const
- imagemagick - 需要将背景设置为非使用 Imagick
- amazon-web-services - ec2 实例在未完成生命周期操作的情况下终止
- jointjs - 将元素粘贴到 Rappid 中的另一个图表?