Trayectoria de un proceso

Started by NesKy, November 25, 2010, 12:43:51 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

NesKy

Buenas, vuelvo a la carga :)

Dentro de mi proyecto, colgado en el foro (Hilo), estoy intentando de hacer aparecer a un "aliado" que te lance powerups de disparos, vida,... El caso es que me gustaria que el dibujo tuviera una trayectoria ondulante a través del eje "x", ya que el dibujo en cuestión es un ovni, para quedar mas acorde jaja. Mis primeros intentos son un poco a lo bestia:
//******ALIADO******
PROCESS aliado()
PRIVATE

END
BEGIN
ctype=C_SCROLL;
x=scroll[0].x0-50;
y=scroll[0].y0 + rand(60,250); //Altura variable
graph=1;
LOOP
graph+=1;
x+=4;
[b] y+=rand(1,3);   //Simula una trayectoria ondulante
y-=rand(1,3);   //Simula una trayectoria ondulante[/b]
IF(graph>=12)
graph=1;
END
IF(x>scroll[0].x0+660) //Para matarlo al salir del scroll
BREAK;
END
FRAME;
END
END

Claro, el proceso tiembla en todo el recorrido ...

He pensado en definir una función para que "y" la siga. He pensado en la funcion de "sinus" (Dibujo) la cual dibuja una trayectoria perfectamente ondulada. ¿Como se tendrian que definir esta función y poner luego que lo siga un proceso? Hay alguna opción mas fácil?

Y a partir de aquí, aprovecho para preguntar que sistema utilizais vosotros para que un proceso (balas, enemigos,...) sigan un trayecto definido. Se me ocurre la trayectoria de un mortero que primero sube, llega a un máximo y vuelve a caer, etc.

Gracias de antemano!

Yawin

Mira, yo para la "coreografía" de los bosses lo que hago es:
loop //Este loop es el general, donde están tanto los ataques como los movimientos
if(i==0)
if(X<278)
i=1;
else
X-=1;
end
else
if(X>358)
i=0;
else
x+=1;
end
end

/* Aqui ya puedo poner todo lo demás que uqiero que haga sin tener interrupciones
que molesten a las habilidades del boss */

end
Sigue el desarrollo de mi motor RPG: https://www.youtube.com/watch?v=TbsDq3RHU7g

process main()
       begin
           loop
               pedo();
               frame;
            end
       end

NesKy

No entiendo la función de "i" en este código. Podrias ponerlo con un poco mas de contexto? Cuando declaras "i", le das valor 0 o 1?

Yawin

La cosa es, si i==1, el proceso se va moviendo hacia la derecha a razón de x++;. ¿Qué ocurre si i==1 y x>380? Pos que i pasa a ser 0, de esa forma, el proceso empieza a ir a la izquierda.

La i no es más que un interruptor 0/1 (puedes emplear también una variable de tipo bool). Si el interuptor es 1 va para un lado y si es 0 va para el otro.

Su declaración sería:
int i=0;
O
int i=1;

Depende del lado al que quiereas que empiece llendo.
Sigue el desarrollo de mi motor RPG: https://www.youtube.com/watch?v=TbsDq3RHU7g

process main()
       begin
           loop
               pedo();
               frame;
            end
       end

DCelso

Justo eso hace mi primera versión de mi mosca

http://forum.bennugd.org/index.php?topic=353.0


process fly(ini_x,ini_y, float amplitud, int frecuencia)
public
    puntos;
    death;
private
    float var_x;
    float var_y;
    float const_a ;
    float const_b ;
    float const_c;
    int sigue_pulsado = 0;
    float valor_dist;
    p_mouse id_mouse;
    int vel_x = 2;
    int v_graphs[1];
    int index_graph;
    int i;
begin
    amplitud = amplitud*100;
    frecuencia = frecuencia * 1000;
    puntos =  frecuencia / amplitud;
    size = 20;
    var_x  = 0;
    const_a = 1;
    const_b = 1;
    v_graphs[0] = load_png("fly.png");
    v_graphs[1] = load_png("fly2.png");
    index_graph = 0;
while (!key(_esc) AND !death )
    graph = v_graphs[index_graph];
        var_x+=vel_x;
        var_y = amplitud*sin(var_x*frecuencia);
        x = ini_x + var_x;
        y = (ini_y + var_y);
        index_graph++;
        index_graph = index_graph%2;
        if (x >= 660)
          num_flies --;
          break;
        end
        Frame;
end
for (i=255;i>0;i--)
   alpha = i;
   frame(50);
end
unload_map(0,v_graphs[0]);
unload_map(0,v_graphs[1]);
end
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

Y aqui, en la segunda versión, voy girando el graph con la tangente al seno para que se vea girar en la direccion de dibujado del seno


process fly(ini_x,ini_y, float amplitud, int frecuencia)
public
   puntos;
   death;
private
   float var_x;
   float var_y;
   float const_a ;
   float const_b ;
   float const_c;
   int sigue_pulsado = 0;
   float valor_dist;
   p_mouse id_mouse;
   int vel_x = 2;
   int v_graphs[1];
   int index_graph;
   int i;
begin
   amplitud = amplitud*100;
   frecuencia = frecuencia * 1000;
   puntos =  frecuencia / amplitud;
   size = 20;
   var_x  = 0;
   const_a = 1;
   const_b = 1;
   v_graphs[0] = load_png("fly.png");
   v_graphs[1] = load_png("fly2.png");
   index_graph = 0;
while (!key(_esc) AND !death )
   // tangente  y = f '(a)·(x - a) + f(a)
   // y = amplitud*cos(a*frecuencia)*frecuencia* (x-a) + amplitud*sin(a*frecuencia)
   // y = amplitud*cos(a*frecuencia)*frecuencia*x-amplitud*cos(a*frecuencia)*frecuencia*a + amplitud*sin(a*frecuencia)
   // m = amplitud*cos(a*frecuencia)*frecuencia = tan(angulo)
   // angulo = arcotan(amplitud*cos(a*frecuencia)*frecuencia)
   
   graph = v_graphs[index_graph];
       angle = -atan(cos(var_x*frecuencia));
       angle = angle%360000;
       var_x+=vel_x;
       var_y = amplitud*sin(var_x*frecuencia);
       x = ini_x + var_x;
       y = (ini_y + var_y);
       index_graph++;
       index_graph = index_graph%2;
       if (x >= 660)
         num_flies --;
         break;
       end
       Frame;
end
for (i=255;i>0;i--)
  alpha = i;
  frame(50);
end
unload_map(0,v_graphs[0]);
unload_map(0,v_graphs[1]);
end


Claro esto para un ovni, como que no :D.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

NesKy

Bueno, como diria Jack el Destripador, vamos por partes.

Del primer post me interesa la sentencia "var_y = amplitud*sin(var_x*frecuencia);". Antes en mi programa he probado sin pensarlo la funcion "y=sin(x)" y veo que efectivamente existe! :). Lo que pasa que supongo la he declarado mal... Veo que tiene que ser una float, lógico.

En el segundo post me he perdido jaja. Bueno, tengo trabajo para estos días. Gracias por la respuesta!

Drumpi

sin es una función trigonométrica que devuelve valores reales (números con decimales positivos y negativos) entre (1,-1), por lo que si lo multiplicas por amplitud, tendrás un rango de valores entre (amplitud,-amplitud) que varía de forma oscilante (véase la gráfica) según el ángulo que se le pase por parámetro (valor entre paréntesis).

Este tipo de recorrido es uno de los más básicos que existen en los videojuegos y se suele usar mucho, como el tiro parabólico (eso que comentabas de la bala que la lanzas al aire y poco a poco va bajando), el recorrído en círculos o el cálculo de distancias.

Aunque no lo parezca, la programación lleva mucha matemática detrás, sobre todo cuando se trabaja con gráficos. Es imprescindible saber algo de trigonometría básica si se quiere trabajar manejando objetos en pantalla, y cuanto más se sepa, mejor :)
Por eso se insiste tanto en clase que las matemáticas son fundamentales, nunca sabes en qué contexto las vas a necesitar :D

Naturalmente hay simplificaciones de estas fórmulas (vease el código del salto en "Castle of Dr Malvado") pero luego requiere del clásico prueba-error para ajustarlo, y depende de los FPS (aunque esto último... ¿quién va a cambiar los FPS a mitad de desarrollo? ;D).
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)

NesKy

