Revistas en papel
 Amiga World Nº21 - Mayo 1991
Anterior
Menú
Logotipo
Sí puedes leer esta frase, la página ha sido actualizada.

El Amiga Me Encanta ha conseguido el permiso por escrito de IDG Comunications España
para ofrecer los artículos de la revista Amiga World España.

TRAYECTORIAS
VECTORIALES

Por Armand Mata y Miquel Cardona.

Con el programa incluído en éste artículo podrá definir,
mediante el ratón, la trayectoria que desee;
pudiendo incorporar ésta posteriormente en sus programas.


Una parte interesante en los juegos de arcade es aquella que controla la trayectoria de los objetos móviles de la pantalla.

Este artículo está pensado para juegos del tipo "mata todo lo que encuentres", en los que el jugador tiene mucha libertad para moverse por la pantalla, pero sin duda también es útil para juegos como, por ejemplo, "Impossible Mission", donde se tiene una libertad de movimientos menor.

En este artículo dividiremos las trayectorias en dos tipos: fijas y variables. Las trayectorias fijas corresponden a las que tienen predeterminada la ruta que seguirán por la pantalla, y las variables son las que basan su camino o trayectoria en algún elemento de la pantalla con una trayectoria aleatoria.


Mover un objeto

Antes de nada conviene explicar el funcionamiento de la rutina que se encarga de mover los objetos por la pantalla. Las operaciones básicas que ha de realizar son:

  1. Borrar la posición anterior, copiando el buffer en la memoria de pantalla. Hay que tener en cuenta si ésta ha variado su emplazamiento por un scroll.

  2. Guardar en un buffer la memoria de pantalla que va a ser ocupada por el dibujo.

  3. Dibujar el objeto en cuestión.

En los listados que presentamos hemos optado por una solución más sencilla, que consiste en las siguientes líneas:

   COLOR 0
   CIRCLE(xp0,yp0),8
   'Borramos el dibujo anterior
   COLOR 1
   CIRCLE(xp,yp),8
   ' Dibujamos el objeto en las nuevas
   ' coordenadas xp0=x:yp0=y
   ' Para repetir el proceso a la
   ' siguiente pasada

Para visualizar la trayectoria completa podemos eliminar las dos primeras líneas.


Trayectorias fijas

Todas estas rutinas
pueden realizarse
en código máquina,
con el consiguiente
aumento
de velocidad.

Como ya hemos dicho, son trayectorias predeterminadas, pero esto se puede dar por dos caminos:

  • A través de una fórmula matemática que calcula todos los puntos.

  • A través de una tabla de puntos que definan la ruta a seguir.

El manejo de tablas generalmente es mucho más rápido en cuanto a tiempo de proceso, pero es menos flexible en cuanto a modificaciones de la trayectoria. En los dos modos, se pueden aplicar ciertas transformaciones a todos los puntos, como son la traslación, la simetría respecto a un eje o respecto a un punto, rotaciones, etc.

Gráfica 1: Ejemplo de persecución 1


TRAYECTORIAS FIJAS POR FORMULAS

Generalmente se dan en ecuaciones paramétricas.

   x = f1(t)
   y = f2(t)

Para obtener los distintos puntos se hace varias t. Si t varía más rápido, aumentamos la velocidad con que se mueve el objeto. Por ejemplo, una elipse de ejes paralelos a los ejes x e y se define como:

   x = xc + A*cos(w*t)
   y = yc + B*sin(w*t)
   (Listado1 - Gráfica 1)

donde xc,yc son las coordenadas del centro de la elipse, A=radio del eje x, B=radio del eje y, t es un número real, y w es una constante (frecuencia angular). Si t se incrementa, la trayectoria gira en un sentido, mientras que si t se decrementa, gira en el contrario. Si A=B=R obtenemos una circunferencia de radio R. Si w = 2*Pi, haciendo variar t entre 0 y 1 obtenemos la trayectoria completa de una elipse (una vuelta). Si cambias la variable "paso" modificarás el salto que da tu sprite entre posición y posición.

   Espiral:
   x = xc + K1*t*cos(w*t)
   y = yc + K2*t*sin(w*t)
   (Gráfica 2)

Esta espiral parte del centro para t=0 y se va alejando. En el listado 2 hemos modificado el parámetro para hacer que la elipse parta del exterior hacia el centro; posteriormente se aleja del centro y, cuando vuelve a la posición inicial, reinicializamos "t" para que repita la misma trayectoria.

Curvas de Lissajous: corresponden a la fórmula general

   x = xc + A*cos(w1*t+phi1)
   y = yc + B*sin(w2*t+phi2)
   (Listado 3 - Gráfica 3)

