elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Los 10 CVE más críticos (peligrosos) de 2020


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 [2] Ir Abajo Respuesta Imprimir
Autor Tema: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.  (Leído 11,192 veces)
Tachikomaia


Desconectado Desconectado

Mensajes: 1.201


Superhacker (es broma xD )


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #10 en: 9 Mayo 2023, 21:52 pm »

Pudiera ser que no tengas la suficiente para pasar la pelota a exactamente 18.6 m al llegar a la red, pero sí a 19.5 m.
Ese caso sólo ocurriría si también la bola está muy alto y la debe golpear hacia abajo ¿no? Porque sino, si la puede elevar a 19.5 m también debería poderla elevar a 18.6 ¿no? Si es así, nos estamos entendiendo.

Citar
Eso no estaba estaba originalmente
En mi opinióbn sí, es la condición nro 5:
Citar
5- Las velocidades deben ser tales que la pelota caiga en cierto punto. Por ejemplo:

https://foro.elhacker.net/programacion_general/ayuda_con_calculos_para_que_la_trayectoria_de_una_pelota_cumpla_ciertas_condiciones-t516487.0.html;msg2266250#msg2266250

Citar
Sin conocer bien todos los parámetros, como las coordenadas (¿y AlexAcc es la gravedad?), es difícil saber bien lo que pasa, pero en ninguno de los casos la fuerza se está repartiendo al 100% en XY. Como te había dicho anteriormente, la velocidad total no es la suma de las individuales sino:

v = raiz(vx2 + vy2).

De hecho, aún incorporando la velocidad en Z, no llega al 100% de la disponible. ¿Estás usando el método del otro foro?
Te comenté que el código de eso, con la cancha naranja y las letras, es un lío y lo hice hace mucho, 2012, así que no te puedo explicar mucho.

AlexAcc es la puntería del jugador (Acc = accuracy), la idea era que si es menos de 10 los tiros se pudieran desviar más entre menos sea el valor. Pero es 10 ahí y no programé del todo eso, así que nada hace.
La gravedad es 0.01 ahí también si mal no recuerdo (es difíciil porque no la definí en una variable ni siquiera como spin, gran error).

Lo de la suma lo entendí, pero en este método se hace eso que pusiste, es decir se reparte la fuerza en XY así como pusiste, pero luego se vuelve a usar toda la fuerza en Z si se necesita, pero entonces la fuerza se puede usar toda 2 veces, está mal.

El método está basado en algo que me dijeron hace años, y lo de Z lo hice yo, mal. No está basado en lo que me dijeron en el foro que te mostré.

Las medidas de la cancha también son distintas de las que uso ahora (cancha azul).


La mínima altura por la que debe pasar la pelota era distinta también, creo que 24.51.

Le pongo tantos comentarios * como pueda.
Código
  1. Pow = _level0.AlexPow;
  2. // * Considéralo una abreviación.
  3. Caso = "";
  4. W = 1;
  5. E = 1;
  6. // * No recuerdo qué hace eso, está relacionado con casos más adelante.
  7. // Efectos de la pelota en lv0.
  8. // Relacionando velocidades.
  9. _level0.BallZ = _level0.BallZ*-1;
  10. // * Este código está dentro de un objeto dentro de otro, un lío sí, y en tal caso, estar por encima del centro es estar a menos algo, por eso se hace negativo al número.
  11. _level0.BallZInicial = _level0.BallZ;
  12. _level0.BallX = _level0.AlexX+13.4;
  13. // * Esto es porque la pelota está un poco hacia la derecha del jugador, aquí se define recién. Como estaba dentro del jugador, no había sido necesario.
  14. _level0.DistanciaX = _level0.BallX-Destiny;
  15. // * Destiny es lo que ahora llamo DestinoX. Uno de los dos puntos señalados en la parte de arriba de la imagen. También se puede sacar hacia el centro, pero en el video no lo hice, no cambia mucho.
  16. Norma = Math.sqrt(374.6*374.6+_level0.DistanciaX*_level0.DistanciaX+_level0.BallZ*_level0.BallZ);
  17. // * 374.6 sería como la distancia Y. Como al sacar eso es constante, no lo puse como variable. Pero estos métodos los necesito también cuando el jugador haya sacado. Por ahora no fue necesario.
  18. _level0.BallYSpeed = 374.6/Norma*-Pow;
  19. _level0.BallZSpeed = _level0.BallZ/Norma*-Pow;
  20. // * El - es porque en este caso la bola irá hacia donde baja el Y y Z.
  21. // * Ahora empieza lo difícil de entender.
  22. // Calcula la distancia que recorrería antes de tocar el suelo.
  23. Abrev = (200*_level0.BallZSpeed-1)*(200*_level0.BallZSpeed-1);
  24. // * Abrev es abreviación. Distancia probablemente se refiere a Y solamente. Estas fórmulas las obtuve dando casos a un programa llamado Eureka; le das variables y él intenta encontrar una relación entre ellas.
  25. ShotTZ = Math.ceil(((200*_level0.BallZSpeed-1)+Math.sqrt(Abrev+800*_level0.BallZ))/2);
  26. Excess = -374.6+ShotTZ*Math.abs(_level0.BallYSpeed);
  27. if (Excess<0) {
  28. // Casos normales.
  29. Caso = Caso+"A";
  30. // Calcula cuánto caería por causa de la gravedad.
  31. ShotTY = Math.ceil(374.6/Math.abs(_level0.BallYSpeed));
  32. // Abrev as caída extra.
  33. Abrev = ShotTY*(ShotTY+1)/200;
  34. // Calcula la velocidad Z restándole la caída extra a la altura.
  35. _level0.BallZSpeed = (_level0.BallZ-Abrev)/Norma*-Pow;
  36. if (_level0.BallZSpeed<=0) {
  37. Caso = Caso+"B";
  38. // B
  39. // Calcula la distancia que recorrería antes de tocar el suelo.
  40. Abrev = (200*_level0.BallZSpeed-1)*(200*_level0.BallZSpeed-1);
  41. ShotTZ = Math.ceil(((200*_level0.BallZSpeed-1)+Math.sqrt(Abrev+800*_level0.BallZ))/2);
  42. Excess = -374.6+ShotTZ*Math.abs(_level0.BallYSpeed);
  43. if (Excess>=0) {
  44. // Va a W
  45. E = 0;
  46. }
  47. }
  48. if (E == 1) {
  49. Caso = Caso+"D";
  50. // D
  51. // Equilibrar fuerza.
  52. Norma = Math.sqrt(374.6*374.6*2+_level0.DistanciaX*_level0.DistanciaX);
  53. _level0.BallYSpeed = 374.6/Norma*-Pow;
  54. _level0.BallZSpeed = _level0.BallYSpeed*-1;
  55. // E
  56. Caso = Caso+"E";
  57. // Calcula la distancia que recorrería antes de tocar el suelo.
  58. Abrev = (200*_level0.BallZSpeed-1)*(200*_level0.BallZSpeed-1);
  59. ShotTZ = Math.ceil(((200*_level0.BallZSpeed-1)+Math.sqrt(Abrev+800*_level0.BallZ))/2);
  60. Excess = -374.6+ShotTZ*Math.abs(_level0.BallYSpeed);
  61. if (Excess<0) {
  62. W = 0;
  63. // ACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  64. Caso = Caso+"ACAAAAAAAAAAAAAAAAAA";
  65. } else {
  66. Caso = Caso+"F";
  67. // F
  68. // Calcula cuánto caería por causa de la gravedad.
  69. ShotTY = Math.ceil(374.6/Math.abs(_level0.BallYSpeed));
  70. // Abrev as caída extra.
  71. Abrev = ShotTY*(ShotTY+1)/200;
  72. // Calcula la velocidad Z restándole la caída extra a la altura.
  73. _level0.BallZSpeed = ((_level0.BallZ-Abrev)/Norma)*-Pow;
  74. // Calcula la distancia que recorrería antes de tocar el suelo.
  75. Abrev = (200*_level0.BallZSpeed-1)*(200*_level0.BallZSpeed-1);
  76. ShotTZ = Math.ceil(((200*_level0.BallZSpeed-1)+Math.sqrt(Abrev+800*_level0.BallZ))/2);
  77. Excess = -374.6+ShotTZ*Math.abs(_level0.BallYSpeed);
  78. }
  79. }
  80. }
  81. if (W == 1) {
  82. Caso = Caso+"W";
  83. do {
  84. // Recalcular velocidad Y de modo que no haya exceso.
  85. _level0.BallYSpeed = _level0.BallYSpeed+Excess/ShotTZ;
  86. Excess = 0;
  87. // Puede causar q la pelota no pase la red (se calcula dónde pasa).
  88. TR = Math.ceil(253.6/Math.abs(_level0.BallYSpeed));
  89. Abrev = 0.005*(TR+1);
  90. ZR = _level0.BallZ+_level0.BallZSpeed*(TR+1)+Abrev-Abrev*(TR+1)-_level0.BallZSpeed;
  91. if (ZR<24.5) {
  92. Abrev = _level0.BallZSpeed;
  93. // Calcula velocidad Z de modo que pase encima de la red.
  94. _level0.BallZSpeed = TR*0.005+0.005-(_level0.BallZ-24.51)/TR;
  95. if (Abrev<0) {
  96. // Si velocidad Z era N.
  97. if (_level0.BallZSpeed<Abrev or _level0.BallZSpeed>0) {
  98. // ERROR: La fuerza aplicada hacia abajo aumentó.
  99. _level0.BallZSpeed = Abrev;
  100. break;
  101. }
  102. } else if (Abrev>0) {
  103. // Si velocidad Z era P.
  104. if (_level0.BallZSpeed>Abrev or _level0.BallZSpeed<0) {
  105. // ERROR: La fuerza aplicada hacia arriba aumentó.
  106. _level0.BallZSpeed = Abrev;
  107. break;
  108. }
  109. } else {
  110. // Si velocidad Z era 0.
  111. // La fuerza aplicada a Z ya no puede reducirse.
  112. break;
  113. }
  114. }
  115. // Puede causar exceso (calcular cuánto).
  116. Abrev = (200*_level0.BallZSpeed-1)*(200*_level0.BallZSpeed-1);
  117. ShotTZ = Math.ceil(((200*_level0.BallZSpeed-1)+Math.sqrt(Abrev+800*_level0.BallZ))/2);
  118. Excess = -374.6+ShotTZ*Math.abs(_level0.BallYSpeed);
  119. } while (Excess>0);
  120. }
  121. ShotTY = Math.ceil(374.6/Math.abs(_level0.BallYSpeed));
  122. // (*)
  123. _level0.BallXSpeed = -_level0.DistanciaX/ShotTY;
  124. _level0.BallZSpeedf = _level0.BallZSpeed;
  125. // * Eso es velocidadZ inicial, nombrada así nomás.
  126.  

