elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Guía rápida para descarga de herramientas gratuitas de seguridad y desinfección


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  Java
| | | |-+  Necesito una mano para calcular distancias XY
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Necesito una mano para calcular distancias XY  (Leído 6,182 veces)
WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Necesito una mano para calcular distancias XY
« en: 23 Octubre 2016, 00:57 am »

Hola, tengo una duda, me he dado muchas vueltas y no llego a puerto aun.

Tengo un plano de 100x100, tengo un objeto en la posición 30x30, ¿cómo lo puedo mover de posición x cantidad de espacios usando un grado de inclinación?.

Por ejemplo, quiero moverlo en dirección hacia arriba y a la derecha en 45 grados.

El problema central es el siguiente: Tengo un circulo y un objeto que se mueve al rededor de el en su superficie, ambos objetos se mueven de manera independiente pero necesito que el objeto se mueva de manera que simule estar unido al borde del circulo, despues de esto tengo una función que debiera aumentar la separación entre el circulo y el objeto sin perder la sincronización de rotación ya que este circulo va rotando en una dirección al azar (ccw o cw).

Actualmente hice sin problemas que el objeto esté centrado con respecto al circulo y que este rote en la misma velocidad del circulo usando su base y no su centro, ahora solo necesito establecer su distancia, pero esta distancia esta relacionada con la cantidad de grados de rotación del objeto y ahi es donde quedé.

Hice este post en programación general porque no necesito que me hagan el código, quiero entenderlo para aplicarlo en muchas situaciones. De todas maneras este es el código que uso para hacer rotar el objeto sobre el circulo:

Código
  1. // Cambia el tamaño
  2.        this.matrix.setScale(1, 1);
  3.  
  4.        // Rota la imagen a partir de su centro
  5.        this.matrix.postRotate(this.angle, this.image.getWidth() / 2, this.image.getHeight());
  6.  
  7.        // Posiciona la nave al centro del circulo
  8.        this.matrix.postTranslate(
  9.                this.start_circle.getLeft() + (this.start_circle.getWidth() / 2) - (this.image.getWidth() / 2),
  10.                this.start_circle.getTop() + (this.start_circle.getHeight() / 2) - this.image.getHeight()
  11.        );

Es código Java para Android + canvas.

Una solución que encontré fue tomar el punto de rotación vertical muy abajo, para que simulara la rotación sobre un circulo, pero esto significaba que a la posición final tenía que restarle pixeles y cuando tenia que mover el objeto se me hacia todo un desmadre incontrolable y para solucionarlo tenía que crear condicionales para saber si el opbjeto estaba rotando o habia que aumentar el espacio y tenia un código muy mal optimizado, asi que lo eliminé y ando en busca de algo mas óptimo.

El tema debiera quedar algo así:

  • Si el grado es 0 entonces se suma la distancia el 100% sobre vertical
  • Si el grado es 45 entonces se suma la distancia el 50% sobre vertical y 50% horizontal
  • Si el grado es 90 entonces se suma la distancia el 100% sobre horizontal
  • si el grado es 135 entonces se suma la distancia el 50% horizontal y se resta el 50% vertical
  • si el grado es 180 entonces se resta la distancia el 100% vertical
  • si el grado es 225 entonces se resta la distancia el 50% sobre vertical y 50% horizontal
  • si el grado es 270 entonces se resta la distancia 100% sobre horizontal
  • Si el grado es 315 entonces se resta la distancia 50% sobre horizontal y se suma 50% sobre vertical
  • Si el grado es 360 entonces se suma la distancia el 100% sobre vertical

Saludos.


« Última modificación: 23 Octubre 2016, 01:12 am por WHK » En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Necesito una mano para calcular distancias XY
« Respuesta #1 en: 23 Octubre 2016, 01:44 am »

no estoy muy seguro que quieres hacer, podrías dibujar algo para hacerlo más visual

primero para mover un objeto con respecto a un angulo usas seno y coseno
Código:
x += sin(alfa)*escalar
y += cos(alfa)*escalar


para simular un movimiento circular esas esto en base al angulo del circulo, aunque como es un movimiento uniforme puedes simplemente calcular la inclinación como movimiento


fijate este ejemplo, está en "java" (para processing) lo puedes pegar y ejecutar aquí