si w1/w2 es un número racional, entonces la trayectoria descrita se repite después de un determinado número de "vueltas". La elipse no es más que un caso particular de curva de Lissajous en que w1=w2 y phi1=phi2. Como curiosidad observa que ocurre cambiando la variable "paso" por 0.5 o 5, por ejemplo.

Gráfica 2: Ejemplo de persecución 2


TRAYECTORIAS FIJAS POR TABLAS (Listado 4)

Las tablas de valores se pueden obtener "muestreando" la posición del ratón o a partir de fórmulas, guardando los distintos valores de x e y. El movimiento del objeto se obtiene recorriendo la tabla secuencialmente y dibujando en la posición marcada por la tabla, introduciendo entre las distintas lecturas un retardo; cuanto menor sea éste, mayor será la velocidad con que se moverá el objeto. Tanto en el modo 1) como en el 2) se pueden obtener trayectorias derivadas de ellas sumando valores a las x y a las y (desplazamiento), o bien calcular la trayectoria simétrica respecto a un punto o respecto a un eje, o efectuar una rotación.


Un poco de cinemática y vectores...

VECTORES de 2 dimensiones:

Un vector s=(sx,sy) se representa como sigue:

(gráfica 4)

El manejo de tablas
generalmente es
mucho más rápido
en cuanto a tiempo
de proceso,
pero es menos
flexible en cuanto
a modificaciones
de la trayectoria.

El módulo del vector s, lsi es su longitud, y se calcula lsl=sqr(sx2+sy2).

Un vector de módulo 1 se denomina vector unitario.

Un vector unitario en la dirección de s será

   us=(ux,uy)=(sx/lsl,sy/lsl).

Un vector de módulo m y de dirección igual a la de s será m=(m*ux,m*uy). Suma de 2 vectores: si tenemos r=(rx,ry) y s=(sx,sy), el vector suma v=(vx,vy)=r+s=(rx+sx,ry+sy).

El vector definido por 2 puntos (x1,y1),(x2,y2) tiene por coordenadas (x,y)=(x2-x1,y2-y1).

Las rutinas de persecución se basan en la cinemática.


CINEMÁTICA:

Se define el vector de posición r=(x,y) como el vector que une el origen de coordenadas con la posición del móvil.

Definimos la velocidad v=(vx,vy) como la variable que experimenta el inc(r)= vector de posición por unidad de tiempo v=lim ---- = dr/dt t2->t1 inc(t), La aceleración a=(ax,ay)=dv/dt=d2r/dt2.

En el movimiento rectilíneo uniforme, v es constante, y r=r0+v*(t-10).

Se define el vector de posición r=x,y)
como el vector que une el origen
de coordenadas con la posición del móvil.

Gráfica 3: Ejemplo de persecución 3

De este modo, podemos definir la trayectoria, velocidad y aceleración mediante ecuaciones en función de t, que se relacionan entre si por medio de derivación e integración. Afortunadamente, podemos realizar unas aproximaciones que nos simplifican enormemente el cálculo:

  1. Si consideramos incrementos de tiempo suficientemente pequeños, podemos considerar que durante ellos el móvil se mueve con movimiento rectilíneo uniforme.

  2. Dado que las unidades son arbitrarias, podemos considerar que el incremento de tiempo entre dos intervalos consecutivos vale 1, con lo que tendremos vx=vx0+ax, vy=vy0++ay, x=x0+vx, y=y0+vy.

RUTINAS DE PERSECUCIÓN

Presentan un objeto móvil (un círculo dibujado con CIRCLE (x,y),8) que persigue el puntero del ratón.

PERSECUCIÓN GENERAL

Primero determinamos el vector a. Entonces calculamos v = v0 + a. finalmente, r = r0 + v, que, expresado en coordenadas, resulta:

   x = x0 + vx
   y = y0 + vy

(Hemos tomado incremento de t = 1).

PERSECUCIÓN 1

Es la más sencilla posible de todas las rutinas de persecución. Básicamente ejecuta el siguiente algoritmo:

Si xm >= xp + incremento_x entonces xp = xp + incremento_x. Si xm <= xp - incremento_x, xp = xp - incremento_x. Si ym >= ym + incremento_y, yp + incremento_y. Si ym <= yp - incremento_y, yp = yp - incremento_y

Calculamos d2 = (xm-xp)2 + (ym-yp)2 (distancia al cuadrado). Si d2 es menor o igual que dmin2, hay colisión (en el listado persecución_1 el valor es 30). Esta rutina es fácil de implementar en código máquina gracias a las instrucciones de multiplicación que posee el µP 68000. Y por tanto también será rápida.

PERSECUCIÓN 2

Copiamos las sucesivas posiciones de objeto perseguido en un array utilizado de forma cíclica, es decir, cuando completamos el último elemento del array, utilizamos el primer elemento como posición n+1. El objeto perseguidor se limita a seguir los pasos del perseguido con un cierto retraso, pero si éste se para, el otro no lo hace, con lo cual va disminuyendo la distancia que los separa.

El listado persecución_2 ilustra este caso. Esta rutina es también muy sencilla de implementar en lenguaje máquina, igual que persecución_!.

PERSECUCIÓN 3

El vector velocidad del "perseguidor" P está dirigido hacia el "perseguidor" M, y tiene módulo constante. Es decir, P se dirige a M con una velocidad constante. Ecuaciones resultantes:

   vx = lvl*(xm-xp0)/sqr/((xm-xp0)*(xm-xp0)+(ym-yp0)*(ym-xp0))
   vy = lvl*(ym-yp0)/sqr((xm-xp0)*(xm-xp0)+(ym-yp0)*ym-yp0))
   xp = xp0+vx
   yp = yp0+vy

Nota: La posición actual de M es (xm,ym); la posición anterior de P es (xp,yp); la velocidad de P es (vx,vy).

PERSECUCIÓN 4

Es una variante de la anterior en la que existe una cierta inercia en el movimiento de P. Los cambios respecto a las ecuaciones anteriores son:

   ax = lal*(xm-xp0)/sqr((xm-xp0)*(xm-xp0)+(ym-yp0)*ym-yp0))
   ay = lal*(ym-yp0)/sqr((xm-xp0)*(xm-xp0)+(ym-yp0)*(ym-yp0))
   vx = ki*vx+ax
   vy = ki*vy+ay

(En el programa a = 7)

La constante ki es arbitraria, y surge debido a que sin ella las sucesivas xp, yp oscilan demasiado. Los valores experimentales que funcionan bien están comprendidos entre ki=0 y ki=0.85. Si ki=0 no existe inercia. Prueba con ki = 0.99 ¡y ya verás!

PERSECUCIÓN 5

El módulo de la aceleración de P es inversamente proporcional a la distancia al cuadrado que lo separa de M. Es del tipo de la aceleración gravitatoria.

   ax = K*(xm-xp0)/((xm-xp0)*(xm-xp0)+(ym-yp0)*(ym-yp0))
   ay = K*(ym-yp0)/((x,-xp0)*(xm-xp0)+(ym-yp0)*(ym-yp0)

El resto de formulas no varían.

PERSECUCIÓN 6

El módulo de la aceleración de P disminuye linealmente al aumentar la distancia que separa P de M hasta llegar a la distancia mdl1, a partir de la cual dicho módulo es constante (ver gráfica 3).

Si am es la aceleración máxima de P (cuando la distancia es nula), y a0 es la aceleración de P cuando la distancia es mayor o igual a mdl1:

   lal = am - (am-a0)*mdl/mdl1
   para 0<= mdl <= mdl1
   lal = a0
   para mdl >= mdl1

Todas estas rutinas pueden realizarse en código máquina, con el consiguiente aumento de velocidad. Para crear sprites en este lenguaje o en C deberás leerte el Rom Kernel: Libraries and Devices o algún número anterior de Amiga World.

        **********************************
        SUBRUTINA DE IMPRESION EN PANTALLA
      (C) 1991 Armand Mata y Miquel Cardona
               (C) 1991 AMIGA WORLD
Esta rutina ha de incluirse en todos los programas.
        **********************************
SUB dibuja(x,y) STATIC
SHARED x0,y0
COLOR 0
CIRCLE(x0,y0),10 'borra el anterior; poner REM para
                 'visualizar trayectoria completa
COLOR 1
CIRCLE(x,y),10   'dibuja
x0=x
y0=y
END SUB
  *********************************
              ELIPSE
(C) 1991 Armand Mata y Miquel Cardona
(C) 1991 AMIGA WORLD
  *********************************
'Incluir subprograma Dibuja()
pi=3.1415926539# 'Constante
xc=320           'Centro elipse
yc=75            'Centro elipse
A=180            'Mirar gr�fica 1
B=60             'Mirar gr�fica 1
' Si A=8 => circunferencia
' Si A=A(t) y B=B(t) trayectoria m�s compleja
x0=0
y0=0
t=0
paso=.02
WHILE -1
 x=xc+A*COS(2*pi*t) 'Ecuaciones
 y=yc+B*SIN(2*pi*t) 'Elipse
 t=t + paso
 CASLL dibuja(x,y)
 'IF t>40 THEN GOTO acaba
WEND
acaba:
END
  *********************************
        CURVAS DE LISSAJOUS
(C) 1991 Armand Mata y Miquel Cardona
(C) 1991 AMIGA WORLD
  *********************************
'incluir Dibuja()
pi=3.1415926539# 'Constante
t1=5
t2=7
xc=320   'Centro curva
yc=75    'Centro curva
x0=0
y0=0
t=0
paso = .5
WHILE -1
 x=xc+160*SIN(2*pi*t/t1-.54)
 y=yc+65*SIN(2*pi*t/t2)
 t=t+paso
 CALL dibuja(x,y)
 ' IF t>40 THEN GOTO acaba
WEND
acaba:
END
  *********************************
         ESPIRAL REVERSIBLE
(C) 1991 Armand Mata y Miquel Cardona
(C) 1991 AMIGA WORLD
  *********************************
'Incluir subprog. Dibuja()
PI=3.1415926539#  'Constante
xc=320  'Centro espiral
yc=85   'Centro Espiral
x0=320  'Posici�n inicial
y0=75
a=75
b=25
t=0
paso=.05
WHILE -1
 tao = 3.25-t
 x=xc+tao*a*COS(2*PI*tao)
 y=yc+tao*b*SIN(2*PI*tao)
 IF ABS(tao) <=.25 THEN
   t=t+paso    'Hacemos variar m�s r�pido
 ELSE          'para simular una velocidad lineal
   t=t+paso/2  'm�s constante
 END IF
 CALL dibuja(x,y)
 IF t>=6.5 THEN t=0
WEND
acaba:
END
  *********************************
   GENERADOR DE TRAYECTORIAS FIJAS
              POR RATON
(C) 1991 Armand Mata y Miquel Cardona
(C) 1991 AMIGA WORLD
  *********************************
DIM xy%(1000,2)
btn=0
l%=1
a%=0:b%=1
menu1:
 key$=""
 CLS
 PRINT:PRINT:PRINT
 COLOR 0,1
 PRINT " 1. DEFINICION DE TRAYECTORIA"
 COLOR 1,0
 PRINT
 PRINT " 2. PRUEBA DE TRAYECT. EN MEM."
 PRINT
 PRINT " 3. ACABAR"
 PRINT
 COLOR 0,1
 PRINT " Opci�n: "
 WHILE key$=""
       key$=INKEY$
 WEND
 IF key$ = "2" THEN GOTO test
 IF key$ = "3" THEN GOTO acaba
 IF key$ <> "1" THEN GOTO menu1
COLOR 1,0
btn = 0
FOR j=0 TO 500:NEXT j
WHILE btn = 0  'Espera la pulsaci�n del rat�n
      btn = MOUSE(0)
WEND
i%=1  'posiciones guardadas
WHILE btn<>0   'muestreo mientras est� pulsada
               'la tecla del rat�n
btn=MOUSE(0)
xm%=MOUSE(1)
ym%=MOUSE(2)
LOCATE 1,1
PRINT i%
xy%(i%,1)=xm%:xy%(i%,2)=ym%  'guardamos las posiciones del mouse
                             'en un array
FOR j=0 TO 20:NEXT j         'retardo; variando el valor cambia
                             'la frecuencia de muestreo
i%=i%+1
IF i%>1000 THEN btn=0        'salida del bucle
WEND
i%=i%-1
PRINT "Nombre del fichero de salida [RETURN para no grabar] :";
INPUT file$
IF file$="" THEN GOTO menu1
OPEN file$ FOR OUTPUT AS #1  'Grabaci�n datos
j=1
WHILE j<i%-4                 'De tres en tres
PRINT#1."DATA";xy%(j,1);",";xy%(j,2) ;",";xy%(j+1,1);
        ",";xy%(j+1,2);",";xy%(j+3,1);",";xy%(j+3,2);","
j=j+4
WEND
FOR k=j+1 TO i%-1
PRINT #1,"DATA ";xy%(k,1);",";xy%(k,2);","
NEXT k
PRINT #1,"DATA ";xy%(i%,1);",";xy%(i%,2)
CLOSE #1
GOTO menu1
test:
 IF i%=1 THEN
    PRINT CHR$(7);" No hay trayectoria en memoria!"
    GOTO menu1
 END IF
 COLOR 1,0
 FOR j=1 TO i%  ' Representaci�n de los valores guardados
COLOR 1,0
   CLS
   PRINT j
   x=xy%(j,1)
   y=xy%(k,2)
   CIRCLE (x,y),8
   FOR k=0 TO 100:NEXT k
REM COLOR 0,1
REM CIRCLE (x,y),8
   NEXT j
   GOTO menu1
acaba:
   COLOR 1,0
   PRINT "Final del programa"
END

Envía esta página web a un amigo:
Esta opción está desactivada temporalmente, rogamos disculpen las molestias

Volver a la página anterior

Al menú principal