QuoteAunque no lo parezca, la programación lleva mucha matemática detrás
Por suerte las mates no eran mi debilidad, incluso me gustaban. Será cuestión de repasar conceptos, así refresco la memória. A ver si puedo colgar algo estos dias y me dais nota jaja.

NesKy

Primero de todo karma+ para DCelso (no se si te lo di ya...). Ayer hice unas pruebas y al final me quedo con la siguiente trayectoria: ejemplo.

Es un poco lio ya que las coordenadas (0,0) se encuentran en el lado superior-izquierda cuando en realidad esta abajo-izquierda. Al encontrar la función adecuada tienes que mirar al revés, por ejemplo, yo me he decidido por la equación: y =0.01*(-x*x) + (4*x) - (240), la cual dibujada en un eje de coordenadas cartesianas da una curba con un màximo, es decir sube y después baja. En el juego es al revés, viene de arriba, llega a un mínimo y vuelve a subir.

Para darle un toque de profundidad le he añadido que al llegar al máximo empieze un size-=1 para hacer el efecto de que se aleja. El efecto queda muy chulo. También, por cosas del juego final, la nave queda parada en este máximo durante un instante y continua la trayectoria.

Después de todo esto, vuelvo a hacer la pregunta del inicio: Vosotros que métodos utilizais para hacer trayectorias? O esta es la mejor (o peor)?

oriun

Quote from: NesKy on November 25, 2010, 12:43:51 PM
Buenas, vuelvo a la carga :)

Dentro de mi proyecto, colgado en el foro (Hilo), estoy intentando de hacer aparecer a un "aliado" que te lance powerups de disparos, vida,... El caso es que me gustaria que el dibujo tuviera una trayectoria ondulante a través del eje "x", ya que el dibujo en cuestión es un ovni, para quedar mas acorde jaja. Mis primeros intentos son un poco a lo bestia:
//******ALIADO******
PROCESS aliado()
PRIVATE

END
BEGIN
ctype=C_SCROLL;
x=scroll[0].x0-50;
y=scroll[0].y0 + rand(60,250); //Altura variable
graph=1;
LOOP
graph+=1;
x+=4;
[b] y+=rand(1,3);   //Simula una trayectoria ondulante
y-=rand(1,3);   //Simula una trayectoria ondulante[/b]
IF(graph>=12)
graph=1;
END
IF(x>scroll[0].x0+660) //Para matarlo al salir del scroll
BREAK;
END
FRAME;
END
END

Claro, el proceso tiembla en todo el recorrido ...

He pensado en definir una función para que "y" la siga. He pensado en la funcion de "sinus" (Dibujo) la cual dibuja una trayectoria perfectamente ondulada. ¿Como se tendrian que definir esta función y poner luego que lo siga un proceso? Hay alguna opción mas fácil?

Y a partir de aquí, aprovecho para preguntar que sistema utilizais vosotros para que un proceso (balas, enemigos,...) sigan un trayecto definido. Se me ocurre la trayectoria de un mortero que primero sube, llega a un máximo y vuelve a caer, etc.

Gracias de antemano!

Puedes probar a poner el frame entre :
                y+=rand(1,3);   //Simula una trayectoria ondulante
      y-=rand(1,3);
Es decir:
                y+=rand(1,3);   //Simula una trayectoria ondulante
                frame;
      y-=rand(1,3);
Y quitar lo del final.

NesKy

#11
Lo del rand(1,3) ya lo he dejado por ser bastante cutre ;D.

Problemas al aplicarlo con el scroll. Le meto el siguiente código:
nota: el primer IF, no se porque, no sale bien, es: IF(x<scroll[0].x0+160)
PROCESS aliadod()
PRIVATE
int i;
BEGIN
ctype=C_SCROLL;
x=scroll[0].x0;
graph=701;  
LOOP
IF(x<scroll[0].x0+160)
x+=2;
y=0.01*(-x*x) + (4*x) - (240);
END

IF(x==scroll[0].x0+160)
IF(i<20)
x=scroll[0].x0+160;
i++;
ELSE
x=scroll[0].x0+161;
END
END

IF(x>scroll[0].x0+160)
size-=1;
x+=2;
y=0.01*(-x*x) + (4*x) - (240);
END

IF(x>scroll[0].x0+320)
BREAK;
END

       FRAME;
END
END

