Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Posiciones relativas aldededor de un sprite rotando

Iniciado por Pitxardo, 15 de Abril de 2007, 05:51:04 PM

« anterior - próximo »

Pitxardo

Buenas, tengo un problema trigonometrico que no consigo resolver, y seguro que alguno de vosotros lo ha logrado, ya que es algo muy visto en los juegos 2D.

Mi problema es el siguiente, tengo dos sprites, uno hace como de "padre" del otro. Seria algo asi.



Mas o menos, no es que sea gran cosa el dibujo, pero bueno...  :P
Los sprites es lo de color negro, y los recuadros azules es la region del sprite.

Supones que el padre mide 200x200, esta en la posicion (0,0), tiene 0 grados de rotacion y es la raya esa.
Por otro lado el hijo mide 30x30, esta en la posicion (120,0), tiene 0 grados de rotacion y es la bola negra con dos rayitas.

Si el padre se mueve a la posicion (50,20), entonces el hijo estara en la (170,20). Es decir, comparten la misma posicion X/Y en pantalla, pero el hijo tiene un desplazamiento relativo de 120 hacia la derecha del padre.

Hasta aqui todo bien, ahora viene el problema. Rotamos al padre, 45 grados (por ejemplo).



Ahora los nuevos valores son:
El padre mide 200x200, esta en la posicion (0,0), tiene 45 grados de rotacion y es la raya esa.
El hijo mide 30x30, esta en la posicion (120,0), tiene 0 grados de rotacion y es la bola negra con dos rayitas.

El caso, esque la bola negra con dos rayitas que hace de hijo deberia de ir "pegada" en la puntita de la raya del padre, es decir, ahora mismo deberia de estar en esta posicion:



Pues la pregunta es: Como descubro cuales son las coordenadas XY de ese lugar para que el hijo gire alrededor del padre? (no para el caso de los 45 grados, si no para cualquier angulo que tome el padre)

Algunos datos: tenemos las posiciones X e Y centrales de ambos sprites, y los º de rotacion de ambos. Tambien decir que lo estoy programando con SDL_gfx (aunque mas bien es un asunto trigonometrico universal que valdria para cualquier libreria/lenguaje).

Muchas gracias, espero a ver sido claro  :roll:

_Grey

Lo mio no son las mates, pero este tema lo he tocado un poco, a ver si te puedo ayudar.

Veamos el siguiente codigo:

int x=10,y=0;
int nx=0,ny=0;
float rot=3.1415f;

nx=(x * cos(rot) - y * sin(rot));
ny=(x * sin(rot) + y * cos(rot));

cout << "x: " << x << " y: " << y << endl;
cout << "rot: " << rot << endl;
cout << "nx: " << nx << " ny: " << ny << endl;


Este programilla te mostrada las coordenadas (10,0) rotadas 180º;
x e y,  son las coordenadas del punto a rotar,nx y ny, son las coordenadas del punto rotado, rot es el angulo de rotacion;
lo de enmedio es la formula usada para rotar las coordenadas, y el final es solo para mostrar el resultado.

Pruebalo y en seguida lo veras.

Tienes que tener en cuenta algunas cosas, esta rotacion es siempre sobre un punto central, que estaria situado en (0,0), Si quieres rotar sobre otro centro, simplemente tendras que desplazar las coordenadas, en tu ejemplo seria sumar las coordenadas resultantes de la rotacion a la posicion del sprite "padre".

Estas funciones de la libretia matematica de C/C++ (sin(), cos()) USAN RADIANES NO GRADOS, una vuelta completa, 360º, seria pi*2, 180º, seria pi, y 90º seria pi/2.

A partir de ahi, deberias tener en cuenta tu sistema de coordenadas 2D, segun sea, la rotacion sera en el sentido de las agujas del reloj, o a la inversa.

Espero haberlo dicho bien... saludos.

Pitxardo

Muchisimas Gracias _Grey!!!!  :D

Era tal y como decias, solo he tenido que hacer una pequeña conversion de decimales a radianes y poner el angulo negativo.

La cosa ha quedado tal que asi:

   float pi=3.141592f;
   float angle=gira*pi/180;
   x = xx + (cos(-angle)*posx - sin(-angle)*posy);
   y = yy + (sin(-angle)*posx + cos(-angle)*posy);

   posicion.x = x - camx;
   posicion.y = y - camy;


x e y son las posiciones del sprite, xx e yy son las del padre, posx y posy las relativas y gira el angulo en decimales del padre.

Ahora funciona todo perfecto ;)

tamat

En 3d se usan matrices para eso. La idea es que el hijo está en coordenadas de padre, si el padre se modifica el hijo se modifica tambien, y cuando vas a pintar lo que haces es convertir las coordenadas locales a coordenadas de mundo (que es lo que tu preguntabas).

Con una matriz simplemente multiplicas el vertice a transformar por la matriz y el resultado es el vertice en coordenadas de mundo.

Lo bueno de usar matrices es que engloban las tres transformaciones básicas que puede recibir un objeto, que son rotacion, traslacion y escalado.

Puede que te  suene a chino pero no está mal que te vayas familiarizando con el concepto.

Por otra parte tu problema era un problema básico de trigonometria y la trigonometria es algo que cualquier programador de videojuegos tiene que tener muy por la mano, te recomiendo que le des un repasillo al capitulo de la wikipedia al respecto.
Por un stratos menos tenso

fjfnaranjo

Cita de: "tamat"Lo bueno de usar matrices es que engloban las tres transformaciones básicas que puede recibir un objeto, que son rotacion, traslacion y escalado.

Y no nos olvidemos de lo ULTRA caras que son las operaciones trigonométricas (cos, sin, tan) en lo que a tiempo de procesador se refiere ;)
fjfnaranjo.com - Creating entertainment - Creando entretenimiento
fjfnaranjo [4t] gm4il [d0t] c0m (mail y msn)

TrOnTxU

Cita de: "fjfnaranjo"
Cita de: "tamat"Lo bueno de usar matrices es que engloban las tres transformaciones básicas que puede recibir un objeto, que son rotacion, traslacion y escalado.

Y no nos olvidemos de lo ULTRA caras que son las operaciones trigonométricas (cos, sin, tan) en lo que a tiempo de procesador se refiere ;)

No entiendo tu puntualización. Para construir las matrices de rotación a partir de un angulo (Euler) hay que realizar las mismas operaciones trigonométricas (sin y cos).

Si lo que quieres es velocidad mi recomendación es que decidas cuantas particiones (secciones) de la circunferencia quieres crear (por ejemplo 360 como los grados), luego creas dos arrays con el tamaño de esas particones y precalculas senos y cosenos. Para acceder solo tienes que buscar en la posición del array los valores que quieres.

Por otra parte, puedes ahorrarte espacio y ver las relaciones entre senos y cosenos y los grados o radianes. Quiero decir que da lo mismo seno de 0 que cos de pi, etc. Puedes un solo array con pocos valores y hacer una funcion para cada "funcion trigonometrica" que busque el valor adecuado en el array. Esto se llaman tablas precalculadas.

Un saludo.
Vicent: Linked-In  ***  ¡¡Ya tengo blog!!

sés

Si lo único que quieres es tener un hijo girando alrededor del padre a una distancia de 120:

xHijo = xPadre + 120 * cos( ang );
yHijo = yPadre + 120 * sin( ang );


Para coordenadas de pantallas, sólo cambia lo que ya sabes:
yHijo = yPadre - 120 * sin( ang );
Soy indeciso... ¿o no?

sés

Lo de utilizar una tabla sería algo así:

Para crearla:
float sintable[450];
for( int i=0; i<450; i++ ) sintable[i] =  sin( i * PI / 180.0 );


Para usarla:
xHijo = xPadre + 120 * sintable[ang+90];
yHijo = yPadre - 120 * sintable[ang];


Fíjate que ahora los ángulos están en grados.


Hay más formas de crear estas tablas, date una vuelta por Google.
Soy indeciso... ¿o no?

killrazor

Si quereis optimizar el uso de sin y cos, lo podeis hacer siempre que conozcais la rotacion del padre. Imaginad que teneis la posicion inicial y el angulo de rotacion (por ejemplo, a cada tiempo t lo giramos 5 grados). Lo unico que debemos hacer el crear un vector de 360/5 posiciones y calcular el sin y el cos de tdos los angulos.

Upps el ultimo mensaje dice lo mismo que yo!!!! sorry!!

Pitxardo

Bueno, el juego sera en 2D y ya he implementado todo lo necesario respecto a este tema. De todos modos gracias a todos por las respuestas  :D

Lo que si que es cierto es que quizas haga la tabla esa. Aunque la cantidad final de objetos que muestro en pantalla no hace que se cargue mucho el proceso de calculos de angulos (son unos 6 padres con 5 hijos cada uno), quizas en ordenadores mas lentos podria ser un problema, y una bajada de framerate muy seria.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.