Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





[vb6] Caminar En Diagonal?

Iniciado por Abc7, 30 de Julio de 2004, 10:22:58 PM

« anterior - próximo »

Abc7

 Bueno si... este es mi primer mensaje  :D  asi que primero me presento, soy Jorge de Argentina =D
bueno el problema que tengo esss.. que no puedo hacer caminar en diagonal al tipito :( porq si pongo q cuando presione arriba y derecha por ejemplo, que se mueva para arriba y para la derecha.. si se estaba moviendo para arriba va a hacer una especie de turbo :S
quisiera saber si por algun lado hay algun buen manual o tutorial de como haceeer que se mueva en diagonal usando vb6 y SIN usar un tile engine isometrico

si no me exprese bien entonces diganme que adjunto mi codigo

saludos y gracias  (ole)  (ole)  (ole)  

[EX3]

 Mmm, esto me suena... si eres kien yo creo ke eres bienvenido al foro, y si no tb, por supuesto  :D

Amos a ver, supon ke tu personaje usa dos coordenadas para la posicion, es lo mas normal, vamos, coordenada X ke indica su posicion lateral (derecha e izquierda) y coordenada Y, ke indica su altura en pantalla (Arriba y abajo).

Algo basico, cuando tu personaje se mueve hacia la derecha lo ke hace es incrementar su posicion X (X = X + 1 por ejemplo) y cuando se mueve a la izquierda lo contrario (X = X - 1) y cuando se mueve hacia abajo incrementa Y (Y = Y + 1) y al subir lo contrario (Y = Y - 1). Pues bien, si lo ke kieres es ke se mueva en diagonal, hacia la derecha y abajo, por ejemplo, seria (X = X + 1, Y = Y + 1). En principio no tendria ke hacer ningun efecto de aceleracion ni nada por el estilo.

Si puedes postear algo del codigo para ver ke es lo ke te produce el aceleron seguramente podamos ayudarte algo mas. Seguramente el problema este en ke incrementas mas cantidad en alguna de las coordendas.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

Lord Trancos 2

 EX3, lo que dices no es cierto. Aunque muchisimos juegos lo hacen asi y no le damos importancia. (En mi opinion no es algo que quede mal).

Te pongo un ejemplo en el mundo real. Tu tienes que ir desde donde estas, hasta una calle (imaginemos que no hay edificios de por medio). A la misma velocidad, tardaras menos en llegar si vas "recto" que si vas en diagonal.

Mientras que en el caso que comentas, si la calle es una linea horizontal en la parte inferior de la pantalla, tardarias lo mismo con X = X + 1, Y = Y + 1, que con Y = Y + 1.

La solucion que yo veo es usar Doubles para almacenar las posiciones del personaje, y modificar su posicion en funcion del tiempo y no 1 pixel cada X frames. Despues cuando lo quieres dibujar; conviertes la posicion a enteros y ya esta (o si estas en un modo 3D no hace falta).
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Lord Trancos 2

 Otra cosa. Usando Doubles, para mover en diagonal seria por ejemplo....

 X = X + (cos(Pi/4) * tiempo * velocidad)
 Y = Y + (sin(Pi/4) * tiempo * velocidad)

Y para mover recto por ejemplo...

 X = X + (tiempo * velocidad)

etc...
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

shephiroth

 Muy buenas.

Aqui les pongo mi pequeño codigo, q es el q voya usar en mi rpg xDD

void moviendoJugador()
{
int cantidad =0;
if (keys[teclado.arriba]) cantidad++;
if (keys[teclado.abajo]) cantidad++;
if (keys[teclado.izquierda]) cantidad++;
if (keys[teclado.derecha]) cantidad++;
if (cantidad>=3 || cantidad==0) return;

//aqui faltan algunas comprobaciones, pero no vienen al caso

float muto=getMovimiento();
if (cantidad==2) muto=muto*2/3;
if (keys[teclado.arriba]) pjs->moverArriba(muto);
if (keys[teclado.abajo]) pjs->moverAbajo(muto);
if (keys[teclado.izquierda]) pjs->moverIzquierda(muto);
if (keys[teclado.derecha]) pjs->moverDerecha(muto);
}


El codigo me parece es bastante sencillo.
keys es un array booleano q marca cuando una tecla esta pulsada.
teclado. es una estructura q guarda todas las teclas q utiliza el juego.
pjs es un puntero al personaje en cuestion
getMovimiento() me da cuantos pixeles se ha de mover el muñaco en funcion del tiempo transcurrido desde la ultima llamada

Ademas, creo q el codigo te cuadraría perfecto, pq como ves ahi podrías meter codigo exclusivo para el diagonal, puesto q cuando hay 2 teclas presionadas es pq quiere hacer diagonal (de ahi habría q sacar cuando presiona arriba y abajo a la vez, pero me da igual xDD)

gdl

 
'Amos a ver. ¿No sería más fácil hacer esto?


int deltaX=0, deltaY=0;
int velocidad=pj->VelocidadDelBicho();

if (keys[teclado.arriba]) deltaY-=velocidad;
if (keys[teclado.abajo]) deltaY+=velocidad;
if (keys[teclado.izquierda]) deltaX-=velocidad;
if (keys[teclado.derecha]) deltaX+=velocidad;

pj->MueveBicho(deltaX,deltaY);



jpastor

 Sí, eso está más o menos bien, pero si quieres ser más realista hay que fijarse en lo que dice Lord Trancos 2.

El problema es que para el caso de que velocidad=1, si te mueves a la derecha, izquierda, arriba o abajo mueves el personaje 1 (una) unidad. Mientras que si lo mueves en diagonal lo mueves 1.414.. (sqrt 2), es decir, más rápido.

Pogacha

 Se me ocurre mas mejor:

real t = Tiempo_Del_Frame * Escala_De_Aceleracion;  // tiempo del frame en segundos

struct v { real x, y } // velocidad del personaje
struct p { real x, y } // posicion del personaje
real m; // modulo de velocidad

if(key[Arr]) v.y+=t;
if(key[Aba]) v.y-=t;
if(key[Izq]) v.x-=t;
if(key[Der]) v.x+=t;

m= sqrt(v.x*v.x + v.y*v.y);
if(m>Velocidad_Maxima)
{
  m=Velocidad_Maxima*Tiempo_Del_Frame/m;
  v.x*=m;
  v.y*=m;
}

Manejar_Colisiones_Colision(&p, &v) // en caso de colicion altera la velocidad, (deslizamiento o demas)

p.x+=v.x;
p.y+=v.y;

int x=Enterizar(p.x);
int y=Enterizar(p.y);

Dibujar_Bicho(x,y);

// aplico friccion, muy importante

real Friccion= 0.1

v.x*=Elevar(Friccion, Tiempo_Del_Frame);  // Friccion a la tiempo del frame
v.y*=Elevar(Friccion, Tiempo_Del_Frame);


De esta manera manejamos aceleracion del personaje y se movera mas lindamente.
Jugando con las constantes de aceleracion, friccion y velocidad maxima
vas a encontrar lo que buscas.

Despues faltaria ver la direccion en que se mueve para cada animacion y se me ocurre


real cosalpha = v.x / m;
real alpha = arccos(cosalpha);
if(v.y<0) alpha= - alpha;
int anim = Enterizar(alpha-(PI/8)) % 8;


y las animaciones correspondientes a cada velocidad serian:

3 2 1
4 X 0
5 6 7

Espero que te sirva.

Saludos
Pogacha

shephiroth

 Muy buenas. GDL yo al principio lo hacia como tu dices, obtenia el movimiento y se lo aplicaba en cada direccion sin tener en cuenta cuantas teclas tiene presionadas. Al final tuve q modificar el codigo pq me interesaba saber cuando hay mas de una tecla presionada. Recordemos que ABC7 quiere que su muñeco ande en diagonal, asi que tendrá que saber cuando hay dos teclas presionadas.

Pogacha, tu código me parece bastante complejo, pero va un poco más allá de lo que se pedía (creo yo). Para un juego de coches, de naves, de carreras......tu codigo es perfecto, puesto que tienes en cuenta todos los factores que hay q tener encuenta en ese tipo de juegos. Pero ABC7 quiere mover un muñeco, por lo q creo que tienes encuenta demasiados factores. Por otra parte utilizas mucho las funciones de seno, coseno, tangente......y actualmente cuantas menos operaciones con coma flotante hagamos hacer al ordenador mejor.

ABC7 como ves tienes codigo para elegir. Complicado pero compacto codigo de Pochanga, codigo simple pero directo de GDL, o mi codigo un poco mas elaborado pero no demasiado completo. Luego tienes ideas por ahi que deberías tener en cuenta.

Bueno, ya nos comentarás el codigo final que uses, la cosa puede quedar guapa  (nooo)  

Pogacha

 El tema de las operaciones, si conte bien, son solamente un sqrt, un arcos, y dos pow por frame, eso se hacia en un spectrum, en un pc debe andar mas todavia.

Señor ABC7, creo que hay codigo para que te entretengas.

Saludos Pogacha


shephiroth

 Pogacha, el problema no es que ahi haya esas minimas operaciones de mas (como dices son una chorrada), el problema es cuando hay unas pocas aqui, otras allá...........el problema tampoco esta en los juegos pequeños, pues no son tan extensos como para acumular tantas "operaciones extra"..........sino el problema viene en los juegos grandes que van acumulando estas operaciones, y es lo que hace que un juego necesite un p4 a 3000 en vez de un p3 a 500 para funcionar de forma fluida (me he pasado, lo se  (twist) )

Weno, nada mas. Este post solo era para concienciar sobre el buen uso del cpu en los programas.....hasta yo lo hice mal, puse 2/3 en vez de precalcular el valor 1 sola vez, pero bueno xDD

SALUDOS

Pogacha

 Si eso pensaba antes yo, pero en realidad no importa, te muestro:
No le prestes atencion al codigo, si a los bucles:


for i=0 to 10
A=10*i
B=30*i + 3*i
Z = Funcion_Rara(A+B);
C = Delta[i]
for j=0 to 100000
  Z=Z+j*C;
next j
Epsilon[j]=Z
next i


Esto demora  10 * ( 20 + 100000  * 3 ) =  3000200

y si lo arreglas :


rem   A + B = i * 10 + i * 3 + i * 30  
rem   =>
rem   A+B= i * 43
rem   y
rem    i=i+1
rem   =>
rem  (A+B)=(A+B)+43  
rem   Con B superfluo
rem   A=A+43


A=0
for i=0 to 10
A=A+43
Z = Funcion_Rara(A);
C = Delta[i]
for j=0 to 100000
  Z=Z+j*C;
next j
Epsilon[j]=Z
next i

Esto demora  10 * ( 4 + 100000  * 3 ) =  3000040

Y me cago en la diferencia.

Prefiero dedicar mi tiempo a bajar la demora de los bucles pesados,
lo que se hace una vez por frame no tiene importancia que demore 1 o 10 uSeg,
pero esto es otro tema.

Saludos
Pogacha

gdl

 
Mmm.... si quisiera saber si dos teclas están pulsadas, por ejemplo para ajustar la velocidad en diagonal a raíz de dos, haría una cosa como esta (que sigue siendo simple):

int deltaX=0, deltaY=0;
int velocidad=pj->VelocidadDelBicho();

if (keys[teclado.arriba]) deltaY-=velocidad;
if (keys[teclado.abajo]) deltaY+=velocidad;
if (keys[teclado.izquierda]) deltaX-=velocidad;
if (keys[teclado.derecha]) deltaX+=velocidad;

if((deltaX|deltaY)!=0)//Realmente el !=0 sobra, pero para que quede claro
{
 //Ohhh dos teclas pulsadas, corrijo velocidad para diagonal.
 deltaX=deltaX*5/7;//5/7 es más o menos dividir por raíz de dos.
 deltaY=deltaY*5/7;//No lo precalculo porque uso enteros.
}

pj->MueveBicho(deltaX,deltaY);


Aunque, ahora que lo pienso, si se pulsan dos teclas como izquierda y derecha a la vez, no lo detecta.... claro que como no quieras implementar una mitosis o algo así, no te va a hacer falta.

También veo que usar *5/7 añade una multiplicación y una división extra, que se pueden evitar si precalculas la velocidad en la diagonal. En fin, eso liaría el código y si ABC7 quiere, que se ponga a optimizar.

Y, para ser sinceros, yo suelo usar flotantes en un código como el de Pogacha (versión más mejor), que tiene el cuenta la duración del frame y todo ese follón.

Pogacha

 Creo que el codigo anterior es los mas parecido a lo que ABC7 buscaba, el tema era como organizar el movimiento.

si queres optimisar:

en C:

usando un fixed point de 16:16

#define F_B 16
#define RAIZ_DE_DOS_SOBRE_DOS   0.70710678118654752440084436210485

#define F_RAIZ_DE_DOS_SOBRE_DOS   int(0.70710678118654752440084436210485*(1<
Vel = (Vel * F_RAIZDEDOSSOBREDOS)>>F_B;

Pero acordate, es una vez por frame, ¡que importa!
y despues con decir

if (DeltaX || DeltaY)  // sobra y es mejor para el compilador






shephiroth

 Buenas.

Pochanga, no me referia a evitar operacion como las q dices, con enteros funciona igualmente. Pero create un programa, ponle contador de tiempo, y haz el mismo codigo CON DECIMALES, ya veras q en ambos casos no te da la misma velocidad.

No se si los ordenadores ultimo modelo ya tendán el problema superado......si tienes la oportunidad compilate el programa, y pruebalo en un p2 o p3, en los amd k6 y k6-2 ya era la risa xDD

Weno, un saludo ^^

EDITADO:

Por cierto, para evitar dos teclas iguales, yo utilizo algo como
if (keys[teclado.arriba] && keys[teclado.abajo] || keys[teclado.izquierda] && keys[teclado.derecha]) return;






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.