Hola. Vamos a ver....
Tenemos una nave espacial que tiene la facultad de disparar 2 laser uno a cada lado. O sea:
laser(x+10,y-50,angle);
laser(x-10,y-50,angle);
Está bastante claro el tema. Pero si ahora hacemos que el ángulo de la nave sea modificado..
angle-=1000;
... y disparamos, pues es obvio que la cosa no funciona bien. Tenemos que usar trigonometría y concretamente seno y coseno o mejor aún get_distx y get_disty:
laser(x+get_distx(angle+90000,10),y+get_disty(angle,50),angle);
laser(x+get_distx(angle-90000,10),y+get_disty(angle,50),angle);
Pero esto solo funciona bien cuando estamos en angulos 90000 y -90000. Conforme nos alejamos de esos dos ángulos la cosa se estropea. Y a partir de aquí ya no se seguir ya que la trigonometría nunca fue mi fuerte :P. Por algún motivo, los dos laser no se mantienen separados los 20 pixels originales y se van juntando poco a poco conforme la nave gira.
A ver si alguien puede arrojar algo de luz sobre los cálculos necesarios a hacer para mantener los dos laser separados 20 pixels en cualquier ángulo que la nave pueda adquirir. Con un solo laser el problema estaría resuelto, pero con dos..... :P
laser1: advance 50
laser2: angle = laser1.angle, x = laser1.x, y = laser1.y, advance 50
edit: ahhh, vos decis 2 laser en los costados de la nave... a ver como seria.
yo pondria en la nave 2 puntos de control. uno en donde esta el cañon 1 y otro en el cañon 2... luego usas get_real_point de cada uno de los puntos de control mencionados, y ahi tenes exactamente la posicion de cada laser.
luego para mover el disparo de dichos laser usas advance.
Si SplinterGu, claro que con dos puntos de control lo haríamos pero....Y sin ellos ?
Yo creo que sería interesante conocer el procedimiento a seguir para hacerlo solamente por medio de trigonometría. De hecho creo que ese procedimiento nos serviría para hacer otras muchas cosas aparentemente complejas.
Bueno, en ese caso necesitamos calcular la diferencia de ángulo y la distancia a la que se genera cada disparo (lo que se llama un cambio de coordenadas cartesianas a polares):
Vamos a suponer que tu nave mira hacia la derecha, y que la coordenada (0,0) es el centro de la misma. Bien, tus disparos se generan en las coordenadas (50,-10) y (50,10).
Bien, entonces tendríamos que averiguar el ángulo respecto a la nave. Aquí interviene la arcotangente:
atan(10/50)=11º
Vale, calculemos la distancia:
sqrt(50^2 + 10^2)=51 pixels.
Así que cada disparo aparece a una distancia de 51 pixels a +-11º, así que tus llamadas quedarían así:
laser(x+51*cos(angle+11000),y+51*sin(angle+11000),angle);
laser(x+51*cos(angle-11000),y+51*sin(angle-11000),angle);
El ángulo de salida sería el mismo que el de la nave.
Si no he cometido ningún error, los disparos deberían salir en el sitio indicado independientemente del ángulo. De todas maneras, habría que mirarlo porque es muy tarde y mi cabeza a estas horas no carbura como debería ^^U. También habría que corregir los errores de truncamiento (el ordenador se come los decimales), así que es posible que la distancia o el ángulo sean ligeramente superiores a los calculados.
El que diga que no se necesitan matemáticas en la informática, es que no las ha estudiado en su vida :D :D :D
deberias hacer lo mismo que se hace para obtener el real_point y listo.
wow. Estupendas explicaciones !
Y desde luego las matemáticas son necesarias para todo. Eso lo tengo bien claro.
Por fin veo un ejemplo de como usar el ATAN.
Trataré hoy de probar esos cálculos matemáticos con arco-tangente para ver como funciona.
No obstante que quiere decir el termino 'coordenadas polares', podrías explicarlo ?
gracias
Es un sistema coordenado distinto al cartesiano, donde dejamos de lado x e y teniendo en su lugar un ángulo y una magnitud
la forma general de la expresión de drumpi sería:
laser(x+D*cos(angle+r),y+D*sin(angle+r),angle);
laser(x-D*cos(angle+r),y-D*sin(angle+r),angle);
D=Distancia inicia, al Padre
x=Coordenada x del padre
y=Coordenada y del padre
angle=ángulo del padre
r=reajuste del ángulo del padre (para colocarlo en cualquier posición de la nave)
dentro de laser tendrías lo siguiente:
process laser(x,y,angle)
begin
loop
advance(..)
...
end
end
pd: quizá necesites usar resolution o flotantes para que no se te trunquen los valores... saludos :)
Quote from: SplinterGU on March 21, 2011, 01:49:42 AM
deberias hacer lo mismo que se hace para obtener el real_point y listo.
Obviamente, GET_REAL_POINT es lo más sencillo de usar, pero preguntaba por el método matemático, supongo que por si se da alguna situación en la que no se puedan usar puntos de control.
Quote from: rst on March 21, 2011, 12:58:21 PM
No obstante que quiere decir el termino 'coordenadas polares', podrías explicarlo ?
Como dice PRG, es una manera de indicar la posicion de un punto en el espacio.
Las coordenadas cartesianas son las que conoce todo el mundo: se usan dos ejes perpendiculares como referencia (los ejes de cartesianas, más conocidos como eje x y eje y) y se dan valores de ambos. En la vida real sería como usar las coordenadas de unGPS para indicar el sitio.
Las coordenadas polares se usan muchísimo más, pero nadie lo sabe. Se toma un punto de origen, y un eje que indique el ángulo 0º. Para definir un punto se indica un ángulo respecto al eje, y una distancia respecto al punto de origen. En la vida real es como no tener un mapa, señalar con el dedo y decir "el balneario está hacia allí, a 300 metros" ;D
Ya en 3D la cosa se complica bastante más :D :D :D
magníficas explicaciones amigos !
Por qué decís que se ha de usar resolution ?
http://wiki.bennugd.org/index.php?title=Resolution
:)
si, se usar resolution, pero decíais que puede ser necesario para evitar la truncación de no se que...
A mi tambien me gustaria saber exactamente que hace resolution, lo que entiendo hasta ahora es que le da mas "fidelidad" al proceso, tiene en cuenta mas valores decimales del float y sus movimientos son mas precisos.
las coordenadas x,y,z son numeros enteros, por ende no se pueden hacer incrementos/decrementos menores a 1, y puede que al trabajar con operaciones de avance o trigonometricas sobre las coordenadas, muchas veces den resultados menores a 1 o con decimales, por ende, resolution hace que todas las coordenadas se puedan trabajar con un factor determinado por resolution.
esto es, por ejemplo, que tenemos un resolution = 1000, entonces cada unidad de las coordenadas z, y o z, corresponderan a 1000 unidades... 1px real = 1000px con resolution, con lo cual nos permite trabajar como si tuviesemos 3 decimales.
podemos usar cualquier valor de resolution, resolution es una variable local, solo afecta al proceso que la define.
Truncar un valor es cuando se coje un valor con decimales... y le quitas los decimales.
Por ejemplo: 3'9 se redondea a 4, y es lo que se acepta mundialmente. Los ordenadores truncan 3'9 y hace que valga 3. Lo que era un error de 0'1 se convierte en un error de 0'9.
Y lo de resolution es lo que dice Splinter, hace que cada pixel, en lugar de valer una unidad, valga el valor que se le ponga. O sea: normalmente se avanza un pixel haciendo:
x=x+1;
pero con resolution=3 se avanza sólo si
x=x+3;
Si se usa x=x+1 se tardarán 3 frames en avanzar.
exacto, como bien ha dicho drumpi, aunque yo suguiero usar valores multiplos de 10, para no enredarse luego con los calculos.
o sea, que en este caso usamos resolution para hacer el tema menos sensible ?
me parece que al reves, resolution para tener mejor precision.
aunque insisto en que uses get_real_point.
Si lo quieres pensar de otra forma, resolution es el valor por el que se divide internamente X e Y a la hora de pintar un proceso en pantalla. Así, con resolution=100, si tu proceso está en (x=587,y=348), se dibujará en:
x=587/100=5'87---TRUNCANDO---> x=5
y=348/100=3'48---TRUNCANDO---> y=3
pero no perderás los valores que tenías antes.
es correcto lo que dice Drumpi, pero no solo dibujar, sino tambien para collisiones, advances, y cualquier otra operacion que trabaje con las coordenadas.
no olvides que trabajan sobre 3 coordenas, X, Y y Z.
lo que no se pierde es la parte decimal.
de una forma más sencilla imagina esto:
tienes un proceso que avanza un pixel de distancia cada frame:
advance(1),
x+=cos(angle) y+=sin(angle)
o
x+=get_distx(angle,1)
si el ángulo en que avanzará es 0, 90,180, 270 o 360 el proceso avanzará un pixel en ese ángulo, pero si el ángulo es distinto de estos valores entonces intentará avanzar una fracción de un pixel en x y otra en y, sin embargo usamos enteros para avanzar, por lo tanto intentará hacer algo como esto:
ángulo 45
cos(45)=sin(45)=0.7071
por lo que el proceso intentará avanzar 0.7071 en el eje x y .7071 en el eje, sin embargo sólo puede avanzar enteros y no solo eso, sólo puede almacenar en su variable local x e y enteros, por lo que no avanzará nada nunca.
Puedes hacer el experimento y verás que si el ángulo es distinto de algún múltiplo de 90000 (o cero) el proceso no avanzará.
Con resolution igual a 10, si el proceso intenta avanzar 0.09 no avanzará nunca, pero si intenta avanzar 0.1, al cabo de 10 intentos avanzará un pixel
con resolution de 100 se puede avanzar con 0.01 (después de 100 frames).
Espero no haber cometido errores, si es así corríjanme XD.
saludos :)