(*): No recuerdo qué hice ni lo entiendo, pero sé que está mal. Es como que calculé cuántos frames iba a tardar la bola en llegar al destino, cuánto la gravedad iba a aumentar la velocidad de caída (recuerda que mi método de aplicar la gravedad era otro), y entonces yo sumaba eso a la velocidad Z hacia arriba, para que siempre pasara justito por donde debía, pero puse algunos casos para cuando el personaje tuviera poca fuerza, o algo así.
En fin, puedo intentar decirte cada valor en cada momento para intentar ver qué ocurre, pero ¿vale la pena? No creo.
Lo de ACAAAAAAAAAAAAAAA es que me faltaba algo ahí. Debido a lo confuso del código, en aquél entonces, lo dejé. Ya no programo TAN confuso xD

Citar
Si te refieres a profundo y veloz tal como los definiste arriba, no. Ninguno de los dos tiros que obtengas hará que la pelota pique en el área de saque, porque, de nuevo, esa condición no estaba cuando escribí mis primeras dos respuestas. Con los dos posibles ángulos que te dan mis ecuaciones, la pelota cae directamente en el destino deseado en la cancha rival, simplemente uno es más "globeado" y otro más directo.
Profundo significa que cae en el punto deseado, veloz que puede caer antes (aunque tiene la misma trayectoria en XY y debe pasar encima de la red); si dices que con tu método cae en el punto deseado es profundo, cae lejos de la red (considerando la distancia Y hacia ella) pero en el área de saque. Cuando ya no sea el saque, los tiros sí pueden caer más al fondo de la cancha, pero eso es simplemente que canbia el destino deseado, el método debería servir también. ¿Sabes más o menos las reglas del tenis?

Citar
en algunos casos, usando menos fuerza podrías conseguir tiros que pasen más bajo, es decir, más cercanos a la red (y obviamente, cumpliendo con tus otras condiciones)
No le veo la lógica a eso. Te muestro algunos casos a ver si me explicas.












Veo que estoy cometiendo un error. En la realidad, para que un golpe llegue más lejos, conviene pegarle un poco hacia arriba. Aquí parece que no. ¿Será porque la gravedad ahí es muy fuerte? Simular ahí el 0.01 es complicado. Usé 1 y mi método, pero no creo que eso último sea el problema. En fin, se supone que entre más fuerza se tenga más fuerza hacia adelante se puede usar, y por lo tanto menos fuerza hacia arriba es necesario hacer, sí hacia abajo, pero tener más fuerza no debería impedir que uno pueda golpear más hacia la red ¡al contrario! Por eso no te entiendo.

Citar
complicaría las cosas, por lo que aquí también creo que es mejor que te enfoques en tratar de implementar correctamente mi método o el del otro foro.
Pues dime paso a paso cómo es, lo aplico y te digo si tiene un problema, cual.


« Última modificación: 9 Mayo 2023, 21:57 pm por Tachikomaia » En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #11 en: 11 Mayo 2023, 03:29 am »

