problema vectores, allegro.

Iniciado por MasterPunk, 4 Enero 2012, 16:11 PM

0 Miembros y 1 Visitante están viendo este tema.

MasterPunk

Hola, estoy haciendo un juego en c++ con allegro4 (no se lo suficiente de programación, pero así aprendo).

Estoy teniendo un problema al intentar mejorar una parte del codigo que pretendo que haga que el personaje del juego se mueve hacia donde hago clic con el raton en linea recta a velocidad constante.
Las variables posx y posy son la posicion actual del personaje en la pantalla, derx y dery almacenan las coordenadas del ultimo clic y la variable velocidad es la velocidad del personaje(cuanto menor sea la velocidad mas rapido irá).
Codigo antiguo:
Código (cpp) [Seleccionar]

while(...){
    contador++;

    if( derx!=0 && contador % velocidad == 0)  //en x
        if(posx!=derx) 
            if(posx<derx)
                posx+= 1;
            else
                posx-= 1;
    if( dery!=0 && contador % velocidad == 0)  //en y
        if(posy!=dery) 
            if(posy<dery)
                posy+= 1;
            else
            posy-= 1;
}



Con este codigo como podeis ver el recorrido del personaje no es el adecuado. Primero se mueve trazando un angulo de 45º y una vez que una de las coordenadas ha llegado se desplaza en la otra. =S no se como explicarlo pero creo que se entiende con el codigo.
Otro de los problemas de este codigo es que la velocidad con la que se mueve no es continua.

Por ello escribi este otro codigo:
Código (cpp) [Seleccionar]

distanciax = derx - posx;
distanciay = dery - posy;
float distancia = distanciax/distanciay;
       
if( derx!=0 && contador % (velocidad*(int)distancia) == 0) //en x
         if(posx!=derx)             
              posx += (int)distancia;
                   
if(dery!=0 && contador % velocidad == 0)  //en y
         if(posy!=dery) 
           if(posy<dery)
              posy+= 1;
           else
              posy-= 1;


Hasta ahi bien, el problema es que al ejecutarlo el programa deja de responder.

Me podeis echar una mano??
Gracias, MasterPunk

Kherom

¿El segundo código va dentro de un while? ¿Cuál es la condición de parada?

Así sin mirar mucho el programa no parece que hayas accedido a memoria que no debes por lo que lo normal es que se te cuelgue si entra en bucle infinito.

De todas formas no he hecho mucho caso al código por que me parece raro de cojones, ¿Por qué no te limitas a sumar a la posición un vector velocidad multiplicado por el tiempo entre frames?

MasterPunk

Cita de: Kherom en  6 Enero 2012, 17:18 PM
¿El segundo código va dentro de un while? ¿Cuál es la condición de parada?

Así sin mirar mucho el programa no parece que hayas accedido a memoria que no debes por lo que lo normal es que se te cuelgue si entra en bucle infinito.

De todas formas no he hecho mucho caso al código por que me parece raro de cojones, ¿Por qué no te limitas a sumar a la posición un vector velocidad multiplicado por el tiempo entre frames?

El segundo codigo va igual que el primero dentro de un while (!key[KEY_ESC]){...} para que el juego pare cuando se pulse Esc.
El personaje(posx, posy) para cuando llega a la posicion en la que pulsamos(derx, dery)

En este segundo codigo lo que intento es calcular la diferencia de distancia entre el personaje y el destino en el eje x y en el eje y, para calcular la proporcion en la que tienen que aumentar o disminuir las coordenadas del personaje para ir en la direccion correcta.

Aun llevo poco en el mundo de la programacion y esta es la primera vez que intento hacer algo parecido, asi que si sabes hacerlo mas sencillo dime como :P

SirLanceCC

distanciax = derx - posx;
distanciay = dery - posy;
float distancia = distanciax/distanciay;


Si dery y posy son iguales, al calcular distancia se produce una división entre cero y el programa termina.

Kherom

Lo que yo no entiendo es el por qué de esa división xD Lo lógico sería hacerlo al revés para obtener la tangente...

