from requerimientos import * COLORES = dict() #Definimos una serie de colores pre-definidos en un diccionario COLORES["rojo"] = np.array([ 0, 255, 0 ], dtype=np.uint8) COLORES["blanco"] = np.array([ 255, 255, 255 ], dtype=np.uint8) COLORES["negro"] = np.array([ 0, 0, 0 ], dtype=np.uint8) COLORES["magenta"] = np.array([ 0, 255, 255 ], dtype=np.uint8) COLORES["lila"] = np.array([ 0, 128, 255 ], dtype=np.uint8) COLORES["azul"] = np.array([ 0, 0, 255 ], dtype=np.uint8) COLORES["azul_claro"] = np.array([ 128, 0, 255 ], dtype=np.uint8) COLORES["cian"] = np.array([ 255, 0, 255 ], dtype=np.uint8) COLORES["turquesa"] = np.array([ 255, 0, 128 ], dtype=np.uint8) COLORES["verde"] = np.array([ 255, 0, 0 ], dtype=np.uint8) COLORES["lima"] = np.array([ 255, 128, 0 ], dtype=np.uint8) COLORES["amarillo"] = np.array([ 255, 255, 0 ], dtype=np.uint8) COLORES["naranja"] = np.array([ 128, 255, 0 ], dtype=np.uint8) cierto = const(True) falso = const(False) def dormir(tiempo): """ Permite parar el programa un tiempo determinado. El tiempo puede ser en segundos 1, 2, 3... o puede ser menor de un segundo -> 0.1 (100ms) Ejemplo: dormir(50) # Esperará durante 50s """ sleep(tiempo) def dormir_ms(tiempo): """ Permite parar el programa un tiempo determinado. El tiempo es en milisegundos, 100ms son 0.1s. Ejemplo: dormir_ms(50) # Esperará durante 50ms """ sleep_ms(tiempo) def imprimir(mensaje): """ Muestra un mensaje en la consola del ordenador, es útil para ver información rápido Si colocas una variable entre corchetes mostrará su valor, ejemplo: f"Esto es un mensaje y el valor de X es: {X}" """ print(mensaje) def esperarParaSiempre(): """ El programa se parará aquí indefinidamente, hay que pulsar stop para para parar el programa. Ejemplo: esperarParaSiempre() """ while True: sleep(1) class MiTiraDeLeds(): """ Es la tira con luces, con ella podemos hacer lo siguiente: - pintarLed(numero_led, color): Pintar un led de un color - iluminar(): Enciende los leds en la tira con los colores que se hayan pintado - borrar(): borrar todas las luces - moverDerecha(pasos): Mueve todos los colores a la derecha - moverIzquierda(pasos): Mueve todos los colores a la izquierda - pintarArcoiris(): Pinta un arcoiris Ejemplo: leds = MiTiraDeLeds() # Para usar la configuración por defecto o leds = MiTiraDeLeds(cantidad_de_leds=100) #si queremos cambiar la cantidad de leds """ def __init__(self, pin:int=12, cantidad_de_leds:int=50) -> None: _pin = pin self._cantidad_de_leds = cantidad_de_leds __pinNeoPixel = machine.Pin(12, machine.Pin.OUT) self.__tira_leds = NeoPixel(__pinNeoPixel, self._cantidad_de_leds) self.__capa = np.zeros((self._cantidad_de_leds,3), dtype=np.uint8) self.__brillo = 0.5 self.__lista_colores_arcoiris = ["naranja", "amarillo","lima", "verde", "turquesa", "cian", "azul_claro" , "azul", "lila", "magenta", "rojo"] def __str__(self):#Sobreescribimos el valor str por defecto de la clase con un texto return f"Soy una tira de luces con {self._cantidad_de_leds} leds" def __len__(self):#Devolvemos un valor al llamar a len(objeto) return self._cantidad_de_leds def iluminar(self): """ Enciende las luces con los colores que se hayan pintado, hay que hacerlo cada vez justo después de pintar para que los podamos ver Ejemplo: luces.iluminar() """ self.__tira_leds.buf = self.__capa.tobytes() # Nos saltamos el método __set_item__ y escribimos los colores directamente en formato bytearray self.__tira_leds.write() def pintarLed(self, numero_de_led, color:str="azul"): """ Pintamos una luz del color que queramos, hay que decirle el número del led que queremos y el color, ejemplo: Ejemplo: luces.pintarLed(numero_de_led=1, color="verde") o luces.pintarLed(1, "verde") luces.iluminar() """ if numero_de_led <= self._cantidad_de_leds and numero_de_led > 0: self.__capa[numero_de_led-1] = np.array(COLORES[color], dtype=np.uint8)*(self.__brillo) else: logger.warning(f"El numero de led que se quiere pintar ->{numero_de_led}<- está fuera de rango\nEl número debe ir entre 1 y {self._cantidad_de_leds} ") def borrar(self): """ Borra todos los colores, para ver las luces apagadas hay que usar iluminar. Ejemplo: luces.borrar() luces.iluminar() """ self.__capa = np.zeros((self._cantidad_de_leds,3), dtype=np.uint8) def moverDerecha(self, pasos:int=1): """ Mueve todas las luces a la derecha una cantidad de pasos. Ejemplo: luces.moverDerecha() <- Moverá un paso a la derecha luces.moverDerecha(pasos=2) <- Moverá dos paso a la derecha luces.iluminar() """ self.__capa = np.roll(self.__capa,pasos * 3) def moverIzquierda(self, pasos:int=1): """ Mueve todas las luces a la izquierda una cantidad de pasos. Ejemplo: luces.moverIzquierda() <- Moverá un paso a la izquierda luces.moverIzquierda(pasos=2) <- Moverá dos paso a la izquierda luces.iluminar() """ self.__capa = np.roll(self.__capa,pasos * -3) def pintarArcoiris(self): """ Pinta un arcoiris de colores. Ejemplo: luces.pintarArcoiris() luces.iluminar() """ self.__posicion_arcoiris = 0 self.__capa_arcoiris = np.zeros((self._cantidad_de_leds,3), dtype=np.uint8) self.__capa = np.zeros((self._cantidad_de_leds,3), dtype=np.uint8) casillas_por_color = int(self._cantidad_de_leds/len(self.__lista_colores_arcoiris)) casillas_libres = self._cantidad_de_leds - casillas_por_color * len(self.__lista_colores_arcoiris) posicion = 0 for num, color in enumerate(self.__lista_colores_arcoiris): self.__capa_arcoiris[posicion:posicion+casillas_por_color+casillas_libres] = np.array(COLORES[color], dtype=np.uint8)*(self.__brillo) posicion = posicion + casillas_por_color + casillas_libres if num == 0: casillas_libres = 0 self.__capa = self.__capa_arcoiris if self.__posicion_arcoiris != 0: self.__capa = np.roll(self.__capa_arcoiris, 3*self.__posicion_arcoiris) self.__posicion_arcoiris += 1 if self.__posicion_arcoiris >= self._cantidad_de_leds: self.__posicion_arcoiris = 0 @property def cantidad_de_leds(self): return self._cantidad_de_leds class MisMandos(): """ Los mandos con los que jugaremos al juego, con ellos podemos: - imprimirPasos("SI" o "NO"): Escribe por consola cada vez que se mueve un mando - imprimirBotones("SI" o "NO"): Escribe por consola cada vez que se pulsa un mando - giroMando1(): Es Verdadero si el mando ha girado, falso si no se ha movido - giroMando2(): Es Verdadero si el mando ha girado, falso si no se ha movido - posiciones_mando1: Son la cantidad de pasos que el mando se ha movido - posiciones_mando2: Son la cantidad de pasos que el mando se ha movido - boton1Pulsado(): Es Verdadero si el mando se ha pulsado, falso si no se ha pulsado - boton2Pulsado(): Es Verdadero si el mando se ha pulsado, falso si no se ha pulsado """ def __init__(self) -> None: self.r2 = RotaryIRQ(pin_num_clk=27, pin_num_dt=14, min_val=0, max_val=20, reverse=False, range_mode=RotaryIRQ.RANGE_UNBOUNDED) self.r1 = RotaryIRQ(pin_num_clk=33, pin_num_dt=25, min_val=0, max_val=20, reverse=False, range_mode=RotaryIRQ.RANGE_UNBOUNDED) self.r1.add_listener(self.__llamada_mando1) self.r2.add_listener(self.__llamada_mando2) self.imprimir_pasos = "NO" self.__posiciones_mando_p1 = 0 self.__posiciones_mando_p2 = 0 self.__valor_mando_p2 = 0 self.__valor_mando_p1 = 0 self.__pin1 = machine.Pin(32, machine.Pin.IN, machine.Pin.PULL_UP) self.__pin1.irq(trigger=machine.Pin.IRQ_FALLING, handler=self.__llamada_boton1) self.__pin2 = machine.Pin(26, machine.Pin.IN, machine.Pin.PULL_UP) self.__pin2.irq(trigger=machine.Pin.IRQ_FALLING, handler=self.__llamada_boton2) self.__pulsacion_b1 = False self.__pulsacion_b2 = False self.__imprimir_botones = "NO" self.__tiempo_antirebote = 200 self.__temporizadorB1 = Temporizador(self.__tiempo_antirebote) self.__temporizadorB2 = Temporizador(self.__tiempo_antirebote) self.__temporizadorB1.iniciar(self.__tiempo_antirebote) self.__temporizadorB2.iniciar(self.__tiempo_antirebote) def __str__(self):#Sobreescribimos el valor str por defecto de la clase con un texto return f"Tenemos 2 mandos que son unos encoders rotatorios con pulsadores" def imprimirPasos(self, valor:str="SI"): """ Imprime por consola cada vez que un mando se gira si el valor es "SI", si es "NO" no hace nada Ejemplo: mandos.imprimirPasos("SI") """ self.__imprimir_pasos = valor def imprimirBotones(self, valor:str="SI"): """ Imprime por consola cada vez que un mando se pulsa si el valor es "SI", si es "NO" no hace nada Ejemplo: mandos.imprimirBotones("SI") """ self.__imprimir_botones = valor def __llamada_mando1(self): if self.__valor_mando_p1 != self.r1.value(): self.__posiciones_mando_p1 += self.r1.value() - self.__valor_mando_p1 self.__valor_mando_p1 = self.r1.value() if self.__imprimir_pasos == "SI": print(f"Mando 1: Valor={self.r1.value()}, posiciones={self.__posiciones_mando_p1} ") def __llamada_mando2(self): if self.__valor_mando_p2 != self.r2.value(): self.__posiciones_mando_p2 += self.r2.value() - self.__valor_mando_p2 self.__valor_mando_p2 = self.r2.value() if self.__imprimir_pasos == "SI": print(f"Mando 2: Valor={self.r2.value()}, posiciones={self.__posiciones_mando_p2} ") def __llamada_boton1(self,p): if self.__temporizadorB1.fin(): self.__temporizadorB1.iniciar(self.__tiempo_antirebote) self.__pulsacion_b1 = True if self.__imprimir_botones == "SI": print(f"Botón 1: Valor={self.__pulsacion_b1}") def __llamada_boton2(self,p): if self.__temporizadorB1.fin(): self.__temporizadorB1.iniciar(self.__tiempo_antirebote) self.__pulsacion_b2 = True if self.__imprimir_botones == "SI": print(f"Botón 2: Valor={self.__pulsacion_b2}") def giroMando1(self) -> bool: """ Devuelve Verdadero si el mando ha girado, falso si no se ha movido. Ejemplo: if mandos.giroMando1(): imprimir("El mando 1 ha girado") """ if self.__posiciones_mando_p1: return True else: return False def giroMando2(self) -> bool: """ Devuelve Verdadero si el mando ha girado, falso si no se ha movido. Ejemplo: if mandos.giroMando2(): imprimir("El mando 2 ha girado") """ if self.__posiciones_mando_p2: return True else: return False @property def posiciones_mando1(self) -> int: """ Devuelve la cantidad de posiciones o pasos que ha girado el mando. Ejemplo: pasos = mandos.posiciones_mando1 """ try: return self.__posiciones_mando_p1 finally: self.__posiciones_mando_p1 = 0 @property def posiciones_mando2(self) -> int: """ Devuelve la cantidad de posiciones o pasos que ha girado el mando. Ejemplo: pasos = mandos.posiciones_mando2 """ try: return self.__posiciones_mando_p2 finally: self.__posiciones_mando_p2 = 0 def boton1Pulsado(self): """ Devuelve Verdadero si el mando se ha pulsado, falso si no se ha pulsado. Ejemplo: if mandos.boton1Pulsado(): imprimir("El mando 1 ha sido pulsado") """ try: if self.__pulsacion_b1: return True finally: self.__pulsacion_b1 = False def boton2Pulsado(self): """ Devuelve Verdadero si el mando se ha pulsado, falso si no se ha pulsado. Ejemplo: if mandos.boton2Pulsado(): imprimir("El mando 2 ha sido pulsado") """ try: if self.__pulsacion_b2: return True finally: self.__pulsacion_b2 = False class Bola: #Constructor, __init__ solo se ejecuta al crearse, osea, una vez def __init__(self, posicion:int=8, color:str="blanco"): #Inicializamos la clase y recogemos los argumentos a la hora de crearse self.__color = color self.__color_temporal = self.__color self.__posicion = posicion self.__largo = 1 def __str__(self):#Sobreescribimos el valor str por defecto de la clase con un texto return f"Soy una bola de color {self.__color} y estoy en la posición {self.__posicion}" def __len__(self):#Devolvemos un valor al llamar a len(objeto) return self.__largo @property def posicion(self): return self.__posicion @posicion.setter def posicion(self, valor:int): self.__posicion = valor @property def color(self): return self.__color @color.setter def color(self, valor:str): if valor in COLORES: self.__color = valor else: logger.warning(f"El color elegido no existe") def ocultar(self): self.__color_temporal = self.__color self.__color = "negro" def mostrar(self): self.__color = self.__color_temporal def moverDerecha(self, posiciones:int=1): __posiciones = posiciones __casilla_destino = self.__posicion + __posiciones if __casilla_destino < 50: # Si estamos dentro del rango self.__posicion += __posiciones self.__casillas = np.roll(self.__casillas, __posiciones * 3) return True else: # Nos hemos salido del rango, nos movemos solo hasta el extremo __posiciones = (len(self.__casillas)) - self.__posicion - 1 self.__posicion = (len(self.__casillas))-1 if __posiciones != 0: self.__casillas = np.roll(self.__casillas, __posiciones * 3) return False def moverIzquierda(self, posiciones:int=1): __posiciones = posiciones __casilla_destino = self.__posicion - __posiciones if __casilla_destino >= 0: self.__posicion -= __posiciones self.__casillas = np.roll(self.__casillas, -__posiciones * 3) return True else: __posiciones = self.__posicion self.__posicion = 0 if __posiciones != 0: self.__casillas = np.roll(self.__casillas, -__posiciones * 3) return False @property # Mejor no usar en bucle porque devuelve una copia de toda la array y es muy lento def leer(self): return self.__casillas class Porteria: def __init__(self, largo:int=8, posicion:int=8, color:str="rojo"): #Inicializamos la clase y recogemos los argumentos a la hora de crearse self.__posicion = posicion self.__color = color self.__largo = largo def __str__(self):#Sobreescribimos el valor str por defecto de la clase con un texto return f"Soy una porteria de color {self.__color}, hago {self.__largo} de largo y estoy en la posición {self.__posicion}" def __len__(self):#Devolvemos un valor al llamar a len(objeto) return len(self.__largo) @property def largo(self): return self.__largo @largo.setter def largo(self, valor:int): self.__largo = valor @property def color(self): return self.__color @color.setter def color(self, valor:str): if valor in COLORES: self.__color = valor else: logger.warning(f"El color elegido no existe") @property def posicion(self): return self.__posicion @posicion.setter def posicion(self, valor:int): self.__posicion = valor class Temporizador: """ Inicia un temporizador el cual podemos consultar si ha pasado el tiempo Ejemplo: temporizador.iniciar(tiempo_ms=1000) # El temporizador contara 1 segundo """ def __init__(self,tiempo_ms:int=100) -> None: self.__tiempo_ms = tiempo_ms self.__t = 0 def iniciar(self,tiempo_ms:int=100) -> None: """ Inicia el temporizador Ejemplo: temporizador.iniciar(tiempo_ms=1000) # El temporizador contara 1 segundo """ self.__t = time.ticks_ms() def fin(self) -> bool: """ Para comprobar si el temporizador ha finalizado, devuelve Verdadero si ha acabado sino Falso Ejemplo: if temporizador.fin(): # Si el temporizador ha acabado """ if time.ticks_diff(time.ticks_ms(), self.__t) >= self.__tiempo_ms: return True else: return False class VelocidadYTiempo: def __init__(self, velocidad_min:int=150) -> None: self.__tiempo_inicio = 0 self.__tiempo_juego = 0 self.__velocidad = velocidad_min self.__lista_velocidades = [200, 150, 75, 50, 25, 15, 10, 5, 4, 3, 2, 1, 0] self.__posicion_velocidad = 0 @property def tiempo_juego(self): return self.__tiempo_juego/1000 @property def velocidad(self): return self.__velocidad def iniciarTiempo(self): self.__tiempo_inicio = time.ticks_ms() self.__tiempo_juego = 0 self.generador_tiempo_cambio = self.generarTiemposVelocidad(tiemp_min=1, tiemp_max=5) self.__tiempo_siguiente_cambio = next(self.generador_tiempo_cambio) # logger.info(f"Iniciar Tiempo:\n self.__tiempo_inicio={self.__tiempo_inicio}, self.__tiempo_juego={self.__tiempo_juego}, self.__tiempo_siguiente_cambio={self.__tiempo_siguiente_cambio}") def tiempoCompletado(self) -> bool: self.__tiempo_juego = time.ticks_diff(time.ticks_ms(), self.__tiempo_inicio) if int(self.__tiempo_juego/1000) > self.__tiempo_siguiente_cambio: self.__tiempo_siguiente_cambio = next(self.generador_tiempo_cambio) # logger.info(f"tiempoCompletado:\nself.__tiempo_siguiente_cambio={self.__tiempo_siguiente_cambio}") return True else: return False def reiniciarVelocidad(self): self.iniciarTiempo() self.generador_velocidad = self.generarVelocidad() self.__velocidad = next(self.generador_velocidad) # logger.info(f"reiniciar Velocidad:\nvelocidad={self.__velocidad}") return self.__velocidad def cambiosDeVelocidad(self): if self.__velocidad == 0: return self.__velocidad else: if self.tiempoCompletado(): return self.cambiarVelocidad() else: return self.__velocidad def cambiarVelocidad(self, pasos:int=1) -> int: self.__velocidad = next(self.generador_velocidad) # logger.info(f"Velocidad CAMBIADA={self.__velocidad}") return self.__velocidad def incrementarVelocidad(self): pass def generarVelocidad(self, pasos:int=1) -> int: posicion = 0 while 1: if pasos>=0: if posicion + pasos >= len(self.__lista_velocidades): posicion = len(self.__lista_velocidades) -1 else: posicion += pasos else: if posicion + pasos <= 0: posicion = 0 else: posicion += pasos yield self.__lista_velocidades[posicion] def generarListaTiemos(self): pass def generarTiemposVelocidad(self, tiemp_min:int=3, tiemp_max:int=30) -> int: """ PLANTILLA DE DIFICULTAD """ plantilla = [ # Velocidad [5, 10], # 200 [5, 10], # 150 [5, 10], # 75 [15, 30], # 50 [15, 30], # 25 [15, 30], # 15 [15, 30], # 10 [15, 30], # 5 [20, 40], # 4 [20, 40], # 3 [20, 60], # 2 [20, 80], # 1 [60, 80] # 0 ] t = 0 posicion = 0 while 1: # t += random.randrange(tiemp_min,tiemp_max) try: t +=random.randrange(plantilla[posicion][0],plantilla[posicion][1]) posicion += 1 if posicion >= len(plantilla): posicion -= 1 except: t += plantilla[12][0] yield t """ Necesito una lista de tiempos no lineal y dependiendo de la dificultad self.__lista_velocidades = [200, 150, 75, 50, 25, 15, 10, 5, 4, 3, 2, 1, 0] """ class Tablero: def __init__(self, casillas_totales:int=50, pin_boton_1:int=32, pin_boton_2:int=26) -> None: #Inicializamos la clase y recogemos los argumentos a la hora de crearse self.__casillas_totales = casillas_totales self.r2 = RotaryIRQ(pin_num_clk=27, pin_num_dt=14, min_val=0, max_val=20, reverse=False, range_mode=RotaryIRQ.RANGE_UNBOUNDED) self.r1 = RotaryIRQ(pin_num_clk=33, pin_num_dt=25, min_val=0, max_val=20, reverse=False, range_mode=RotaryIRQ.RANGE_UNBOUNDED) self.myevent = asyncio.Event() asyncio.create_task(self.action()) self.r1.add_listener(self.callback) self.r2.add_listener(self.callback) self.__pin1 = machine.Pin(pin_boton_1, machine.Pin.IN, machine.Pin.PULL_UP) self.__pin1.irq(trigger=machine.Pin.IRQ_FALLING, handler=self.__cbBotonP1) self.__pin2 = machine.Pin(pin_boton_2, machine.Pin.IN, machine.Pin.PULL_UP) self.__pin2.irq(trigger=machine.Pin.IRQ_FALLING, handler=self.__cbBotonP2) self.__temporizadorP1 = Temporizador(tiempo_ms=250) self.__temporizadorP2 = Temporizador(tiempo_ms=250) self.__brillo_general = 40 self.__brillo_bola = 100 self.__brillo_porterias = 75 self.__brillo_puntos = 75 self.__brillo_fondo_puntos = 50 self.__bola = Bola(posicion=25, color="blanco") # logger.info(f"self.__bola:\n{self.__bola}") self.__capa_bola = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.__lista_colores = ["lima", "verde", "turquesa", "cian", "azul_claro" , "azul", "lila", "magenta", "rojo"] self.__lista_colores_arcoiris = ["naranja", "amarillo","lima", "verde", "turquesa", "cian", "azul_claro" , "azul", "lila", "magenta", "rojo"] self.color_p1 = "naranja" self.color_p2 = "amarillo" self.color_fondo_puntos = "rojo" self.color_puntos = "verde" self.__porteria1 = Porteria(largo=10, posicion=0, color=self.color_p1) logger.info(f"self.__porteria1:\n{self.__porteria1}") self.__porteria2 = Porteria(largo=10, posicion=self.__casillas_totales-10, color=self.color_p2) logger.info(f"self.__porteria2:\n{self.__porteria2}") self.__capa_porterias = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.__capa_porterias[0:self.__porteria1.largo] = np.array(COLORES[self.__porteria1.color], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_porterias/100) self.__capa_porterias[self.__porteria2.posicion:self.__porteria2.posicion+self.__porteria2.largo] = np.array(COLORES[self.__porteria2.color], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_porterias/100) self.capa_salida = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.__velocidad = 250 self.__direccion = 0 self.__pulsador = 0 self.__fase = "brillo" self.__dificultad = 5 self.__empezar_p1 = False self.__empezar_p2 = False self.__puntos_p1 = 0 self.__puntos_p2 = 0 self.__puntos_max = 5 self.__valor_encoder_p1 = self.r1.value() self.__valor_encoder_p2 = self.r2.value() self.__posiciones_encoder_p1 = 0 self.__posiciones_encoder_p2 = 0 self.__posicion_arcoiris = 0 self.__tiempoVelocidad = VelocidadYTiempo() __pinNeoPixel = machine.Pin(12, machine.Pin.OUT) self.__tira_leds = NeoPixel(__pinNeoPixel, self.__casillas_totales) def callback(self): self.myevent.set() async def action(self): while True: await self.myevent.wait() if self.__valor_encoder_p1 != self.r1.value(): self.__posiciones_encoder_p1 = self.r1.value() - self.__valor_encoder_p1 self.__valor_encoder_p1 = self.r1.value() if self.__valor_encoder_p2 != self.r2.value(): self.__posiciones_encoder_p2 = self.r2.value() - self.__valor_encoder_p2 self.__valor_encoder_p2 = self.r2.value() self.myevent.clear() def __str__(self): # Sobreescribimos el valor str por defecto de la clase con un texto return f"Soy una bola de color {self.__color} y estoy en la posición {self.__posicion}" def __len__(self): # Devolvemos un valor al llamar a len(objeto) return len(self.__casillas) def __cbBotonP1(self,p): if self.__temporizadorP1.fin(): # logger.info(f"{ticks_ms()}: P1") self.__pulsador = 1 self.__temporizadorP1.iniciar() def __cbBotonP2(self,p): if self.__temporizadorP2.fin(): # logger.info(f"{ticks_ms()}: P2") self.__pulsador = 2 self.__temporizadorP2.iniciar() @property def brillo(self): return self.__brillo_general @brillo.setter def brillo(self, valor:int): if valor >= 0 and valor <=100: self.__brillo_general = valor logger.info(f"El valor de brillo es: {self.__brillo_general}, rango[0-100]") else: logger.warning(f"El valor de brillo está fuera de rango: valor={valor}, rango[0-100]") @property def velocidad(self): return self.__velocidad @velocidad.setter def velocidad(self, valor:int): if valor >= 0 and valor <=1000: self.__velocidad = valor logger.info(f"El valor de velocidad es: {self.__velocidad}, rango[0-1000]") else: logger.warning(f"El valor de velocidad está fuera de rango: valor={valor}, rango[0-1000]") @property def dificultad(self): return self.__dificultad @dificultad.setter def dificultad(self, valor:int): if valor >= 1 and valor <=10: self.__dificultad = valor logger.info(f"El valor de dificultad es: {self.__dificultad}, rango[1-10]") else: logger.warning(f"El valor de dificultad está fuera de rango: valor={valor}, rango[1-10]") async def moverBolaDerecha(self, posiciones:int=1): __posiciones = posiciones __casilla_destino = self.__bola.posicion + __posiciones if __casilla_destino < self.__casillas_totales: # Si estamos dentro del rango self.__bola.posicion += __posiciones self.__capa_bola = np.roll(self.__capa_bola, __posiciones * 3) return True else: # Nos hemos salido del rango, nos movemos solo hasta el extremo __posiciones = self.__casillas_totales - self.__bola.posicion - 1 self.__bola.posicion = self.__casillas_totales-1 if __posiciones != 0: self.__capa_bola = np.roll(self.__capa_bola, __posiciones * 3) await asyncio.wait_for(self.gol(jugador=1),10) return False async def moverBolaIzquierda(self, posiciones:int=1): __posiciones = posiciones __casilla_destino = self.__bola.posicion - __posiciones if __casilla_destino >= 0: self.__bola.posicion -= __posiciones self.__capa_bola = np.roll(self.__capa_bola, -__posiciones * 3) return True else: __posiciones = self.__bola.posicion self.__bola.posicion = 0 if __posiciones != 0: self.__capa_bola = np.roll(self.__capa_bola, -__posiciones * 3) await asyncio.wait_for(self.gol(jugador=2),10) return False def mostrarPuntuacion(self): self.capa_salida = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.capa_salida[0:self.__puntos_max] = np.array(COLORES[self.color_fondo_puntos], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_fondo_puntos/100) self.capa_salida[self.__casillas_totales-self.__puntos_max:self.__casillas_totales] = np.array(COLORES[self.color_fondo_puntos], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_fondo_puntos/100) if self.__puntos_p1>0: self.capa_salida[0:self.__puntos_p1] = np.array(COLORES[self.color_puntos], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_puntos/100) # logger.info(f"self.capa_salida[{0}:{self.__puntos_p1}] = np.array({COLORES[self.color_puntos]}, dtype=np.uint8)*{(self.__brillo_general/100)*(self.__brillo_puntos/100)}") if self.__puntos_p2>0: self.capa_salida[self.__casillas_totales-self.__puntos_p2:self.__casillas_totales] = np.array(COLORES[self.color_puntos], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_puntos/100) # logger.info(f"self.capa_salida[{self.__casillas_totales-self.__puntos_p2}:{self.__casillas_totales}] = np.array({COLORES[self.color_puntos]}, dtype=np.uint8)*{(self.__brillo_general/100)*(self.__brillo_puntos/100)}") self.pintarLeds() def pintarArcoiris(self): self.__capa_arcoiris = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.__capa_porterias = np.zeros((self.__casillas_totales,3), dtype=np.uint8) casillas_por_color = int(self.__casillas_totales/len(self.__lista_colores_arcoiris)) casillas_libres = self.__casillas_totales - casillas_por_color * len(self.__lista_colores_arcoiris) posicion = 0 for num, color in enumerate(self.__lista_colores_arcoiris): self.__capa_arcoiris[posicion:posicion+casillas_por_color+casillas_libres] = np.array(COLORES[color], dtype=np.uint8)*(self.__brillo_general/100) posicion = posicion + casillas_por_color + casillas_libres if num == 0: casillas_libres = 0 self.__capa_porterias = self.__capa_arcoiris if self.__posicion_arcoiris != 0: self.__capa_porterias = np.roll(self.__capa_arcoiris, 3*self.__posicion_arcoiris) self.__posicion_arcoiris += 1 if self.__posicion_arcoiris >= self.__casillas_totales: self.__posicion_arcoiris = 0 def actualizarPorterias(self): self.__capa_porterias = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.__capa_porterias[0:self.__porteria1.largo] = np.array(COLORES[self.__porteria1.color], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_porterias/100) self.__capa_porterias[self.__porteria2.posicion:self.__porteria2.posicion+self.__porteria2.largo] = np.array(COLORES[self.__porteria2.color], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_porterias/100) async def gol(self, jugador:int, puntos:int=1): if jugador == 1: self.__direccion = 0 self.__puntos_p1 +=1 # logger.info(f"Jugador {jugador} puntos: {self.__puntos_p1}") self.reiniciarBola(jugador=2) if jugador == 2: self.__direccion = 0 self.__puntos_p2 +=1 # logger.info(f"Jugador {jugador} puntos: {self.__puntos_p1}") self.reiniciarBola(jugador=1) self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() self.desactivarInterrupciones() self.__bola.ocultar() logger.info(f"Puntuacion: Jugador 1 tiene {self.__puntos_p1} puntos, jugador 2 tiene {self.__puntos_p2} puntos") self.mostrarPuntuacion() await asyncio.sleep(4) self.activarInterrupciones() self.__bola.mostrar() if self.__puntos_p1 >= self.__puntos_max or self.__puntos_p2 >= self.__puntos_max: self.__puntos_p1, self.__puntos_p2 = 0, 0 self.__fase="brillo" self.__bola.ocultar() self.reiniciarBola(jugador=3) def reiniciarBola(self, jugador): if jugador == 1: self.__bola.posicion = self.__porteria1.posicion elif jugador == 2: self.__bola.posicion = self.__casillas_totales - 1 elif jugador == 3: self.__bola.posicion = int(self.__casillas_totales/2) self.__capa_bola = np.zeros((self.__casillas_totales,3), dtype=np.uint8) self.__capa_bola[self.__bola.posicion] = np.array(COLORES[self.__bola.color], dtype=np.uint8)*(self.__brillo_general/100)*(self.__brillo_bola/100) logger.info(f"Bola reiniciada para {jugador} en la posicion: {self.__bola.posicion}") def procesarCapas(self): self.capa_salida = np.where(self.__capa_bola>self.__capa_porterias, self.__capa_bola, self.__capa_porterias) self.pintarLeds() def pintarLeds(self): self.__tira_leds.buf = self.capa_salida.tobytes() # Nos saltamos el método __set_item__ y escribimos los colores directamente en formato bytearray self.desactivarIrqEncoder() self.__tira_leds.write() self.activarIrqEncoder() def desactivarIrqPulsadores(self): self.__pin1.irq(trigger=0, handler=None) self.__pin2.irq(trigger=0, handler=None) def activarIrqPulsadores(self): self.__pin1.irq(trigger=machine.Pin.IRQ_FALLING, handler=self.__cbBotonP1) self.__pin2.irq(trigger=machine.Pin.IRQ_FALLING, handler=self.__cbBotonP2) def desactivarIrqEncoder(self): self.r1._hal_disable_irq() self.r2._hal_disable_irq() def activarIrqEncoder(self): self.r1._hal_enable_irq() self.r2._hal_enable_irq() def desactivarInterrupciones(self): self.activarIrqPulsadores() self.desactivarIrqPulsadores() def activarInterrupciones(self): self.activarIrqPulsadores() self.activarIrqEncoder() async def seleccionarBrillo(self): try: logger.info(f"SELECCIONAR BRILLO") self.__bola.ocultar() self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() while self.__fase == "brillo": self.__velocidad = self.__tiempoVelocidad.cambiosDeVelocidad() if self.__posiciones_encoder_p1 > 0 or self.__posiciones_encoder_p2 > 0: self.__brillo_general -= 10 if self.__brillo_general < 10: self.__brillo_general = 1 self.__posiciones_encoder_p1 = 0 self.__posiciones_encoder_p2 = 0 elif self.__posiciones_encoder_p1 < 0 or self.__posiciones_encoder_p2 < 0: self.__brillo_general += 10 if self.__brillo_general > 100: self.__brillo_general = 100 self.__posiciones_encoder_p1 = 0 self.__posiciones_encoder_p2 = 0 if self.__pulsador == 1: self.__empezar_p1 = True self.__pulsador = 0 if self.__pulsador == 2: self.__empezar_p2 = True self.__pulsador = 0 if self.__empezar_p1 and self.__empezar_p2 == True: self.__empezar_p1 = False self.__empezar_p2 = False self.__fase = "puntos" self.pintarArcoiris() self.procesarCapas() await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de seleccionarBrillo por timeout") self.__fase="puntos" except Exception as e: logger.error(f"Error en seleccionarBrillo: {e}") async def seleccionarPuntos(self): try: logger.info(f"SELECCIONAR PUNTOS") self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() while self.__fase == "puntos": if self.__posiciones_encoder_p1 > 0 or self.__posiciones_encoder_p2 > 0: self.__puntos_max -= 1 if self.__puntos_max < 1: self.__puntos_max = 1 self.__posiciones_encoder_p1 = 0 self.__posiciones_encoder_p2 = 0 elif self.__posiciones_encoder_p1 < 0 or self.__posiciones_encoder_p2 < 0: self.__puntos_max += 1 if self.__puntos_max > 24: self.__puntos_max = 24 self.__posiciones_encoder_p1 = 0 self.__posiciones_encoder_p2 = 0 if self.__pulsador == 1: self.__empezar_p1 = True self.__pulsador = 0 if self.__pulsador == 2: self.__empezar_p2 = True self.__pulsador = 0 if self.__empezar_p1 and self.__empezar_p2 == True: self.__empezar_p1 = False self.__empezar_p2 = False self.__fase = "color" self.mostrarPuntuacion() await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de seleccionarPuntos por timeout") self.__fase="color" except Exception as e: logger.error(f"Error en seleccionarPuntos: {e}") async def seleccionarColor(self): try: logger.info(f"SELECCIONAR COLOR") self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() largo = 10 direccion = True largop1 = self.__porteria1.largo largop2 = self.__porteria2.largo while self.__fase == "color": if direccion: largo += 1 if largo > int(self.__casillas_totales/2)-2: direccion = not direccion else: largo -= 1 if largo < 2: direccion = not direccion self.__porteria1.largo = largo self.__porteria2.largo = largo self.__porteria2.posicion = self.__casillas_totales-largo if self.__posiciones_encoder_p1 > 0: self.__lista_colores.append(self.__porteria1.color) self.__porteria1.color = self.__lista_colores.pop(0) self.__posiciones_encoder_p1 = 0 elif self.__posiciones_encoder_p1 < 0: self.__lista_colores.insert(0,self.__porteria1.color) self.__porteria1.color = self.__lista_colores.pop() self.__posiciones_encoder_p1 = 0 if self.__posiciones_encoder_p2 > 0: self.__lista_colores.append(self.__porteria2.color) self.__porteria2.color = self.__lista_colores.pop(0) self.__posiciones_encoder_p2 = 0 elif self.__posiciones_encoder_p2 < 0: self.__lista_colores.insert(0,self.__porteria2.color) self.__porteria2.color = self.__lista_colores.pop() self.__posiciones_encoder_p2 = 0 if self.__pulsador == 1: self.__empezar_p1 = True self.__pulsador = 0 if self.__pulsador == 2: self.__empezar_p2 = True self.__pulsador = 0 if self.__empezar_p1 and self.__empezar_p2 == True: self.__empezar_p1 = False self.__empezar_p2 = False self.__porteria1.largo = largop1 self.__porteria2.largo = largop2 self.__porteria2.posicion = self.__casillas_totales-self.__porteria2.largo self.__fase = "largo" self.actualizarPorterias() self.procesarCapas() await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de seleccionarColor por timeout") self.__fase="largo" except Exception as e: logger.error(f"Error en seleccionarColor: {e}") async def seleccionarLargo(self): try: logger.info(f"SELECCIONAR LARGO") self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() while self.__fase == "largo": if self.__posiciones_encoder_p1 > 0: self.__porteria1.largo += 1 if self.__porteria1.largo > int(self.__casillas_totales/2)-2: self.__porteria1.largo = int(self.__casillas_totales/2)-2 self.__posiciones_encoder_p1 = 0 elif self.__posiciones_encoder_p1 < 0: self.__porteria1.largo -= 1 if self.__porteria1.largo < 1: self.__porteria1.largo = 1 self.__posiciones_encoder_p1 = 0 if self.__posiciones_encoder_p2 > 0: self.__porteria2.largo += 1 if self.__porteria2.largo > int(self.__casillas_totales/2)-2: self.__porteria2.largo = int(self.__casillas_totales/2)-2 self.__porteria2.posicion = self.__casillas_totales-self.__porteria2.largo self.__posiciones_encoder_p2 = 0 elif self.__posiciones_encoder_p2 < 0: self.__porteria2.largo -= 1 if self.__porteria2.largo < 1: self.__porteria2.largo = 1 self.__porteria2.posicion = self.__casillas_totales-self.__porteria2.largo self.__posiciones_encoder_p2 = 0 if self.__pulsador == 1: self.__empezar_p1 = True self.__pulsador = 0 if self.__pulsador == 2: self.__empezar_p2 = True self.__pulsador = 0 if self.__empezar_p1 and self.__empezar_p2 == True: self.__empezar_p1 = False self.__empezar_p2 = False self.__fase = "inicio" self.actualizarPorterias() self.procesarCapas() await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de seleccionarLargo por timeout") self.__fase="inicio" except Exception as e: logger.error(f"Error en seleccionarLargo: {e}") async def seleccionarDificultad(self): try: logger.info(f"SELECCIONAR DIFICULTAD") self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() self.__bola.mostrar() self.reiniciarBola(jugador=3) while self.__fase == "dificultad": if self.__posiciones_encoder_p1 > 0: self.__dificultad += 1 if self.__dificultad > 10: self.__dificultad = 10 self.__posiciones_encoder_p1 = 0 elif self.__posiciones_encoder_p1 < 0: self.__dificultad -= 1 if self.__dificultad < 1: self.__dificultad = 1 self.__posiciones_encoder_p1 = 0 if self.__posiciones_encoder_p2 > 0: self.__dificultad += 1 if self.__dificultad > 10: self.__dificultad = 10 self.__posiciones_encoder_p2 = 0 elif self.__posiciones_encoder_p2 < 0: self.__dificultad -= 1 if self.__dificultad < 1: self.__dificultad = 1 self.__posiciones_encoder_p2 = 0 if self.__pulsador == 1: self.__empezar_p1 = True self.__pulsador = 0 if self.__pulsador == 2: self.__empezar_p2 = True self.__pulsador = 0 if self.__empezar_p1 and self.__empezar_p2 == True: self.__empezar_p1 = False self.__empezar_p2 = False self.__fase = "inicio" self.actualizarPorterias() self.procesarCapas() await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de seleccionarDificultad por timeout") self.__fase="inicio" except Exception as e: logger.error(f"Error en seleccionarDificultad: {e}") async def inicio(self): try: self.__velocidad = self.__tiempoVelocidad.reiniciarVelocidad() self.__bola.mostrar() self.reiniciarBola(jugador=3) logger.info(f"FASE INICIO") self.actualizarPorterias() self.procesarCapas() while self.__fase == "inicio": if self.__pulsador == 1: self.__direccion = 2 self.__pulsador = 0 self.__fase = "juego" logger.info(f"FASE JUEGO") break if self.__pulsador == 2: self.__direccion = 1 self.__pulsador = 0 self.__fase = "juego" await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de inicio por timeout") self.__fase="brillo" except Exception as e: logger.error(f"Error en inicio: {e}") async def juegoPrincipal(self): try: logger.info(f"JUEGO PRINCIPAL") self.__tiempoVelocidad.iniciarTiempo() while self.__fase == "juego": if self.__pulsador == 1 and self.__bola.posicion <= self.__porteria1.posicion+self.__porteria1.largo-1: # logger.info(f"self.__pulsador={self.__pulsador}, self.__bola.posicion={self.__bola.posicion}, self.__porteria1.posicion={self.__porteria1.posicion+self.__porteria1.largo}") self.__direccion = 2 self.__pulsador = 0 self.__velocidad = self.__tiempoVelocidad.cambiosDeVelocidad() if self.__pulsador == 2 and self.__bola.posicion >= self.__porteria2.posicion: self.__direccion = 1 self.__pulsador = 0 self.__velocidad = self.__tiempoVelocidad.cambiosDeVelocidad() # logger.info(f"self.__pulsador={self.__pulsador}, self.__bola.posicion={self.__bola.posicion}, self.__porteria2.posicion={self.__porteria2.posicion}") self.__pulsador = 0 if self.__direccion == 1: if not await asyncio.wait_for(self.moverBolaIzquierda(),10): self.__direccion = 0 elif self.__direccion == 2: if not await asyncio.wait_for(self.moverBolaDerecha(),10): self.__direccion = 0 else: pass self.procesarCapas() await asyncio.sleep_ms(self.__velocidad) except asyncio.TimeoutError: logger.warning(f"Saliendo de juegoPrincipal por timeout") self.__fase="brillo" except Exception as e: logger.error(f"Error en juegoPrincipal: {e}") luces = MiTiraDeLeds() mandos = MisMandos() temporizador = Temporizador(tiempo_ms=500)