Lógica principal del juego
En este paso, implementaremos la lógica principal del juego Flappy Bird.
def mainGame(movementInfo):
score = playerIndex = loopIter = 0
playerIndexGen = movementInfo["playerIndexGen"]
playerx, playery = int(SCREENWIDTH * 0.2), movementInfo["playery"]
basex = movementInfo["basex"]
baseShift = IMAGES["base"].get_width() - IMAGES["background"].get_width()
## obtener 2 nuevas tuberías para agregar a la lista de upperPipes y lowerPipes
newPipe1 = getRandomPipe()
newPipe2 = getRandomPipe()
## lista de tuberías superiores
upperPipes = [
{"x": SCREENWIDTH + 200, "y": newPipe1[0]["y"]},
{"x": SCREENWIDTH + 200 + (SCREENWIDTH / 2), "y": newPipe2[0]["y"]},
]
## lista de tuberías inferiores
lowerPipes = [
{"x": SCREENWIDTH + 200, "y": newPipe1[1]["y"]},
{"x": SCREENWIDTH + 200 + (SCREENWIDTH / 2), "y": newPipe2[1]["y"]},
]
dt = FPSCLOCK.tick(FPS) / 1000
pipeVelX = -128 * dt
## velocidad del jugador, velocidad máxima, aceleración hacia abajo, aceleración al flap
playerVelY = -9 ## velocidad del jugador a lo largo de Y, por defecto igual a playerFlapped
playerMaxVelY = 10 ## velocidad máxima a lo largo de Y, velocidad máxima de descenso
playerMinVelY = -8 ## velocidad mínima a lo largo de Y, velocidad máxima de ascenso
playerAccY = 1 ## aceleración hacia abajo del jugador
playerRot = 45 ## rotación del jugador
playerVelRot = 3 ## velocidad angular
playerRotThr = 20 ## umbral de rotación
playerFlapAcc = -9 ## velocidad del jugador al flap
playerFlapped = False ## True cuando el jugador hace flap
while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if event.type == KEYDOWN and (event.key == K_SPACE or event.key == K_UP):
if playery > -2 * IMAGES["player"][0].get_height():
playerVelY = playerFlapAcc
playerFlapped = True
## comprobar si hay colisión aquí
crashTest = checkCrash(
{"x": playerx, "y": playery, "index": playerIndex}, upperPipes, lowerPipes
)
if crashTest[0]:
return {
"y": playery,
"groundCrash": crashTest[1],
"basex": basex,
"upperPipes": upperPipes,
"lowerPipes": lowerPipes,
"score": score,
"playerVelY": playerVelY,
"playerRot": playerRot,
}
## comprobar si hay puntaje
playerMidPos = playerx + IMAGES["player"][0].get_width() / 2
for pipe in upperPipes:
pipeMidPos = pipe["x"] + IMAGES["pipe"][0].get_width() / 2
if pipeMidPos <= playerMidPos < pipeMidPos + 4:
score += 1
## cambio de playerIndex y basex
if (loopIter + 1) % 3 == 0:
playerIndex = next(playerIndexGen)
loopIter = (loopIter + 1) % 30
basex = -((-basex + 100) % baseShift)
## rotar al jugador
if playerRot > -90:
playerRot -= playerVelRot
## movimiento del jugador
if playerVelY < playerMaxVelY and not playerFlapped:
playerVelY += playerAccY
if playerFlapped:
playerFlapped = False
## más rotación para cubrir el umbral (calculado en la rotación visible)
playerRot = 45
playerHeight = IMAGES["player"][playerIndex].get_height()
playery += min(playerVelY, BASEY - playery - playerHeight)
## mover las tuberías hacia la izquierda
for uPipe, lPipe in zip(upperPipes, lowerPipes):
uPipe["x"] += pipeVelX
lPipe["x"] += pipeVelX
## agregar una nueva tubería cuando la primera tubería está a punto de tocar el lado izquierdo de la pantalla
if 3 > len(upperPipes) > 0 and 0 < upperPipes[0]["x"] < 5:
newPipe = getRandomPipe()
upperPipes.append(newPipe[0])
lowerPipes.append(newPipe[1])
## eliminar la primera tubería si está fuera de la pantalla
if len(upperPipes) > 0 and upperPipes[0]["x"] < -IMAGES["pipe"][0].get_width():
upperPipes.pop(0)
lowerPipes.pop(0)
## dibujar sprites
SCREEN.blit(IMAGES["background"], (0, 0))
for uPipe, lPipe in zip(upperPipes, lowerPipes):
SCREEN.blit(IMAGES["pipe"][0], (uPipe["x"], uPipe["y"]))
SCREEN.blit(IMAGES["pipe"][1], (lPipe["x"], lPipe["y"]))
SCREEN.blit(IMAGES["base"], (basex, BASEY))
## mostrar el puntaje para que el jugador ocupe el puntaje
showScore(score)
## La rotación del jugador tiene un umbral
visibleRot = playerRotThr
if playerRot <= playerRotThr:
visibleRot = playerRot
playerSurface = pygame.transform.rotate(
IMAGES["player"][playerIndex], visibleRot
)
SCREEN.blit(playerSurface, (playerx, playery))
pygame.display.update()
FPSCLOCK.tick(FPS)
- Definimos la función
mainGame
, que contiene la lógica central del juego Flappy Bird.
- La función maneja la entrada del usuario, actualiza el estado del juego, comprueba las colisiones y lleva un registro del puntaje.
- El bucle del juego se ejecuta continuamente, actualizando la pantalla y la lógica del juego.
- Los controles del jugador se manejan a través de eventos de teclado (espacio o flecha hacia arriba).
- La función también comprueba las colisiones con las tuberías y el suelo, actualiza el puntaje y gestiona la animación del pájaro.
- El bucle del juego continúa hasta que el jugador choca o sale del juego.