De todas formas a mí los floats nunca se me han quedado a cero exacto, aunque podría ser.

MasterPunk

#5
Cita de: SirLanceCC en  8 Enero 2012, 11:12 AM
distanciax = derx - posx;
distanciay = dery - posy;
float distancia = distanciax/distanciay;


Si dery y posy son iguales, al calcular distancia se produce una división entre cero y el programa termina.

Eso es! por eso terminaba el programa =D

Lo he arreglado pero la trayectoria del personaje no es la que esperaba TT.TT

Lo intentare plantear de otra manera, gracias Sir

Cita de: Kherom en  8 Enero 2012, 16:37 PM
Lo que yo no entiendo es el por qué de esa división xD Lo lógico sería hacerlo al revés para obtener la tangente...

De todas formas a mí los floats nunca se me han quedado a cero exacto, aunque podría ser.

Quizas es porque me pasaba las clases de trigonometria haciendo dibujitos en la mesa jajaja

Es broma, lo intentare plantear mejor. Gracias por la ayuda khenom.

Kherom

#6
A ver, sacas la tangente, de ahí el ángulo, con el ángulo y el módulo (módulo*cos ang y módulo*sen ang) sacas el vector velocidad y a partir de ahí haces la suma.

Con tu código lo si se mueve es pura casualidad xD

SirLanceCC

Nada de módulos ni cosenos, necesitas trabajar un poco más con vectores.

Tienes la posición de tu personaje en un vector P, y donde haces clic en otro vector D.
Para obtener un vector que vaya de P a D, resta D - P.
Ahora tienes un vector de un tamaño que puede ser cualquiera, para adaptarlo a tus necesidades lo conviertes en vector unitario, lo multiplicas por la velocidad deseada y le llamas V.
Para avanzar sumamos P += V.

Ahora bien, para calcular el vector unitario se divide X y Y entre la longitud del vector y si el vector mide cero estamos en las mismas (fuuuuuu!!!). Para arreglar eso definimos so un vector mide cero su vector unitario es (0,0). Cuando multipliques por la velocidad seguirá siendo (0,0) y cuando actualices P no cambiará su valor, pero de todos modos habrás llegado a tu destino.

Espero que sea de ayuda.

MasterPunk

Código (cpp) [Seleccionar]
      double tangente;
      if(posx != derx)
              tangente = dery - posy/derx - posx;
      else
              tangente = 10; //un valor maximo
      double angulo = atan(tangente);
     
     
      if(contador % velocidad_bacteria == 0){ //para que no se mueva demasiado rapido

                 posx += (int)(sin(angulo)*5);
                 posy += (int)(cos(angulo)*5);}


Pero con este codigo...

no se como trabajar con los doubles si los pixeles el numero de pixeles es entero... =S

MasterPunk

Cita de: SirLanceCC en  8 Enero 2012, 17:53 PM
Nada de módulos ni cosenos, necesitas trabajar un poco más con vectores.

Tienes la posición de tu personaje en un vector P, y donde haces clic en otro vector D.
Para obtener un vector que vaya de P a D, resta D - P.
Ahora tienes un vector de un tamaño que puede ser cualquiera, para adaptarlo a tus necesidades lo conviertes en vector unitario, lo multiplicas por la velocidad deseada y le llamas V.
Para avanzar sumamos P += V.

Ahora bien, para calcular el vector unitario se divide X y Y entre la longitud del vector y si el vector mide cero estamos en las mismas (fuuuuuu!!!). Para arreglar eso definimos so un vector mide cero su vector unitario es (0,0). Cuando multipliques por la velocidad seguirá siendo (0,0) y cuando actualices P no cambiará su valor, pero de todos modos habrás llegado a tu destino.

Espero que sea de ayuda.

Tienes razon, mejor trabajar con vectores que con 2 variables.
Sobre tu planteamiento...
El vector unitario tiene de modulo 1, por tanto el desplazamiento en x y en y va a ser menor de uno por cada frame, y no puedo desplazarme medios pixeles. Al pasarlo a int va a ser siempre 0. (si no me equivoco).