Disparo con trayectoria en parabola?

Started by Hokutoy, August 23, 2010, 08:14:07 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Hokutoy

Buenas a todos!
Despues de unas buenas vacaciones me apetece hacer un minijuego para ir desenpolvando los skills para acabar los proyectos en marcha.
Quiero hacer el tipico juego al estilo bowman o catapultas de los juegos flash en que dadas un angulo de lanzamiento y una "fuerza" se dipara un proyectil que describe una parabola hasta llegar al suelo o al enemigo.

He intentado muchas cosas desde decrementos de y a perder angulo con el tiempo, etc (tengo los codigos en casa sorry) pero la parabola que desprende la flecha siempre es muy forzada e irregular.

Como siempre, mientras mi profesor de trigonometría daba clase, yo estaba haciendo peyas así que si alguien me puede facilitar la formula matematica para recrear la parabola de una flecha/proyectil le estaré muy agradecido... imagino que aparte del angulo y la fuerza tambien se debe de tener en cuenta la velocida y el tiempo?

Gracias!

Mr Matsusaka

#1
Mira, yo no me considero un buen matematico ni nada, y no me se el algoritmo perfecto para este tipo de caso, pero al menos en mi caso para resolver este tipo de problemas hago muchas pruebas utilizando la tecnica del ensayo-error hasta que consigo lo que quiero.

Lo primero que tenemos (por lo que cuentas) es una catapulta (o arco) a la que se le puede cambiar de angulo. Pues lo que tenemos que hacer es repartir la fuerza del tiro entre la velocidad x y la velocidad y dependiendo del angulo. Si la catapulta tiene un angulo 0 apuntando hacia adelante toda la fuerza ira al incremeto de x, mientras que el incremento de y sera 0. Si disparamos hacia arriba con un angulo de 90 grados, el incremento de y sera muy alto mientras que el incremento de x sera 0.

Tenemos la variable "angulo", que puede ir de 0 hasta 90000 y que varia si pulsamos arriba o abajo.
Tenemos la variable "fuerza" que puede ser constante o podemos hacer que cambie dependiendo de cuanto tiempo pulsemos la tecla de disparo, etc...
Con esas dos variables y usando las siguientes lineas ya podemos determinar la velocidad en x e y de la flecha.

inc_x = sin(angulo) * fuerza;
inc_y = cos(angulo) * fuerza;

El codigo seria algo asi:

angulo;
fuerza;
inc_x;
inc_y;
estado;
EST_APUNTANDO=0;
EST_DISPARANDO=1;

loop
  if (estado==EST_APUNTANDO)
     if (key(_up))
        angulo +=5000;
        if (angulo>90000)
           angulo = 90000;
        end
     end
     if (key(_down))
        angulo -=5000;
        if (angulo<0)
           angulo = 0;
        end
     end
     if (key(_enter))
        estado==EST_DISPARANDO;
        inc_x = sin(angulo) * fuerza;
        inc_y = cos(angulo) * fuerza;
     end
  end

  if (estado==EST_DISPARANDO)
     flecha.x += inc_x;
     flecha.y += inc_y;
     // gravedad
     inc_y++;
  end
end


Esto asi a bote pronto, puede que tenga algun error de base, pero eso te toca probarlo y arreglarlo ya a ti.
En segunda instancia necesitamos cambiar el angulo de la flecha segun los incrementos para que resulte realista
Antes de disparar es sencillo, pues le aplicas en "angulo" al angle de la flecha y ya. Cuando la flecha esta volando es un pelin mas complicado, pero eso ya sera en un segundo capitulo xd


Hokutoy

No solo me das codigo base sinó que ademas te curras una muy buena explicación... Así da gusto. karma up!
Esta tarde/noche intento integrar la idea a mi codigo y te digo que tal anda.

Si alguien mas quiere aportar ideas que no se corte!

Gracias!

Noivern

Otra cosa que puedes hacer es considerar el disparo en el vacio. Si mi memoria no me falla,en este caso la velocidad x es constante y solo varia la velocidad en y por efecto de la gravedad. Te sugiero utilizar la variable local resolution minimo a 10 para que la curva no se vea tan forzada. De esta manera puedes dar un advance(25) que serían 2.5 pixels... bueno no se movera 2.5 pixel sino que la primera vez seran 2 px desde el origen y en el siguiente frame seran 5 px desde el origen. ¿se entiende?
Las coordenadas serán: (nº de px / resolution), asi que para moverte 1 px a la derecha seria x+=10;

Drumpi

Si no, siempre queda el recurso de implementar la gravedad en el salto estilo "castle of Dr Malvado", manteniendo la velocidad horizontal constante.
Al menos yo lo usé en uno de los minijuegos del "crap-training" en el tercer concurso de crap-juegos, y quedaba bastante resultón (creo que el código fuente iba dentro).
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

Hokutoy

Gracias por las respuestas chicos!

Estuve probando con el metodo de Matsusaka
inc_x = sin(angulo) * fuerza;
inc_y = cos(angulo) * fuerza;
// gravedad
inc_y++;


y la verdad es que me ha quedado bastante bien. Ya he creado un sistema para haces la curvatura de la flecha que aunque primitivo da bastante buen resultado.

ANGLE-=inc_y*600;
IF(angle>30000) Angle=30000; end
IF(angle<-65000) Angle=-65000; end


Se me ocurren varias maneras mejores para hacer esto pero la verdad es que esta da buen resultado.

Lo que si que haré es intentar juguetear con el tema de RESOLUTUON ya que cuando hacer un disparo con mucha fuerza y mucho angulo los incrementos son un poco brutos.

Saludos!

PD: Ya postearé mas dudas

Mr Matsusaka

Me alegro me alegro :D
Ya nos enseñaras el juego cuando este presentable

Hokutoy

Una preguntita Matsu,
Usando tu formula, y pensandolo para realizar una IA sencilla mas palante, como calculo/consigo el angulo/fuerza necesarias para llegar a una X determinada?
Es decir, si el enemigo se encuentra a una distancia predeterminada, como consigo calcular el angulo/fuerza para hacertarle de lleno?

Eso de despejar variables nunca ha sido mi fuerte jejeje

Saludos y gracias!

PD: Si sale algo medio decente seras el primero en tenerlo!  ;D

FreeYourMind

Quote from: Hokutoy on August 26, 2010, 10:47:24 AM

PD: Si sale algo medio decente seras el primero en tenerlo!  ;D

Fijate que animo has dado a los otros foreros que quieran ayudarte  ::)

Hokutoy

Quote from: FreeYourMind on August 26, 2010, 10:51:53 AM
Quote from: Hokutoy on August 26, 2010, 10:47:24 AM

PD: Si sale algo medio decente seras el primero en tenerlo!  ;D

Fijate que animo has dado a los otros foreros que quieran ayudarte  ::)

No acabo de entender a que te refieres... toda la ayuda es bien recibida!
Si sale algo medio decente me refiero al minijuego que estoy haciendo... suelo ser bastante crítico con las cosas que hago yo mismo y me cuesta relesear las cosas porque siempre pienso que no tienen nivel para interesar a nadie.

Aunque cuando libero los juegos siempre lo hago con el codigo fuente por si a alguien le sirve.

Saludos!

FreeYourMind

#11
Estaba de coña heheheh

Por cierto, el src del Shock Troopers defense por donde lo tienes ? Me gustaria echarle un vistazo, ya que aún  no he podido probar el juego.

Mr Matsusaka

Si quieres saber donde va a caer la flecha antes de que se haya disparado la flecha no tienes mas que hacer una funcion que simule la fisica. Algo como esto

[code language="bennu"]simulate_x;
simulate_y;
simulate_frames;

funtion simulate_shot(angle, speed)

begin
  inc_x = sin(angulo) * fuerza;
  inc_y = cos(angulo) * fuerza;
  simulate_y = flecha.y;
  while (simulate_y<SUELO_Y)
     simulate_x += inc_y;
     simulate_y += inc_y;
     inc_y++;
     simulate_frames++;
  end
end[/code]

Con esto puedes determinar si el tiro es bueno o malo antes de poder lanzarlo.

Sin embargo me parece que lo que tu quieres es hacer un tiro automatico hacia un enemigo y conseguir los valores de inc_x e inc_y necesarios para acertar automaticamente. La solucion que te propongo no es la mas optima, es una solucion waltraper que puede servirte de momento.

Lo primero es cojer la distancia en x entre la flecha y el enemigo. Cuanto mas lejos este mas inc_y le tenemos que dar para que la flecha dure mas en el aire. Y luego respecto a eso sabremos la velocidad x necesaria.


automatic_incx;
automatic_incy;

[code language="bennu"]function get_shot()

private
  num_frames;

begin
  inc_y = (flecha.x - enemigo.x)/10;
  automatic_incy = inc_Y;

  // precalcula los frames que durara la flecha en el aire
  num_frames = 0;
  y = flecha.y;
  while (y<SUELO_Y)
     y+=inc_y;
     inc_y++;
     num_frames++;
  end
  inc_x = (flecha.x - enemigo.x)/num_frames;

  automatic_incx = inc_x;

end[/code]

Te digo lo mismo de antes, puede que este poco pulido y falle. Vigila el "/10" que me chirria.
Como te digo, no es la mejor solucion probablemente, pero mientras no venga nadie con un algorimo mejor a lo mejor funciona xd

Hokutoy

Quote from: FreeYourMind on August 26, 2010, 12:49:33 PM
Estaba de coña heheheh

Por cierto, el src del Shock Troopers defense por donde lo tienes ? Me gustaria echarle un vistazo, ya que aún  no he podido probar el juego.

Ah valeee!  ;D

Porque no lo has podido probar? El source no esta incluido con el paquete del juego... raro pensaba que sí.
Hay que avisar de que està hecho en FENIX no en BENNU y cuando lo intenté portar me encontré con demasiadas cosas que no funcionaban como debería como para reescribir el còdigo entero otra vez.

Avisar también de que el src es como una patata caliente pero mas pastoso y huele peor!  ::)

Aunque si te digo la verdad tengo la version final casi acabada... bueno acabada del todo (los 20 mapas) a falta de calibrar bien la cantidad y contenido de las oleadas... que no se me da nada bien.
Si no consigo ayuda acabré haciendo algo en plan RANDOM y para casa jejeje

Tenía intención de relesearlo antes de los resultados del concurso de gp32Spain pero no llegué a tiempo así que estoy a la espera de que pase un poco el "escozor" del emu de Psx para relesearlo... con el source.

Saludos!

FreeYourMind

Vale, entonces esperaré la version final para probarlo.
Grácias.