Вы можете использовать переменную state = 'INTRO'/'GAME'/'GAMEOVER'
или отдельные переменные is_intro = True/False
, is_game = True/False
, is_gameover = True/False
, is_pause = True/False
, чтобы управлять тем, какой код выполняется в основном l oop
Это также потребует функции reset_all_values
, которые используют global
для сброса внешних / глобальных значений.
Примерно так.
import pygame
def reset_all_values():
global scoreA
global scoreB
scoreA = 0
scoreB = 0
# reset other values
# --- main ---
size = (700, 500)
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
font = pygame.font.Font(None, 50)
reset_all_values()
# -------- Main Program Loop -----------
state = 'INTRO'
carry_on = True
while carry_on:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
if state == 'INTRO':
if event.key == pygame.K_ESCAPE:
state = 'GAME'
reset_all_values() #
# other keys for intro
elif state == 'GAME':
if event.key == pygame.K_ESCAPE:
state = 'GAMEOVER'
# other keys for game
elif state == 'GAMEOVER':
if event.key == pygame.K_ESCAPE:
state = 'INTRO'
#reset_all_values() # TODO
# other keys for gameover
# --- changes/moves/collisions ---
if state == 'INTRO':
pass
elif state == 'GAME':
scoreA += 1
if scoreA >= 100:
state = 'GAMEOVER'
elif state == 'GAMEOVER':
pass
# --- draws ---
screen.fill((0,0,0))
if state == 'INTRO':
text = font.render('INTRO - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
elif state == 'GAME':
text = font.render('GAME - Wait for Score 100', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
elif state == 'GAMEOVER':
text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
pygame.display.flip()
clock.tick(30)
pygame.quit()
Вы также можете поместить код в такие функции, как intro_event_handle()
, intro_change()
, intro_draw()
и др. 1039 *. чтобы сделать его более читабельным.
import pygame
def intro_handle_event(event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'GAME'
reset_all_values() #
# other keys for intro
def game_handle_event(event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'GAMEOVER'
# other keys for game
def gameover_handle_event(event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'INTRO'
# other keys for gameover
def intro_change():
pass
def game_change():
global state
global scoreA
scoreA += 1
if scoreA >= 100:
state = 'GAMEOVER'
def gameover_change():
pass
def intro_draw(screen):
text = font.render('INTRO - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
def game_draw(screen):
text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
def gameover_draw(screen):
text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
def reset_all_values():
global scoreA
global scoreB
scoreA = 0
scoreB = 0
# reset other values
# --- main ---
size = (700, 500)
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
font = pygame.font.Font(None, 50)
reset_all_values()
# -------- Main Program Loop -----------
state = 'INTRO'
carry_on = True
while carry_on:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
if state == 'INTRO':
intro_handle_event(event)
elif state == 'GAME':
game_handle_event(event)
elif state == 'GAMEOVER':
gameover_handle_event(event)
# --- changes/moves/collisions ---
if state == 'INTRO':
intro_change()
elif state == 'GAME':
game_change()
elif state == 'GAMEOVER':
gameover_change()
# --- draws ---
screen.fill((0,0,0))
if state == 'INTRO':
intro_draw(screen)
elif state == 'GAME':
game_draw(screen)
elif state == 'GAMEOVER':
gameover_draw(screen)
pygame.display.flip()
clock.tick(30)
pygame.quit()
Вы можете хранить функции в словаре
handle_event = {
'INTRO': intro_handle_event,
'GAME': game_handle_event,
'GAMEOVER': gameover_handle_event,
}
и использовать только state
(вместо if/elif
) для выполнения правильной функции.
handle_event[state](event)
import pygame
def intro_handle_event(event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'GAME'
reset_all_values() #
# other keys for intro
def game_handle_event(event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'GAMEOVER'
# other keys for game
def gameover_handle_event(event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'INTRO'
# other keys for gameover
def intro_change():
pass
def game_change():
global state
global scoreA
scoreA += 1
if scoreA >= 100:
state = 'GAMEOVER'
def gameover_change():
pass
def intro_draw(screen):
text = font.render('INTRO - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
def game_draw(screen):
text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
def gameover_draw(screen):
text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
def reset_all_values():
global scoreA
global scoreB
scoreA = 0
scoreB = 0
# reset other values
# --- main ---
size = (700, 500)
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
font = pygame.font.Font(None, 50)
reset_all_values()
handle_event = {
'INTRO': intro_handle_event,
'GAME': game_handle_event,
'GAMEOVER': gameover_handle_event,
}
change = {
'INTRO': intro_change,
'GAME': game_change,
'GAMEOVER': gameover_change,
}
draw = {
'INTRO': intro_draw,
'GAME': game_draw,
'GAMEOVER': gameover_draw,
}
# -------- Main Program Loop -----------
state = 'INTRO'
carry_on = True
while carry_on:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
handle_event[state](event)
# --- changes/moves/collisions ---
change[state]()
# --- draws ---
screen.fill((0,0,0))
draw[state](screen)
pygame.display.flip()
clock.tick(30)
pygame.quit()
In similar way you can keep it in classes.
import pygame
class Intro():
def __inti__(self):
self.reset()
def reset(self):
pass
def handle_event(self, event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'GAME'
scene[state].reset()
# other keys for intro
def change(self):
pass
def draw(self, screen):
text = font.render('INTRO - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
class Game():
def __inti__(self):
self.reset()
def reset(self):
global scoreA
global scoreB
scoreA = 0
scoreB = 0
# reset other values
def handle_event(self, event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'GAMEOVER'
scene[state].reset()
# other keys for game
def change(self):
global state
global scoreA
scoreA += 1
if scoreA >= 100:
state = 'GAMEOVER'
scene[state].reset()
def draw(self, screen):
text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
class GameOver():
def __inti__(self):
self.reset()
def reset(self):
pass
def handle_event(self, event):
global state
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
state = 'INTRO'
scene[state].reset()
# other keys for gameover
def change(self):
pass
def draw(self, screen):
text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
# --- main ---
size = (700, 500)
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
font = pygame.font.Font(None, 50)
scene = {
'INTRO': Intro(),
'GAME': Game(),
'GAMEOVER': GameOver(),
}
# -------- Main Program Loop -----------
state = 'INTRO'
carry_on = True
while carry_on:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carryOn = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
scene[state].handle_event(event)
# --- changes/moves/collisions ---
scene[state].change()
# --- draws ---
screen.fill((0,0,0))
scene[state].draw(screen)
pygame.display.flip()
clock.tick(30)
pygame.quit()
Таким образом, вы строите Finite State Machine
Другим методом может быть создание отдельных циклов для каждого состояния и помещение его во внешний l oop, который запустит выбранное l oop или выйдет из игры.
import pygame
def intro_loop(screen):
print('start intro loop')
carry_on = True
next_state = None
while carry_on and not next_state:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carry_on = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
if event.key == pygame.K_ESCAPE:
next_state = 'GAME'
# --- changes/moves/collisions ---
# --- draws ---
screen.fill((0,0,0))
text = font.render('INTRO - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
pygame.display.flip()
clock.tick(30)
return carry_on, next_state
def game_loop(screen):
global scoreA
global scoreB
scoreA = 0
scoreB = 0
# reset other values
print('start game loop')
carry_on = True
next_state = None
while carry_on and not next_state:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carry_on = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
if event.key == pygame.K_ESCAPE:
next_state = 'GAMEOVER'
# --- changes/moves/collisions ---
scoreA += 1
if scoreA >= 100:
next_state = 'GAMEOVER'
# --- draws ---
screen.fill((0,0,0))
text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
pygame.display.flip()
clock.tick(30)
return carry_on, next_state
def gameover_loop(screen):
print('start gameover loop')
carry_on = True
next_state = None
while carry_on and not next_state:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
carry_on = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_x:
carry_on = False
if event.key == pygame.K_ESCAPE:
next_state = 'INTRO'
# --- changes/moves/collisions ---
# --- draws ---
screen.fill((0,0,0))
text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
rect = text.get_rect(center=screen.get_rect().center)
screen.blit(text, rect)
text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
rect = text.get_rect()
screen.blit(text, rect)
pygame.display.flip()
clock.tick(30)
return carry_on, next_state
# --- main ---
size = (700, 500)
pygame.init()
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()
font = pygame.font.Font(None, 50)
# -------- Main Program Loop -----------
state = 'INTRO'
carry_on = True
while carry_on:
if state == 'INTRO':
carry_on, state = intro_loop(screen)
elif state == 'GAME':
carry_on, state = game_loop(screen)
elif state == 'GAMEOVER':
carry_on, state = gameover_loop(screen)
pygame.quit()