FASE (Fucking Awesome Spectrum Engine)

Chit chat general. Habla con los MojonTwins y con los amigos de los MojonTwins. Reza a Vah-ka. Delinque. Aviso: está PROHIBIDO tirarse peos fuerte. Si les cortas el pescuezo, vale.

Moderador: na_th_an

antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor antoniovillena » Sab, 17 May 2014, 20:53

Por si te sirve de ayuda, he implementado inercia y gravedad en el personaje principal para la demo. Para simplificar el suelo es una línea recta y el salto no es acumulativo. Pongo aquí el código y más abajo el TAP para que lo probéis:

Código: Seleccionar todo

#include  <stdlib.h>
#include  "fase.h"

#define gconst  20
#define maxvx   600
#define maxvy   600

extern unsigned char *ending;
const unsigned char data[20]= {
  0x00, 0x42, 0x11, 0,
  0x08, 0x60, 0x60, 2,
  0x09, 0x58, 0x48, 3,
  0x0a, 0x22, 0x02, 1,
  0x0b, 0x50, 0x6e, 2};

char i, j, killed, mapx, mapy, spacepressed, dirbul[4], num_bullets;
unsigned char tmpx, tmpy;
short x, vx, ax, y, vy, ay;
void remove_bullet( char k );
void update_screen();
void update_scoreboard();

main(){

start:
  killed= mapx= mapy= spacepressed= num_bullets= *shadow= 0;
  x= 0x3000;
  y= 0x1000;
  update_scoreboard();

  // inicializar engine
  INIT;

  // pasar datos a sprites y balas
  for ( i = 0; i < 5; i++ )
    sprites[i].n= data[0 | i<<2],
    sprites[i].x= data[1 | i<<2],
    sprites[i].y= data[2 | i<<2],
    sprites[i].f= data[3 | i<<2];
  for ( i = 0; i < 4; i++ )
    bullets[i].y= 255;

  // mostrar la primera pantalla al comienzo y marcador
  *screen= 0;

  while(1){

    // esto hace que el engine procese un frame generando el escenario
    M_OUTP(0xfe, 0);
    FRAME;
    M_OUTP(0xfe, 2);

    // movimiento de los enemigos
    for ( i = 1; i < 5; i++ )
      if( sprites[i].n<0x80 ){
        for ( j= 0; j < num_bullets; j++ )
          if( abs(bullets[j].x-sprites[i].x) + abs(bullets[j].y-sprites[i].y) < 10 ){
            sprites[i].n-= 0x80;
            remove_bullet( j );
            tmpx= sprites[i].x>>4;
            tmpy= sprites[i].y>>4;
            tiles[tmpy*scrw+tmpx]= 68;
            tilepaint(tmpx, tmpy, tmpx, tmpy);
            killed++;
            if( killed==10 ){
              EXIT;
              Dzx7b((unsigned int) (&ending-1), 0x5aff);
              Pause(100);
              goto start;
            }
            *drwout= (unsigned int)update_scoreboard;
          }
        if( sprites[i].f&1 )
          if( sprites[i].y>0 )
            sprites[i].y--;
          else
            sprites[i].f^= 1;
        else
          if( sprites[i].y<scrh*16 )
            sprites[i].y++;
          else
            sprites[i].f^= 1;
        if( sprites[i].f&2 )
          if( sprites[i].x>0 )
            sprites[i].x--;
          else
            sprites[i].f^= 2;
        else
          if( sprites[i].x<scrw*16 )
            sprites[i].x++;
          else
            sprites[i].f^= 2;
      }

    // movimiento de las balas
    for ( i = 0; i < num_bullets; i++ ){
      if( dirbul[i]&3 ){
        if( dirbul[i]&1 ){
          if( bullets[i].x<scrw*16 )
            bullets[i].x+= 2;
          else
            remove_bullet( i );
        }
        else{
          if( bullets[i].x>2 )
            bullets[i].x-= 2;
          else
            remove_bullet( i );
        }
      }
      if( dirbul[i]&12 ){
        if( dirbul[i]&4 ){
          if( bullets[i].y<scrh*16 )
            bullets[i].y+= 2;
          else
            remove_bullet( i );
        }
        else{
          if( bullets[i].y>2 )
            bullets[i].y-= 2;
          else
            remove_bullet( i );
        }
      }
    }



    vx+= ax;
    x+= vx;
    if( vx+8>>3 )
      ax= -vx>>3;
    else
      ax= vx= 0;
    if( (unsigned int)x > scrw<<12 )
      if( vx>0 )
        if( mapx < mapw-1 )
          x= 0,
          mapx++,
          update_screen();
        else
          x= scrw<<12,
          vx= 0;
      else if( mapx )
        x= scrw<<12,
        mapx--,
        update_screen();
      else
        vx= x= 0;
    sprites[0].x= x>>8;

    if( vy>maxvy )
      vy= maxvy;
    else
      vy+= ay+gconst;
    if( (unsigned int)y <= 15<<11 )
      y+= vy;
    else
      vy= 0,
      y= 15<<11;
    sprites[0].y= y>>8;


    // movimiento del protagonista
    if( inKey(KeybYUIOP) & 0x01 ) // P
      ax= vx<maxvx ? 40 : 0;
    else if( inKey(KeybYUIOP) & 0x02 ) // O
      ax= vx>-maxvx ? -40 : 0;
    if( inKey(KeybGFDSA) & 0x01 ){ // A
/*    if( sprites[0].y<scrh*16 )
        sprites[0].y++;
      else if( mapy < maph-1 )
        sprites[0].y= 0,
        mapy++,
        update_screen();*/
    }
    else if( inKey(KeybTREWQ) & 0x01 ){ // Q
      if( (unsigned int)y == 15<<11 )
        vy= -800;
    }
    if( inKey(KeybBNMs_) & 0x01 && !spacepressed && num_bullets<4 ){ // Space
      bullets[num_bullets].x= sprites[0].x;
      bullets[num_bullets].y= sprites[0].y;
      i= inKey(KeybTREWQ)<<3&8 | inKey(KeybGFDSA)<<2&4 | inKey(KeybYUIOP)&3;
      dirbul[num_bullets]= i ? i : 1;
      num_bullets++;
    }
    spacepressed= inKey(KeybBNMs_) & 0x01;
  }
}

void remove_bullet( char k ){
  if( num_bullets ){
    num_bullets--;
    while ( k<num_bullets )
      dirbul[k]= dirbul[k+1],
      bullets[k].x= bullets[k+1].x,
      bullets[k].y= bullets[++k].y;
    bullets[k].y= 255;
  }
}

void update_screen(){
  *screen= mapy*mapw + mapx;
  for ( j= 1; j < 5; j++ )
    if( sprites[j].n>0x7f )
      sprites[j].n-= 0x80;
}

void update_scoreboard(){
  unsigned int scr, dst;
  char count;
  scr= 0x3d80+killed*8;
  dst= 0x50de|*shadow<<8;
  for ( count= 0; count<8; count++ )
    zxmem[dst]= zxmem[scr++]^0xff,
    dst+= 0x100;
}

    #asm
        BINARY  "ending.rcs.zx7b"
._ending
    #endasm

Adjuntos
game.tap
(20.15 KiB) Descargado 178 veces
Avatar de Usuario
Hark0
Mensajes: 96
Registrado: Mar, 28 Ene 2014, 07:42
Ubicación: Cornellà de Llobregat - Barcelona
Contactar:

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor Hark0 » Lun, 19 May 2014, 07:06

Me gusta la suavidad del movimiento... es genial!

(otra vez pon una pausa más larga en la pantalla de la chica... :mrgreen: que casi no da tiempo a verla ;) )
litiopixel.blogspot.com - Desarrollo videojuegos Indie · Pixel-Art · Retroinformática · Electrónica
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor antoniovillena » Lun, 19 May 2014, 14:48

Es suave porque son 50fps reales. El inconveniente es que tienes que ajustarte al tiempo que te sobra del frame para la lógica del juego, y si te pasas te saltas un frame. Si te saltas varios frames seguidos el juego iría ralentizado a la mitad de la velocidad real.

El secreto para no gastar muchos ciclos en la lógica es usar como mucho enteros de 16 bits, y no usar multiplicaciones ni cuadrados, ni potencias ni cualquier cosa que no pueda hacer el Z80 rápidamente.

En cuanto a la chica ahí está la gracia, quedarte con las ganas de verla más tiempo y obligarte a echar otra partida.
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor antoniovillena » Mar, 20 May 2014, 18:14

He convertido la demo a HTML5 para facilitar la depuración. ¿Qué significa esto? Que si tienes instalado un apache en local puedes ejecutar directamente el código sin necesidad de compilación. Como el javascript es muy parecido al C luego no te va a costar mucho trabajo traducirlo, es un copy/paste con algún que otro ajuste.

