# PyGame test de excepciones


import pygame
import math


class Motor:
    def __init__(self, tam_ventana, jugador, pnjs):
        self.__j = jugador
        self.__screen = pygame.display.set_mode(tam_ventana)
        self.__clock = pygame.time.Clock()
        self.__pnjs = pnjs
        
        if pygame.font:
            self.__font = pygame.font.SysFont(None, 40)
        ...
    ...    


    def start(self):
        self.__dt = 0.0
        running = True
        
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                ...
            ...
        
            self.__screen.fill("beige")
            
            if self.__j.vidas <= 0:
                self.__escribe("Has muerto.")
            else:
                self.__mostrar_frame_juego()
            ...
            
            pygame.display.flip()
            self.__dt = self.__clock.tick(60) / 1000
        ...    
    ...
    
    def __escribe(self, msg):
        if pygame.font:
            text_surface = self.__font.render(msg, False, (0, 0, 0))
            self.__screen.blit(text_surface, (0,0))
        ...
    ...
    
    def __mostrar_frame_juego(self):
        scr = self.__screen
        
        # Mostrar personajes
        pygame.draw.circle(scr, "blue", self.__j.pos, self.__j.tam, self.__j.tam)
        for pnj in self.__pnjs:
            pygame.draw.rect(scr, "red",
                             pygame.Rect(pnj.pos.x, pnj.pos.y, pnj.tam, pnj.tam),
                             pnj.tam)
        ...    
          
        # Info del juego
        self.__escribe(f"Vidas: {self.__j.vidas}")
        
        # Movimiento
        self.__j.mueve(self.__dt, self.__pnjs, pygame.key.get_pressed())
        for pnj in self.__pnjs:
            pnj.mueve(self.__dt, self.__j)
        ...
    ...        
...


class Personaje:
    def __init__(self, maxX, maxY, posX, posY, tam):
        self.__tam_ventana = (maxX, maxY)
        self.__pos = pygame.Vector2(posX, posY)
        self.__tam = tam
    
    @property
    def pos(self):
        return self.__pos
    ...
    
    @property
    def tam(self):
        return self.__tam
    ...
    
    @property
    def tam_ventana(self):
        return self.__tam_ventana
    ...
    
    def distancia_a(self, otro):
        toret = self.__tam_ventana[0] * 2
        
        if isinstance(otro, Personaje):
            mix = self.pos.x + (self.tam / 2)
            miy = self.pos.y + (self.tam / 2)
            sux = otro.pos.x + (otro.tam / 2)
            suy = otro.pos.y + (otro.tam / 2)
            xs = (mix - sux) ** 2
            ys = (miy - suy) ** 2
            toret = math.sqrt(xs + ys)
        ...
        
        return toret
    ...
    
    def hay_colision_con(self, otro):
        return self.distancia_a(otro) < (self.tam * 2)
    ...
...
   
class PersonajeJugador(Personaje):
    def __init__(self, maxX, maxY, posX, posY, tam):
        super().__init__(maxX, maxY, posX, posY, tam)
        self.__vidas = 3
    ...
    
    @property
    def vidas(self):
        return self.__vidas
    ...
    
    def pierde_vida(self):
        self.__vidas -= 1
        print(f"\aVidas jugador: {self.vidas}")
    ...    
    
    def mueve(self, dt, pnjs, keys):
        ancho = self.tam_ventana[0]
        alto = self.tam_ventana[1]
        
        try:
            if keys[pygame.K_w]:
                self.pos.y -= 300 * dt
                if self.pos.y < 0:
                    raise ValueError(('y', self.pos.y))
            if keys[pygame.K_s]:
                self.pos.y += 300 * dt
                if self.pos.y >= alto:
                    raise ValueError(('y', self.pos.y))
            if keys[pygame.K_a]:
                self.pos.x -= 300 * dt
                if self.pos.x < 0:
                    raise ValueError(('x', self.pos.x))
            if keys[pygame.K_d]:
                self.pos.x += 300 * dt
                if self.pos.x >= ancho:
                    raise ValueError(('x', self.pos.x))
                
            for pnj in pnjs:
                if self.hay_colision_con(pnj):
                    raise ValueError((pnj,))
                ...
            ...    
        except ValueError as exc:
            self.__corrige_pos(exc.args[0])
        ...
    ...
    
    def __corrige_pos(self, datos):
        ancho = self.tam_ventana[0]
        alto = self.tam_ventana[1]
        
        if datos[0] == 'x':
            if datos[1] < 0:
                self.pos.x = ancho
            elif datos[1] >= ancho:
                self.pos.x = 0
            ...    
        elif datos[0] == 'y':
            if datos[1] < 0:
                self.pos.y = alto
            elif datos[1] >= alto:
                self.pos.y = 0
            ...
        else:
            # Colision
            self.pierde_vida()
            self.pos.y = datos[0].pos.y + 40
            self.pos.x = datos[0].pos.x + 40
        ...
    ...
...


class PersonajeNoJugador(Personaje):
    def __init__(self, maxX, maxY, posX, posY, tam):
        super().__init__(maxX, maxY, posX, posY, tam)
    ...
    
    def mueve(self, dt, jugador):
        paso = 50
        nuevo_x = paso * dt
        nuevo_y = paso * dt
        
        if self.pos.x > jugador.pos.x:
            nuevo_x *= -1
        ...
        
        if self.pos.y > jugador.pos.y:
            nuevo_y *= -1
        ...
        
        self.pos.x += nuevo_x
        self.pos.y += nuevo_y
    ...
...


if __name__ == "__main__":
    tam_ventana = (800, 600)
    pygame.init()
    
    try:
        pygame.font.init()
    except (ImportError, NotImplementedError) as exc:
    	# En ocasiones, no se inicializa font correctamente
        print(f"Font module not found: {exc}")
        pygame.font = None
    
    j = PersonajeJugador(tam_ventana[0], tam_ventana[1],
                         tam_ventana[0] / 2, tam_ventana[1] / 2, 20)
    pnjs = [
        PersonajeNoJugador(tam_ventana[0], tam_ventana[1], 100, 100, 20),
        PersonajeNoJugador(tam_ventana[0], tam_ventana[1], 512, 512, 20),
        PersonajeNoJugador(tam_ventana[0], tam_ventana[1], 256, 300, 20),
        PersonajeNoJugador(tam_ventana[0], tam_ventana[1], 45, 45, 20)
    ]
    
    m = Motor(tam_ventana, j, pnjs)
    m.start()
    pygame.quit()
...