Código
  1. class Circulo { //clase circulo... no importa para esto, simplemente dibuja en pantalla
  2.  float y, x, size;
  3.  color c;
  4.  
  5.  Circulo(float nx, float ny, float ns, int r, int g, int b) {  
  6.    y = ny;
  7.    x = nx;
  8.    size = ns;
  9.    c = color(r,g,b);
  10.  }
  11.  void update() {
  12.    fill(c)
  13.    ellipse(x, y, size, size);
  14.  }
  15. }
  16.  
  17. Circulo base, satelite;
  18. float alfa= 0;
  19.  
  20. void setup() {//tampoco importa, solo da las condiciones iniciales
  21.  size(500, 500);
  22.  smooth();
  23.  noStroke();
  24.  base = new Circulo(0,0,100, 255,255,0); //aqui se crea el circulo en (0,0) y diametro 100
  25.  satelite = new Circulo(150,200,20,0,0,255);//aqui el otro objeto diametro 20
  26. }
  27.  
  28. void draw()
  29. {
  30.  
  31.  background(0,0,0);
  32.  satelite.x = base.x + sin(alfa)*base.size/2 ;
  33.  //el objeto se coloca en el x de la base, y se le suma el angulo  por el radio
  34.  satelite.y = base.y + cos(alfa)*base.size/2;
  35.  //lo mismo en y
  36.  
  37.  base.x += 0.1;//muevo el circulo para observar como el satelite acompaña
  38.  base.y += 0.1;
  39.  
  40.  base.update();
  41.  satelite.update();
  42.  alfa += 0.03;//cambio 0.03 grados por frame
  43.  alfa %= 360; // limito a 360 grados
  44. }
  45.  


En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Re: Necesito una mano para calcular distancias XY
« Respuesta #2 en: 23 Octubre 2016, 01:46 am »

Muchas gracias, probaré lo de cos y sin.
En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Necesito una mano para calcular distancias XY
« Respuesta #3 en: 23 Octubre 2016, 01:48 am »

creo que es lo más optimo y no consume casi procesador actualmente (a menos que lo hagas miles de veces por frame)
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Re: Necesito una mano para calcular distancias XY
« Respuesta #4 en: 23 Octubre 2016, 04:24 am »

Muy bien!, ahora me toca ajustar la relación entre grados y el alpha que se le asignó, porque si le paso como alpha directamente el angulo, rota muy rápido, por ejemplo mi circulo rota 360 grados cada 5 segundos aprox y el valor del alpha que se ajusta perfectamente es 0.022, asi que tocará ajustar eso que no creo que sea tan dificil.

Por lo menos lo que me tenía mas preocupado funciona de lujo.

Código
  1. float alfa= 360;
  2.  
  3.    @Override
  4.    public synchronized void update() {
  5.        super.update();
  6.  
  7.        // Control de frames
  8.        if (last_millisecond == null) {
  9.            this.last_millisecond = Calendar.getInstance().getTimeInMillis();
  10.        }
  11.  
  12.        Long current_millisecond = Calendar.getInstance().getTimeInMillis();
  13.        Long diff_millisecond = current_millisecond - this.last_millisecond;
  14.        this.last_millisecond = current_millisecond;
  15.  
  16.        // Contexto
  17.        if(!this.launched) {
  18.            this.angle = this.angle + (diff_millisecond / 10);
  19.            this.angle = (this.angle % 360); // Previene el desbordamiento
  20.        }else{
  21.            this.diameter_rotation_ship = this.diameter_rotation_ship + (diff_millisecond / 12);
  22.        }
  23.  
  24.        // Controlador
  25.  
  26.        // Cambia el tamaño
  27.        this.matrix.setScale(1, 1);
  28.  
  29.        // Rota la imagen a partir de su centro
  30.        this.matrix.postRotate(this.angle, this.image.getWidth() / 2, this.image.getHeight());
  31.  
  32.        // Posiciona el objeto al centro del circulo
  33.        this.matrix.postTranslate(
  34.                this.start_circle.getLeft() + (this.start_circle.getWidth() / 2) - (this.image.getWidth() / 2) +
  35.                        (((Double)Math.sin(alfa)).floatValue() * (this.start_circle.getWidth() / 2)),
  36.                this.start_circle.getTop() + (this.start_circle.getHeight() / 2) - this.image.getHeight() +
  37.                        (((Double)Math.cos(alfa)).floatValue() * (this.start_circle.getHeight() / 2))
  38.        );
  39.  
  40.        /*
  41.         this.matrix.postTranslate(
  42.                 this.start_circle.getLeft() + (((Double)Math.sin(alfa)).floatValue() * (this.start_circle.getWidth() / 2)),
  43.                 this.start_circle.getTop() + (((Double)Math.cos(alfa)).floatValue() * (this.start_circle.getHeight() / 2))
  44.         );
  45.         */
  46.  
  47.        alfa -= 0.022;//cambio 0.03 grados por frame
  48.        alfa %= 360; // limito a 360 grados
  49.        if(alfa == 0)
  50.            alfa = 360;
  51.    }
