Sugerencias con juego de tenis

emasg - 14/07/2009 03:07
Hola a todos, sé que esto no tiene mucho que ver con modelado o con 3d, pero seguramente hay mucha gente que conoce de matemáticas y física por aquí.

Sin más preámbulos:
Estoy empezando a hacer un juego de tenis en frebasic con la librería ninfa3d.

Venia todo bien hasta que me tope con la parte de calcular el tiro.

Voy a empezar usando un tiro oblicuo sin considerar el rozamiento del aire ni el spin de la pelota. Lo que conozco son 3 puntos, el punto desde dónde parte el tiro, el punto a la altura de la red donde quiero que pase la pelota, y finalmente donde quiero que caiga y por ahora solo consideré 2 dimensiones, más tarde me encargo de la tercera.

Llame a los puntos (xo,yo) (xc, yc) y (xf,yf).

Este es un gráfico de la situación:
La pregunta es: se puede calcular voy (velocidad inicial de y) y vox(velocidad inicial de x (constante)) conociendo estos 3 puntos? Como llego al resultado?
Llevo un par de días tratando y unas 10 hojas de tachones, agradezco cualquier ayuda. Gracias y saludos.
Bluder - 14/07/2009 14:02
Hola emasg. He de decirte que no entiendo cómo planteas el problema. En el juego de tenis lo que deberías conocer es con que velocidad sale despedida la pelota de la raqueta y de donde, los otros puntos son variables, además otro tema seria el ángulo respecto al suelo, o a la normal del suelo como prefieras, que también influye en el tiro. Es un problema de tiro parabólico además un movimiento acelerado ya que la gravedad es una aceleración, no es constante. Un saludo.
emasg - 14/07/2009 14:06

Hola emasg. He de decirte que no entiendo cómo planteas el problema. En el juego de tenis lo que deberías conocer es con que velocidad sale despedida la pelota de la raqueta y de donde, los otros puntos son variables, además otro tema seria el ángulo respecto al suelo, o a la normal del suelo como prefieras, que también influye en el tiro. Es un problema de tiro parabólico además un movimiento acelerado ya que la gravedad es una aceleración, no es constante. Un saludo.

El problema es que no puedo tirar una velocidad al azar porque nunca voy a saber dónde cae la pelota.

Básicamente lo que necesito es lograr la ecuación para un tiro seguro, que pase por encima de la red y caiga donde quiero.
Caronte - 14/07/2009 14:08
Sinceramente, creo que te estás metiendo en berenjenales. Hoy día nadie calcula esas cosas, simplemente debes usar un motor de físicas para que al lanzar la pelota se calcule la trayectoria y sus rebotes automáticamente.
Bluder - 14/07/2009 14:12
A ver. No comprendo, si es un juego debería poderse fallar ¿no? Edito: como te ha dicho Caronte, hay otras opciones más sencillas. Si quieres hacer tu las cosas, por amor al arte, por que te gusta, o por la razón que sea, puedes mirar estos enlaces sobre el tiro parabólico: [url]http://descartes, cnice, mec.es/descartes2/previas_web/materiales_didácticos/comp_movimientos/parabolico.htm[/url]. [url]http://www.youtube.com/watch?v=dkovgwkyaj4[/url].
emasg - 14/07/2009 15:24
Les agradezco los consejos. Ahora, estoy usando ninfa3d, tiene algo de física, le puedo aplicar un impulso a un cuerpo, pero no puedo conocer la trayectoria, es decir, nunca se dónde va a tocar con el suelo entre otras cosas. Me podrían recomendar algún engine?
Por otra parte, el tiro seguro es necesario para programar la inteligencia artificial, se empieza por hacer un jugador que no falle y luego se le agrega un margen de error de acuerdo con el nivel del jugador.

