Saltar al contenido
Inicio 100 Días de Código en Python — Día 22: Pong, el Famoso Juego de Arcade

100 Días de Código en Python — Día 22: Pong, el Famoso Juego de Arcade

Nivel: Grado décimo Área: Tecnología e Informática Modalidad: Tutorial práctico Fuente: Curso "100 Days of Code: The Complete Python Pro Bootcamp" (Angela Yu, App Brewery). Contenido del Día 22 (nivel intermedio).

Este tutorial adapta pedagógicamente el Día 22. Las secciones 📝 Ejercicio original del curso provienen de los archivos del curso. Los retos 🟢🟡🟠🔴, el proyecto extra y el proyecto integrador son creaciones de esta adaptación. Las correcciones al material original aparecen como 🛠️ Nota técnica.

Nota sobre las verificaciones: con Python 3.14 se verificaron el error de time.sleep con valores negativos, la reducción de la pausa al multiplicar por 0,9 y las distancias de colisión entre la pelota y la paleta. El comportamiento de onkey y onkeypress se consultó en la documentación del propio módulo. Los programas con ventana se revisaron siguiendo la lógica del código y la documentación oficial (se abre en otra pestaña). Ejecútalos en tu computador para ver el resultado.


Tabla de contenidos

  1. Antes de empezar: diseñar antes de programar
  2. La pantalla y la primera paleta
  3. La clase Paddle y la segunda paleta
  4. La clase Ball: movimiento con x_move y y_move
  5. Rebotes: paredes y paletas
  6. Puntos perdidos, marcador y velocidad
  7. 🚀 Proyecto del día: Pong completo
  8. 🌟 Proyecto extra: Rompe-Ladrillos Ecológico
  9. 🏆 Proyecto integrador del Día 22: Torneo Intercursos de Pong
  10. 🧩 Comprueba lo aprendido
  11. 🤖 Programar con apoyo de IA
  12. 🛠️ Correcciones técnicas al material original
  13. 📋 Matriz de trazabilidad
  14. 📦 Evidencias de aprendizaje del Día 22

0. Antes de empezar: diseñar antes de programar

(Fuentes: 160 - Day 22 Goals- what you will make by the end of the day.md, 169 - Picturing fears- even the worst-case scenario is not so scary.md)

Pong es uno de los primeros juegos de arcade: una pelota cruza una mesa y dos jugadores la devuelven con sus paletas. Si alguien falla, el otro anota un punto. Según cuenta el curso, lo programó Allan Alcorn, un recién contratado de Atari, como prueba. Fue tal éxito que los dueños de los bares llamaban porque las máquinas "se trababan": estaban repletas de monedas.

🔍 Actividad inicial del curso: análisis en papel

Antes de ver la solución, el curso pide tomar una hoja y responder:

  • ¿Qué componentes tiene el juego?
  • ¿Cuáles podrían ser clases separadas?
  • ¿En qué partes se puede dividir la lógica?

Guarda tu hoja: al final del día compararás tu diseño con el del curso. Pong es más complejo que la serpiente, así que pensar la estructura primero ahorra mucho trabajo.

Los 8 pasos del curso:

Paso Tarea
1 Crear la pantalla
2 Crear y mover una paleta
3 Crear la otra paleta
4 Crear la pelota y hacerla moverse
5 Detectar el choque con las paredes y rebotar
6 Detectar el choque con las paletas
7 Detectar cuándo una paleta falla
8 Llevar el marcador

Mensaje de cierre del curso: todos tenemos miedos: no ser lo suficientemente buenos, no entender, no llegar a ser programadores. Nadie es valiente "de nacimiento": lo sentimos y lo hacemos de todos modos. Pregúntate qué es lo peor que podría pasar si lo das todo. Probablemente, no mucho.

Prerequisito general: herencia de Turtle y super().__init__() (Día 21), tracer, update y sleep (Día 20), eventos con onkey (Día 19), coordenadas (Día 19) y el marcador del Día 21.


1. La pantalla y la primera paleta

(Fuentes: 161 - Set up the Main Screen.md, 162 - Create a Paddle that responds to Key Presses.md)

📝 Ejercicio original del curso 1: la pantalla

Enunciado: ventana de 800 de ancho × 600 de alto, fondo negro, título "Pong", que no se cierre hasta hacer clic. (Se resuelve con Screen, bgcolor, setup, title y exitonclick, igual que en el Día 20.)

📝 Ejercicio original del curso 2: una paleta que se mueve

Enunciado: crear una paleta de 20 de ancho × 100 de alto en la posición (350, 0), que suba y baje 20 píxeles con las flechas ↑ y ↓.

🔍 Antes de programar

  • Una tortuga cuadrada mide 20 × 20. ¿Cuánto hay que "estirarla" y en qué dirección para obtener 20 × 100?
  • Si la paleta solo sube y baja, ¿qué coordenada cambia y cuál no?

📖 Explicación: shapesize

shapesize(stretch_wid, stretch_len) estira la forma de la tortuga:

  • stretch_len: estira en la dirección en que mira la tortuga (el Este al inicio, es decir, horizontal).
  • stretch_wid: estira perpendicular a esa dirección (vertical al inicio).

Para 20 × 100: shapesize(stretch_wid=5, stretch_len=1) → 20 × 5 = 100 de alto.

Solución del curso (primera versión, en main.py):

Python
paddle = Turtle()
paddle.shape("square")
paddle.color("white")
paddle.shapesize(stretch_wid=5, stretch_len=1)
paddle.penup()
paddle.goto(350, 0)


def go_up():
    new_y = paddle.ycor() + 20
    paddle.goto(paddle.xcor(), new_y)      # X no cambia


def go_down():
    new_y = paddle.ycor() - 20
    paddle.goto(paddle.xcor(), new_y)


screen.listen()
screen.onkey(go_up, "Up")
screen.onkey(go_down, "Down")

Pregunta del curso: ¿cómo evitar ver la paleta "viajar" del centro a (350, 0)? Respuesta: screen.tracer(0). Pero entonces la pantalla queda en blanco, así que se necesita el bucle del juego:

Python
game_is_on = True
while game_is_on:
    screen.update()

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: cambia el tamaño de la paleta a 20 × 160. ¿Qué valor de shapesize usas?
  • 🟡 Reto 2: impide que la paleta salga por arriba o por abajo de la ventana.
  • 🟠 Reto 3: gira la paleta para que sea horizontal (como en el juego de romper ladrillos) sin cambiar shapesize, solo con setheading. Explica qué pasó con stretch_len y stretch_wid.
  • 🔴 Reto 4: calcula en qué rango de Y puede estar el centro de la paleta para que ninguna parte salga de la ventana de 600 de alto.

2. La clase Paddle y la segunda paleta

(Fuente: 163 - Write the Paddle Class and Create the Second Paddle.md)

📝 Ejercicio original del curso

Enunciado: llevar el código de la paleta a paddle.py, en una clase Paddle que herede de Turtle y reciba la posición como una tupla:

Python
r_paddle = Paddle((350, 0))
l_paddle = Paddle((-350, 0))

La paleta derecha se mueve con ↑ y ↓, y la izquierda con W y S.

Cómo lo hace el curso:

  1. class Paddle(Turtle): con super().__init__().
  2. Buscar y reemplazar (Edit → Find → Replace): cambiar todos los paddle. por self.. Dentro de la clase, el objeto es la tortuga.
  3. PyCharm advierte "argumento inesperado" al pasar la posición: se agrega el parámetro position a __init__ y se usa en self.goto(position).
  4. go_up y go_down pasan a ser métodos (con self).
  5. En main.py: screen.onkey(r_paddle.go_up, "Up"), screen.onkey(l_paddle.go_up, "w") y así con las demás.

La lección del curso: para demostrar el poder de las clases, se crea una tercera paleta en (100, 100) con una sola línea y ya tiene todo su comportamiento. "Podemos crear tantas paletas como queramos."

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: agrega un parámetro color a Paddle y haz una paleta roja y otra azul.
  • 🟡 Reto 2: agrega un parámetro step (cuánto se mueve por pulsación) con valor por defecto 20.
  • 🟠 Reto 3: crea AIPaddle(Paddle), una paleta que se mueve sola siguiendo la Y de la pelota. ¿Qué método agregas y cuándo se llama?
  • 🔴 Reto 4: crea un Pong para cuatro jugadores: dos paletas verticales y dos horizontales. ¿Qué cambia en la clase y qué se mantiene?

3. La clase Ball: movimiento con x_move y y_move