Aquí vas a ver muchas cosas que parecen contrarias a la intuición, pero resultan claras una vez que se entiende bien el tema. Trataré de darte ejemplos breves para aclarar tus dudas, pero lo ideal es tener unas buenas bases de trigonometría y algo de física (mecánica, en concreto) para entenderlo al 100%.

Como recordatorio: el ángulo representa la distribución de velocidades. Como en tu programa se busca que la pelota avance (obviamente, no es aceptable tirar la pelota hacia atrás), mientras mayor sea el ángulo, habrá más velocidad hacia arriba y menos hacia adelante, o sea, la pelota se elevará más.

La principal confusión que veo que tienes es sobre la manera en que el ángulo influye en la distancia recorrida. No es válido decir que si le das más altura a la pelota, mayor será la distancia, ni tampoco lo opuesto. La realidad es que depende. Cuando el lanzamiento es muy bajo, hay mayor velocidad hacia adelante (horizontal), y se avanza más rápido, pero como la pelota está cerca del suelo, también cae rápido, así que no tiene tiempo de viajar mucho. Si el tiro es elevado, avanza hacia adelante más lentamente, pero tarda más en caer, lo que le da más tiempo para avanzar. Por lo tanto, si se quisiera que la pelota llegara lo más lejos posible, no debería ir ni muy elevada ni muy baja. Para cada tiro existe un ángulo que ofrece el mejor balance y da la mayor distancia posible con la fuerza disponible. Dicho de otra forma, si lo que se busca es recorrer una distancia específica, este es el ángulo que te permite lograrlo usando menos fuerza. No es tan simple decir cuál es este ángulo más eficiente, ya que depende de la altura y velocidad iniciales de la pelota, pero de cualquier forma no lo necesitas. Baste saber que ese ángulo existe, y que mientras más te alejes de él (ya sea hacia arriba o hacia abajo) menor será la eficiencia, y por lo tanto, mayor la cantidad de fuerza necesaria para recorrer una distancia d.

si la puede elevar a 19.5 m también debería poderla elevar a 18.6 ¿no?

Eso podría ser correcto si sólo interesara elevar la pelota, sin importar donde caiga ni nada más, pero aquí de lo que se trata es de que llegue a un punto específico (y se eleve a cierta altura al pasar por la red), lo cual hace que no sea tan simple, como expliqué arriba. Si se diera el caso de que para llegar al punto deseado y alcanzar una altura de 18.6 m al pasar la red, requirieras más fuerza de la disponible, lo que habría que hacer es intentar acercarse al ángulo más eficiente: si el ángulo que se usó es mayor que el óptimo, hay que hacer tiros más bajos; si es menor, hay que hacer tiros más altos. En este último caso, para llegar al destino buscado, un tiro más elevado requeriría menos fuerza que uno más bajo. Obviamente, no necesitas estar probando ángulos, ya que el método del otro foro y el de aquí te calculan directamente el que debes usar, pero el ejemplo sirve para ilustrar el punto.

Citar
En mi opinióbn sí, es la condición nro 5:
...
 Profundo significa que cae en el punto deseado, veloz que puede caer antes (aunque tiene la misma trayectoria en XY y debe pasar encima de la red); si dices que con tu método cae en el punto deseado es profundo, cae lejos de la red (considerando la distancia Y hacia ella) pero en el área de saque. Cuando ya no sea el saque, los tiros sí pueden caer más al fondo de la cancha, pero eso es simplemente que canbia el destino deseado, el método debería servir también. ¿Sabes más o menos las reglas del tenis?

Sí, me había confundido porque acababa de ver el video que pusiste, y como no me quedaba muy claro que sucedía, pensé que te referías a otra cosa.

Citar
En la realidad, para que un golpe llegue más lejos, conviene pegarle un poco hacia arriba.

...se supone que entre más fuerza se tenga más fuerza hacia adelante se puede usar, y por lo tanto menos fuerza hacia arriba es necesario hacer

Creo que eso ya quedó aclarado con lo anterior: son suposiciones que, aunque puedan sonar lógicas, no son del todo correctas. En ciertos cases se cumplen y en otros ocurre lo contrario.

Citar
Pues dime paso a paso cómo es, lo aplico y te digo si tiene un problema, cual.

Pues creo que ya lo había explicado al inicio, aunque supongo que pudiera ser algo confuso porque está repartido en dos mensajes. Ahora no tengo tiempo, pero cuando pueda pongo los pasos en uno sólo.


En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #12 en: 14 Mayo 2023, 21:21 pm »

Aquí va el procedimiento resumido. Las explicaciones ya están en mis otros mensajes, y de hecho, aquí prácticamente me limité a copiar y pegar, además de cambiar algunos nombres de variables.

En todos los siguientes cálculos, h se refiere a la altura inicial de la pelota y v0 es la velocidad inicial o la fuerza del personaje.

Primero, conviene sacar aquí este resultado intermedio, pues sirve para determinar ciertas condiciones y  ahorrar cálculos:

Código:
Disc = v0 * v0 * v0 * v0 - (g * (g * DistanciahastaDestinoXY * DistanciahastaDestinoXY - 2 * v0 * v0 * h))

Si Disc < 0, no puedes hacer el tiro
Si Disc == 0, hay un solo angulo posible
Si Disc > 0, hay dos angulos

Se calcula el ángulo o ángulos (raiz es la raíz cuadrada):

Código:
theta = arctan((v0 * v0 + raiz(Disc)) / (g * DistanciahastaDestinoXY))
phi = arctan((v0 * v0 - raiz(Disc)) / (g * DistanciahastaDestinoXY))

Se calcula el tiempo que se tarda en llegar a la red:

Código:
DistanciahastaRed = DistanciahastaDestinoXY * abs(RedY - BallY) / abs(DistanciahastaDestinoY)
TiempoHastaRedTheta = (DistanciahastaRed) / (v0 * cos(theta))

Y si hay dos ángulos, lo mismo para el segundo:

Código:
TiempoHastaRedPhi = (DistanciahastaRed) / (v0 * cos(phi))

Luego se calcula la altura a la que pasan al llegar a la red. Esto es igual que como lo puse en mi primer mensaje, pero como ahí todavía suponía que la altura inicial era cero, no incluía la variable h. Así es como debería quedar:

Código:
AlturaEnRedTheta = h + v0 * sen(theta) * TiempoHastaRedTheta - (g * TiempoHastaRedTheta * TiempoHastaRedTheta) / 2
AlturaEnRedPhi = h + v0 * sen(phi) * TiempoHastaRedPhi - (g * TiempoHastaRedPhi * TiempoHastaRedPhi) / 2

Si ambos pasan por encima, elige el más alto o bajo, según prefieras. A ese ángulo elegido, lo llamaré a partir de aquí angulo, a secas.

Calculas las velocidades:

Código:
VelocidadAdelante = v0 * cos(angulo)
VelocidadArriba = v0 * sen(angulo)

// Esta variable es redundante, pero clarifica lo que se esta haciendo
VelocidadZ = VelocidadArriba

si (DistanciahastaDestinoX == 0)
   BallYSpeed = VelocidadAdelante
   BallXSpeed = 0
sino
   AnguloPendiente = arctan(DistanciahastaDestinoY / DistanciahastaDestinoX)
   BallXSpeed = VelocidadAdelante * cos(AnguloPendiente)
   BallYSpeed = VelocidadAdelante * sen(AnguloPendiente)

Todo lo anterior sólo lo necesitas hacer al inicio del tiro. Luego, en cada instante de tiempo que transcurra, se debe actualizar la posición de la pelota y dibujarla. Como desde el principio querías conocer las velocidades para cada dimensión, imagino que en cada iteración haces algo como esto:

Código:
BallX = BallX + VelocidadX
BallY = BallY + VelocidadY

Estos valores (coordenadas de la pelota) también se podrían obtener a partir de la ecuación para x que te puse al inicio de mi primer mensaje, y que calcula las posiciones en función del tiempo, pero si te es más simple hacerlo con las velocidades, lo puedes dejar así. Obviamente, si en la representación en pantalla la pelota va hacia arriba y a la izquierda, las velocidades en x e y deben ser restadas. En el caso de la altura (z), puesto que está sometida a una aceleración (la gravedad), la velocidad vertical está cambiando constantemente, así que no la puedes sacar de esa manera, sino que hay que hacerlo en función del tiempo. Aquí t se refiere al tiempo transcurrido:

Código:
BallZ = h + VelocidadZ * t - (g * t * t)/2

Por cierto, esto también se podría calcular con la fórmula para el movimiento con aceleración constante que te puse dos o tres mensajes atrás cuando preguntaste sobre la gravedad.

No estoy tomando en cuenta lo que pones en la condición 5, pero como dijiste más arriba, sólo sería cuestión de cambiar el destino.
En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.201


Superhacker (es broma xD )


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #13 en: 15 Mayo 2023, 08:04 am »

Miro el foro todos los días o casi, no entiendo cómo no vi tu mensaje antes :rolleyes:

Cuando el lanzamiento es muy bajo, hay mayor velocidad hacia adelante (horizontal), y se avanza más rápido, pero como la pelota está cerca del suelo, también cae rápido, así que no tiene tiempo de viajar mucho. Si el tiro es elevado, avanza hacia adelante más lentamente, pero tarda más en caer, lo que le da más tiempo para avanzar. Por lo tanto, si se quisiera que la pelota llegara lo más lejos posible, no debería ir ni muy elevada ni muy baja.
Pienso lo mismo pero en mis ejemplos no parece ocurrir. ¿No?

Citar
si lo que se busca es recorrer una distancia específica, este es el ángulo que te permite lograrlo usando menos fuerza
Debes que imaginar que el jugador es perfecto en cuanto a inteligencia y puntería y quiere que la bola caiga en cierto punto, para lo cual usará toda la fuerza que pueda (según la que tenga, en ese sentido no es perfecto), no la mínima necesaria; no hará globitos si puede hacer que el tiro sea rápido y pase cerca de la red. No sé si has entendido eso. Si tiene la fuerza suficiente, el tiro debería pasar cerca de la red, sino sí haría un globito por lo que has explicado arriba, porque si golpea muy hacia abajo no llega. Mira el video
https://drive.google.com/file/d/1jyrIyycu_joxlfIblj5IDEwZ_Y3giSPR/view
Entre más fuerza tenga más bajo pasa la bola, excepto cuando ni siquiera tiene suficiente fuerza como para hacerla pasar. O piensa que, si hará un smash, apuntará a un punto usando toda la fuerza que pueda , no la mínima necesaria.
https://www.youtube.com/watch?v=BLaHot9vIKo
2:44, pudo haber golpeado más suave ¡pero no es la idea!

...

¡Vaya ecuaciones! :o :rolleyes:

Me quedó así:
Código
  1. // Datos para determinar velocidades del tiro.
  2. DistanciahastaDestinoX = BallX-280.1;
  3. DistanciahastaDestinoY = BallY-180;
  4. DistanciahastaDestinoXY = Math.sqrt(DistanciahastaDestinoX*DistanciahastaDestinoX+DistanciahastaDestinoY*DistanciahastaDestinoY);
  5. // Se calcula el ángulo o ángulos.
  6. Parte = AlexFuerzadetiros*AlexFuerzadetiros*AlexFuerzadetiros*AlexFuerzadetiros;
  7. Disc = Parte-(Gravedad*(Gravedad*DistanciahastaDestinoXY*DistanciahastaDestinoXY-2*AlexFuerzadetiros*AlexFuerzadetiros*BallZ));
  8. // Si Disc < 0, no puedes hacer el tiro.
  9. // Si Disc == 0, hay un solo angulo posible.
  10. // Si Disc > 0, hay dos angulos.
  11. theta = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros+Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  12. phi = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros-Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  13. // Se calcula el tiempo que se tarda en llegar a la red.
  14. DistanciahastaRed = DistanciahastaDestinoXY*Math.abs(RedZ-BallZ)/Math.abs(DistanciahastaDestinoY);
  15. TiempoHastaRedTheta = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(theta));
  16. if (Disc>0) {
  17.    // Si hay dos ángulos, se calcula el 2ndo.
  18.    TiempoHastaRedPhi = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(phi));
  19.    // Se calcula la altura a la que pasa la bola al llegar a la red.
  20.    AlturaEnRedTheta = BallZ+AlexFuerzadetiros*Math.sin(theta)*TiempoHastaRedTheta-(Gravedad*TiempoHastaRedTheta*TiempoHastaRedTheta)/2;
  21.    AlturaEnRedPhi = BallZ+AlexFuerzadetiros*Math.sin(phi)*TiempoHastaRedPhi-(Gravedad*TiempoHastaRedPhi*TiempoHastaRedPhi)/2;
  22.    // Se elige el ángulo conque la bola pasa más bajo.
  23.    if (AlturaEnRedTheta<AlturaEnRedPhi) {
  24.        Angulo = AlturaEnRedTheta;
  25.    } else {
  26.        Angulo = AlturaEnRedPhi;
  27.    }
  28. } else {
  29.    Angulo = AlturaEnRedTheta;
  30. }
  31. // Cálculo de las velocidades.
  32. VelocidadAdelante = AlexFuerzadetiros*Math.cos(Angulo);
  33. VelocidadArriba = AlexFuerzadetiros*Math.sin(Angulo);
  34. // Esta variable es redundante, pero clarifica lo que se esta haciendo.
  35. VelocidadZ = VelocidadArriba;
  36. if (DistanciahastaDestinoX == 0) {
  37.    BallXSpeed = 0;
  38.    BallYSpeed = VelocidadAdelante*-1;
  39. } else {
  40.    AnguloPendiente = Math.atan(DistanciahastaDestinoY/DistanciahastaDestinoX);
  41.    BallXSpeed = VelocidadAdelante*Math.cos(AnguloPendiente)*-1;
  42.    BallYSpeed = VelocidadAdelante*Math.sin(AnguloPendiente)*-1;
  43. }
  44. // Datos para determinar posiciones de la pelota.
  45. Tiempotranscurridodeltiro = 0;
  46. BallXwhenstriked = BallX;
  47. BallYwhenstriked = BallY;
  48. BallZwhenstriked = BallZ;