Pero bueno, si insisten quiero comprender lo que proponen, sería algo, así como lanzar la pelota con una velocidad inicial que invento de alguna forma basándome en la posición de la cancha en la que está la pelota. De acuerdo con esa velocidad cálculo la trayectoria para que la pelota no toque la red y toque el suelo donde quiero. El problema en este caso seria conseguir esa velocidad inicial, requeriría de un algoritmo que le de sentido puesto que si la pelota esta baja y muy cerca de la red no se le puede pegar a 100 km/h porque nunca va a entrar, por ejemplo.

Con respecto al enlace de tiro parabólico me gustó, está muy bien explicado, pero no encontré en ninguna web ni libro un ejemplo donde se calcule un tiro oblicuo a partir de 3 puntos, tal vez sea imposible (¿).
Bluder - 14/07/2009 15:49
Bueno. Teniendo el último punto, el punto central y el ángulo creo que puedes obtener la v inicial, basándote el alcance máximo y altura máxima:
X = (vo2)*sen(2*a)/g (x del punto de caída).

Y(max) = (vo2)*(sen(a))2/(2*g) (y del punto central).

La duda que tengo es si dispones del ángulo.

Aquí puedes encontrar como hallar la parábola a partir de los puntos: [url]http://es.answers, Yahoo.com/question/index?Qid=20070711133557abpkr7[/url]. [url]http://leonardoparada.cl/matemática/encontrando-la-función-correspondiente-a-una-parábola-dados-3-puntos/[/url].
emasg - 14/07/2009 16:12
La duda que tengo es si dispones del ángulo.[/quote]Gracias bluder. No tengo el ángulo, porque todo depende de todo, eso es lo que no término de comprender.

Si parametrizo el tiempo que quiero que tarde el tiro en tocar el piso o la velocidad inicial o el ángulo solucionó, pero no es lo que quiero parametrizar porque así no es el tenis, en el tenis uno calcula la altura a la que se quiere que pase la pelota por encima de la red y donde se quiere que caiga, de ahí sale el ángulo y la velocidad de x.

En principio parece una función cuadrática que pasa por 3 puntos, busque en internet y encontré cosas en Wikipedia, pero no lo pude aplicar.
mentalthink - 14/07/2009 20:02
Hola pues a mí se me ocurre esto, no sé si será correcto ya que no soy programador, pero bueno. Seria una cosa así supongo.

Maxtiempo=colisión con la pala1.

Mintiempo=clision con la pala0.

Bucle.

If colisión con la pala=1 then gravedad=gravedad+1 and x=x-1.

If colisión con la pala0=1 then gravedad=ravedad+1 and x=x+1.

If recorrido=0 // donde 0 en la mitad de la pista de tenis// then gravedad=gravedad-1.

Repetir bucle.

No se a lo mejor no te funciona, pero prueba a ver supongo que, será una cosa así.
Caronte - 14/07/2009 20:32
Metalthink, te has pasado 3 pueblos con ese pseudo-código. Insisto, usa un motor de físicas (yo te recomendaría bullet que es el que usa Blender) y así no tendrás que reinventar la rueda y podrás centrarte tanto en la inteligencia artificial de tu juego como en aspectos más importantes, por ejemplo, la jugabilidad.
krateos_29 - 14/07/2009 20:41
Si quieres hacerlo por el método tradicional, saca los apuntes de tiro parabólico. De lo que me acuerdo es que cuando la pelota está en su punto más alto, la velocidady=0.

La velocidadx es siempre constante.

Y bueno, supongo que, sería cuestión de poner las ecuaciones del tiro parabólico en el programa.

Ten en cuenta que es un movimiento uniformemente acelerado (gravedad).
emasg - 14/07/2009 21:05
Se puede usar bullet en frebasic? O en que programo? La idea era usar todo software libre, pero bueno, si hay que comprar algo no tengo drama, ahora ya me cope, es un desafío.
Pepius - 14/07/2009 21:45
Entiendo lo que quieres hacer, es bastante importante en un juego de tenis que el programando pueda controlar donde vaya a caer la pelota.

Yo no parametrizaría nada. Como te comentan por aquí, usa las físicas de las que dispongas. Si dices que ninfa3d te permite dar impulsos, es suficiente. Yo no calcularía velocidad inicial, sino la fuerza y dirección del impulso (teniendo en cuenta masa de la pelota y gravedad) del que debes dotar a la pelota. Diría que es una ecuación con bastantes incógnitas (posición donde va a caer la pelota, altura a la que ira, velocidad que llevara). ¿forma rápida de hacerlo? Pues a ojo, pruebas valores, hasta que des con unos que envíen la pelota a fondo de pista pasando cerca de la red. A partir de ahí los modificas levemente y apuntas los que den resultado satisfactorio.

Un poco patatero, pero vaya.
emasg - 14/07/2009 21:57
Claro, tendría que hacer un ciclo que vaya probando valores hasta que de con lo que yo quiero. Eso podría generar un terrible bug en el momento en el que cálculo la trayectoria.

Aunque no es mala la idea si está bien organizada.

Se vuelve una especie de batalla código vs. Matematica.

Ahora, lo que me pasa es que cada vez que miro el gráfico, con los 3 puntos y la parábola pienso no puede ser tan difícil.

Así que cuando salga del trabajo voy a seguir tachando hojas, en lugar de estudiar para la Facu, hasta que me salga la ecuación.

Ah, y entrando al foro para ver si alguien sabio la resolvió.
Pepius - 14/07/2009 22:35
Pues entonces haz lo que te han recomendado por arriba, revisa los apuntes de movimiento parabólico, aunque ya te digo: sacar todo un juego de tenis haciendo esos cálculos va a ser algo muy difícil. Más que nada porque después la bola tendrá que volver a subir por el rebote, y tendrás que hacer esos cálculos también. Además, los tiros no se realizaran con una velocidad de pelota 0. Y esa es otra, tendrás que tener en cuenta aceleraciones también. Suerte.
emasg - 15/07/2009 00:26
Yo creo que a partir de esta ecuación tengo casi todo resuelto el tema de la física. Para que quede más claro porque no sirven los apuntes de física:
En todo apunte de tiro parabolico se considera que:
Y = g/2 * t2 + voy * te + yo.

Cuál es el problema? Siempre de una manera u otra, voy es un parámetro establecido o bien lo es t. Ya sea mediante el ángulo del tiro o de la velocidad misma.

En este caso no es así, por lo tanto no tenemos una simple función cuadrática que despejamos con una resolvente.

Para resolver esto, lo que se necesita es de alguna forma conocer voy sin conocer el ángulo del tiro ni la velocidad inicial, todavía no sé si es posible, pero lo aclaro para los próximos que entren o alguno de los que entro que me quiera dar una mano.

Después les dedico el skin de algún jugador. Saludos.
emasg - 16/07/2009 03:47
Lo solucioné. Al final hice un loop que prueba valores, pero de todas maneras es super corto, no da más de 10 vueltas en la mayoría de los casos.

La idea es primero obtener el ángulo entre la horizontal y la recta que pasa por el punto inicial (xo, yo) y el que está por encima de la red (xc,yc).

Después con ese ángulo obtengo la velocidad para que tenga raíz en el punto final (xf,yf).

De esa forma aumento el ángulo inicial hasta que la curva pase por el punto (xc,yc) y listo.