No entiendo lo que falla. En la ejecución se me ejecuta "bien" pero sólo en los primeros 320x240 y no sale mas. No lo entiendo, ya que en todas las líneas le pongo referente al scroll... He probado casi de todo y nada de nada.

Supongo que es culpa de la función ya que tiene unos valores (x,y) que van desde (73,0) hasta (326,0). Pero si en todo momento le digo que coja las x referente al scroll no me cuadra el porque solo sale en este intervalo.

No se si me he explicado bien.

DCelso

mira, te he hecho un ejemplo para que veas como funciona start_scroll, region y como poner las coordenadas relativas al scrooll.

import "mod_map"
import "mod_key"
import "mod_video"
import "mod_proc"
import "mod_math"
import "mod_screen"
import "mod_scroll"
import "mod_text"
import "mod_draw"

global
MAX_X =1000;
map;
end

/*
ini_x          <- posicion x en pantalla inicial
ini_y          <- posicion y en pantalla inicial
float amplitud <- amplitud en pixeles en la que oscilará el seno, pej 200, 200 pixeles hacia arriba y 200 pixeles hacia abajo
int frecuencia <- la frecuencia a la que se vuelve a repetir un valor en y. a mayor frecuencia antes se repite el valor en y.
*/
process seno(ini_x,ini_y, float amplitud, int frecuencia)
private
float var_x;
float var_y;
int vel_x = 2;

begin
write_var(0,700,20,0,x);
write_var(0,700,40,0,y);

// esto hace que solo se dibuje en un scrool
ctype = c_scroll;

// esto hace que el scrool se mueva con este proceso
Scroll.camera = id; // elimina esta línea para ver que el seno se dibuja en las coordenadas del scrool.

region =1;
var_x  = 0;
graph = new_map(16,16,32);
map_clear(0,graph,RGB(255,0,0));
while (!key(_esc) )
var_x+=vel_x;
var_y = amplitud*sin(var_x*frecuencia);
x = ini_x + var_x;
y = (ini_y + var_y);
if (x >= MAX_X)
  break;
end
Frame;
end
unload_map(0,graph);
end
begin
set_mode(800,600,32);
region_define ( 1 , 20 , 20,640,480);
map = new_map(MAX_X,480,32);
    map_clear(0,map,RGB(240,240,240));
drawing_color(RGB(0,0,250));
drawing_map(0,map);
draw_box(200,200,670,280);
    // Start a new scroll
    // scrollNumber = 0
    // fileID = 0
    // foregroundGraphID = map
    // backgroundGraphID = 0: no background
    // region = 0: use entire screen
    // lockindicator = 0: don't repeat graphics
    start_scroll(0,0,map,0,1,0);
seno(0,240,240,1000);

while (!key(_esc))
frame;
end;
let_me_alone();
unload_map(0,map);
end
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

NesKy

Si, lo que dices lo tengo mas o menos claro. Lo que pasa que en mi caso, el scroll.camera lo tengo sobre un proceso que no tiene imagen ni nada, solo se mueve hacia la derecha a una velocidad dada por su único parámetro.

El problema viene cuando quiero hacer aparecer el proceso nave(), que es un ovni, y que tiene que seguir la función antes descrita. No sé como se tendria que hace para que hiciera el mismo trayecto que el ejemplo que he colgado pero con las coordenadas relativas al scroll.

Es un poco complicado de explicar jaja.

Drumpi

Sustituye en la fórmula todas las X por (x+scroll[0].x0), ya que la coordenada superior izquierda cambia de valor a cada frame, no vale siempre 0 sino scroll[0].x0, por lo que tienes que desplazar la posición horizontal de la curva.

Una de las cosas que se aprende programando es que una cosa es lo que ve el jugador y otra muy distinta lo que ve el ordenador, que suele esconder información o alterarla.
Para un juego de naves, por ejemplo, se puede hacer que el scroll sea automático, pero las naves siempre se mueven de forma independiente al mismo, por lo que no necesitas que estén en el scroll. Caso especial pueden ser las torretas que sí se muevan con el scroll, pero collision no distingue si un proceso está en el scroll y otro no, sólo entiende de superposición.

Hace poco hice un matamarcianos (nivel 2 de Screen Break Time), si miras el código, los procesos que controlan los escuadrones no se basa en el scroll de fondo, ni las naves, ni nada: el scroll es sólo un fondo, la "nave" no se mueve de la pantalla ;)
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)