Recomiendo usarlo con Chrome, que es el navegador que uso y por tanto con el que funciona seguro, además va bastante fluído.

Esto vale sólo para depurar, la versión HTML5 no está optimizada ni en velocidad ni en compatibilidad con otros navegadores. Si el objetivo es tener el juego bajo navegador también podría hacerse pero ya no sería tan cómodo para depurar (habría que tratar algunos archivos como map.tmx).

El enlace para probarlo está aquí:

http://antoniovillena.es/fase/game.html

Y el código fuente como siempre, en el repositorio, aunque también podéis extraerlo de aquí arriba, está sin ofuscar.
Avatar de Usuario
na_th_an
Mensajes: 26412
Registrado: Vie, 09 Ene 2009, 12:18

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor na_th_an » Mar, 20 May 2014, 18:35

Qué chulo :O
Como diría Rorshach: "Urm..."
Avatar de Usuario
Hark0
Mensajes: 96
Registrado: Mar, 28 Ene 2014, 07:42
Ubicación: Cornellà de Llobregat - Barcelona
Contactar:

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor Hark0 » Mié, 21 May 2014, 07:47

antoniovillena escribió:He convertido la demo a HTML5 para facilitar la depuración. ¿Qué significa esto? Que si tienes instalado un apache en local puedes ejecutar directamente el código sin necesidad de compilación. Como el javascript es muy parecido al C luego no te va a costar mucho trabajo traducirlo, es un copy/paste con algún que otro ajuste.

Recomiendo usarlo con Chrome, que es el navegador que uso y por tanto con el que funciona seguro, además va bastante fluído.

Esto vale sólo para depurar, la versión HTML5 no está optimizada ni en velocidad ni en compatibilidad con otros navegadores. Si el objetivo es tener el juego bajo navegador también podría hacerse pero ya no sería tan cómodo para depurar (habría que tratar algunos archivos como map.tmx).

El enlace para probarlo está aquí:

http://antoniovillena.es/fase/game.html

Y el código fuente como siempre, en el repositorio, aunque también podéis extraerlo de aquí arriba, está sin ofuscar.


:o Que bien se mueve en mi aipad!

Por Dios Antonio, métele soporte a un teclado que rule en una tableta!!! (yo no fui capaz por mucho que me mire lo que me pasaste/contaste... mis conocimientos son más limitados)
litiopixel.blogspot.com - Desarrollo videojuegos Indie · Pixel-Art · Retroinformática · Electrónica
Avatar de Usuario
Metalbrain
Mensajes: 9
Registrado: Mié, 21 May 2014, 21:19

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor Metalbrain » Jue, 22 May 2014, 21:25

La verdad es que el engine es alucinante. Un trabajo para quitarse el sombrero, Antonio.

Una micro optimización:

Código: Seleccionar todo

        ld      a, $18
        jr      z, do2
        ld      a, $17


se puede cambiar por:

Código: Seleccionar todo

        ld      a, $18
        jr      z, do2
        dec     a


Y también he visto que en las partes en las que se discrimina según la anchura (por ejemplo, al decidir entre del3, del4 o del5), la parte de código más corta (y por tanto más rápida) se beneficia de no tener que dar el salto hacia delante, lo cual acentúa las diferencias de velocidad respecto a las otras. Tal vez sea conveniente mover un poquito el código para que la parte más larga y lenta se beneficie de no tener que dar el salto.
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor antoniovillena » Jue, 22 May 2014, 23:06

Hark0 escribió: :o Que bien se mueve en mi aipad!

Por Dios Antonio, métele soporte a un teclado que rule en una tableta!!! (yo no fui capaz por mucho que me mire lo que me pasaste/contaste... mis conocimientos son más limitados)


Ahora mismo es que no se trata de portar el juego a HTML5, sino de tener un mecanismo rápido de depuración. Si te das cuenta no se necesita línea de comandos para nada, es editar y pulsar F5 en el navegador. La idea es hacer las pruebas en HTML5 y una vez estén los cambios definitivos trasladarlos a C.

Si más adelante tiene éxito podemos hablar de un port para HTML5, en este caso sí que sería interesante tener un teclado en pantalla.

Metalbrain escribió:La verdad es que el engine es alucinante. Un trabajo para quitarse el sombrero, Antonio.

