Cómo crear el juego Pong con Python y Turtle

Actualizado el: 11/07/2026
Tempo de leitura: 4 minutos
Projeto clássico do jogo Pong desenvolvido com Python

Pong es uno de los proyectos más útiles para aprender programación de juegos. Su mecánica es sencilla: dos paletas controlan una pelota que rebota y cada jugador intenta evitar que salga por su lado. Detrás de esa idea aparecen conceptos importantes como coordenadas, eventos de teclado, bucle de juego, colisiones, velocidad, puntuación y separación del código en funciones.

Para seguir esta guía conviene revisar el tutorial de Turtle en Python, el proyecto de Snake con Turtle, los fundamentos de funciones, la explicación de bucles y la guía de programación orientada a objetos.

Las referencias externas principales son la documentación oficial de turtle y la documentación oficial del módulo time, que utilizaremos para controlar la velocidad del bucle.

Crear la ventana

import turtle

pantalla = turtle.Screen()
pantalla.title("Pong con Python")
pantalla.bgcolor("black")
pantalla.setup(width=900, height=600)
pantalla.tracer(0)

tracer(0) desactiva el refresco automático. Después actualizaremos la ventana una vez por iteración mediante pantalla.update(). Esto evita parpadeos y proporciona un movimiento más uniforme.

Crear una función para las paletas

def crear_paleta(x, y):
    paleta = turtle.Turtle()
    paleta.speed(0)
    paleta.shape("square")
    paleta.color("white")
    paleta.shapesize(stretch_wid=5, stretch_len=1)
    paleta.penup()
    paleta.goto(x, y)
    return paleta


paleta_izquierda = crear_paleta(-400, 0)
paleta_derecha = crear_paleta(400, 0)

La forma cuadrada se estira verticalmente. penup() impide que el objeto dibuje líneas al moverse.

Crear la pelota

pelota = turtle.Turtle()
pelota.speed(0)
pelota.shape("circle")
pelota.color("white")
pelota.penup()
pelota.goto(0, 0)

pelota.dx = 4
pelota.dy = 4

dx y dy representan el desplazamiento horizontal y vertical por fotograma. Turtle permite añadir atributos a la instancia, aunque en un proyecto mayor sería más claro crear una clase.

Mover las paletas

LIMITE_Y = 240
PASO_PALETA = 30


def subir_izquierda():
    nuevo_y = min(
        LIMITE_Y,
        paleta_izquierda.ycor() + PASO_PALETA,
    )
    paleta_izquierda.sety(nuevo_y)


def bajar_izquierda():
    nuevo_y = max(
        -LIMITE_Y,
        paleta_izquierda.ycor() - PASO_PALETA,
    )
    paleta_izquierda.sety(nuevo_y)

Los límites evitan que la paleta salga de la ventana. Crea funciones equivalentes para la derecha:

def subir_derecha():
    paleta_derecha.sety(
        min(LIMITE_Y, paleta_derecha.ycor() + PASO_PALETA)
    )


def bajar_derecha():
    paleta_derecha.sety(
        max(-LIMITE_Y, paleta_derecha.ycor() - PASO_PALETA)
    )

Configurar el teclado

pantalla.listen()
pantalla.onkeypress(subir_izquierda, "w")
pantalla.onkeypress(bajar_izquierda, "s")
pantalla.onkeypress(subir_derecha, "Up")
pantalla.onkeypress(bajar_derecha, "Down")

En onkeypress se pasa la función sin paréntesis. Si escribes subir_izquierda(), la función se ejecutará al registrar el evento y no cuando se pulse la tecla.

Crear el marcador

puntos_izquierda = 0
puntos_derecha = 0

marcador = turtle.Turtle()
marcador.speed(0)
marcador.color("white")
marcador.penup()
marcador.hideturtle()
marcador.goto(0, 250)


def actualizar_marcador():
    marcador.clear()
    marcador.write(
        f"{puntos_izquierda}  |  {puntos_derecha}",
        align="center",
        font=("Arial", 24, "normal"),
    )


actualizar_marcador()

Debemos declarar como globales los puntos dentro de las funciones que los modifican, o agrupar el estado en una clase.

Crear el bucle principal

import time

while True:
    pantalla.update()
    time.sleep(1 / 120)

    pelota.setx(pelota.xcor() + pelota.dx)
    pelota.sety(pelota.ycor() + pelota.dy)

La pausa limita aproximadamente la frecuencia del ciclo. No garantiza una tasa exacta, pero evita que el juego consuma toda la CPU. En motores más avanzados se utiliza el tiempo transcurrido entre fotogramas.

Colisiones con los bordes superior e inferior

if pelota.ycor() > 285:
    pelota.sety(285)
    pelota.dy *= -1

if pelota.ycor() < -285:
    pelota.sety(-285)
    pelota.dy *= -1

Reposicionar la pelota dentro del límite evita que siga fuera después de invertir la dirección.

Detectar puntos

def reiniciar_pelota(direccion):
    pelota.goto(0, 0)
    pelota.dx = abs(pelota.dx) * direccion
    pelota.dy = 4

Dentro del bucle:

if pelota.xcor() > 440:
    puntos_izquierda += 1
    actualizar_marcador()
    reiniciar_pelota(-1)

if pelota.xcor() < -440:
    puntos_derecha += 1
    actualizar_marcador()
    reiniciar_pelota(1)

Si este código está en el nivel principal, las variables pueden modificarse directamente. Si está dentro de una función, utiliza una clase o declara el alcance adecuadamente.

Colisión con las paletas

def choca_con_paleta(paleta, lado):
    cerca_en_x = abs(pelota.xcor() - paleta.xcor()) < 25
    cerca_en_y = abs(pelota.ycor() - paleta.ycor()) < 60

    if lado == "izquierda":
        va_hacia_paleta = pelota.dx < 0
    else:
        va_hacia_paleta = pelota.dx > 0

    return cerca_en_x and cerca_en_y and va_hacia_paleta

En el bucle:

if choca_con_paleta(paleta_izquierda, "izquierda"):
    pelota.setx(-375)
    pelota.dx *= -1

if choca_con_paleta(paleta_derecha, "derecha"):
    pelota.setx(375)
    pelota.dx *= -1

Comprobar la dirección evita múltiples rebotes mientras la pelota sigue superpuesta a la paleta.

Cambiar el ángulo según el impacto

Para que el juego sea menos predecible, ajusta la velocidad vertical según la distancia entre la pelota y el centro de la paleta:

def rebotar_en_paleta(paleta, nuevo_x):
    diferencia = pelota.ycor() - paleta.ycor()
    pelota.setx(nuevo_x)
    pelota.dx *= -1
    pelota.dy = diferencia * 0.12

Un impacto cerca de los extremos genera un ángulo mayor. Limita dy para evitar trayectorias casi verticales:

pelota.dy = max(-7, min(7, pelota.dy))

Aumentar gradualmente la dificultad

def acelerar_pelota():
    limite = 9
    pelota.dx = max(-limite, min(limite, pelota.dx * 1.04))

Llama a esta función después de cada rebote. Mantén un límite para que el juego siga siendo jugable.

Añadir una línea central

linea = turtle.Turtle()
linea.color("gray")
linea.hideturtle()
linea.penup()
linea.goto(0, -300)
linea.setheading(90)

for _ in range(15):
    linea.pendown()
    linea.forward(20)
    linea.penup()
    linea.forward(20)

Pausar el juego

pausado = False


def alternar_pausa():
    global pausado
    pausado = not pausado


pantalla.onkeypress(alternar_pausa, "space")

En el bucle, mueve la pelota únicamente cuando pausado sea falso. En un diseño orientado a objetos, el estado pertenecería a una instancia del juego.

Terminar con una puntuación máxima

PUNTOS_PARA_GANAR = 10

if puntos_izquierda >= PUNTOS_PARA_GANAR:
    mostrar_ganador("Jugador izquierdo")
    break

if puntos_derecha >= PUNTOS_PARA_GANAR:
    mostrar_ganador("Jugador derecho")
    break

Después del bucle puedes usar pantalla.mainloop() para mantener visible el resultado, o presentar una opción de reinicio.

Separar el proyecto en clases

Cuando el código crece, crea clases Paleta, Pelota, Marcador y Juego. Así cada objeto administra su estado y comportamiento. Por ejemplo:

class Pelota(turtle.Turtle):
    def __init__(self):
        super().__init__()
        self.shape("circle")
        self.color("white")
        self.penup()
        self.dx = 4
        self.dy = 4

    def mover(self):
        self.goto(self.xcor() + self.dx, self.ycor() + self.dy)

Probar la lógica sin abrir la ventana

Las colisiones pueden extraerse a funciones puras:

def hay_colision(px, py, paleta_x, paleta_y):
    return abs(px - paleta_x) < 25 and abs(py - paleta_y) < 60

Después crea tests con coordenadas dentro y fuera de los límites. Esto permite verificar la lógica sin depender de eventos gráficos.

Errores frecuentes

Los fallos habituales son olvidar pantalla.update(), registrar callbacks con paréntesis, no limitar las paletas, invertir la dirección varias veces en una misma colisión y usar una pausa demasiado larga. También es común mezclar todo el estado en variables globales, lo que dificulta reiniciar o probar el juego.

Mejoras posibles

Puedes añadir sonidos, menú inicial, selección de dificultad, inteligencia artificial para una paleta, efectos visuales, modo a un jugador y almacenamiento de récords. Mantén la física sencilla y limita la velocidad. Antes de añadir funciones, separa el código en componentes claros.

Conclusión

Crear Pong con Turtle enseña eventos, coordenadas, colisiones, bucles y estado de juego. Empieza con una ventana, dos paletas y una pelota, añade límites y marcador y después mejora los rebotes. Una vez que funcione, reorganiza el proyecto en clases y extrae la lógica para poder probarla sin la interfaz.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Projeto de jogo da velha desenvolvido em Python como exercício de lógica de programação
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear el juego de tres en raya con Python

    Crea tres en raya con Python usando listas, validación, detección de victoria, empate, marcador, IA y pruebas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Foto de uma pessoa usando uma calculadora
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear una calculadora en Python paso a paso

    Crea una calculadora en Python con funciones, validación, manejo de errores, Decimal, historial, memoria y pruebas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Calendário mensal gerado automaticamente com Python
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo generar un calendario mensual con Python

    Genera un calendario mensual con Python usando calendar y datetime, valida fechas, añade eventos y exporta a TXT, HTML o

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Jogo da forca para iniciantes desenvolvido com Python
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear el juego del ahorcado en Python

    Crea el juego del ahorcado en Python con palabras aleatorias, sets, validación, vidas, ASCII, categorías, pistas, puntuación y pruebas.

    Ler mais

    Tempo de leitura: 4 minutos
    11/07/2026
    Quiz interativo no terminal desenvolvido com Python
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear un quiz interactivo en Python

    Crea un quiz interactivo en Python con preguntas, opciones, validación, puntuación, JSON, categorías, mezcla aleatoria y pruebas.

    Ler mais

    Tempo de leitura: 3 minutos
    11/07/2026
    Jogo de adivinhação de números desenvolvido com Python
    Proyectos
    Foto de perfil de Leandro Hirt da Academify

    Cómo crear un juego de adivinar números con Python

    Crea un juego de adivinar números con Python usando random, validación, intentos, niveles, pistas, puntuación, récords y pruebas.

    Ler mais

    Tempo de leitura: 3 minutos
    11/07/2026