Karoshi MSX Community
05 de Julio de 2021, 03:54:49 pm *
Bienvenido(a), Visitante. Por favor, ingresa o regístrate.

Ingresar con nombre de usuario, contraseña y duración de la sesión
Noticias:
 
   Inicio   Ayuda Buscar Ingresar Registrarse  
Páginas: [1]
  Imprimir  
Autor Tema: Division con decimales  (Leído 5569 veces)
0 Usuarios y 1 Visitante están viendo este tema.
OKI09
Karoshi Maniac
****
Mensajes: 275



WWW Email
« : 21 de Mayo de 2009, 04:24:08 pm »

Hola a todos.

Estoy intentando calcular el incremento de x e y para mover un disparo por la pantalla desde unas coordenadas fijas hasta otras dadas por la x e y ocupadas por otro sprite, pero estoy atascado.

Me habian comentado sobre el algoritmo de Bresehan, pero creo que es mejor calcularlo por medio de incrementos, no creeis. (pero las divisiones con los decimales se me estan atragantando) Embarrassed

Hay alguna otra forma mas sencilla? Huh
En línea

La derrota no es una opción y no hay excusas.
"Parasiempre"
SapphiRe_MSX
Visitante
« Respuesta #1 : 21 de Mayo de 2009, 07:43:22 pm »

Estoy intentando calcular el incremento de x e y para mover un disparo por la pantalla desde unas coordenadas fijas hasta otras dadas por la x e y ocupadas por otro sprite, pero estoy atascado.

Veamos. El tema clave está en la pregunta "¿en cuántos pasos quieres que el disparo recorra su camino?". Lo mejor sería moverlo en un número de pasos que fuese potencia de dos, ya que como el Z80 no permite dividir fácilmente por otros números ya empezaríamos a liarla parda.

Partamos del hecho de que tienes un incremento IX y otro incremento IY (no confundir con los registros de igual nombre que pululan por el Z80). Supongamos, además, que quieres hacer 2^k pasos, por lo que tienes que dividir entre 2^k, lo que equivale a desplazar k veces hacia la derecha. Bien, la idea sería en cada uno de los 2^k pasos sumar el incremento (para cada coordenada) dividido por 2^K, con lo que al final del proceso el resultado será que se ha sumado el incremento total y el disparo llega a su destino.

¿Cómo tratar los decimales en el Z80? Con números de 16 bits. Pensemos que un número de 16 bits puede ser visto como un valor entre 0 y 65535 si lo vemos como un número entero, pero si pensamos que está formado por 8 bits de parte entera y 8 bits de parte decimal (8.8 para abreviar), entonces podremos representar un número entre 0 y 255+255/256. Realmente ambos casos son iguales, simplemente el segundo equivale a dividir por 256 el primero, nada más.

Así pues el procedimiento sería (pongo partes en pseudocódigo ya que ahora voy algo justo de tiempo):

Código:
ld h,incremento
ld l,0

así hl (visto como decimal 8.Cool contendría el incremento

Código:
rotar hl hacia la derecha k veces

obteniendo así el incremento dividido por 2^k en hl

Código:
ld [incremento],hl

guardando el incremento en una variable en memoria que representa un valor 8.8

Código:
ld h,coordenadainicial
ld l,0

lo mismo para la coordenada inicial

Código:
ld [coordenadaactual],hl

que la guardamos en una variable en memoria que también ha de ser vista como un valor 8.8. Con esto ya tenemos la inicialización completa (obviamente calcularemos incremento y coordenada inicial para cada dimensión). Luego, a cada paso:

Código:
ld hl,[coordenadaactual]
ld de,[incremento]
add hl,de
ld [coordenadaactual],hl

y ya tenemos la coordenada actual actualizada (valga la redundancia). Como el Z80 almacena siempre primero el byte de menor peso, nos bastaría con acceder al contenido de coordenadaactual+1 para saber la parte entera de la coordenada actual, que es el valor que hay que poner en la coordenada del sprite.

Espero que esta explicación pueda despejar tus dudas. Obviamente esto puede extenderse y trabajar con números 4.4 que caben en un byte, o incluso con números 3.5, 13.3, etc. Todo un mundo de posibilidades que dependen de cómo miremos los números.

Un saludo
--
Sph.


En línea
OKI09
Karoshi Maniac
****
Mensajes: 275



WWW Email
« Respuesta #2 : 21 de Mayo de 2009, 10:22:42 pm »

Citar
"¿en cuántos pasos quieres que el disparo recorra su camino?

Bueno lo logico seria, que si vamos a incrementar la y de 1 en 1, el incremento de x, seria:
(estando el sprite origen en x0,y0 y el sprite destino en x,y)

y-y0/x-x0

Esto ya nos daria el incremento de la x (que es lo que se me atraganta)

En cuanto a tu explicacion SaphiRe, no lo acabo de entender, sobre todo lo de los 2^k(??) Embarrassed

En línea

La derrota no es una opción y no hay excusas.
"Parasiempre"
SapphiRe_MSX
Visitante
« Respuesta #3 : 22 de Mayo de 2009, 08:06:22 am »

Bueno lo logico seria, que si vamos a incrementar la y de 1 en 1, el incremento de x, seria:
(estando el sprite origen en x0,y0 y el sprite destino en x,y)

y-y0/x-x0

No, no te vale. ¿Por qué? Imagina que y=y0 (un desplazamiento horizontal puro), el incremento de X sería 0 y no se movería. Peor aún, imagina que x=x0 (un desplazamiento vertical puro), no podrías calcular el incremento de x porque intentarías dividir por cero.

Tú propones calcular la pendiente de la recta que une ambos puntos, mientras que mi propuesta va por expresar la recta en coordenadas paramétricas (échale un vistazo a http://es.wikipedia.org/wiki/Curva_param%C3%A9trica aunque no hablan de rectas explícitamente). Mi propuesta es tomar esa recta, dividirla en un número N de segmentos (N=2^k) y en cada paso mover el sprite a cada uno de los segmentos. Esto significa que la velocidad del sprite siempre va a depender de la longitud de la recta, ya que para rectas grandes se moverá más rápido que para rectas pequeñas, pero siempre puedes ajustar k (N, por tanto) para cada trayectoria.
En línea
OKI09
Karoshi Maniac
****
Mensajes: 275



WWW Email
« Respuesta #4 : 26 de Mayo de 2009, 06:15:42 pm »

Bueno, ya se que igual es un poco chapuza, pero he encontrado una forma que parece que funciona bien para que la bala vaya dirigida a su objetivo.

Hago lo siguiente:

Primero comprueba que las X e Y no sean iguales y si no lo son pues:

x_relativa=x-x1
y_relativa=y-y1

Miro cual de las dos es mas grande y roto a la izquierda los dos numeros pero en funcion del mayor, cuando este sea menor de $20, pues en x_relativa tenemos el incremento de x y en y_relativa tenemos el incremento de y.

Claro que despues tengo que tener en cuenta el cudrante en el que esta situado para sumar a restar las relativas.

Que os parece?
En línea

La derrota no es una opción y no hay excusas.
"Parasiempre"
OKI09
Karoshi Maniac
****
Mensajes: 275



WWW Email
« Respuesta #5 : 26 de Mayo de 2009, 08:34:13 pm »

Puntualizo.

Cuando compruebo que sea menor de $20, lo hago porque tengo montado el byte de tal forma que los 4 bits mas bajos son los decimales y los 4 mas altos son los enteros.

Con esto hago la aproximacion.

Tengo que puntualizar que solo lo he probado cuando ambos son positivos.

Veremos cuando acabe la rutina si funciona para positivos y negativos. Grin
En línea

La derrota no es una opción y no hay excusas.
"Parasiempre"
OKI09
Karoshi Maniac
****
Mensajes: 275



WWW Email
« Respuesta #6 : 27 de Mayo de 2009, 03:51:34 pm »

Bueno, ya esta comprobado.

Va a la perfeccion. Cheesy

Comprobado el movimiento en todas las direcciones y la verdad es que la aproximacion es muy buena.

Una rutinilla mas acabada para el juego.Je,je,je Grin
En línea

La derrota no es una opción y no hay excusas.
"Parasiempre"
Páginas: [1]
  Imprimir  
 
Ir a:  

Impulsado por MySQL Impulsado por PHP Powered by SMF 1.1.21 | SMF © 2013, Simple Machines XHTML 1.0 válido! CSS válido!