« Última modificación: 23 Octubre 2016, 04:26 am por WHK » En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Necesito una mano para calcular distancias XY
« Respuesta #5 en: 23 Octubre 2016, 04:36 am »

si quieres una vuelta cada 5 segundos sin importar el framerate, puedes hacerlo con el diff_millisecond (esto sería el diferencial de tiempo sobre update)

Código:
alfa = diff_millisecond * 360/5000 

360/5000 es la cantidad de grados que debe avanzar por milisegundo para mantenerse al ritmo.... al multiplicarlo por diff_millisecond, lo multiplicas por la cantidad de milisegundos avanzados desde la ultima vez... esta tecnica se usa para mantener sincronia en perdida de fps :P


por curiosidad, que haces?
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Re: Necesito una mano para calcular distancias XY
« Respuesta #6 en: 23 Octubre 2016, 18:04 pm »

jajajaja pues si, tenía varias opciones para controlar los fps, al comienzo solo sabia manejar animaciones en base al while del update del canvas, pero con el tiempo me di cuenta que la velocidad del while era diferente en diferentes dispositivos, en el pc era rápido, en el movil era mas lento y no siempre era una velocidad constante, a veces la velocidad variaba de muy rápido a muy lento o a veces producía pequeños cortes, entonces como el audio se desincronizaba con la animación se me vino la pregunta de como corregir esto:

Una opción era enviar el numero del frame al controlador para que la animación y la pista de audio se sincronizara en base a la velocidad del frame, pero despues de esto tuve otro problema, este problema consistia en que cuando se bloqueaba la app por un tiempo muy corto (menos de un segundo) tanto la animación como el juego se cortaban, entonces cuando el lagg era muy grande la animación se veia muy cortado y los controles ya no funcionaban bien porque para terminar una acción con un botón tenias que mantenerlos sostenido o perdias la acción. Despues me di cuenta que este tipo de desface tambien lo sufrian la mayoría de los juegos de videos antiguos como los de ps1, snes, emuladores, etc, y ahi me di cuenta que todos esos juegos viejos se basan en la sincronización por frames.

Cuando me pasó eso me di cuenta que los juegos de hoy no sucede eso, por ejemplo si la animación se está ejecutando y hay lagg entonces el desface hace que por ejemplo si lanzas una pelota y a mitad de camino se bloquea la app lo verás al final del camino cuando se desbloquee, eso quiere decir que la sincronización ya no depende del frame sino del tiempo, a diferencia de la sincronización por frame que cuando se desbloquea la app ahi recien se ve la siguiente posicion de la pelota.

Me di cuenta que esto solucionaría el problema del desface del audio ya que a pesar de que la animación se bloquee este no impide que la animación se siga sincronizando con el audio, a demás permite que pequeños lags no afecte a la experiencia final del juego ya que podrás seguir jugando a la velocidad que acostumbras a pesar de que dejes de ver un par de frames.

Por eso se me ocurrió calcular la diferencia del tiempo en milisegundos y en base a eso calcular la siguiente posición del dibujado del canvas, de esa manera no limito la animación a x cantidad de frames por segundo sino que en ves de eso en cada frame la app calculará la posición y la posicionará donde debe ir, de otra manera si el juego se sincroniza por frames y tiempos (frameskip) hará que un juego diseñado a 60fps no se vea a mayor velocidad en dispositivos con una taza de refresco mas alta, pero de esta manera la animación se adapta a la taza de animación soportada por el hardware y le da una mejor experiencia al usuario final.

Realmente no lo leí de otros lados, lo saqué en base a conclusiones solamente.

Estoy creando un motor de animación en android con físicas, un framework para crear cosas como juegos, animaciones tipo power point, presentación de documentos, animaciones en general de todo tipo, quiero hacer algo como unity 3d pero en lenguaje nativo usando librerías en ves de embeber una app dentro de otra, esto hará que el motor sea mucho mas optimizado que unity y las animaciones sean mucho mas fluidas ya que no necesitarás embeber un sistema en mono (c#) utilizando la interpretación de la interpretación de un código, sino de manera nativa directamente sin una interfaz gráfica, solamente utilizando código. Mas que nada para facilitar el uso de animaciones en apps incluyendo físicas. Como ejemplo estoy probando crear la animación de un cohete despegando de planeta en planeta.
En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Necesito una mano para calcular distancias XY
« Respuesta #7 en: 23 Octubre 2016, 18:09 pm »

@.@ y lo estás haciendo a mano, no usas ningún framework... por lo menos para C++ hay un framework genial que puedes compilar para android (y pc), se llama openframeworks
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
WHK
Moderador Global
***
Desconectado Desconectado

Mensajes: 6.589


Sin conocimiento no hay espíritu


Ver Perfil WWW
Re: Necesito una mano para calcular distancias XY
« Respuesta #8 en: 23 Octubre 2016, 19:43 pm »

Finalmente quedó así:

Código
  1. /**
  2.      * Actualiza la posición de los objetos
  3.      */
  4.    @Override
  5.    public synchronized void update() {
  6.        super.update();
  7.  
  8.        /**
  9.          * Control de frames.
  10.          * Controla los frames dependiendo del tiempo transcurrido,
  11.          * esto prefieve en desface por lagg.
  12.          */
  13.        if (last_millisecond == null) {
  14.            this.last_millisecond = Calendar.getInstance().getTimeInMillis();
  15.        }
  16.  
  17.        Long current_millisecond = Calendar.getInstance().getTimeInMillis();
  18.        Long diff_millisecond = current_millisecond - this.last_millisecond;
  19.        this.last_millisecond = current_millisecond;
  20.  
  21.  
  22.        /**
  23.          * Contexto.
  24.          * Calcula el grado de inclinación de los objetos y todo aquello
  25.          * que sea necesario para calcular distancias y posicionamiento.
  26.          */
  27.        if(!this.launched) {
  28.            // CW o CCW
  29.            if(clock_wise) {
  30.                this.angle += (diff_millisecond / 10);
  31.            }else{
  32.                this.angle -= (diff_millisecond / 10);
  33.            }
  34.            // Previene el desbordamiento
  35.            this.angle = (this.angle % 360);
  36.        }else{
  37.            this.diameter_rotation_ship = this.diameter_rotation_ship + (diff_millisecond / 12);
  38.        }
  39.  
  40.  
  41.        /**
  42.          * Controlador.
  43.          * Controla el posicionamiento de los objetos para ser dibujado.
  44.          */
  45.  
  46.        // Cambia el tamaño
  47.        this.matrix.setScale(1, 1);
  48.  
  49.        // Rota la imagen a partir de su centro
  50.        this.matrix.postRotate(this.angle, this.image.getWidth() / 2, this.image.getHeight());
  51.  
  52.        // % del angulo de 0 a 360
  53.        Float angle_percent = ((this.angle * 100.0F) / 360);
  54.  
  55.        // -3.1 a 3.1
  56.        Float alpha = -(((6.2F * angle_percent) / 100.0F) - 3.1F);
  57.  
  58.        // Posiciona el objeto al centro del circulo
  59.        this.matrix.postTranslate(
  60.                this.start_circle.getLeft() + (this.start_circle.getWidth() / 2) - (this.image.getWidth() / 2) +
  61.                        (((Double)Math.sin(alpha)).floatValue() * (this.start_circle.getWidth() / 2)),
  62.                this.start_circle.getTop() + (this.start_circle.getHeight() / 2) - this.image.getHeight() +
  63.                        (((Double)Math.cos(alpha)).floatValue() * (this.start_circle.getHeight() / 2))
  64.        );
  65.    }

Le agregué la opción para rotar en sentido contrario cuando sea necesario.

Me di cuenta que la función cos y sin no inician directamente desde el grado 0 al 360 sino que utiliza valores mas extraños, por ejemplo el valor de alpha del 0 al 6.2 da una vuelta en 360 grados pero este inicia a partir de un costado y no desde el grado cero que es la parte superior central del circulo, por lo cual calculé que la posición de grado cero es 3.1 y para 360 es -3.1, por lo cual 180 grados son 0 en alpha, asi que lo que hice sin tener que utilizar el valor del tiempo dle frame como en el ejemplo que me diste, me basé mejor en el grado de inclinación haciendo que sea mas fluido para cualquier cantidad de fps, entonces tomé el porcentaje de 0 a 360 y me dió un valor, luego de 0 a 6.2 le saqué el valor de ese porcentaje y luego le resté 3.1 para que volviera otraves de 3.1 a -3.1 y listo! :D me anda de lujo en el pc y en el movil.



Muchas gracias por la ayuda.

Saludos.
« Última modificación: 23 Octubre 2016, 20:00 pm por WHK » En línea

engel lex
Moderador Global
***
Desconectado Desconectado

Mensajes: 15.514



Ver Perfil
Re: Necesito una mano para calcular distancias XY
« Respuesta #9 en: 23 Octubre 2016, 20:04 pm »

no está en sexagesimale, sino en radian XD casualmente media vuelta era 3.1416 grados cuando un circulo tiene incluso 2 pi de perimetro jejeje

hombre te has dado cuenta de detalles base de la ciencia rapido jejeje, en poco seguro das con turing u otro teorema de otra ciencia XD

exito con el programa ;)
En línea

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.
Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines