CPCtelera, desarrollar juegos para Amstrad de forma sencilla

Programando el Amstrad en BASIC, C, etc.
Avatar de Usuario
MiguelSky
Lord of Short Time
Lord of Short Time
Mensajes: 6965
Registrado: Sab 08 Oct , 2005 2:02 am
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor MiguelSky » Sab 15 Ago , 2015 12:31 pm

Pues la 1.2.3 creo que la descargué en zip desde el enlace de aquí arriba, probaré desde el repositorio, a ver. La instalo ejecutando el setup.sh. He reinstalando sobre una versión que tenía ya instalada pero que he cambiado de directorio bajo Windows 7/Cygwin 32. El Cygwin lo instalé cuando salido CPCtelera y no he probado a actualizarlo (ahora no se qué versión tengo, me ocurre en el portátil, probaré a actualizar).

Esta tarde pruebo de nuevo y te digo.

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Sab 15 Ago , 2015 1:25 pm

En Windows 7 no he probado con Cygwin 32 (ahí tengo Cygwin 64). Ahora probaré a instalarlo a ver.

Si no has sobreescrito el directorio anterior de CPCtelera no hay ningún problema en instalar versiones nuevas cuando ya habían versiones anteriores. La instalación está toda dentro del propio directorio.

Avatar de Usuario
MiguelSky
Lord of Short Time
Lord of Short Time
Mensajes: 6965
Registrado: Sab 08 Oct , 2005 2:02 am
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor MiguelSky » Sab 15 Ago , 2015 5:57 pm

Si no has sobreescrito el directorio anterior de CPCtelera no hay ningún problema en instalar versiones nuevas cuando ya habían versiones anteriores. La instalación está toda dentro del propio directorio.
Pues este debía ser el problema: he eliminado la carpeta y la he vuelto a copiar desde el comprimido de más arriba y ahora sí que va :)

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Sab 15 Ago , 2015 6:08 pm

Me alegro de que la solución haya sido tan fácil. Ya estaba pensando en condiciones extrañas que pudieran darse en Cygwin32 bajo Win7 :). Habrá sido algún archivo de versión anterior mezclado con los de la versión nueva.

Avatar de Usuario
MiguelSky
Lord of Short Time
Lord of Short Time
Mensajes: 6965
Registrado: Sab 08 Oct , 2005 2:02 am
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor MiguelSky » Sab 15 Ago , 2015 8:28 pm

Estoy tratando de hacer el script para lanzar el emu y me da errores sintácticos en

Código: Seleccionar todo

while [ "$#" -gt "0" ]; do
case "$1" in
Lo he repasado 8000 veces y no veo nada raro...

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Sab 15 Ago , 2015 8:35 pm

Si lo has copiado y pegado en un editor de Windows, Cygwin te puede estar dando problemas por tener caracteres extraños y saltos de línea de MSDOS (\r). Si tienes algún editor que filtre eso y pueda salvarlo en formato UNIX (creo que Notepad++ lo hace) mejor. Si no, puedes bajarte la utilidad dos2unix con el setup.exe de Cygwin y te convertirá el fichero a formato UNIX.

Avatar de Usuario
MiguelSky
Lord of Short Time
Lord of Short Time
Mensajes: 6965
Registrado: Sab 08 Oct , 2005 2:02 am
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor MiguelSky » Sab 15 Ago , 2015 9:35 pm

Creo que el salto /r venía en el primer error, voy a tirar por ahí ;)

Avatar de Usuario
AmstradGamer
Forero habitual
Forero habitual
Mensajes: 189
Registrado: Dom 08 Jun , 2014 10:08 am

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor AmstradGamer » Mié 19 Ago , 2015 4:04 pm

Buenas.

No sé si es el lugar adecuado, pero tengo unas dudas y las planteo aquí. A ver si tengo suerte y me las podéis resolver:

1- He leído el formato que debe tener un sprite con máscara para poder aplicarle transparencias. Lo tengo claro, pero, ¿hay manera de exportar desde RGAS en dicho formato o me tengo que currar el array a mano?

2- Leyendo antes en en hilo comentaís que se pierde tiempo metiendo y sacando de la pila los parámetros cuando se hacen llamadas a funciones. ¿Es preferible entonces utilizar variables globales que ir moviéndolas entre llamadas a funciones?

3 - ¿Es interesante que utilicemos __z88dk_callee y __z88dk_fastcall en nuestro código para optimizar cuando sea posible?

4 - Para implementar una función de redifición de teclas, ¿cual es la manera aconsejada de hacerlo? No hay en cpctelera una función específica que lea qué tecla ha sido pulsada y no creo que recorrer toda la enumeración de teclas sea lo adecuado para saber qué tecla se ha pulsado.

5 - ¿Dónde podemos reportar erratas en la documentación de cpctelera? Es una chorrada lo que he visto, pero creo que en la documentación de la función cpct_waitVSYNC donde dice "This function is optimized for size (instead of space)" debería poner speed en lugar de space.

6 - Duda sobre el uso de doble buffer. Si todos los cálculos que ha de hacer en un ciclo del juego, a 50HZ, da tiempo de sobras a hacerlos en 1/50 segundos y esperamos al VSYNC para pintar, ¿hay alguna ventaja en utlizar doble buffer?

Como véis, no son pocas las dudas. He acabado mi propuesta para la #cpcretrodev2015 y como he aprendido (y refrescado, que no recuerdo la última vez que había programado en C) mucho y hay tiempo de sobras, me he liado con un proyecto un poco más ambicioso y me gustaría que saliera lo mejor posible.

Muchas gracias por adelantado. :)

Saludos.

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Jue 20 Ago , 2015 10:16 am

Buen montón de preguntas, @AmstradGamer :). Vamos con ellas...
  1. La última versión de RGAS viene en la carpeta tools de CPCtelera. Esa versión exporta los gráficos que hagas a array de C, listo para que lo copies a un fichero .c y lo pongas en un proyecto de CPCtelera. El formato tienes que elegirlo al principio, cuando creas el set de sprites (CPCtelera C Array). Después, cada sprite que quieras con máscara lo debes definir en el momento que creas el sprite o en sus propiedades: te da la opción de poner los con máscara. Por último, en la barra de iconos de RGAS tienes una opción que exporta el código de los sprites que tienes.
  2. No te recomiendo que te entretengas con esto. Meter cosas en variables globales también tiene un coste de lectura y escritura: nada es gratis. Es mejor que procures hacer un buen código, legible y mantenible, que tratar de optimizar usando globales. Hay muchas formas de optimizar, y esta, en caso de que se haga bien, no es apenas significativa. Ganarás más, por ejemplo, aprendiendo a escribir código de forma que SDCC te genere una mejor salida: funciones con pocas variables, buen uso de punteros... De esto, cuando tenga tiempo, me gustaría hacer algunos artículos y ejemplos.
  3. __z88dk_callee sólo lo puedes usar si programas funciones en ensamblador. Si sabes cómo hacerlo, sí, es muy recomendable. __z88dk_fastcall lo puedes usar incluso en C: es recomendable ponerlo para cualquier función que tenga exactamente 1 parámetro. No vale para ninguna otra cosa: es específico para eso.
  4. Ahora mismo no hay ninguna función que te diga la última tecla pulsada en CPCtelera, pero se puede hacer de varias formas, aunque son un poco "de bajo nivel", por así decirlo. La forma más fácil sería esperar a que se pulse una tecla usando cpct_isAnyKeyPressed() para esperar a que se pulse una tecla y, después, escanear para ver qué tecla ha sido pulsada. Este escaneo es exactamente recorrer todas las teclas una a una para ver cuál ha sido pulsada, pero de forma eficiente: para eso está el array global cpct_keyboardStatusBuffer. Se trata de un array de bits que contiene el estado de todas las teclas. Haciendo un bucle, podemos comprobar cuál está pulsada y construir su código de tecla para devolverlo:

    Código: Seleccionar todo

    cpct_keyID esperaUnaTecla() {
    // Recorreremos el vector de teclas desde el final hacia el principio,
    // para poder hacer que el bucle acabe en 0 (así el compilador podrá optimizarlo)
    u8 i = 10, *keys = cpct_keyboardStatusBuffer + 9;
    u16 keypressed;

    // Esperamos hasta que se pulse una tecla
    do { cpct_scanKeyboard(); } while ( ! cpct_isAnyKeyPressed() );

    // Detectamos cuál tecla ha sido pulsada
    do {
    // Si en este grupo de 8 teclas hay una pulsada, alguno de los bits estará a 0
    // En caso contrario, todos estarán a 1, y un XOR con 0xFF dará 0 (false) como resultado
    keypressed = *keys ^ 0xFF;
    if (keypressed)
    return (keypressed << 8) + (i - 1); // Formato cpct_keyID: 8 primeros bits = máscara de tecla, 8 siguientes fila del teclado (0-9)
    keys--;
    } while(--i);
    return 0;
    }
    Lo único que te faltará aquí son los nombres de las teclas (en formato ASCII strings) para poder escribirlos por pantalla. Para eso te hará falta un array de constantes o similar.
  5. El lugar más adecuado para reportar erratas es github, abriendo issues. Aunque sean chorradas, como en este caso, siempre es útil corregir cualquier detalle :). Gracias por el aviso.
  6. El problema por el que se usa el double buffer no son los "cálculos" en general. El problema es pintar en pantalla, que es una operación muy muy lenta en el CPC. Pintar en pantalla es copiar bytes desde una posición de memoria X a la memoria de vídeo. Como esta operación es muy lenta (si es con máscara, aún más), en cuanto haya que copiar varios sprites nos puede pillar el haz de electrones y hacer que en pantalla se vea una parte del sprite del frame anterior, y otra parte del frame que aún no hemos acabado de pintar. Esto es lo que produce el flickering. Las 2 formas de evitarlo son: tener muy bien estructurado y medido el bucle de pintado, para garantizar que nunca nos va a pillar el haz de electrones, o pintar fuera de la memoria de vídeo, para que no se vea: en esta segunda opción, cuanto terminamos de pintar, le decimos que cambie la ubicación de la memoria de vídeo, y así pasa a pintar en pantalla nuestro nuevo frame, que ya está terminado. Esto es el double buffering. Las rutinas de pintado de CPCtelera vienen con mediciones de tiempo para que puedas calcular. Ten en cuenta que un barrido competo del haz de electrones tarda 19968 microsegundos, a 64 por cada scanline (312 scanlines, 200 de pantalla, 112 de borde + VSYNC). Con esto puedes calcular si te dará tiempo a dibujar o no algo antes de que te llegue el haz.
Ya tienes terminado tu juego para el #CPCRetroDev? Pero si quedan 2 meses!! Aún tienes tiempo de hacerle mejoras todas las que quieras ;).

Espero que estas respuestas te sean de ayuda. Si tienes más dudas, ya sabes dónde estamos ;).

Avatar de Usuario
AmstradGamer
Forero habitual
Forero habitual
Mensajes: 189
Registrado: Dom 08 Jun , 2014 10:08 am

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor AmstradGamer » Jue 20 Ago , 2015 11:25 am

Hola.

Qué gusto da leer respuestas así. Muchas gracias.

1 - No vi la opción, está claro que no miré bien. Mis perdones. He utilizado RGAS para todo los gráficos y salvo algún casque eventual me parece una herramienta muy cómoda cuando le coges el tranquillo.

2 - Gracias por la aclaración. Estaré atento a tus artículos. De momento me centraré en hacer el código lo mejor que pueda sin romperme la cabeza por optimizar usando globales.

3 - Revisaré mis funciones y añadiré fastcall a aquellas que tengan 1 parámetro, si es que las hay.

4 - Gracias por la explicación y el ejemplo. Reconozco que me cuesta pensar en algo más pequeño que un byte (bits).

5 - Si detecto algún punto más lo reportaré en github. Gracias.

6 - En mi juego estoy utilizando doble buffer por hardware, basados en tus ejemplos de cpctelera, pero dedicar la mitad de la RAM solo a video me parece una pasada. Por suerte no creo que sea un problema y me cabrá todo el juego en el resto.

A ver, he acabado un juego, pero no es el que voy a presentar, así que no lo voy a mejorar. De hecho lo "terminé" para hacerlo jugable y acabable, pero no incluí todo lo que tenía pensado.

Se trata de un juego musical, digamos que una versión de DJ MAX de PSP pero para CPC. No me ha gustado el resultado final, aunque en el hardware real queda mucho más resultón que en el emulador donde probaba cuando estaba de vacaciones, y por eso me he animado a hacer el que tengo entre manos.

Menos mal que quedan dos meses y me da tiempo a hacer éste otro. Un arcade de los de toda la vida que me está resultando muy gratificante y es mucho más vistoso y divertido. Espero que guste el resultado final.

En fin, muchas gracias por las explicaciones. Espero poder adelantar este fin de semana y tu ayuda seguro que me sirve de mucho.

Un saludo.

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Vie 21 Ago , 2015 2:44 pm

Me alegro de que las respuestas te sean de utilidad, para eso estamos :).

Ciertamente, dedicar la mitad de la RAM a video es bastante doloroso. Cuando se trabaja a bajo nivel, esto puede reducirse utilizando una pantalla partida, de modo que se cambia de buffer a mitad del dibujado de cada frame para pintar un marcador fijo, y se tienen 2 bufferes de pantalla más pequeños que 1 página completa de memoria. Con estas técnicas, se pueden usar entre 20 y 24K de memoria para la pantalla, liberando 8-12K adicionales para el programa, lo que es bastante ganancia. Tengo previsto incorporar estas técnicas en un futuro a CPCtelera, pero requerirán mucho diseño para poder hacerlas desde C, a alto nivel, sin un coste importante para el programador.

La otra opción, que es la más complicada, es la de usar un sólo buffer y hacer una rutina de dibujado sincronizada con el haz de electrones para garantizar que no te pilla. Esto se puede hacer ya mismo con CPCtelera sin excesivo esfuerzo. Para hacer algo así, recomendaría estas pautas:
  • Dibujar la zona de juego en la parte inferior de la pantalla y el marcador en la superior (así hay más tiempo hasta que llega el haz a la zona de juego)
  • Contar los microsegundos disponibles hasta que llega el haz de electrones
  • Diseñar una rutina de dibujado que tenga en cuenta lo que debe tardar como máximo y que se asegure de dibujar menos.
  • Opcionalmente, hacer que la rutina dibuje en orden, de arriba hacia abajo de la zona de juego.
Con esto puedes conseguir buenos resultados :).

Me alegra mucho ver que hay gente como tú haciendo varios juegos. Siempre digo que las primeras cosas que uno hace son para tirarlas a la basura porque forman parte del aprendizaje. Espero que nos des buenas sorpresas con lo que entregues al concurso :)

Avatar de Usuario
AmstradGamer
Forero habitual
Forero habitual
Mensajes: 189
Registrado: Dom 08 Jun , 2014 10:08 am

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor AmstradGamer » Vie 21 Ago , 2015 8:37 pm

Buenas.

De momento me voy a limitar a las funcionalidades que ofrece CPCtelera y ya haré cosas más sofisticadas a medida que ésta las permita. :)

No sé si es abusar... pero tengo otra duda.

Verás. Quiero utilizar EasyTileMaps para dibujar el suelo de mi juego, aún sabiendo que el ancho máximo es de 127 tiles, siempre puedo tener varios mapas he ir pasando de uno a otro. El problema no es este.

Creo que no es descabellado hacer lo que intento, simplificando y sin chequeos:

TScreenTilemap floor = { 0, 0, {0, 0, 30, 3}}; //0,0 no es la posición adecuada para el suelo, pero para el ejemplo sirve

while(1){

floor.viewport.x++;

drawFloor(&floor);

}

void drawFloor(TScreenTilemap *floor) {


u8* pvideo = cpct_getScreenPtr(g_scrbuffers[1], floor->x, floor->y);

cpct_etm_drawTileBox2x4(floor->viewport.x, floor->viewport.y,
floor->viewport.w, floor->viewport.h,
FLOOR_WIDTH, pvideo, g_floorTilemap);

}


Las estructuras son las mismas que en el ejemplo de CPCtelera sobre easytilemaps.

Lo que entiendo que debería hacer esto es dibujar un rectángulo de 30 x 3 tiles, en la posición, 0,0 y al ir incrementando el valor de viewport.x se debería ir desplazando la parte visible del tilemap de modo que siempre tuviera un rectángulo de 30 x 3 en la posición 0,0 pero el efecto sería de ir desplanzando el tilemap y por lo tanto un scroll...

Pero lo que ocurre es que al incrementar el valor del viewport, también se incrementa el valor de la posición de pantalla donde se dibuja, así que efectivamente se desplaza la parte visible del tilemap, pero también la ventana a lo ancho de la pantalla. Si me explico, en la primera iteración tengo el rectángulo en 0,0, en la siguiente en 1,0 , luego 2,0 , etc...

He mirado la documentación y veo esto:

pvideomem should be a pointer to the video memory or backbuffer address where the upper-left corner of the tilemap is drawn. Please note that it should point to the start of the tilemap, and NOT the start of the tilebox, in video memory or backbuffer.

No sé si de ahí he de deducir que obtengo el punto a la memoria de video he de restar el desplazamiento de la coordenada, cosa imposible y sin demasiado sentido.

Igual es que simplemente estoy utilizando funciones que no están pensadas para lo que quiero hacer.

Un saludo y gracias de nuevo por la ayuda.

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Vie 21 Ago , 2015 9:01 pm

Tienes un problema de inicialización de variables. Hace tiempo que tengo pendiente escribir un artículo al respecto, porque todo el mundo pasar por ahí almenos una vez, pese a que en muchos ejemplos de CPCtelera se indica en los comentarios. Creo que hace falta un artículo teórico que lo referencie explícitamente.
Tu problema esta en esta línea:

Código: Seleccionar todo

TScreenTilemap floor = { 0, 0, {0, 0, 30, 3}};
Declaras floor como una variable global con un inicializador. Esto en SDCC no debe hacerse cuando creas un programa que vaya a funcionar en RAM. SDCC es un compilador embebido, y está pensado para generar ROMs. En una ROM no es posible inicializar variables (porque la ROM es de sólo lectura). Por este motivo, SDCC incluye código para copiar los valores de ROM a RAM durante la inicialización. Esto en un programa para funcionar en la RAM del CPC es un completo desastre. Significa tener los valores iniciales almacenados en una parte de la RAM y copiarlos sobre las variables (en otra parte de la RAM) usando código durante la inicialización. Así, los valores estarían duplicados y, además, tendríamos código de copia ocupando tiempo y espacio.

Por este motivo, el fichero crt0.s estándar que define el mapa de memoria y las funciones básicas (llamar al main después de hacer estas copias) no incluye el código de inicialización. Eso significa que cualquier variable global con inicializador no va a ser inicializada. Por lo tanto, tu variable floor es muy probable que esté toda a 0's, y el 30 y el 3 se hayan perdido en el cosmos.

Por esto es por lo que todas las "variables globales" en CPCtelera se declaran utilizando const. Porque las constantes en SDCC sólo ocupan un espacio en memoria (dentro del binario) y tienen ya su valor asignado. Técnicamente, las constantes no pueden modificarse. Sin embargo, si obtienes un puntero a una constante y lo usas, puedes modificarla perfectamente porque son valores almacenados en RAM. Obtienes un warning, pero como sabemos que lo estamos haciendo a propósito, no hay problema.

Puedes ver un ejemplo de esto en el ejemplo de easyTilemaps precisamente, cuando se declaran los 2 buffers:

Código: Seleccionar todo

u8* const g_scrbuffers[2] = { (u8*)0xC000, (u8*)0x8000 };
//.....
void swapBuffers(u8** scrbuffers) {
u8* aux;
cpct_setVideoMemoryPage( (u16)(scrbuffers[1]) >> 10 );
aux = scrbuffers[0];
scrbuffers[0] = scrbuffers[1];
scrbuffers[1] = aux;
}
//.....
swapBuffers(g_scrbuffers);
//....
Si quitas el const, verás como el programa peta, por no inicializar los valores. Además, a la función swapBuffers se le llama pasándole una copia del puntero g_scrbuffers que es constante, pero la copia se hace sobre la variable scrbuffers que es un puntero no-constante. Esto da un warning al compilar, pero funciona perfectamente, y los buffers se modifica in-place (sin generar copias absurdas) a través del puntero scrbuffers.

Esto es todo un poco largo, pero espero haberme explicado suficientemente bien como para que se entienda :).

Avatar de Usuario
AmstradGamer
Forero habitual
Forero habitual
Mensajes: 189
Registrado: Dom 08 Jun , 2014 10:08 am

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor AmstradGamer » Vie 21 Ago , 2015 9:47 pm

Entendidísimo.

No había tenido en cuenta todas estas consideraciones, intentaré ser más riguroso leyendo los comentarios de los ejemplos.

Muchas gracias, das una soporte estupendo tanto en este como en otros foros.

Un saludo.

Avatar de Usuario
ronaldo
Forum Addict
Forum Addict
Mensajes: 358
Registrado: Sab 14 Sep , 2013 9:31 pm
Ubicación: Alicante
Contactar:

Re: CPCtelera, desarrollar juegos para Amstrad de forma senc

Mensajepor ronaldo » Vie 21 Ago , 2015 9:59 pm

Gracias. Siempre que pueda ayudar, lo intento, mientras tenga tiempo para hacerlo :).

Es normal que estos detalles se escapen: es mucha información para procesar. Hay muchos detalles que conocer cuando se quieren hacer las cosas teniendo todo el control. Normalmente se aprenden "the hard way". Yo mismo me encontré con este comportamiento de SDCC depurando en ensamblador y luego lo leí en las especificaciones. Tiene sentido cuando lo entiendes, pero mientras tanto es doloroso :).

A ver si tengo tiempo para añadir documentación a CPCtelera que incluya estas explicaciones :)


¿Quién está conectado?

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


La Comunidad Española
ESP Soft, juegos para tu CPC Foro de Amstrad CPC Todos los juegos para CPC en un CD Web dedicada al Amstrad CPC (utilidades) Información útil para el CPC (talleres) Selección de juegos de Amstrad CPC Mundo CPC Pree Play then any Key CPC Basic