Una micro optimización:

Código: Seleccionar todo

        ld      a, $18
        jr      z, do2
        ld      a, $17


se puede cambiar por:

Código: Seleccionar todo

        ld      a, $18
        jr      z, do2
        dec     a


Y también he visto que en las partes en las que se discrimina según la anchura (por ejemplo, al decidir entre del3, del4 o del5), la parte de código más corta (y por tanto más rápida) se beneficia de no tener que dar el salto hacia delante, lo cual acentúa las diferencias de velocidad respecto a las otras. Tal vez sea conveniente mover un poquito el código para que la parte más larga y lenta se beneficie de no tener que dar el salto.


Gracias, ya he trasladado el cambio al repositorio. El engine lo tengo un poco abandonado, apenas lo he cambiado desde que lo hice, lo único que he hecho es soportar Z88DK y darle inercia y gravedad al protagonista de la demo. Yo no programo juegos, no tengo experiencia, mi idea era crear el germen de una Churrera mejorada sin las limitaciones actuales. Pero claro, se necesita programar el resto del juego en C.

Cuando lo acabé tenía unas ideas para ir mejorando el engine, pero claro esto depende del éxito que tenga:

  • La gran limitación es el número de sprites, como están prerrotados no caben muchos en memoria. Ahora mismo hay soporte para los mismos que la Churrera, es decir 16 sprites.
  • Una posible solución es usar tablas para rotar los sprites como hace splib, aunque creo que va a ser bastante más lento de lo que hay, y por lo tanto se reduciría el número máximo de sprites que se pueden mover sin parpadeo (ahora mismo en un 48K el límite es más o menos 8 sprites)
  • Otra solución es calcular las prerrotaciones de los sprites en cada pantalla. Es decir, puedo tener un montón de sprites de enemigos almacenados sin rotar. En el momento en que cambio de pantalla genero las versiones rotadas de los enemigos que aparecen en dicha pantalla. Esto hace que el cambio de pantalla sea más lento pero si aumenta la variedad de sprites merece la pena. Tendríamos la limitación de 4 tipos distintos de enemigos por pantalla, aunque con eso hay de sobra.
  • También tenía pensado meter varios niveles con multicarga trasparente. Es decir que automáticamente el engine se encargue de generar los bloques. Si tenemos un 128K se cargan del tirón, si es un 48K se hace por niveles mostrando los típicos mensajes de "rebobina", "dale al play", etc...

Si te resulta interesante el proyecto, tanto para continuarlo como para hacer un juego con él, te doy acceso al repositorio. Y si no te manejas con GIT te lo muevo a otro sitio.

En cuanto al salto y la anchura en su momento le di el camino más corto a la anchura de 2 bytes, supongo que era la que más se repetía, al menos en los sprites de la demo. Tendría que analizar distintos sets de sprites para ver cual de los 3 anchos merece la pena acortar.
Avatar de Usuario
D_Skywalk
Mensajes: 352
Registrado: Mar, 01 Oct 2013, 13:36

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor D_Skywalk » Jue, 29 May 2014, 11:58

Muy wapo antonio el html5, una mini sugerencia:

Código: Seleccionar todo

canvas {  image-rendering: -moz-crisp-edges; }


Eso quita el suavizado en mozilla, pero en chrome no funciona su versión webkit (ya que el canvas lo generas con el js), si quieres revisarlo... https://code.google.com/p/chromium/issu ... ?id=134040

Por cierto, en Junio tengo un par de semanas libres y estoy preparando una pequeña JAM para hacer un pequeño juego/ejemplo con FASE. Ahora lo posteo por aquí también por si algún compa se anima también ;)
David Skywalker
Weblog: http://david.dantoine.org
antoniovillena
Mensajes: 494
Registrado: Jue, 24 Oct 2013, 15:52

Re: FASE (Fucking Awesome Spectrum Engine)

Mensajepor antoniovillena » Vie, 30 May 2014, 03:49

Gracias por la sugerencia. El suavizado no molesta, incluso queda mejor. En Firefox se gana algo de rendimiento sin suavizado. El código que hay ahora es simple, no está optimizado en velocidad. En cada frame se sobreescribe el fondo completo, cuando lo más rápido sería restaurar sólo las porciones que quedan detrás de los sprites.

Genial, si quieres puedes publicarla (la demo) en el propio repositorio de FASE, en otra carpeta.

Volver a “General”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado