-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUPIIZ_BALL.py
More file actions
254 lines (207 loc) · 14.5 KB
/
Copy pathUPIIZ_BALL.py
File metadata and controls
254 lines (207 loc) · 14.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
import pygame
import math
import sys
# - - - FUNCIONES - - -
def func_dist(p1, p2):
return math.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)
def func_col(cent_bal, cent_pun, velBx, velBy, reboteB):
dx=cent_bal[0]-cent_pun[0]
dy=cent_bal[1]-cent_pun[1]
dist=math.sqrt(dx**2+dy**2)
nx=dx/dist
ny=dy/dist
velR=velBx*nx+velBy*ny
if velR>0:
return velBx, velBy
velBx-=2*velR*nx
velBy-=2*velR*ny
velBx*=reboteB
velBy*=reboteB
return velBx, velBy
# - - - CONSTANTES - - -
anch, larg=800, 600 #Ancho y largo de la ventana
grav=3708.87 #Gravedad en pixeles por segundo cuadrado
velM=3780.71 #Velocidad máxima en pixeles por segundo
fricc=0.25 #Constante de fricción del suelo suponiendolo de madera
p1=581, 165 #Punto de colisión del aro 1 (izquierdo)
p2=703, 165 #Punto de colisión del aro 2 (derecho)
pygame.init() #Iniciar los modulos de la librería
screen=pygame.display.set_mode((anch, larg)) #Dar tamaño a la ventana mediante variables
pygame.display.set_caption("UPIIZ BALL") #Agregar titulo a la ventana
balon=pygame.image.load("assets/balon.png").convert_alpha() #Cargar imagen del balon
fondo=pygame.image.load("assets/fondo.png").convert() #Cargar imagen del fondo
opacidad=pygame.Surface((800, 600), pygame.SRCALPHA) #Crear una superficie para objetos con opacidad
# - - - PROPIEDADES DEL BALON - - -
posBx, posBy=30, 420 #Posición inicial del balon en los ejes X, Y (x0, y0)
velBx, velBy=0, 0 #Velocidad inicial del balon en los ejes X, Y (vx0, vy0)
tiemLanz=None #Tiempo desde el lanzamiento
reboteB=-0.75 #Factor de rebote del balon (Para cada rebote pierde 25% de la velocidad y cambia de dirección, por eso el menos)
activoB=False #Variable para determinar si el balon ha sido lanzado
masa=0.62 #Masa del balón en kilogramos
peso=masa*grav #Peso del balón en newtons
Fnormal=peso #Fuerza normal del balón en newtons
# - - - PROPIEDADES DEL JOYSTICK - - -
posJx, posJy=400, 300 #Posición inicial del joystick en los ejes X, Y (x0, y0)
radJ=120 #Radio máximo de movimiento del joystick
activoJ=False #Variable para determinar si el joystick se esta arrastrando
# - - - VARIABLES PARA LA PARÁBOLA - - -
parabP=[] #Arreglo para guardar la posición de cada punto
tiP, dtP=0, 0.08 #Tiempo inicial y aumento de tiempo para cada punto
visibilidad=0, 0, 0, 150 #Variable para modificar la visibilidad de los puntos (actualmente visible)
cargar=False #Variable para indicar al juego que cargue los puntos
# - - - SISTEMA DE PUNTAJE - - -
cont_punt=0 #Variable para contar los puntos
encestado=False #Variable para determinar si el balon ha sido encestado
tiempo=60 #Tiempo total de juego
TIMER_EVENT=pygame.USEREVENT+1 #Crear evento
pygame.time.set_timer(TIMER_EVENT, 1000)
# - - - FUENTES PARA TEXTO - - -
fuente=pygame.font.SysFont("Bahnschrift", 18)
velText=fuente.render("Velocidad: 0 px/s", True, (0, 0, 0))
anguText=fuente.render("Ángulo: 0°", True, (0, 0, 0))
canastText=fuente.render("Canastas: 0", True, (0, 0, 0))
tiemText=fuente.render("Tiempo: 60s", True, (0, 0, 0))
clock=pygame.time.Clock() #Inicializar un reloj
running=True
while running: #Mientras la variable "running" sea "True", se ejecuta el programa
for event in pygame.event.get(): #Para todo evento
if event.type==pygame.QUIT: #Si ese evento es "pygame.QUIT" (Cerrar)
running=False #"running" sera "False". Por lo tanto se detiene el programa
elif event.type==TIMER_EVENT:
if tiempo>0:
tiempo-=1
tiem=f"Tiempo: {int(tiempo)} s"
tiemText=fuente.render(tiem, True, (0, 0, 0))
else:
running=False
elif event.type==pygame.MOUSEBUTTONDOWN: #Si ese evento es "pygame.MOUSEBUTTONDOWN" (Click derecho)
mouse_x, mouse_y=pygame.mouse.get_pos() #Obtener la posición del mouse
dist=math.sqrt((mouse_x-posJx)**2+(mouse_y-posJy)**2) #Obtener la distancia entre joystick y la del mouse
if dist<=55: #Si el clic está dentro del círculo del joystick
activoJ=True #El joystick está activo
elif event.type==pygame.MOUSEMOTION and activoJ: #Si ese evento es "pygame.MOUSEMOTION" (Ratón en movimiento), y el joystick está activo
mouse_x, mouse_y=pygame.mouse.get_pos() #Obtener la posición del mouse
dx, dy=mouse_x-400, mouse_y-300 #Desplazamiento del mouse en cada eje respecto la posición inicial
dist=math.sqrt(dx**2+dy**2) #Obtener la distancia entre la posición inicial del joystick y la del mouse
visibilidad=0, 0, 0, 150 #Variable para modificar la visibilidad de los puntos (actualmente visible)
if dist>radJ: #Si la distancia es mayor al radio máximo
angu=math.atan2(dy, dx) #Obtener el angulo contiguo al origen, formado por el triángulo rectangulo con C.O=dy y C.A=dx, donde dy y dx son las distancias del mouse al punto inicial
posJx=400+radJ*math.cos(angu) #Recalcular posición del joystick para evitar que sobrepase el area definida en el eje X, tomando como referencia la posición del mouse
posJy=300+radJ*math.sin(angu) #Recalcular posición del joystick para evitar que sobrepase el area definida en el eje Y, tomando como referencia la posición del mouse
else:
posJx, posJy=mouse_x, mouse_y #La posición del joystick es igual a la posición del mouse
if not activoB: #Si el balón no está activo
tiP=0 #Reiniciar el tiempo inicial
parabP=[] #Limpiar el arreglo con la posición de los puntos
dx=posJx-400 #Obtener distancia entre la posición inicial y la posición final del joystick en el eje X
dy=posJy-300 #Obtener distancia entre la posición inicial y la posición final del joystick en el eje Y
dist=math.sqrt(dx**2+dy**2) #Obtener distancia entre la posición inicial y la posición final del joystick
angu=math.atan2(dy, dx) #Obtener el angulo contiguo al origen, formado por el triángulo rectangulo con C.O=dy y C.A=dx, donde dy y dx son las distancias del joystick al punto inicial
if dist>0: #Si la distancia es mayor a 0
vel=(velM/radJ)*dist #Obtener la magnitud de la velocidad (donde la velocidad máxima será 10m/s o 3780.71 px/s)
velBx=-vel*math.cos(angu) #Obtener magnitudes para el eje X (negativo por que se lanzara en dirección contraria al joystick)
velBy=-vel*math.sin(angu) #Obtener magnitudes para el eje Y (negativo por que se lanzara en dirección contraria al joystick)
else:
velBx, velBy=0, 0 #El balón no tendrá velocidad
for i in range(1, 10): #For del 1 al 9
x=(posBx+45)+velBx*tiP #Obtener la posición en el eje X del punto en el tiempo "i"
y=(posBy+45)+velBy*tiP+0.5*grav*tiP**2 #Obtener la posición en el eje X del punto en el tiempo "i"
parabP.append((int(x), int(y))) #Almacenar la posición del punto "i" en el primer espacio libre del arreglo
tiP+=dtP #Aumentar el tiempo inicial para cada iteración
cargar=True #Indicar al juego que debe cargar los puntos
velT=f"Velocidad: {int(math.sqrt(velBx**2+velBy**2))} px/s"
anguT=f"Ángulo: {int(-(math.degrees(angu)-180))}°"
velText=fuente.render(velT, True, (0, 0, 0))
anguText=fuente.render(anguT, True, (0, 0, 0))
elif event.type==pygame.MOUSEBUTTONUP and activoJ: #Si ese evento es "pygame.MOUSEBUTTONUP" (Soltar click derecho)
if activoJ and not activoB: #Si el joystick está activo
dx=posJx-400 #Obtener distancia entre la posición inicial y la posición final del joystick en el eje X
dy=posJy-300 #Obtener distancia entre la posición inicial y la posición final del joystick en el eje Y
dist=math.sqrt(dx**2 + dy**2) #Obtener distancia entre la posición inicial y la posición final del joystick
angu=math.atan2(dy, dx) #Obtener el angulo contiguo al origen, formado por el triángulo rectangulo con C.O=dy y C.A=dx, donde dy y dx son las distancias del joystick al punto inicial
if dist>0: #Si la distancia es mayor a 0
vel=(velM/radJ)*dist #Obtener la magnitud de la velocidad (donde la velocidad máxima será 10m/s o 3780.71 px/s)
velBx=-vel*math.cos(angu) #Obtener magnitudes para el eje X (negativo por que se lanzara en dirección contraria al joystick)
velBy=-vel*math.sin(angu) #Obtener magnitudes para el eje Y (negativo por que se lanzara en dirección contraria al joystick)
activoB=True #El balón está activo
tiemLanz=pygame.time.get_ticks() #Guardar la cantidad de ticks desde que se inicializo el reloj
clock.tick() #Reinicar el reloj
else:
velBx, velBy=0, 0 #El balón no tendrá velocidad
activoJ=False #El joystock ya no está activo
posJx, posJy=400, 300 #Reiniciar la posición del joystick
if activoB: #Si el balón está activo
visibilidad=0, 0, 0, 0 #Variable para modificar la visibilidad de los puntos (actualmente invisible)
dt=clock.tick(120)/1000 #Diferencial de tiempo
PposBx, PposBy=posBx, posBy #Guardar valor de la posición en la primer iteración del reloj
velBy+=grav*dt #Calcular la velocidad a partir de la gravedad en el eje Y
posBx+=velBx*dt #Calcular la posición en el eje X
posBy+=velBy*dt #Calcular la posición en el eje Y
dif_posBx=abs(posBx-PposBx) #Obtener diferencial de posición en el eje X
dif_posBy=abs(posBy-PposBy) #Obtener diferencial de posición en el eje Y
if dif_posBx<0.1: #Si el diferencial de posición en el eje X es despreciable
velBx=0 #Igualar la velocidad en el eje X a 0
if dif_posBy<0.1 and posBy>=larg-90: #Si el diferencial de posición en el eje Y es despreciable, y la posición en dicho eje es mayor o igual al punto de colisión en el eje Y
velBy=0 #Igualar la velocidad en el eje Y a 0
if posBy>=larg-90: #Si la posición en el eje Y es mayor o igual al punto de colisión en el eje Y
posBy=larg-90 #La posición de la pelota será el punto de colisión
velBy*=reboteB #Multiplicar la velocidad en el eje Y por el factor de rebote
if velBx!=0: #Si la velocidad en el eje X es diferente de 0
friccF=fricc*peso #Calcular la fuerza de fricción a partir del coeficiente de fricción y el peso
if velBx>0: #Si la velocidad es mayor a 0 (hacia el eje X positivo)
acelF=-friccF/masa #Calcular desaceleración debida a la fuerza de fricción
velBx+=acelF*dt #Recalcular la velocidad a partir de esa desaseleración
else:
acelF=friccF/masa #Calcular desaceleración debida a la fuerza de fricción
velBx+=acelF*dt #Recalcular la velocidad a partir de esa desaseleración
if posBx<=0: #Si la posición en el eje Y es mayor o igual al punto de colisión en el eje X, lado izquierdo
posBx=0 #La posición de la pelota será el punto de colisión
velBx*=reboteB #Multiplicar la velocidad en el eje X por el factor de rebote
if posBx>=anch-90: #Si la posición en el eje Y es mayor o igual al punto de colisión en el eje X, lado derecho
posBx=anch-90 #La posición de la pelota será el punto de colisión
velBx*=reboteB #Multiplicar la velocidad en el eje X por el factor de rebote
cent_bal=(posBx+45, posBy+45)
if func_dist(cent_bal, p1)<46:
posBx, posBy=PposBx, PposBy
velBx, velBy=func_col(cent_bal, p1, velBx, velBy, -reboteB)
if func_dist(cent_bal, p2)<46:
posBx, posBy=PposBx, PposBy
velBx, velBy=func_col(cent_bal, p2, velBx, velBy, -reboteB)
if func_dist((cent_bal), (642, 165))<=20 and velBy>0 and encestado==False:
cont_punt+=1
encestado=True
canasta=f"Canastas: {int(cont_punt)}"
canastText=fuente.render(canasta, True, (0, 0, 0))
if tiemLanz and pygame.time.get_ticks()-tiemLanz>4000: #Si "tiemLanz" no es "None", y el tiempo transcurrido desde que se inicializo el reloj menos el tiempo que transcurrio desde el lanzamiento, es mayor a 5 segundos (5000 milisegundos)
posBx, posBy=30, 420 #Devolverr balon a su posición inicial
velBx, velBy=0, 0 #Igualar el valor de las velocidades en cada eje a 0
tiemLanz=None #Reiniciar la variable "tiemLanz"
activoB=False #Establecer al balón como inactivo
encestado=False
opacidad.fill((0, 0, 0, 0)) #Limpiar la superfice "opacidad"
pygame.draw.circle(opacidad, (225, 225, 225, 180), (400, 300), 75) #Dibujar circulos para el joystick en la superficie "opacidad"
pygame.draw.circle(opacidad, (120, 120, 120, 180), (posJx, posJy), 55)
pygame.draw.circle(opacidad, (180, 180, 180, 180), (posJx, posJy), 25)
pygame.draw.circle(opacidad, (0, 0, 0, 0), (581, 165), 1) #Dibujar puntos de colisión de la canasta
pygame.draw.circle(opacidad, (0, 0, 0, 0), (703, 165), 1)
if cargar==True: #Si cargar es "True", mostrar los puntos
pygame.draw.circle(opacidad, visibilidad, parabP[0], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[1], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[2], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[3], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[4], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[5], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[6], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[7], 4)
pygame.draw.circle(opacidad, visibilidad, parabP[8], 4)
screen.fill((225, 225, 225)) #Rellenar el fondo de la ventana
screen.blit(fondo, (0, 0)) #Insertar imagen de fondo con inicio en 0, 0
screen.blit(opacidad, (0, 0)) #Insertar superficie para objetos con opacidad
screen.blit(velText, (20, 545))
screen.blit(anguText, (20, 565))
screen.blit(canastText, (260, 545))
screen.blit(tiemText, (260, 565))
screen.blit(balon, (posBx, posBy)) #Insertar imagen del balon iniciando en la posición dada mediante variables
pygame.display.flip() #Actualizar la ventana para cargar los cambios
pygame.quit() #Salir del programa
sys.exit()