You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1168 lines
49 KiB

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)