Aquí está el código por si a algún trastornado se le ocurre lo mismo que ha mi:
A=atan((yc#-yo#)/(xc#-xo#)).

Ycn#=0.
While ycn# Wend.

Vox#=vo#*cosa#.

Voy#=vo#*sina#. Gracias a todos por las ideas, si se les ocurre una forma mejor me avisan. Saludos.
IsGreen - 16/07/2009 22:08
Saludos emasg. He desarrollado un poco de código con ninfa3d donde establecemos un Vector de impulso (x y, z) a una esfera, de dónde obtenemos la orientación e inclinación.

Sabiendo que tan @ = sen @ / cos @, y que sen @ = ejez, y cos @ = ejex, aplicamos la inversa de tan @ = (eje Z / eje x) para despejar @ (en este caso, la orientación).

Para despejar la inclinación, utilizamos la misma fórmula tan @ = sen @ / cos @, donde sabemos que sen @ = ejey, y para calcular cos @ debemos obtener la distancia entre el ejece central (sería (0,0)) y el punto (x, z).

La distancia se obtiene de raíz cuadrada de la suma de los cuadrados de ejex y ejez (no se considera el otro punto ya que se trata de la posición (0,0)), es decir, (ejex2+ejez2)(1/2).

Entonces, la inclinación la obtendríamos aplicando la función inversa a tan @ = (ejey / (ejex2+ejez2)(1/2)) para despejar @ (en este caso, la inclinación).

Sabiendo la orientación y la inclinación ya podemos obtener el Vector de movimiento (utilizaríamos la función moveentity() de ninfa3d). Las funciones las he obtenido de algunas páginas web buscadas con google.

Eje x = vectorx*cos(orientación)*tiempo.

Eje y = vectory*sin(inclinación)*tiempo-4.9*(tiempo22).

Eje z = vectorz*sin(orientación)*tiempo).

Vectorx, vectory, vectorz : valores (x y, z) respectivamente, del Vector de impulso.

Al ejey y, le he aplicado el efecto de la gravedad donde añadimo (1/2) * 9.8 (t2).

La variable tiempo es un factor que he utilizado para simular la velocidad del sistema de nuestra ordenador.

Tiempo2 es otra variable tipo tiempo acumulativa para simular aceleración.
[code]#include ninfa3d, bi.

Dim shared Camera as ncamera.

Dim as nlight light01.

Dim shared as nmesh objeto.

Dim as nsprite sprite.

Dim shared as byte lanzar=0.

Dim shared as single posx=0,Posy=5,posz=-200.

Dim shared as single vectorx=100,vectory=100,vectorz=100.

Dim shared as single orientación, inclinación.

Dim shared as single tiempo=0.001, tiempo2=0.001.

Enable vertical synch.

Enablevsync().

Starts the ninfa3d engine.

Initengine (640,480,32,0) tbackgroundcolor(128,128,12 background color tambientlight(32,32,32)ambient color.

Include the file samplefuntions, bi.

It contains useful features, such as drawing the interfaz and create the test área.
#include samplefunctions, bi.

Create a Camera.

Camera = createcamera ().

Positionentity(Camera,0,64,-280) position.

Creates the lights.

Light01 = createlight(lgt_point) tpositionentity(light01,0,128,12 position tlightradius(light01,256) Radius of the light tlightcastshadow(light01).

Sprite = loadsprite (media/Glow.bmp) tentityparent(sprite, light01) tscalesprite (sprite,30,30).

Createground()creates the test área.

Load Mesh.

Objeto=createmeshsphere (.

Scalemesh(objeto,5,5,5).

Positionentity(objeto,posx,Posy,posz).

Sub moverobjeto ().

Moveentity(objeto,vectorx*cos(orientación)*tiempo,vectory*sin(inclinación)*tiempo-4.9*(tiempo22),vectorz*sin(orientación)*tiempo).

Tiempo2+=tiempo.

If entityy(objeto)<0 then lanzar=0:positionentity(objeto,posx,Posy,posz).

End sub.

Sub actualizarraton().

If mousedown(mouse_left) then vectorx+=mousex()-320+mousey()-240.

If mousedown(mouse_right) then vectory+=mousex()-320+mousey()-240.

If mousedown(mouse_midle) then vectorz+=mousex()-320+mousey()-240.

Movemouse (320,240).

End sub.

Movemouse (320,240).

Hidemouse ().
While (enginerun)returns 1 if the engine is running tbegins scene tbeginscene ().

If keyhit(key_space) then.

Posx=entityx(objeto):Posy=entityy(objeto):posz=entityz(objeto).

Orientacion=atn(vectorz/vectorx)*sgn(vectorx)*sgn(vectorz).

Inclinacion=atn(vectory/(sqr(vectorx*vectorx+vectorz*vectorz)))*sgn(vectory).

Lanzar=1.

Tiempo2=tiempo.

End if.

If (lanzar) then moverobjeto () else moveentity(objeto,-keydown(key_left)+keydown(key_right),keydown(key_control)*(-keydown(key_down)+keydown(key_up)),-keydown(key_down)+keydown(key_up)):actualizarraton() tby pressing the escape closes the engine tif keyhit(key_escape) then closeengine () tupdate the engine tchanging the value (only afects the physics) that Will update the tphysical faster or slower tupdateengine (0) tdisplays the interfaz (fps and triangles) tinterface ().

Text(15,80,Vector:,0,0)displays on the screen.

Text(15,90, x: +str$(vectorx),0,0)displays on the screen.

Text(15,100, y: +str$(vectory),0,0)displays on the screen.

Text(15,110, z: +str$(vectorz),0,0)displays on the screen tend the scene tendscene ().
Wend.

Ends ninfa3d engine.

Endengine ()[/code]

Espero que puedas aprovechar algo del código anterior en tu proyecto.
emasg - 16/07/2009 23:04
De mi código no me va a servir mucho más que la idea (el ciclo que aumenta el ángulo). Con tu parte llevo mi 2d a 3d. Genial. Isgren. Muchas gracias.
emasg - 18/07/2009 02:45
Solución definitiva. Obvie las definiciones y fui directo al bucle principal. Es una fusión entre el algoritmo de isgren y el mío.
While (enginerun).

Cls.

Beginscene () t.

If keyhit(key_escape) then closeengine ().

If mousehit(mouse_left) then.

Orientacion=atn((zf-zo)/(xf-xo)).

Inclinacion=atn((yc-yo)/(zc-zo)).

Sino=sin(orientación).

Coso=cos(orientación).
While ycn
Sini=sin(inclinación).

Cosi=cos(inclinación).

Vo=((4.9*(zf-zo)2)/(sini*cosi*(zf-zo)+(cosi2)*yo-(cosi2)*yf))(1/2).

Vx=vo*cosi*coso.

Vy=-vo*sini.

Vz=vo*cosi*sino.

Tiempoc=((zc-zo)/(vz)).

Ycn=-4.9*(tiempoc2)+vy*tiempoc+yo.

Inclinacion=inclinación-(3.1415926535897932/180).
Wend.

Tiempo=0.01 :tiempo2=0.

End if.

If tiempo>0 then.

Positionentity(ball, x*tiempo+xo,-4.9*(tiempo2)+vy*tiempo+yo, z*tiempo+zo).

Tiempo=tiempo+0.01.

If entityy(ball)<0 then tiempo=0:tiempo2=0 termino el tiro (ni ganas de resetear).

End if.

Endscene () t.
Wend.

Una vez más gracias a todos por los aportes y espero que le sirva a alguien más. Saludos.
mentalthink - 23/07/2009 12:50
Pues Caronte me habré pasado 3 o 4 pueblos, pero cuando yo hago algo pue lo pienso así, si te gusta bien, y si no ya sabes.
Caronte - 23/07/2009 13:37
Pues intenté hacerte ver en forma coloquial que el tema no es tan sencillo como tú lo quieres solucionar, pero ya que te pones borde, te puedo decir que tú pseudo-código no serviría ni para simular un pong de 1972 por el simple hecho de que ni siquiera tiene sentido, por otro lado, te digo lo mismo, si no te gusta lo que les, ya sabes.
emasg - 23/07/2009 14:20
Por ahí te falto un poco de claridad Metalthink, yo la verdad que no pude interpretar tu código. Igual esta buena la intención.
Cibertronic - 27/07/2009 09:49
Hola emasg. Realemte muy interesante tu propuesta. Y si bien es cierto que redescubrir la pólvora no tiene sentido practico, entenderla y estar en condiciones de hacerla si merece la pena, el estudio.

Si bien resolviste tu problema con físicas yo te dejo aquí mi propuesta utilizando determinantes, la manera más fácil de resolver el problema que planteas.

Espero también te sea útil mi propuesta, te dejo el ejecutalbe y el código fuente.

Espero poder escanearte mis apuntes y subirlos también. Un saludo y para delante.

-- IMÁGENES ADJUNTAS --

🖼️

Estamos trabajando para mostrar las imágenes del foro

Adjunto #110734



🖼️

Estamos trabajando para mostrar las imágenes del foro

Adjunto #110735

emasg - 27/07/2009 13:25
Gracias Cibertronic, ahora lo reviso. Edito: lo vi un poco apurado en el trabajo, me gustó mucho. Hace lo mismo que mi algoritmo, pero sin un ciclo y con cálculos más sencillos.
Cibertronic - 27/07/2009 16:25
Aquí las notas, que realice. Como pueden ver todo se centra en un simple sintema lineal de 3 variables por 3 incógnitas, poara los que tenemos un mínimo conocimiento de matemáticas superior sabemos que es perfectamente resolvible.

Pero si alguien todavía ya sea por edad o profesión todavía no las conoce, no se asuste, esos que escribí en el papel, está en internet son operaicones tan simples que seguro que están(y si no están deberían) yo las resulevo manualmente (reinvento la pólvora) como practicando, porque ya me estaba olvidando el tema este de determinantes.

Y tamiben como pueden ver solo son 3 variables, a, b, c si las constantes de la ecuación cuadrática.

Y. Gravedad, ángulo, velocidad, aunque no lo crean están descritas en y=ax2+bx+c, salvo velocidad, pero esa se le dará desde el programa.

Excelente exercise.

-- IMÁGENES ADJUNTAS --

🖼️

Estamos trabajando para mostrar las imágenes del foro

Adjunto #110764

emasg - 27/07/2009 16:59
Las notas, te pusiste a hacer todos los cálculos, que grande. Había considerado usar determinantes, pero no sabía cómo plantear las ecuaciones.

Bueno, voy a tener que rescribir todo mi código.
emasg - 27/07/2009 20:11
Bueno ya lleve el ejemplo a 3d, el problema ahora es que todos los tiros viajan a la misma velocidad. De la forma que lo había hecho antes calculaba la velocidad en base a la trayectoria.

Igual ya estoy algo perdido.
Cibertronic - 28/07/2009 03:34
Hola emasg. De repente te sirva uno apunte más:
una forma
Yo para hacer que algo valla más padipo uso el salto.

Z=z+1, avanzara de uno en uno.

Z=z+10 ira de 10 en 10 más rápido aparentemente un juego no tiene que ser realístico, sino creíble, es decir debe hacernos creer que es posible lo que estamos realizando.
otra forma. No estoy seguro, pero leíste algo de derivadas si tenemos:
Y=ax2+bx+c, ecuación de posición podemos derivarlo con respecto a x.

Dy/dx= v así tendríamos la ecuación para la velocidad en un punto dado ahora bien DV/dx=a derivando otra vez tenemos la ecuación para la aceleración respeco a la posición si me hubieran dicho que podía haber utilizado esas formulas para hacer un video juego, seguro habría prestado más interés. Un saludo.
emasg - 05/08/2009 02:15
E, bueno ya quede conforme con la física y se cómo hacer lo que quiero, ahora me voy a dedicar a modelar los personajes: Anim8or, an8tob3d y uvmapper.

A ver que sale.