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.sleepcon 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 deonkeyyonkeypressse 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
- Antes de empezar: diseñar antes de programar
- La pantalla y la primera paleta
- La clase
Paddley la segunda paleta - La clase
Ball: movimiento conx_moveyy_move - Rebotes: paredes y paletas
- Puntos perdidos, marcador y velocidad
- 🚀 Proyecto del día: Pong completo
- 🌟 Proyecto extra: Rompe-Ladrillos Ecológico
- 🏆 Proyecto integrador del Día 22: Torneo Intercursos de Pong
- 🧩 Comprueba lo aprendido
- 🤖 Programar con apoyo de IA
- 🛠️ Correcciones técnicas al material original
- 📋 Matriz de trazabilidad
- 📦 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
Turtleysuper().__init__()(Día 21),tracer,updateysleep(Día 20), eventos cononkey(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):
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:
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
shapesizeusas? - 🟡 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 consetheading. Explica qué pasó constretch_lenystretch_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:
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:
class Paddle(Turtle):consuper().__init__().- Buscar y reemplazar (Edit → Find → Replace): cambiar todos los
paddle.porself.. Dentro de la clase, el objeto es la tortuga. - PyCharm advierte "argumento inesperado" al pasar la posición: se agrega el parámetro
positiona__init__y se usa enself.goto(position). go_upygo_downpasan a ser métodos (conself).- 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
coloraPaddley 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:
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:
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:
def bounce_y(self):
self.y_move *= -1 # +10 → -10, o -10 → +10En main.py:
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:
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
bouncese renombró abounce_y(Refactor → Rename) y se creóbounce_x, que inviertex_move.
🛠️ Nota técnica (cálculo verificado):
distance < 50forma 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 ax = 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()) < 60y 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 > 0para 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ó.
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
ifseparados? 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 escribel_scoreen (−100, 200) yr_scoreen (100, 200).l_point(): suma 1 al_scorey 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:
- Atributo
self.move_speed = 0.1enBall. No se llamaspeed, porqueTurtleya tiene un métodospeed(¡lo sobrescribiríamos, Día 21!). - En
main.py:time.sleep(ball.move_speed). - En
bounce_x():self.move_speed *= 0.9. - 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)produceValueError: 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):
onkeyse 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 usaronkeypress, 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 (cononkeypressyonkeyrelease) 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,onkeyreleasey dos atributos booleanos. Prueba en tu computador si se resuelve el problema de la teclaW.
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
- Ventana negra de 800 × 600.
- Dos paletas: derecha (↑ ↓) e izquierda (
WS). - Pelota que se mueve sola y rebota arriba, abajo y en las paletas.
- Si una paleta falla, el otro jugador anota y la pelota sale del centro hacia el que perdió.
- Marcador grande para cada jugador.
- 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:
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:
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
winsounden 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
- Una paleta horizontal abajo que se mueve con ← y → (reutiliza
Paddlecon herencia o parámetros). - 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).
- Al menos 3 filas de 8 ladrillos (
Brick(Turtle)), guardados en una lista. Cada fila tiene un color y un valor distinto. - Al chocar con un ladrillo: la pelota rebota, el ladrillo desaparece (
hideturtle()y se quita de la lista) y se suman puntos. - 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 conbricks[:], 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
- Al iniciar,
textinputpide los nombres de los dos cursos (por ejemplo, "10A" y "10B") ynuminputlos puntos para ganar (entre 3 y 11, validado). - El marcador muestra los nombres de los cursos y sus puntos.
- Detección de paletas rectangular (sección 4) y protección contra el "temblor" dentro de la paleta.
- Movimiento continuo de las paletas que funcione igual para ambos jugadores (Reto 4 del Tema 5).
- La velocidad tiene un límite máximo.
- 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.
- Constantes para todas las medidas (ventana, paletas, límites, velocidades).
Etapas de desarrollo
- Pong del curso funcionando.
- Corrección de las colisiones y de los controles.
- Configuración inicial y validaciones.
- 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
- ¿Por qué rebotar en las paredes superior e inferior cambia
y_movey nox_move? - ¿Por qué el curso no llamó
speedal atributo de velocidad? - ¿Qué diferencia hay entre
onkeyyonkeypress?
Análisis de código
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
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.
- Describe a una IA el problema de la tecla
Wtal como lo cuenta el curso. - Anota su explicación. Luego verifica en la documentación oficial (se abre en otra pestaña) qué hacen
onkey,onkeypressyonkeyrelease. - ¿La IA mencionó que
onkeyse activa al soltar? ¿Afirmó algo con seguridad que no pudiste comprobar? - 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
distancecon objetos alargados. - Registro de la prueba de la tecla
Wen tu sistema operativo. - Proyecto extra (Rompe-Ladrillos) o integrador (Torneo Intercursos).
- Cuaderno de errores:
shapesizecon los estiramientos invertidos, el atributospeedque tapa un método,ValueErrorpor pausa negativa, pelota que atraviesa los extremos de la paleta y texto superpuesto en el marcador.