Migración de juegos Fenix a Bennu - Apuntes de diferencias y resoluciones.

Started by FreeYourMind, September 30, 2009, 05:20:12 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

splinter_work

Quote from: DCelso on October 01, 2009, 07:44:17 AM
...
De todas formas, si no recuerdo mal, en DIV los identificadores de los procesos eran siempre números impares, a lo mejor esto, mezclado con un XOR hace que en un id puedas llevar en un mismo id más de un proceso identificado.

par o impar no tiene nada que ver.

splinter_work

Quote from: FreeYourMind on October 01, 2009, 10:14:55 AM
No tiene nada de mas, es el ejemplo es el que puse despues hay un case, te lo completo para que veas, aunque yo ahora utilizo el OR, pero es lo mismo, lo que hace es que al colidir pilla el id del grafico colidido, es muyyyy dificil que pille 2 en el mismo momento, pero me imagino ya que esto de los numeros tiene siempre una orden, que si pilla 2 internamente habra siempre uno primero que otro.

Te pongo el original:

Process disparo(x,y,angle)
Begin

graph=graf_disp;
  Repeat

If(id_colision=collision(Type enemigo1) XOR collision(Type enemigo2) XOR collision(Type enemigo3))

Switch(graf_disp); // gráfico de disparo
          Case 1:
              id_colision.vida-=5; // vida es una variable comun en cada proceso enemigo
              If(id_colision.vida > 0) explosion_del_tiro(x, y); End
              Break;
             End
          End
          Case 2:
              id_colision.vida -= 10;
              If(id_colision.vida > 0) explosion_del_tiro(x, y); End
              Break;
             End
          End

      advance(10);
      Frame;
  Until(y<0);
End

ya esta con esto le quita energia al id pillado, y desaparece el tiro con una pequeña explosion de impacto :)


------------------------------


Ahora tengo un nuevo problema, parece que es con el advance() del proceso disparo,
que funciona bien en DIV y Fenix pero no en Bennu:

El tiro se desplaza en el eje Y pero no lo hace en el eje X....

Ejemplo:

Creo 3 tiros:

disparo(x, y, 90000); // Hacia arriba
disparo(x - 6, y, 95000); // Hacia Arriba, Izquierda
disparo(x + 6, y, 85000); // Hacia Arriba, derecha


como se puede ver en el proceso disparo Process disparo(x,y,angle), con advance(10) el tiro se desloca en el eje Y (hacia arriba)
y en el eje X (un tiro hacia la derecha y otro hacia la izquierda), esto funciona en DIV y en Fenix, pero en Bennu, solo se esta moviendo
en el eje Y, no se mueve en el eje X !!!

Soluciones ?¿

Gracias.




OR y XOR no son lo mismo para nada...

una condicion con OR, si el primer terminos unido al OR da TRUE, entonces ya no se chequean las condiciones/terminos siguiente... y XOR evalua todos los terminos, esto con los operadores logicos...
DIV y FENIX (version antigua)... los operadores logicos no existen, son todos operadores binarios, lo que implica que todos los terminos se ejecuten si o si... pero en las ultimas version de Fenix, eso no es asi, hay operadores logicos y binarios por separados... los logicos cuando la condicion evaluada resuelve toda la expresion, ya no se sigue evaluando las demas condiciones... con los operadores binarios, se evaluan todas las condiciones, porque logicamente se necesitan...

sin embargo XOR (logico o binario, el logico solo existe en Bennu y ultimas version de fenix, en ningun otro lenguaje que yo conozca existe), necesita si o si se evaluen todos los terminos de la expresion... por la propiedad del XOR.

esa es la gran diferencia...

y el ejemplo, solo te funciona en div y viejas versiones de fenix, solo si la colision se produce en cantidades impares de disparos simultaneamente... o sea, el if sera en esos casos disparado por TRUE... pero el id sera el del ultimo tipo controlado.

como sea, no es un buen mecanismo.

con respecto al avance... cuando se usa avance hay que usar resolution... porque en casos donde de valores entre 0-1 (angulos rectos o casi rectos) puede al redondear nunca se incremente alguna de las coordenadas (como dijo drumpi).

por ejemplos completos, no sirve de mucho trozos de codigo en los que agregas nuevos bugs...

splinter_work

el escalado nativo de bennu, es solo representacion de los datos en pantalla, el juego sigue corriendo (y todo se sigue dibujando) en la resolucion original, solo el dumpeo a pantalla se hace escalado...

ahora si vos estas haciendo un escalado a mano de todo tu codigo, entonces el problema quizas viene por ahi.

otra cosa, es que las coordenadas son enteras, asi que no sirve de nada que hagas un +.5 o -.5 (segun el caso), el redondeo es siempre quitando la parte decimal, es el redondeo natural que se hace en los ordenadores.

debes usar resolution (que nada tiene que ver con el escalado de imagen)

splinter_work

Quote from: FreeYourMind on October 01, 2009, 02:39:09 PM
Jo muy buena tu observación Drumpi, si tuviera más carmas que el único que tengo te lo regalaba :)

Pero me temo que no sea ese el problema, el 10 lo puse en el ejemplo, en realidad hacia un advance(16); en el original y estoy haciendo un advance(8); en el port, ya que tiene mitad de la resolución :)

Y tampoco funciona ninguna de las dos en el eje X.

Como funciona eso de float ?, se pueden poner posiciones con float ?? por ejemplo es posible poner un gráfico en la posición x = 3,5 ??
Ese es otro problema al reducir todas las coordenadas cuando se hace un port para mitad de la resolución, con las posiciones que son impares en el original.
Me moskea que con la función de rescalado de resolucion interna lo haga pero a pelo no sepa si es posible ....

Otra cosa, dices que redondear 0.8 se queda en 0, pero no se queda en 1 ?? yo estoy teniendo en cuenta que por ejemplo si es mayor que 1,5 lo redondea a 2, como se hace en las matematicas en general, un redondeo para abajo no tiene sentido !!!

Los valores de posición y movimiento que me dan valores con comas, por ejemplo 2,5, las estoy arredondando manualmente para el valor siguiente, o sea, en este caso seria valor 3.

FreeYourMind

Lo del XOR lo he entendido ya hace varios post. No soy yo que sigo insistiendo, lo mejor seria no mezclar las cosas :)

Ahora el problema es el advance, y tienes el ejemplo completo, puedes mirarlo ya compilado con esta modificacion del ejemplo de

DCelso, con la tecla 'd' puedes echar lineas continuas de disparos, estos 2 angulos no me funcionan, no se mueve en el eje X:

disparo(x - 3, y, 95000);
disparo(x + 3, y, 85000);

veras que estos disparos solo se mueven en la vertical y los otros se mueven tb en el eje x formando lineas oblicuas en forma de piramide.

Por favor dime como utilizar el resolution, que ya lo intente pero no consegui nada. Si puedes ponlo en el ejemplo para que los 10 tiros funcionen todos correctamente, en especial estos 2 que son los que no van.

Gracias.

FreeYourMind

Quote from: splinter_work on October 01, 2009, 06:35:03 PM
el escalado nativo de bennu, es solo representacion de los datos en pantalla, el juego sigue corriendo (y todo se sigue dibujando) en la resolucion original, solo el dumpeo a pantalla se hace escalado...

ahora si vos estas haciendo un escalado a mano de todo tu codigo, entonces el problema quizas viene por ahi.

otra cosa, es que las coordenadas son enteras, asi que no sirve de nada que hagas un +.5 o -.5 (segun el caso), el redondeo es siempre quitando la parte decimal, es el redondeo natural que se hace en los ordenadores.

debes usar resolution (que nada tiene que ver con el escalado de imagen)


Esto que dices es lo mismo que decia yo :)

Lo se, la pregunta es:

En los casos en que no quieres usar el escalado nativo (como el caso) por problemas de definición de algunos gráficos o fuentes.
Por código no hay forma de definir posiciones x o y con valores decimales ??
Porque como comente haciendo el rescalado manualmente por código, como trabajas con enteros vas a tener este problema en algunos casos, en que con el redondeo no vas a tener la posicíón exacta o deslocación identica al original en el port de menor resolución.

Y sobre el rescalado, al hacer la representación en pantalla, esta representación segun parece si pone todos los gráficos en su respectiva posición exacta al rescalar el juego a mitad de resolución.

DCelso

Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

DCelso

Tenías razón Splinter y tu tambien Drumpi, este problema es por resolución. Probado
Free, el resolution es una variable local, como x, e y. Sirve para hacer que las coordenadas del proceso se refieran al width y height puestos en set mode multiplicados por resolution. Es decir, si set mode es tal que asi set_mode(320,200,32) y en un proceso ponemos resolution =10;
para ese proceso los valores posibles en pantalla serán los comprendidos enre 3200 y 2000, por tanto un advance(1) en este contexto sería parecido (ya que no se puede) a hacer un advance(0.1) sin resolution.
Así que para aprovecharnos de la resolucion, tenemos que cambiarla en el proceso, multipicar x e y de entrada por este valor y multiplicar el advance también por este valor.
El código ejemplo que me pasaste lo he modificado para que veas su funcionamiento.
Por otro lado el while(key(_d))frame;end, es un truco para evitar el encadenamiento masivo de llamadas al disparo, lo que dice es mientras esté pulsada la tecla d pasa al siguiente frame y no hagas nada, quiere decir que hasta que no soltemos la tecla no saldremos del bucle por tanto no se generarán nuevos disparos, para hacer dos disparos deberias de pulsar dos veces la tecla.


import "mod_key"
import "mod_proc"
import "mod_map"
import "mod_video"
import "mod_time"
import "mod_grproc"
global
 int graf_disp;
 type st_pose
   int graph;
   int m_sec;
 end
Begin
   set_mode(320,240,32);
   graf_disp=load_png("recursos/bolafuego.png");
   dragon();

   Repeat
       frame;
   Until(key(_ESC))

   exit();

End

Process dragon()
Private
  st_pose poses[5];
  i;
  int cur_pos;
  int ini_time,passed;
Begin
   x=160;
   y=200;
   for (i=0;i<5;i++)
     poses[i].graph = load_png("recursos/dragon"+(i+1)+".png");
     poses[i].m_sec = 200;
   end
   poses[0].m_sec = 1000;
   poses[4].m_sec = 300;
   ini_time = get_timer();
   while(!key(_esc))
       passed = get_timer() - ini_time;
       if (passed > poses[cur_pos].m_sec)
         ini_time = get_timer();
         cur_pos++;
         if (cur_pos >= 5)
           cur_pos = 0;
         end
       end
       graph=poses[cur_pos].graph;
       if (key(_d))
           disparo(x - 3, y, 95000);
           disparo(x + 3, y, 85000);
           while(key(_d)) frame; end
       end
       frame;
   End
   for (i=0;i<5;i++)
     unload_map(0,poses[i].graph);
   end
End

Process enemigo1()
begin
end
Process enemigo2()
begin
end
Process enemigo3()
begin
end

Process disparo(x,y,angle)
local
 id_colision;
Begin
 resolution = 10;
 x*=resolution;
 y*=resolution;
 graph=graf_disp;
 Repeat
    If(id_colision=collision(Type enemigo1) XOR collision(Type enemigo2) XOR collision(Type enemigo3))

      Switch(graf_disp); // gráfico de disparo
         Case 1:
             //id_colision.vida-=5; // vida es una variable comun en cada proceso enemigo
             //If(id_colision.vida > 0) explosion_del_tiro(x, y); End
             Break;
         End
         Case 2:
             //id_colision.vida -= 10;
             //If(id_colision.vida > 0) explosion_del_tiro(x, y); End
             Break;
         end
     End
    End

    advance(5*resolution);
    Frame;//(500);
 Until(y<0);
End
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/

Drumpi

Verás, Freeyourmind, X e Y no pueden tener nunca valores decimales porque se refieren a pixels en pantalla, y por definición, un pixel es la unidad mínima de información de una pantalla.
Sin embargo, resolution te da una alternativa, resolution indica cuantos puntos hay dentro de un pixel. Si vale dos, significa que para pasar de un pixel a otro tendrás que moverte 2 puntos (sumar 2 a la coordenada X), si vale diez los incrementos deberán ser de 10.
Obviamente, si resolution vale 10, cuando se vaya a dibujar en pantalla, la x=357 de sibujará en el pixel horizontal x=35. Los lenguajes de programación no redondean, truncan (eliminan las cifras de menor peso), que es como decir que redondean hacia cero.

Para moverte 0.08 pixels deberías tener resolution=100 y moverte 8 pixels por frame. Espero que con el código que te ha puesto DCelso esté más claro.

Para que los ángulos funcionen perfectos se recomiendan valores de resolution de 1000, pero esto provoca un desbordamiento de int demasiado pronto (mi FZero me lo advirtió), así que un valor de 100 es más que suficiente.

Por cierto: los ID de los procesos valen números impares, es cierto, y en DIV y Fenix era un detalle importante, porque antes de que Splinter le metirea mano al código, TODOS los valores impares eran equivalentes a TRUE, y TODOS los pares a FALSE. A partir de Fenix 0.85 hasta el Bennu actual sólo el cero se considera valor FALSE, y el resto TRUE.
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

FreeYourMind

DCelso, ya habia visto tu ejemplo en el post del bug de advance :)

Dumpi, gracias a los dos, ya me habia dado cuenta por el ejemplo de DCelso mas o menos del tema.

Sólo hay unos pocos casos contados en que tendria problema al dividir coordenadas de x,y a la mitad (o sea, casos en que eran impares y la división da un decimal 1,5; 2,5,etc.) En estos casos lo que hice fue redondear manualmente el valor de x,y.

Ya me entero que el compilador en redondeos ignora el segundo quitando el decimal y quedandose solo con la parte entera.
Si por ejemplo tuvieramos 2,8 el valor final seria 2.

Aunque esto no es visible a nuestos ojos, lo hara en sus funciones internas como por ejemplo el advance(), porque si pones por ejemplo x=2,5 el compilador te va da error de compilación, así que tampoco te lo deja poner :) o que es lo mismo, tampoco va efectuar ningun redondeo en ese caso :)

Hacer el resolution para estos casos de posición seria entonces una solución, pero para lo engoroso que puede resultar en algunos casos, es mejor dejar un entero aproximado que ponerse con eso, ya que en ese proceso puede que utilizemos los valores de x,y para otras operaciones en que no tengamos problemas de division con decimales al hacer el rescalado manualmente, y tendriamos que adaptar todos los x,y teniendo en cuanta que los estabamos afectando con el resolution.


---------

Para terminar el tema del advance(), queda por resolver la otra diferencia que comentaba en el foro de 'bug de advance', es que utilizando el resolution para crear los 10 disparos, no se forma una piramide perfecta (linea horizontal en la parte de arriba del flujo de tiro), pero si un arco (que queda chulo, pero no es mismo comportamiento, para una conversión pixel perfect:)), es como si en las lineas de disparo que tienen mayor angulo (desde la origen del tiro, o sea las lineas externas) a medida que el angulo aumenta el valor de la velocidad del Y diminuye, y deberia ser la misma velocidad en todas las lineas, porque al poner por ejemplo advance(8) el desplazamiento deberia ser identico en eje Y, independientemente del angulo, vamos, como lo hace Fenix (0.84) o Div (y que estos no tienen problemas con angulos pequeños, ni tenemos que usar el resolution para estos angulos, pero eso ya es otra historia).

Drumpi

Por eso hay que tener en cuenta el uso de resolution desde el principio.
Respondiendo al segundo tema, te remito al hilo que mencionas.
Hala, como con 1001 procesos sólo va a 9 FPS, vamos a meterle 32 veces más, a ver si revienta.
(Drumpi epic moment)

SplinterGU

fenix, versiones anteriores hacian mal las cosas, y menos esa version soportaba decimales... el advance no se comportaba realmente bien, que avance en angulos pequeños no significaba que lo estaba haciendo bien... de hecho lo hacia mal, ahora que ese comportamiento incorrecto te daba un efecto atractivo es otra cosa... pero era incorrecto...

el usar resolution, no es para nada engorroso, al contrario, es la idea de solucion simple... y existe desde tiempo de div... y advance es una de las razones de porque existe resolution, por eso me extraña que te funcione... si miras los ejemplos del help de div lo veras.

por otra parte, el compilador no da error al asignar decimales a x, el error esta en que el separador de decimales es el punto y no la coma.

gracias por reportar/preguntar estas cosas, ayudan a que muchos aprendan cosas nuevas que de otra forma no tenemos tiempo de explicar espontaneamente...

saludos...
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

FreeYourMind

Me imagino que del advance() o del resolution ya se hablo en más ocasiones, pero el problema el lo que dices, uno se pierde o no puede ver todo lo que se dice en todos los foros.

Que funcionara mal en Fenix se entiende, pero es que en Div funcionaba igual, entonces Div como producto comercial tambien funcionaba mal :)

Ya sabemos que Fenix tuvo lo suyo de ingenieria inversa para ser compatible con Div, pero con tantas funciones que tienen los mismos problemas/bugs que Div, tambien pienso que 'algo' del código de Div sirvio para crear Fenix :)

Y sobre lo de reportar cosas, y diferencias, para eso he abierto este hilo, en el cual pretendo poco a poco poner todas las diferencias que ya he vivido en los ports de Fenix a Bennu, que ayudaran a mas de uno que haga sus ports a Bennu, de eso estoy seguro :)

SplinterGU

te entiendo, uno no puede ver todo, no te hagas problemas...

asi es, como ya te dije, agradezco que hagas estas preguntas... nos da pie a dar informacion util para muchos...

gracias
Download Lastest BennuGD Release: http://www.bennugd.org/node/2

DCelso

Free, veo que se han mezclado los dos "topics" y no tiene sentido leer uno sin el otro, están relativamente encadenados.
Yo por mi parte intenté separarlos en dos temas independiente, el que te pasaba a tí de la resolución, este. Y el que me pasó a mí de solapamiento de procesos, el otro. Ya me parece casi imposible separarlos :(.
Yo suguiero para futuros posts intentar no mezclaros ya que , por ejemplo , en este caso se han resuelto las cosas dos veces y aún así quedan lagunas :D. Si ves, para este he usado tu ejemplo de disparo al completo, y para el otro he reducido al mínimo el ejemplo para mostrar el problema que tenía de solapamiento.
Monstruos Diabólicos

"A PAck of classic GAMEs For BennuGD" en desarrollo
http://code.google.com/p/apagame4be/