0% found this document useful (0 votes)
8 views4 pages

Import Os

txt text
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views4 pages

Import Os

txt text
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

import os

import sys
import numpy as np
import pygame as pg

# ---
# Utilidades 2D homogéneo
# ---
def to_homogeneous(P):
return np.vstack([P, np.ones((1, P.shape[1]))])

def from_homogeneous(PH):
M = PH[2, :]
return PH[:2, :] / M

def T(dx, dy):


return np.array([[1, 0, dx],
[0, 1, dy],
[0, 0, 1]], dtype=float)

def S(sx, sy):


return np.array([[sx, 0, 0],
[0, sy, 0],
[0, 0, 1]], dtype=float)

def R(theta_deg):
th = np.deg2rad(theta_deg)
c, s = np.cos(th), np.sin(th)
return np.array([[c, -s, 0],
[s, c, 0],
[0, 0, 1]], dtype=float)

def transform_around(point, M_local):


cx, cy = point
return T(cx, cy) @ M_local @ T(-cx, -cy)

# ---
# Inicialización Pygame
# ---
pg.init()
W, H = 900, 600 # Corregido: M cambió a W para coincidir con línea 69
screen = pg.display.set_mode((W, H))
pg.display.set_caption("Sprite + Matrix homogénea (S=R=T) – Controles
FIX")
clock = pg.time.Clock()
font = pg.font.SysFont("consolas", 18)

# ---
# Carga de sprite (fallback)
# ---
IMAGE_PATH = "sprite.png"
if os.path.isfile(IMAGE_PATH):
sprite = pg.image.load(IMAGE_PATH).convert_alpha()
else:
# Crear un sprite de ejemplo si no existe el archivo
sprite = pg.Surface((120, 80), pg.SRCALPHA)
sprite.fill((220, 235, 255, 255))
pg.draw.rect(sprite, (50, 120, 230), sprite.get_rect(), 4) #
Corregido: get_pect() -> get_rect()
pg.draw.line(sprite, (230, 80, 80), (0, 0), (120, 80), 3)
pg.draw.line(sprite, (80, 180, 80), (120, 0), (0, 80), 3)

spr_w, spr_h = sprite.get_width(), sprite.get_height()


square_local = np.array([[0, spr_w, spr_w, 0, 0],
[0, 0, spr_h, spr_h, 0]], dtype=float)

# ---
# Estado transformaciones
# ---
sx, sy = 1.0, 1.0
theta = 0.0
dx, dy = W/2, H/2
pivot = (spr_w/2, spr_h/2)

# Velocidades (más altas para que se note bien)


SPEED_T = 450.0 # px/s (corregido: SPEED_I no definido, cambiado a
SPEED_T)
SPEED_R = 180.0 # deg/s
SPEED_S = 2.5 # unidades de escala por segundo (+/-)
last_input = "-"

def draw_text_lines(lines, x, y):


yy = y
for ln in lines:
surf = font.render(ln, True, (30, 30, 30))
screen.blit(surf, (x, yy))
yy += surf.get_height() + 2

running = True
while running:
dt = clock.tick(60) / 1000.0 # segundos

# Asegura que la ventana procese eventos (necesario para get_pressed)


for e in pg.event.get():
if e.type == pg.QUIT:
running = False
elif e.type == pg.KEYDOWN:
if e.key == pg.K_ESCAPE:
running = False
if e.key == pg.K_r:
sx, sy = 1.0, 1.0
theta = 0.0
dx, dy = W/2, H/2
last_input = "Reset (R)"

keys = pg.key.get_pressed()

# Traslación: Flechas o WASD


if keys[pg.K_LEFT] or keys[pg.K_a]:
dx -= SPEED_T * dt # Corregido: := no es válido en Python,
cambiado a -=
last_input = "Traslación ← (Left/A)"
if keys[pg.K_RIGHT] or keys[pg.K_d]:
dx += SPEED_T * dt
last_input = "Traslación → (Right/D)"
if keys[pg.K_UP] or keys[pg.K_w]:
dy -= SPEED_T * dt # Corregido: := no es válido en Python,
cambiado a -=
last_input = "Traslación ↑ (Up/W)"
if keys[pg.K_DOWN] or keys[pg.K_s]:
dy += SPEED_T * dt
last_input = "Traslación ↓ (Down/S)"

# Rotación: Q/E
if keys[pg.K_q] or keys[pg.K_COMMA]: # coma por si cambia layout
theta += SPEED_R * dt
last_input = "Rotación + (Q)"
if keys[pg.K_e] or keys[pg.K_PERIOD]: # punto
theta -= SPEED_R * dt
last_input = "Rotación - (E)"

# Escala X: Z/X o '-'/'=' (teclado principal)


if keys[pg.K_z] or keys[pg.K_MINUS]:
sx -= SPEED_S * dt
last_input = "Escala X - (Z/-)"
if keys[pg.K_x] or keys[pg.K_EQUALS]:
sx += SPEED_S * dt
last_input = "Escala X + (X/=)"

# Escala Y: V/C o '['/']'


if keys[pg.K_v] or keys[pg.K_LEFTBRACKET]:
sy -= SPEED_S * dt
last_input = "Escala Y - (V/[)"
if keys[pg.K_c] or keys[pg.K_RIGHTBRACKET]: # Corregido:
RIGHTBROCKET -> RIGHTBRACKET
sy += SPEED_S * dt
last_input = "Escala Y + (C/])"

# Clamp de escala
sx = max(0.05, sx)
sy = max(0.05, sy)

# Matrix compuesta: escalar+rotar alrededor del centro local, luego


trasladar
M_local = R(theta) @ S(sx, sy) # Corregido: 5(sx, sy) -> S(sx, sy)
M = T(dx, dy) @ transform_around(pivot, M_local)

# Transformar esquinas
square_h = to_homogeneous(square_local)
square_world = from_homogeneous(M @ square_h)

# Render
screen.fill((248, 248, 248))

# Ejes
pg.draw.line(screen, (180, 180, 180), (0, dy), (W, dy), 1) #
Corregido: M -> W
pg.draw.line(screen, (180, 180, 180), (dx, 0), (dx, H), 1)

# Contorno transformado (exacto según matriz)


pts = list(map(tuple, square_world.T)) # Corregido: .1 -> .T
(transpuesta)
pg.draw.lines(screen, (40, 90, 200), False, pts, 3)

# Imagen (aprox con rotozoom escala uniforme)


scale_uniform = (sx + sy) * 0.5
spr_rot = pg.transform.rotozoom(sprite, -theta, scale_uniform)
spr_rect = spr_rot.get_rect(center=(dx, dy))
screen.blit(spr_rot, spr_rect)

info = [
"Controles (duplicados para evitar layouts):",
" Traslación: Flechas o WASD",
" Rotación: Q/E (alterno: , . )",
" Escala X: Z/X (alterno: - = )",
" Escala Y: V/C (alterno: [ ] )",
" Reset: R | Salir: ESC",
f"Estado -> sx={sx:.2f} sy={sy:.2f} θ={theta:.1f}°
pos=({dx:.1f},{dy:.1f})",
f"Último input: {last_input}",
"TIP: haz clic dentro de la ventana si no responde (foco)."
]

# Recuadro UI
pg.draw.rect(screen, (235, 235, 235), pg.Rect(10, 10, 560, 150))
pg.draw.rect(screen, (210, 210, 210), pg.Rect(10, 10, 560, 150), 1)
yy = 16
for line in info:
surf = font.render(line, True, (30, 30, 30))
screen.blit(surf, (18, yy))
yy += surf.get_height() + 2

pg.display.flip()

pg.quit()
sys.exit()

You might also like