(Fuente: 164 - Write the Ball Class and Make the Ball Move.md)

📝 Ejercicio original del curso

Enunciado: crear ball.py con una clase Ball(Turtle): 20 × 20, blanca, en (0, 0), que se mueva sola hacia la esquina superior derecha en cada actualización de la pantalla.

Solución del curso, versión 1:

Python
class Ball(Turtle):
    def __init__(self):
        super().__init__()
        self.color("white")
        self.shape("circle")     # en el Pong original era un cuadrado: tú eliges
        self.penup()

    def move(self):
        new_x = self.xcor() + 10
        new_y = self.ycor() + 10
        self.goto(new_x, new_y)

En el bucle del juego: ball.move(). La pelota sale disparada de la pantalla. Para que vaya más despacio, el curso muestra dos opciones:

  • Mover menos píxeles por vuelta (1 en lugar de 10).
  • Pausar el bucle con time.sleep(0.1). ← la elegida.

Versión 2 (necesaria para los rebotes): el desplazamiento se guarda en atributos:

Python
self.x_move = 10
self.y_move = 10

def move(self):
    new_x = self.xcor() + self.x_move
    new_y = self.ycor() + self.y_move
    self.goto(new_x, new_y)

Conexión con Matemáticas y Física: (x_move, y_move) es un vector de velocidad. En cada fotograma, la posición cambia según ese vector.


4. Rebotes: paredes y paletas

(Fuentes: 165 - Add the Ball Bouncing Logic.md, 166 - How to Detect Collisions with the Paddle.md)

🎯 Objetivo de aprendizaje

  • Explicar un rebote como el cambio de signo de una componente de la velocidad.
  • Combinar varias condiciones para detectar choques con objetos alargados.

📝 Ejercicio original del curso 1: rebotar en las paredes superior e inferior

Pregunta del curso: cuando la pelota rebota en la pared de arriba, ¿qué pasa con X y con Y? ¿Cuál se invierte y cuál se mantiene?

Respuesta: X sigue igual (la pelota sigue yendo a la derecha), pero Y cambia de sentido. Por eso:

Python
def bounce_y(self):
    self.y_move *= -1          # +10 → -10, o -10 → +10

En main.py:

Python
if ball.ycor() > 280 or ball.ycor() < -280:
    ball.bounce_y()

Primero se probó con 300, pero la pelota desaparecía antes de rebotar. Con 280 (300 menos el ancho de la pelota) se ve bien. Consejo del curso: si te cuesta entenderlo, imprime new_y y y_move antes y después del rebote y observa los números.

Solo se revisan las paredes de arriba y abajo: los lados izquierdo y derecho son "portería", es decir, puntos.

📝 Ejercicio original del curso 2: rebotar en las paletas

El problema de distance: mide de centro a centro. La paleta mide 100 de alto: si la pelota golpea el borde de la paleta, la distancia entre centros es mucho mayor que 20 y no se detecta el choque.

Solución del curso: combinar dos condiciones:

Python
if ball.distance(r_paddle) < 50 and ball.xcor() > 320 or ball.distance(l_paddle) < 50 and ball.xcor() < -320:
    ball.bounce_x()
  • xcor() > 320: la pelota ya llegó a la zona de la paleta derecha.
  • distance < 50: está a la altura de la paleta.
  • El curso empezó con 340 y lo ajustó a 320 para que la pelota no pareciera "entrar" en la paleta antes de rebotar.
  • El método bounce se renombró a bounce_y (Refactor → Rename) y se creó bounce_x, que invierte x_move.

🛠️ Nota técnica (cálculo verificado): distance < 50 forma un círculo de radio 50 alrededor del centro de la paleta, pero la paleta es un rectángulo. Visualmente, la pelota toca la paleta si la diferencia vertical entre sus centros es menor que 60 (50 de media paleta + 10 de radio). Pero, cuando la pelota llega a x = 330 (a 20 de la paleta en X), el círculo solo alcanza una diferencia vertical de √(50² − 20²) ≈ 45,8. Resultado: hay unos 14 píxeles en cada extremo de la paleta donde la pelota parece golpearla, pero la atraviesa. Una alternativa más precisa es comparar las coordenadas por separado: abs(ball.ycor() - paddle.ycor()) < 60 y la X en la zona de la paleta.

Advertencia de análisis (posible fallo): si la pelota ya pasó la línea de la paleta y la paleta se mueve hacia ella, ambas condiciones pueden cumplirse en varios fotogramas seguidos. En ese caso, bounce_x() invierte la dirección una y otra vez y la pelota puede quedar "temblando" dentro de la paleta. Una solución: rebotar solo si la pelota se dirige hacia esa paleta (ball.x_move > 0 para la derecha).

⚠️ Errores frecuentes

Error Qué ocurre Solución
Invertir x_move en las paredes superior e inferior La pelota "rebota" hacia atrás en lugar de seguir Arriba y abajo cambian Y; las paletas cambian X
Solo distance < 20 para las paletas Solo detecta los golpes en el centro Combina X y distancia (o usa el método del rectángulo)
and y or mezclados sin paréntesis Condiciones que no hacen lo esperado and se evalúa antes que or; usa paréntesis para que sea claro

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: agrega paréntesis a la condición de las paletas para que sea más legible, y comprueba que funciona igual.
  • 🟡 Reto 2: implementa la detección rectangular de la nota técnica y compárala con la del curso golpeando con los extremos.
  • 🟠 Reto 3: haz que el ángulo del rebote dependa de dónde golpea la pelota: en el centro sale recta; en los extremos, más inclinada.
  • 🔴 Reto 4: escribe una función rebote_simulado(y, y_move, pasos) sin Turtle que devuelva la lista de posiciones Y de una pelota que rebota entre −280 y 280. Úsala para predecir dónde estará la pelota en 50 fotogramas.

5. Puntos perdidos, marcador y velocidad

(Fuentes: 167 - How to Detect when the Ball goes Out of Bounds.md, 168 - Score Keeping and Changing the Ball Speed.md)

📝 Ejercicio original del curso 1: detectar cuándo falla una paleta

Razonamiento del curso: la paleta derecha está en x = 350 y ocupa de 340 a 360. Si la pelota pasa de 380, la paleta definitivamente falló.

Python
if ball.xcor() > 380:          # falló la paleta derecha
    ball.reset_position()

if ball.xcor() < -380:         # falló la paleta izquierda
    ball.reset_position()

reset_position() lleva la pelota a (0, 0) y llama self.bounce_x(): así el otro jugador recibe el saque.

¿Por qué dos if separados? Porque en el siguiente paso cada uno dará el punto a un jugador distinto.

📝 Ejercicio original del curso 2: el marcador

Scoreboard(Turtle) con l_score y r_score, blanco, penup, hideturtle, fuente ("Courier", 80, "normal"):

  • update_scoreboard(): clear(), luego escribe l_score en (−100, 200) y r_score en (100, 200).
  • l_point(): suma 1 a l_score y actualiza. r_point(): igual para la derecha.
  • En main.py: si falla la paleta derecha → scoreboard.l_point(); si falla la izquierda → scoreboard.r_point().

Es el mismo patrón del Día 21: clear() antes de reescribir y un método para no repetir el write.

📝 Ejercicio original del curso 3 (desafío extra): acelerar la pelota

Enunciado: que la pelota vaya más rápido cada vez que toca una paleta.

Idea clave: la velocidad depende de cuánto duerme el bucle. Menos pausa = más rápido. Pero la pausa nunca puede ser negativa.

Solución del curso:

  1. Atributo self.move_speed = 0.1 en Ball. No se llama speed, porque Turtle ya tiene un método speed (¡lo sobrescribiríamos, Día 21!).
  2. En main.py: time.sleep(ball.move_speed).
  3. En bounce_x(): self.move_speed *= 0.9.
  4. En reset_position(): self.move_speed = 0.1, para que la velocidad vuelva a la normalidad después de cada punto.

Verificación:

  • time.sleep(-0.1) produce ValueError: sleep length must be non-negative.
  • Multiplicar por 0,9 nunca llega a cero ni a un número negativo. Después de 10 golpes, la pausa es 0,1 × 0,9¹⁰ ≈ 0,035 s, es decir, unas 3 veces más rápido.

🛠️ El misterio de la tecla que no se repite

Al final de la lección, el curso cuenta un fallo que no pudo resolver: al mantener presionada W, la paleta izquierda no se mueve de forma continua, mientras que S y las flechas sí. Concluye que "es algo del módulo turtle" y bromea con darle el lado izquierdo a tu amigo.

🛠️ Nota técnica (verificada en la documentación del módulo): onkey se vincula al evento de soltar la tecla (key-release). Mantener una tecla presionada solo genera repeticiones si el sistema operativo envía eventos repetidos, y eso depende del sistema y de la tecla. Por ejemplo, en macOS mantener presionada una letra puede abrir el menú de acentos en lugar de repetirla, aunque no podemos confirmar que esa fuera la causa en el video del curso. Una mejora recomendada es usar onkeypress, que se activa al presionar. Para un movimiento continuo y uniforme en todos los sistemas, la técnica profesional es guardar si la tecla está presionada (con onkeypress y onkeyrelease) y mover la paleta en el bucle del juego.

Retos adicionales (creados para esta adaptación)

  • 🟢 Reto 1: cambia 0,9 por 0,8 y por 0,95. ¿Cuál hace el juego más divertido? Justifica.
  • 🟡 Reto 2: pon un límite de velocidad: la pausa nunca baja de 0,02 (pista: max()).
  • 🟠 Reto 3: el primer jugador en llegar a 5 puntos gana. Muestra "GANA EL JUGADOR IZQUIERDO/DERECHO" y termina el juego.
  • 🔴 Reto 4: implementa el movimiento continuo de las paletas con onkeypress, onkeyrelease y dos atributos booleanos. Prueba en tu computador si se resuelve el problema de la tecla W.

6. 🚀 Proyecto del día: Pong completo

(Fuentes: 160 a 168)

Problema

Construir un Pong para dos jugadores en el mismo teclado.

Contexto

Recrear un juego que cambió la historia de los videojuegos. Es ideal para el descanso o una feria de tecnología.

Requisitos funcionales

  1. Ventana negra de 800 × 600.
  2. Dos paletas: derecha (↑ ↓) e izquierda (W S).
  3. Pelota que se mueve sola y rebota arriba, abajo y en las paletas.
  4. Si una paleta falla, el otro jugador anota y la pelota sale del centro hacia el que perdió.
  5. Marcador grande para cada jugador.
  6. La pelota acelera con cada golpe y vuelve a la velocidad normal después de cada punto.

Restricciones técnicas

Clases Paddle, Ball y Scoreboard heredadas de Turtle, cada una en su archivo; main.py solo coordina.

Planificación

Compara tu hoja de la sección 0 con este diseño:

Texto
main.py  ──crea y coordina──▶  Paddle (×2), Ball, Scoreboard
                                   │        │        │
                                   └────────┴────────┴──▶ heredan de Turtle
Clase Atributos Métodos
Paddle (posición heredada) go_up, go_down
Ball x_move, y_move, move_speed move, bounce_y, bounce_x, reset_position
Scoreboard l_score, r_score update_scoreboard, l_point, r_point

¿Qué acertaste? ¿Qué pensaste diferente? ¿Tu diseño también funcionaría?

Construcción paso a paso

Sigue los 8 pasos de la sección 0. Después de cada paso, ejecuta el juego y comprueba que todo lo anterior sigue funcionando.

Pruebas

Caso Resultado esperado
La pelota toca la pared de arriba Rebota hacia abajo, sigue en la misma dirección horizontal
La paleta derecha devuelve la pelota La pelota va a la izquierda y un poco más rápido
La paleta derecha falla +1 para el jugador izquierdo; la pelota sale del centro hacia la izquierda a velocidad normal
Se mantiene presionada W Anota en tu cuaderno qué pasa en tu sistema operativo
La pelota golpea el extremo de la paleta Anota si la detecta (nota técnica de la sección 4)

🧪 Prueba y depuración

Este ball.py tiene tres errores. Encuéntralos:

Python
from turtle import Turtle

class Ball(Turtle):
    def __init__(self):
        super().__init__()
        self.color("white")
        self.shape("circle")
        self.x_move = 10
        self.y_move = 10
        self.speed = 0.1

    def move(self):
        self.goto(self.xcor() + self.x_move, self.ycor() + self.y_move)

    def bounce_y(self):
        self.x_move *= -1

    def reset_position(self):
        self.goto(0, 0)
        self.bounce_x()

(Pistas: un atributo que tapa un método de Turtle (¿qué pasa si luego alguien llama ball.speed("fastest")?); una componente equivocada; un método que no existe. Pregunta extra: ¿qué se dibuja en la pantalla con este código, y por qué?)

⭐ Extensión del proyecto

  • Paleta controlada por la computadora (Reto 3 del Tema 2).
  • Sonido al golpear (investiga el módulo winsound en Windows).
  • Pantalla de inicio con "Pulsa ESPACIO para empezar".

7. 🌟 Proyecto extra: Rompe-Ladrillos Ecológico

Situación

Para la semana del medio ambiente, el club de programación crea un juego tipo Breakout: cada ladrillo representa un foco de contaminación y la pelota los "limpia".

Requisitos

  1. Una paleta horizontal abajo que se mueve con ← y → (reutiliza Paddle con herencia o parámetros).
  2. Una pelota que rebota en las paredes laterales, en la de arriba y en la paleta. Si cae por abajo, se pierde una vida (3 vidas).
  3. Al menos 3 filas de 8 ladrillos (Brick(Turtle)), guardados en una lista. Cada fila tiene un color y un valor distinto.
  4. Al chocar con un ladrillo: la pelota rebota, el ladrillo desaparece (hideturtle() y se quita de la lista) y se suman puntos.
  5. Gana quien elimina todos los ladrillos.

Decisiones que debes tomar

  • Al chocar con un ladrillo, ¿la pelota debe invertir X o Y? ¿Depende de por dónde lo golpea?
  • ¿Por qué es peligroso eliminar elementos de una lista mientras la recorres con for? *(Pista: recorre una copia con bricks[:], el *slicing* del Día 21.)*

Reflexión

¿Qué clases de Pong reutilizaste sin cambios? ¿Cuáles tuviste que adaptar?


8. 🏆 Proyecto integrador del Día 22: Torneo Intercursos de Pong

Proyecto integrador creado para esta adaptación. Integra herencia, eventos, animación, colisiones, marcador y validación de datos (Días 19 a 22).

Situación problema

El consejo estudiantil organiza un torneo intercursos de Pong. Necesita una versión configurable, justa y con reglas claras.

Pregunta orientadora

¿Cómo convertir un juego que "funciona" en un producto confiable para una competencia real?

Requerimientos

  1. Al iniciar, textinput pide los nombres de los dos cursos (por ejemplo, "10A" y "10B") y numinput los puntos para ganar (entre 3 y 11, validado).
  2. El marcador muestra los nombres de los cursos y sus puntos.
  3. Detección de paletas rectangular (sección 4) y protección contra el "temblor" dentro de la paleta.
  4. Movimiento continuo de las paletas que funcione igual para ambos jugadores (Reto 4 del Tema 5).
  5. La velocidad tiene un límite máximo.
  6. Al terminar, se anuncia el ganador en pantalla y se imprime en la consola un resumen: puntos de cada curso y cantidad total de golpes.
  7. Constantes para todas las medidas (ventana, paletas, límites, velocidades).

Etapas de desarrollo

  1. Pong del curso funcionando.
  2. Corrección de las colisiones y de los controles.
  3. Configuración inicial y validaciones.
  4. Fin de partida y resumen.

Entregables

  • El código (4 archivos como mínimo).
  • Un reglamento de una página escrito para los jugadores.
  • Un informe de pruebas: tabla con 8 casos probados, resultado esperado, resultado obtenido y corrección, si hizo falta.

Casos de prueba

Caso Esperado
Puntos para ganar = 20 Mensaje de error y nueva pregunta
Golpe con el extremo de la paleta La pelota rebota
Paleta que se mueve contra una pelota que ya pasó La pelota no queda temblando
Ambos jugadores mantienen presionadas sus teclas Ambas paletas se mueven de forma continua

Criterios técnicos

  • Ningún número "mágico" dentro de los métodos: todo está en constantes.
  • El juego se puede jugar completo sin mensajes de error en la consola.

9. 🧩 Comprueba lo aprendido

Conceptuales

  1. ¿Por qué rebotar en las paredes superior e inferior cambia y_move y no x_move?
  2. ¿Por qué el curso no llamó speed al atributo de velocidad?
  3. ¿Qué diferencia hay entre onkey y onkeypress?

Análisis de código

Python
x_move = 10
for i in range(3):
    x_move *= -1
    print(x_move)

Predicción

La pelota está en (0, 0) con x_move = 10 y y_move = 10, y el límite de las paredes es 280. ¿En qué fotograma rebota por primera vez? ¿Cuál es su posición en el fotograma 30?

Depuración

Python
if ball.distance(r_paddle) < 50 or ball.xcor() > 320:
    ball.bounce_x()

¿Qué comportamiento extraño produciría? ¿Por qué?

Modificación

Cambia el juego para que la pelota salga del centro en una dirección vertical aleatoria (arriba o abajo) después de cada punto.

Creación

Escribe Ball.is_moving_right(), que devuelva True si la pelota se mueve hacia la derecha, y úsala para corregir el "temblor" en la paleta.


10. 🤖 Programar con apoyo de IA

El curso reconoce abiertamente un problema que no supo resolver (la tecla W). Es un buen ejemplo de que investigar es parte de programar.

Actividad: investigar un fallo con IA y documentación.

  1. Describe a una IA el problema de la tecla W tal como lo cuenta el curso.
  2. Anota su explicación. Luego verifica en la documentación oficial (se abre en otra pestaña) qué hacen onkey, onkeypress y onkeyrelease.
  3. ¿La IA mencionó que onkey se activa al soltar? ¿Afirmó algo con seguridad que no pudiste comprobar?
  4. Prueba su solución en tu computador y registra el resultado. Si tus compañeros tienen otro sistema operativo, comparen.

11. 🛠️ Correcciones técnicas al material original

Archivo Afirmación o comportamiento del curso Observación Tratamiento
166 distance < 50 y xcor > 320 detectan el golpe con la paleta El círculo de radio 50 no cubre los extremos del rectángulo: unos 14 px por extremo sin detección (cálculo verificado); posible "temblor" si la pelota ya pasó Notas técnicas del Tema 4
168 El fallo de la tecla W "es algo del módulo turtle" onkey se activa al soltar la tecla (documentación del módulo); la repetición depende del sistema operativo. Se recomienda onkeypress o el movimiento en el bucle Tema 5
168 La pausa nunca debe ser negativa Correcto: ValueError: sleep length must be non-negative; multiplicar por 0,9 nunca llega a 0 (verificado) Tema 5

12. 📋 Matriz de trazabilidad

Contenido original Archivo de origen Concepto desarrollado Ejercicio original Reto adicional Proyecto relacionado
Historia de Pong, análisis en papel, 8 pasos 160 Sección 0 Diseño en papel Comparación en el proyecto Sección 6
Pantalla 800 × 600 161 Tema 1 Configurar la pantalla — Secciones 6, 7 y 8
Paleta, shapesize, teclas, tracer 162 Tema 1 Paleta que se mueve Retos 1–4 del Tema 1 Secciones 6 y 7
Clase Paddle con posición, segunda paleta 163 Tema 2 Refactorizar y dos paletas Retos 1–4 del Tema 2 Secciones 6, 7 y 8
Clase Ball, move, sleep 164 Tema 3 Pelota hacia la esquina — Secciones 6 y 7
Rebote en paredes, bounce_y 165 Tema 4 Rebote arriba y abajo Retos 1–4 del Tema 4 Secciones 6 y 7
Choque con paletas, bounce_x 166 Tema 4 Rebote en paletas Detección rectangular Sección 8
Pelota fuera, reset_position 167 Tema 5 Detectar fallos — Secciones 6 y 8
Marcador, velocidad, fallo de la tecla W 168 Tema 5 Marcador y aceleración Retos 1–4 del Tema 5 Secciones 6 y 8
Los miedos 169 Sección 0 — — —
(No existe en el curso original) — — — Rompe-Ladrillos Ecológico Sección 7
(No existe en el curso original) — — — Torneo Intercursos de Pong Sección 8

13. 📦 Evidencias de aprendizaje del Día 22

  • La hoja de diseño hecha antes de programar y la comparación con la estructura del curso.
  • Pong completo funcionando, con captura de un marcador.
  • Explicación escrita del rebote como cambio de signo y del problema de distance con objetos alargados.
  • Registro de la prueba de la tecla W en tu sistema operativo.
  • Proyecto extra (Rompe-Ladrillos) o integrador (Torneo Intercursos).
  • Cuaderno de errores: shapesize con los estiramientos invertidos, el atributo speed que tapa un método, ValueError por pausa negativa, pelota que atraviesa los extremos de la paleta y texto superpuesto en el marcador.