El cálculo de las posiciones lo estoy haciendo en base al tiempo, así:
Código
  1. function Ballmoving () {
  2.    Tiempotranscurridodeltiro = Tiempotranscurridodeltiro+1;
  3.    BallX = BallXwhenstriked+BallXSpeed*Tiempotranscurridodeltiro;
  4.    BallY = BallYwhenstriked+BallYSpeed*Tiempotranscurridodeltiro;
  5.    BallZAnterior = BallZ;
  6.    BallZ = BallZwhenstriked+VelocidadZ*Tiempotranscurridodeltiro-(Gravedad*Tiempotranscurridodeltiro*Tiempotranscurridodeltiro)/2;
  7.    BallZSpeed = BallZ-BallZAnterior;
  8.    if (BallZ<=0) {
  9.        // Si la pelota llega al suelo, BallZSpeed se invierte con disminución según la cancha.
  10.        BallZ = 0;
  11.        BallZSpeed = BallZSpeed*Fuerzaderebotedepelota;
  12.        // Si BallZSpeed es menor que 0.01: Queda en 0.
  13.        if (BallZSpeed<0.01) {
  14.            BallZSpeed = 0;
  15.        }
  16.        // La pelots, al rozarse con el suelo, disminuye sus velocidades.
  17.        // BallXSpeed = BallXSpeed+Influenciadelrozamiento;
  18.        if (BallXSpeed>0) {
  19.            BallXSpeed = 0;
  20.        }
  21.        // BallYSpeed = BallYSpeed+Influenciadelrozamiento;
  22.        if (BallYSpeed>0) {
  23.            BallYSpeed = 0;
  24.        }
  25.    }
  26. }

No sé qué está mal.
https://drive.google.com/file/d/1vDabAavB-YZrNTW1s6YW7o7y-kSBzyj_/view?usp=share_link
¿Te digo algún dato que no haya dicho ahí, cual?

Ah, el tema del pique se me complica, mejor luego del pique vuelvo al método simple de sumar ¿no? Aunque la pelota bajará a distinta velocidad. Yo lo que hacía es que cuando tocaba el suelo la bola, a su velocidad Z se le hacía *-1 y se reducía un poco, pero ahora de momento no sé cómo hacerlo.
La bola que queda en la red o en pantalla no es un error, hago que aparezca para ver qué tan cerca de la red pasó.
« Última modificación: 15 Mayo 2023, 08:10 am por Tachikomaia » En línea

RayR

Desconectado Desconectado

Mensajes: 239


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #14 en: 17 Mayo 2023, 03:01 am »

Pienso lo mismo pero en mis ejemplos no parece ocurrir. ¿No?

Pues es que si el método y la gravedad no son correctos, los resultados tampoco lo serán.

Citar
Debes que imaginar que el jugador es perfecto en cuanto a inteligencia y puntería y quiere que la bola caiga en cierto punto, para lo cual usará toda la fuerza que pueda (según la que tenga, en ese sentido no es perfecto), no la mínima necesaria; no hará globitos si puede hacer que el tiro sea rápido y pase cerca de la red. No sé si has entendido eso.

Claro. Pero el párrafo de donde sacaste esa frase es hipotético. Ya sé que no buscas la fuerza mínima necesaria, pero lo usé como ejemplo para explicar la relación entre el ángulo la y distancia recorrida.

En cuanto a tu código, tienes varios errores. Fíjate bien lo que te puse, y de ser necesario, ve las  explicaciones de mensajes anteriores, porque además te estás saltando algún paso. Por ejemplo, aquí:

Código:
DistanciahastaRed = DistanciahastaDestinoXY*Math.abs(RedZ-BallZ)/Math.abs(DistanciahastaDestinoY);

En vez de RedZ-BallZ va RedY - BallY.

Luego, como te comenté (y expliqué con más detalle en mi segundo mensaje), si Disc es negativo, no puedes hacer el tiro, no tienes la fuerza necesaria, así que ya ni siquiera tiene sentido calcular los ángulos y todo lo demás. En todo caso, podrías escoger un nuevo destino más cercano, como lo mencionaste en relación al punto 5, y repetir el procedimiento a ver si este sí lo puedes hacer.

Además, fíjate que después de calcular AlturaEnRedTheta y AlturaEnRedPhi puse:

Citar
Si ambos pasan por encima, elige el más alto o bajo, según prefieras

Pero tú ya directamente supones que ambos lo hacen y pasas a elegir el ángulo más bajo. Primero debes comprobar si alguno de los ángulos pasa por arriba de la red. Si sólo uno de los ángulos lo hace, obviamente lo tienes que usar, no hay otra opción. Únicamente si ambos pasan sobre la red, toca elegir el más bajo o alto. Y naturalmente, si ninguno lo consigue, toca aquí también elegir nuevo destino o lo que quieras.

Citar
Ah, el tema del pique se me complica, mejor luego del pique vuelvo al método simple de sumar ¿no?

Pues sí, podrías probar en ese caso tu método simple. Al final lo que estás haciendo es un juego y no una simulación perfecta, así que puede que con eso tengas un resultado aceptable.

En relación a lo anterior, este cálculo no es correcto:

Código:
    BallZSpeed = BallZ-BallZAnterior;

porque simplemente te daría la velocidad promedio a lo largo del último intervalo de tiempo, en este caso, el último segundo (porque creo que incrementas el tiempo un segundo a la vez, ¿no?), pero tú lo que buscas es el valor de la velocidad en el instante actual, que es distinto. La forma de hacerlo sería esta:

Código:
    BallZSpeed =  VelocidadZ - Gravedad * Tiempotranscurridodeltiro;

Una última cosa: supongo que estás usando escalas adecuadas, ¿no? Por ejemplo, suponiendo que quisieras modelar una cancha con longitud de 20 m, y que en el juego mida 400 pixels, esto significaría que cada metro equivale a 20 pixels (400 / 20 = 20). Si eliges arbitrariamente la gravedad y le pones 1 pixel/s2, por ejemplo, vas a tener resultados absurdos, porque eso significaría que la gravedad equivale a 1/20 m/s2 = .05 m/s2. ¡Más débil incluso que en la luna! Para tener resultados coherentes, debes elegir valores realistas para la gravedad, fuerza, altura inicial y altura de la red, y multiplicarlos por este factor de escala. Siguiendo con este ejemplo, sería: Gravedad = 9.8 m/s2 * 20; AlexFuerzadetiros = 25 m/s * 20; etc.
En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.201


Superhacker (es broma xD )


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #15 en: 24 Mayo 2023, 08:43 am »

He estado pensando en otras cosas o cansado, pero aquí vuelvo ;D

Fíjate bien lo que te puse, y de ser necesario, ve las  explicaciones de mensajes anteriores, porque además te estás saltando algún paso.
Vale, luego de leer tu post.

Citar
Por ejemplo, aquí:

Código:
DistanciahastaRed = DistanciahastaDestinoXY*Math.abs(RedZ-BallZ)/Math.abs(DistanciahastaDestinoY);

En vez de RedZ-BallZ va RedY - BallY.
Ok, asumí que RedY era la altura así que lo llamé RedZ, y cuando vi -BallY me confundí y lo cambié por BallZ, supongo que fue por eso. Me confunde que Y sea Z...

Citar
Luego, como te comenté (y expliqué con más detalle en mi segundo mensaje), si Disc es negativo, no puedes hacer el tiro, no tienes la fuerza necesaria, así que ya ni siquiera tiene sentido calcular los ángulos y todo lo demás.
¿Qué sucede si se calcula? Pensé que el tiro saldría corto ¿no ocurre eso? Si no se tiene suficiente fuerza igual debe haber un tiro, como si el personaje hubiera querido hacer un buen tiro. No tiene sentido que no se haga un tiro.

Citar
En todo caso, podrías escoger un nuevo destino más cercano, como lo mencionaste en relación al punto 5, y repetir el procedimiento a ver si este sí lo puedes hacer.
Sí ¿y si el más cercano tampoco sirve?

Citar
Además, fíjate que después de calcular AlturaEnRedTheta y AlturaEnRedPhi puse:
"Si ambos pasan por encima, elige el más alto o bajo, según prefieras"
Pero tú ya directamente supones que ambos lo hacen y pasas a elegir el ángulo más bajo. Primero debes comprobar si alguno de los ángulos pasa por arriba de la red. Si sólo uno de los ángulos lo hace, obviamente lo tienes que usar, no hay otra opción. Únicamente si ambos pasan sobre la red, toca elegir el más bajo o alto. Y naturalmente, si ninguno lo consigue, toca aquí también elegir nuevo destino o lo que quieras.
Pensé que tu método indicaba si pasaban o no.
...
Se me hizo líoso hacerlo, pero creo que está. También corregí, creo, que en vez de usar los ángulos usaba las alturas. ¿Disc qué abrevia o qué significa?

Citar
este cálculo no es correcto:
Código:
   BallZSpeed = BallZ-BallZAnterior;
porque simplemente te daría la velocidad promedio a lo largo del último intervalo de tiempo, en este caso, el último segundo (porque creo que incrementas el tiempo un segundo a la vez, ¿no?), pero tú lo que buscas es el valor de la velocidad en el instante actual, que es distinto. La forma de hacerlo sería esta:
Código:
   BallZSpeed =  VelocidadZ - Gravedad * Tiempotranscurridodeltiro;
Creo que eso me quedó sin borrar del método anterior, creo que no influye salvo en el pique, que aún no lo arreglé. Gracias igual, si llego a eso y no lo puedo resolver te consulto. Lo borro por ahora a ver.

Citar
Una última cosa: supongo que estás usando escalas adecuadas, ¿no?
Probablemente no, el personaje es muy bajo por ejemplo. En el juego original los saques se hacen por encima del alcance de la raqueta y no se nota, pero en mi caso son acordes al alcance y me parece un poco bajo. El juego original:
https://www.youtube.com/watch?v=fc0_P2IGgJ4
¿Crees que habrá mucha diferencia en las escalas con el mío? Que yo sepa lo único que hice fue que la cancha entrara toda en la pantalla y también parte del fondo y los laterales, ya que en el juego original hay como paredes invisibles que si la bola toca es punto :-\ (no se nota salvo casos muy poco probables). También achiqué un poco al personaje porque ahí pareciera que ocuparan demasiado de la cancha.

En mi juego la cancha mide 239.9 de ancho (sin contar el corredor de dobles) y 480 de largo. Ese .9 es por motivos que no comprendo ni sé arreglar (ni volveré a dedicar tiempo a intentarlo), pero es mínimo, debería ser 240. La altura de la red es de unos 17.4 (pero la bola debe pasar a 18.6 mínimo). En fin, puse la gravedad que me pareció agradable a mi vista, no creo que sea ni tan poca ni tanta, pero ahora que lo dices, si con tu método es menos intensa aunque se use el mismo número, puede que deba aumentarla.
En el juego la fuerza de los tiros depende del tiempo de preparación, la fuerza de brazos, piernas, calidad de la raqueta y cuánto se usó en darle efecto a la bola, no sé si algo más... No he pensado o consultado tanto sobre eso. No tiene sentido que te de más detalles de eso tampoco ¿no? Te digo porque me llama la atención el 25 que pusiste ¿a qué se debe?

No tengo mucho interés en que sea tan realista en cuanto a velocidades o tamaños (especialmente la bola, sino no la veo mucho), tengo pensado que haya gran variedad de campeonatos variando el tamaño de algunas cosas por ejemplo. En otros aspectos sí quiero que sea realista, como he explicado.

Bueno, reviso el código de principio a fin, lo comparo con lo que has puesto.

Pusiste:
Disc = v0 * v0 * v0 * v0 - (g * (g * DistanciahastaDestinoXY * DistanciahastaDestinoXY - 2 * v0 * v0 * h))

Puse:
Código
  1. Parte = AlexFuerzadetiros*AlexFuerzadetiros*AlexFuerzadetiros*AlexFuerzadetiros;
  2. Disc = Parte-(Gravedad*(Gravedad*DistanciahastaDestinoXY*DistanciahastaDestinoXY-2*AlexFuerzadetiros*AlexFuerzadetiros*BallZ));

Luego debido a los ifs es complicado poner parte por parte, lo haré más adelante; este es el código con las partes más relevantes de este contexto supongo:
Código
  1. Gravedad = 0.01;
  2. RedZ = 18.6;
  3. // Datos para determinar velocidades del tiro.
  4. DistanciahastaDestinoX = BallX-280.1;
  5. DistanciahastaDestinoY = BallY-180;
  6. // DistanciahastaRed = BallY-300;
  7. // DistanciahastaMinsafeBallZ = BallZ-18.6;
  8. DistanciahastaDestinoXY = Math.sqrt(DistanciahastaDestinoX*DistanciahastaDestinoX+DistanciahastaDestinoY*DistanciahastaDestinoY);
  9. // Se calcula el ángulo o ángulos.
  10. Parte = AlexFuerzadetiros*AlexFuerzadetiros*AlexFuerzadetiros*AlexFuerzadetiros;
  11. Disc = Parte-(Gravedad*(Gravedad*DistanciahastaDestinoXY*DistanciahastaDestinoXY-2*AlexFuerzadetiros*AlexFuerzadetiros*BallZ));
  12. if (Disc<0) {
  13.    // Fuerza insuficiente, si es posible habrá que acercar el destino.
  14.    TiroRealizable = "Fuerza insuficiente";
  15. } else {
  16.    DistanciahastaRed = DistanciahastaDestinoXY*Math.abs(RedZ-BallY)/Math.abs(DistanciahastaDestinoY);
  17.    // Le he llamado RedZ a lo que has llamado RedY.
  18.    // Se calcula el ángulo Z;
  19.    theta = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros+Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  20.    // Se calcula el tiempo que se tarda en llegar a la red.
  21.    TiempoHastaRedTheta = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(theta));
  22.    // Se calcula la altura a la que pasa la bola al llegar a la red.
  23.    AlturaEnRedTheta = BallZ+AlexFuerzadetiros*Math.sin(theta)*TiempoHastaRedTheta-(Gravedad*TiempoHastaRedTheta*TiempoHastaRedTheta)/2;
  24.    if (Disc == 0) {
  25.        // Sólo hay 1 ángulo Z posible.
  26.        if (AlturaEnRedTheta>=18.6) {
  27.            // Si la bola pasa la red con ese ángulo, usarlo.
  28.            TiroRealizable = "1 ángulo, ok";
  29.            Angulo = theta;
  30.        } else {
  31.            TiroRealizable = "1 ángulo, imposible";
  32.            // Probar acercar destino supongo.
  33.            Angulo = "Ninguno";
  34.        }
  35.    } else {
  36.        // Disc>0, hay 2 angulos posibles, calcular el faltante.
  37.        phi = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros-Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  38.        TiempoHastaRedPhi = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(phi));
  39.        AlturaEnRedPhi = BallZ+AlexFuerzadetiros*Math.sin(phi)*TiempoHastaRedPhi-(Gravedad*TiempoHastaRedPhi*TiempoHastaRedPhi)/2;
  40.        if (AlturaEnRedTheta>=18.6) {
  41.            if (AlturaEnRedPhi>=18.6) {
  42.                // Con ambos ángulos la bola pasa la red, usar el más bajo.
  43.                if (AlturaEnRedTheta<AlturaEnRedPhi) {
  44.                    Angulo = theta;
  45.                } else {
  46.                    Angulo = phi;
  47.                }
  48.            } else {
  49.                // Sólo sirve el 1er ángulo.
  50.                Angulo = theta;
  51.            }
  52.        } else if (AlturaEnRedPhi>=18.6) {
  53.            // Sólo sirve el 2ndo ángulo.
  54.            Angulo = phi;
  55.        } else {
  56.            // Ningún ángulo sirve.
  57.            Angulo = "Ninguno";
  58.            // Probar acercar destino supongo.
  59.        }
  60.    }
  61.    if (Angulo != "Ninguno") {
  62.        // Cálculo de las velocidades.
  63.        VelocidadAdelante = AlexFuerzadetiros*Math.cos(Angulo);
  64.        VelocidadArriba = AlexFuerzadetiros*Math.sin(Angulo);
  65.        // Esta variable es redundante, pero clarifica lo que se esta haciendo.
  66.        VelocidadZ = VelocidadArriba;
  67.        if (DistanciahastaDestinoX == 0) {
  68.            BallXSpeed = 0;
  69.            BallYSpeed = VelocidadAdelante*-1;
  70.        } else {
  71.            AnguloPendiente = Math.atan(DistanciahastaDestinoY/DistanciahastaDestinoX);
  72.            BallXSpeed = VelocidadAdelante*Math.cos(AnguloPendiente)*-1;
  73.            BallYSpeed = VelocidadAdelante*Math.sin(AnguloPendiente)*-1;
  74.        }
  75.        // Datos para determinar posiciones de la pelota.
  76.        Tiempotranscurridodeltiro = 0;
  77.        BallXwhenstriked = BallX;
  78.        BallYwhenstriked = BallY;
  79.        BallZwhenstriked = BallZ;
  80.    }
  81. }

Dijiste:
Si Disc < 0, no puedes hacer el tiro

Puse:
Código:
if (Disc<0) {
// Fuerza insuficiente, si es posible habrá que acercar el destino.
TiroRealizable = "Fuerza insuficiente";
} else {
Y que yo sepa nada ocurrirá ahí, en el caso de true. Lo de cambiar destino lo haré más adelante.

Dijiste:
Si Disc == 0, hay un solo angulo posible
Si Disc > 0, hay dos angulos
Esos casos son mi else, calculo 1 ángulo y luego si Disc>0 calculo el otro. Alteré un poco el orden de tu código pero creo que no hay problema.

Haces:
theta = arctan((v0 * v0 + raiz(Disc)) / (g * DistanciahastaDestinoXY))
DistanciahastaRed = DistanciahastaDestinoXY * abs(RedY - BallY) / abs(DistanciahastaDestinoY)
TiempoHastaRedTheta = (DistanciahastaRed) / (v0 * cos(theta))

Hice:
Código
  1. DistanciahastaRed = DistanciahastaDestinoXY*Math.abs(RedZ-BallY)/Math.abs(DistanciahastaDestinoY);
  2. // Le he llamado RedZ a lo que has llamado RedY.
  3. theta = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros+Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  4. TiempoHastaRedTheta = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(theta));
  5. AlturaEnRedTheta = BallZ+AlexFuerzadetiros*Math.sin(theta)*TiempoHastaRedTheta-(Gravedad*TiempoHastaRedTheta*TiempoHastaRedTheta)/2;

Lo último te lo copié de esto:
AlturaEnRedTheta = h + v0 * sen(theta) * TiempoHastaRedTheta - (g * TiempoHastaRedTheta * TiempoHastaRedTheta) / 2

Luego lo que hago depende del caso como habías dicho:

Código
  1. if (Disc == 0) {
  2. // Sólo hay 1 ángulo Z posible.
  3. if (AlturaEnRedTheta>=18.6) {
  4. // Si la bola pasa la red con ese ángulo, usarlo.
  5. TiroRealizable = "1 ángulo, ok";
  6. Angulo = theta;
  7. } else {
  8. TiroRealizable = "1 ángulo, imposible";
  9. // Probar acercar destino supongo.
  10. Angulo = "Ninguno";
  11. }
  12. } else {
  13. // Disc>0, hay 2 angulos posibles, calcular el faltante.
  14. phi = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros-Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  15. TiempoHastaRedPhi = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(phi));
  16. AlturaEnRedPhi = BallZ+AlexFuerzadetiros*Math.sin(phi)*TiempoHastaRedPhi-(Gravedad*TiempoHastaRedPhi*TiempoHastaRedPhi)/2;
  17. if (AlturaEnRedTheta>=18.6) {
  18. if (AlturaEnRedPhi>=18.6) {
  19. // Con ambos ángulos la bola pasa la red, usar el más bajo.
  20. if (AlturaEnRedTheta<AlturaEnRedPhi) {
  21. Angulo = theta;
  22. } else {
  23. Angulo = phi;
  24. }
  25. } else {
  26. // Sólo sirve el 1er ángulo.
  27. Angulo = theta;
  28. }
  29. } else if (AlturaEnRedPhi>=18.6) {
  30. // Sólo sirve el 2ndo ángulo.
  31. Angulo = phi;
  32. } else {
  33. // Ningún ángulo sirve.
  34. Angulo = "Ninguno";
  35. // Probar acercar destino supongo.
  36. }
  37. }
¿Todo bien?

Habías dicho:
Código:
phi = arctan((v0 * v0 - raiz(Disc)) / (g * DistanciahastaDestinoXY))
TiempoHastaRedPhi = (DistanciahastaRed) / (v0 * cos(phi))
AlturaEnRedPhi = h + v0 * sen(phi) * TiempoHastaRedPhi - (g * TiempoHastaRedPhi * TiempoHastaRedPhi) / 2

Yo ahí puse:
Código
  1. phi = Math.atan((AlexFuerzadetiros*AlexFuerzadetiros-Math.sqrt(Disc))/(Gravedad*DistanciahastaDestinoXY));
  2. TiempoHastaRedPhi = (DistanciahastaRed)/(AlexFuerzadetiros*Math.cos(phi));
  3. AlturaEnRedPhi = BallZ+AlexFuerzadetiros*Math.sin(phi)*TiempoHastaRedPhi-(Gravedad*TiempoHastaRedPhi*TiempoHastaRedPhi)/2;

Luego dices:
Código:
VelocidadAdelante = v0 * cos(angulo)
VelocidadArriba = v0 * sen(angulo)

// Esta variable es redundante, pero clarifica lo que se esta haciendo
VelocidadZ = VelocidadArriba

Puse:
Código:
if (Angulo != "Ninguno") {
// Cálculo de las velocidades.
VelocidadAdelante = AlexFuerzadetiros*Math.cos(Angulo);
VelocidadArriba = AlexFuerzadetiros*Math.sin(Angulo);
// Esta variable es redundante, pero clarifica lo que se esta haciendo.
VelocidadZ = VelocidadArriba;

Dices:
Código:
si (DistanciahastaDestinoX == 0)
   BallYSpeed = VelocidadAdelante
   BallXSpeed = 0
sino
   AnguloPendiente = arctan(DistanciahastaDestinoY / DistanciahastaDestinoX)
   BallXSpeed = VelocidadAdelante * cos(AnguloPendiente)
   BallYSpeed = VelocidadAdelante * sen(AnguloPendiente)

Puse:
Código:
if (DistanciahastaDestinoX == 0) {
BallXSpeed = 0;
BallYSpeed = VelocidadAdelante*-1;
} else {
AnguloPendiente = Math.atan(DistanciahastaDestinoY/DistanciahastaDestinoX);
BallXSpeed = VelocidadAdelante*Math.cos(AnguloPendiente)*-1;
BallYSpeed = VelocidadAdelante*Math.sin(AnguloPendiente)*-1;
}
Los *-1 los quito si veo que los tiros van para atrás o algo.

Los cambios en la pantalla por el movimiento los hago así:
Código:
Tiempotranscurridodeltiro = Tiempotranscurridodeltiro+1;
BallX = BallXwhenstriked+BallXSpeed*Tiempotranscurridodeltiro;
BallY = BallYwhenstriked+BallYSpeed*Tiempotranscurridodeltiro;
BallZ = BallZwhenstriked+VelocidadZ*Tiempotranscurridodeltiro-(Gravedad*Tiempotranscurridodeltiro*Tiempotranscurridodeltiro)/2;

Veo que habías dicho:
x = v0 * cos(θ) * t
y = v0 * sen(θ) * t - (g * t2)/2

Y más recientemente:
BallZ = h + VelocidadZ * t - (g * t * t)/2

Ahí me maree. BallZ lo tengo igual parece, lo otro no y como es la perspectiva 2d me confundo.

Bueno, pruebo el código, grabo video y demás y te muestro el resultado.
...
De momento me da errores gráficos no sé bien por qué (la pantalla se agranda o se achica, me ha pasado otras veces cuando se ordena modificar el tamaño de un objeto inexistente). He probado con distintas fuerzas y obtuve casos de fuerza insuficiente y de 2 ángulos pero que ninguno sirve. Agregué más estados de la variable TiroRealizable para ver eso. No sé, voy a probar quitar el código e irlo poniendo de a poco a ver cual es el problema. O pruebo desde la versión anterior mejor.
...
Ya arreglé el tema de los gráficos pero sólo obtengo casos de fuerza insuficiente si le pongo muy poca o casos de "2 ángulos pero ninguno sirve".
Por ejemplo:
Gravedad = 0.01
RedZ = 18.6
AlexFuerzadetiros = 2.975
AlexX = 488
AlexY = 548
DistanciahastaDestinoX = 240.9
DistanciahastaDestinoY = 368
DistanciahastaDestinoXY = 439.837253992883
Parte = 78.333562890625
Disc = 66.960524890625
DistanciahastaRed = 632.744136586501
theta = 1.31809820149062
TiempoHastaRedTheta = 850.689542137363
AlturaEnRedTheta = -1122.89688542468
phi = 0.150652307511496
TiempoHastaRedPhi = 215.123727738993
AlturaEnRedPhi = -90.2989548532666
TiroRealizable = "2 ángulos, pero ninguno sirve"
Angulo = "Ninguno"
BallXwhenstriked = 521
BallYwhenstriked = 548
BallZwhenstriked = 45.04

Medio supongo que tiene que ver con esas alturas negativas en la red, voy a revisar si hice algo mal ahí y si es el caso edito el post medio pronto, sino es que no sé.
« Última modificación: 24 Mayo 2023, 10:33 am por Tachikomaia » En línea

Tachikomaia


Desconectado Desconectado

Mensajes: 1.201


Superhacker (es broma xD )


Ver Perfil
Re: Ayuda con cálculos para que la trayectoria de una pelota cumpla ciertas condiciones.
« Respuesta #16 en: 26 Mayo 2023, 11:51 am »

Cambié BallY por BallZ y funciona bien ;-) salvo con mucha fuerza, pasa por debajo de la red y pica después de donde debe ¿quizá es por cómo calculos las posiciones? ¿o un error del Flash que uso?
Te muestro:
https://drive.google.com/file/d/1DjvvtvnTAwY5aiseW7afowmS0nZdFTwL/view?usp=drive_link

Una duda: ¿En qué casos sólo es posible 1 ángulo? Quisiera obtener alguno para asegurarme de que funcione bien también en esos casos.
« Última modificación: 26 Mayo 2023, 11:54 am por Tachikomaia » En línea

Páginas: 1 [2] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines