martes, 22 de diciembre de 2015

Ejemplo de cursor en pantalla

He aquí un ejemplo de como podemos implementar un cursor en pantalla. 

Está pensado para trabajar, como un cursor en pantalla de modo texto, al uso de lo que estamos acostumbrados. 

Para realizar el cursor, tenemos que tener en cuenta tanto las características del BASIC como las limitaciones en pantalla a la hora de imprimir texto. 

Es decir, tenemos que gestionar dos cosas:

1) El texto que se encuentra en las coordenadas del cursor.

2) Los atributos de dicho texto (color del texto, color de fondo, brillo e intermitencia). 

El cursor debe desplazarse por la pantalla sin modificar el valor original de la celda donde se encuentre. Para ellos tenemos que tener en cuenta los puntos 1 y 2 cuando movamos dicho cursor. 

Para esto usaremos dos funciones del BASIC; 

1) SCREEN$ para obtener el carácter que está en las coordenadas X,Y.

2) ATTR para obtener sus atributos (color, fondo brillo e intermitencia). Usa el mismo mecanismo de coordenadas X e Y. 

La función SCREEN$ nos devuelve (solo) el carácter que está en la celda X,Y. No devuelve ni sus atributos (que se obtienen con ATTR) ni valor cuando el carácter en la celda es un UDG

Para obtener un valor si es un UDG hay una manera, que se describe en otro ejemplo

El valor que nos devuelve ATTR es un valor numérico que se descompone de la siguiente manera:
  • Si el valor es superior a 128, el carácter está en modo intermitente (FLASH 1).
  • Si el valor es superior a 68, el carácter tiene brillo (BRIGHT 1). 
  • El valor de ATTR (si toca restar porque es mayor de 68 y/o 128) dividido entre 8 nos da el color del fondo (PAPER). 
  • El valor de ATTR menos el valor del fondo (PAPER) nos da el color del carácter (INK). 

Extracto del programa de ejemplo: 
LET f=0
IF z>128 THEN LET f=1: LET z=z-128
LET b=0
IF z>64 THEN LET b=1: LET z=z-64
LET p=INT (z/8)
LET co=z-(p*8)
PRINT FLASH f; INK co; BRIGHT b; PAPER p;z$

La filosofía del cursor es sencilla:

1) Guardamos en dos variables el valor de la celda y sus astributos.

2) Imprimimos el cursor encima (OVER 1) ,intermitente (FLASH 1) y con brillo (BRIGHT 1) para que se vea fácil en el ejemplo.

3) Al movernos, restauramos el valor de la celda donde estábamos.

Llenamos la pantalla de caracteres generados de forma aleatoria y vemos como funciona el cursor. En la parte de abajo nos da una linea de ayuda con las teclas para mover dicho cursor.

He usado unos UDG de flechas en la linea de ayuda, para hacerlo más amigable.

El código BASIC lo puedes descargar de aquí.

Una versión del ejemplo pasada a código máquina la tienes aquí.

Debajo de la imagen está el listado completo por si lo quieres copiar y pegar.



















5 CLEAR
10 LET t$="Ejemplo de cursor"
20 CLS
30 BORDER 4
40 GO SUB 460
50 PRINT AT 0,INT ((32-LEN t$)/2); INK 2;t$
60 FOR y=1 TO 20
70 FOR x=0 TO 31
80 LET co=INT (RND*8)
90 IF co=2 THEN GO TO 80
100 LET ff=INT (RND*10)
110 LET f=0
120 IF ff>8 THEN LET f=1
130 LET p=INT (RND*8)
140 IF p=2 THEN GO TO 130
150 PRINT AT y,x; INK co; FLASH f; PAPER p;CHR$ (65+(1+(RND*60)))
160 NEXT x
170 NEXT y
180 LET x=0: LET y=1: LET xant=x: LET yant=y: LET z$= SCREEN$ (y,x): LET z=ATTR (y,x): PRINT AT y,x; OVER 1; FLASH 1; INK 2; BRIGHT 1;"\::"
190 PRINT AT 21,0; INK 0;"u(";CHR$ 144;"),d(";CHR$ 145;"),l(";CHR$ 146;"),r(";CHR$ 147;") o q"
200 LET i$=INKEY$
210 IF i$="q" THEN GO TO 420
220 IF i$<>"l" AND i$<>"r" AND i$<>"u" AND i$<>"d" THEN GO TO 200
230 LET xant=x: LET yant=y
240 IF i$="l" THEN IF x>=1 THEN LET x=x-1
250 IF i$="r" THEN IF x<31 THEN LET x=x+1
260 IF i$="u" THEN IF y>1 THEN LET y=y-1
270 IF i$="d" THEN IF y<20 THEN LET y=y+1
280 GO SUB 300
290 GO TO 200
300 LET f=0
310 IF z>128 THEN LET f=1: LET z=z-128
320 LET b=0
330 IF z>64 THEN LET b=1: LET z=z-64
340 LET p=INT (z/8)
350 LET co=z-(p*8)
360 PRINT AT yant,xant; OVER 0; FLASH f; INK co; BRIGHT b; PAPER p;z$
370 LET z$= SCREEN$ (y,x)
380 LET z=ATTR (y,x)
390 PRINT AT y,x; OVER 1; FLASH 1; INK 2; BRIGHT 1;"\::"
400 PRINT AT 0,26;"     ": PRINT AT 0,26;y;" ";x
410 RETURN
420 CLS : CLEAR : BORDER 7: PRINT AT 0,0; INK 0;"Adios"
430 STOP
440 DATA 0,24,60,126,126,24,24,0,0,24,24,126,126,60,24,0
450 DATA 0,16,48,126,126,48,16,0,0,8,12,126,126,12,8,0
460 RESTORE 440
470 FOR i=0 TO 15
480 READ a
490 IF i<=7 THEN POKE USR "a"+i,a
500 IF i>7 THEN POKE USR "b"+(i-8),a
510 NEXT i
520 RESTORE 450
530 FOR i=0 TO 15
540 READ a
550 IF i<=7 THEN POKE USR "c"+i,a
560 IF i>7 THEN POKE USR "d"+(i-8),a
570 NEXT i
580 RETURN



jueves, 17 de diciembre de 2015

¡ZX Retro8ogue actualizado !. Avances

¡Avances de este nuevo ZX Retro8ogue!

Ya tenemos un pequeño motor del juego capaz de: 
  • Generar un mapa aleatorio conteniendo de 1 a 4 edificios.
  • Rellenar los exteriores con árboles y rocas. 
  • Generar las salidas y entradas a otros mapas. 
  • Espacio para información de nuestro héroe. 
  • Sistema de texto emergente, para la ayuda / información en juego / inventario.
  • Depurado del motor hasta el momento.
  • Revisión del código para mejor rendimiento del compilador HiBasic a código máquina. 
  • Tamaño de código. Actualmente está en 10Kb de BASIC y 14Kb compilado a mcode. 
  • Pasados los UDG a decimal (¡espacio!).
  • Optimizaciones varias de rendimiento (bucles y re-utilización de variables).

Por el momento, el motor en su estado actual está probado tanto en BASIC como en código máquina.

Podéis descargar del código fuente de este enlace (formato tap) y la cinta con su cargador y su código máquina, en este otro enlace (formato tap).

Una vez ejecutado y cargado, puedes usar "h" para ver el sistema de texto emergente. con "q" salimos del programa. El efecto de vuelta al mapa desde la ventana de texto emergente, es muy chulo :D.

Puedes descargar una grabación hecha en el emulador Fuse desde aquí. Para visualizarla usa el  menú "File/recording/Play".


¡ Seguiré informando de los avances de este nuevo ZX Retro8ogue !.

lunes, 14 de diciembre de 2015

BASIC, no puedo localizar UDG's con SCREEN$ !!. He aqui una opción buena bonita y barata.

Una de las funciones más útiles que tiene el BASIC de nuestro ZX Spectrum es SCREEN$. 

Gracias a esta función podemos saber que carácter se encuentra presente en la pantalla, dadas las coordenadas X e Y.

En el modo de "texto" tenemos 22 líneas (Y) y 32 columnas (X). Es muy cómodo, utilizar SCREEN$ como mecanismo de detección de colisiones en un juego en el que hallamos usado caracteres (de 8x8) como gráficos. 

Como se puede ver en !Como me gustan los UDG! es muy sencillo usar los 20 caracteres de gráficos de usuario que nos facilita el Spectrum, para hacer nuestros propios sprites de 8x8. 

Los podemos usar en pantalla, y todo bien, hasta que se nos ocurre la brillante idea de usar SCREEN$ para obtenerlos de pantalla. SCREEN$ nos devolverá un vacío, dado que no es capaz de gestionar los UDG. Nuestro gozo en un pozo. 

He aquí unas cuantas líneas de código para tener nuestro propio "SCREEN$" y poder identificar los UDG en pantalla. 

La idea es la misma, le damos unas coordenadas de linea/columna, y el código nos devuelve el código UDG al cual pertenece. Si la variable de control (res) es un cero (0) es que el carácter que se encuentra en las coordenadas proporcionadas, no es un UDG. Si la variable de control res tiene un valor igual o superior a 144, nos está devolviendo el código del UDG que ha encontrado en esas coordenadas. 

  10 REM Localizacion de  UDG por coordenadas x,y
  20 REM igual que el SCREEN$(y,x) pero funciona con UDG
  30 REM vamos a cargar el UDG 149 (f)
  40 FOR i=0 TO 7
  50 POKE USR "f"+i,255
  60 NEXT i
  70 PRINT AT 7,13;CHR$ 149
  80 REM le damos las coordenadas y res nos devuelve el UDG
  90 LET x=13: LET y=7
 100 GO SUB 260
 110 PRINT AT 0,0;"El UDG es el ";res
 120 GO TO 310
 130 LET res=udg
 140 LET vY=y*8
 150 LET vX=x
 160 FOR S=0 TO 7
 170 LET iY=vY+S
 180 LET BLOCK=INT (iY/64)
 190 LET CROW=INT (iY/8)
 200 LET YR=iY-(CROW*8)
 210 LET CROW=CROW-(BLOCK*8)
 220 LET ADD=16384+BLOCK*2048+CROW*32+YR*256
 230 IF (PEEK ((USR (CHR$ udg))+s))<>(PEEK (add+vX)) THEN LET res=0: RETURN
 240 NEXT S
 250 RETURN
 260 FOR i=144 TO 164
 270 LET udg=i
 280 GO SUB 130
 290 IF res>=144 THEN RETURN
 300 NEXT i
 310 STOP
Hay varias cosas que tener en cuenta:


  • Las coornedas linea/columa las fijamos igual que en el SCREEN$. Ya se encarga el cógido de las "visicitudes" y "saltos" de las direcciones de memoria en pantalla. 
  • Está optimizado para UDG's de 8x8. Con un poco de paciencia y coco, se puede adaptar a 16x16, o 32x32 de forma sencilla. 
  • Puedes leer  "Jugando a los Sprites, episodio I" para ampliar la funcionalidad.
  • Si res vale cero(0), no es un UDG.
  • Si res es 144 o más , es un UDG y res es el código del mismo. 
  • Se compara byte a byte el caracter en pantalla, con la(s) definición(es) de(los) UDG.
  • Está optimizado para el mejor rendimiento (en caso de diferencia, aborta y al siguiente). 


Ahora ya no tienes excusa para usar los UDG's en esos juegos que puedes hacer y basar tu detección de colisiones de forma muy sencilla desde BASIC.



miércoles, 2 de diciembre de 2015

Que usar para programar el BASIC del Commodore 64 en tu PC.

Me puse como objetivo encontrar un entorno de programación  gráfico al estilo de BasinC para ZX Spectrum

La idea es tener una GUI (Graphical User Inerface) con todas las herramientas necesarias para la programación BASIC del Commodore 64 en nuestro PC. No solamente código fuente, sino herramientas gráficas y de sprites, manuales y otro tipo de complementos que nos permitan hacer todo desde un mismo sitio. 

Voy a resaltar CBM .prg Studio de Arthur Jordison

Es un entorno completo al estilo de los entornos de programación actuales, como puede ser Visual Studio o Eclipse. 

Traducido de su página web, podemos ver capacidades y funcionalidad: 

Permite realizar desarrollos para : 

  • Commodore 64 (and SuperCPU)
  • Commodore 128
  • Commodore VIC 20
  • Commodore 16
  • Commodore Plus/4
  • Commodore PET BASIC 2 machines, e.g. PET 2001
  • Commodore PET BASIC 4 machines, e.g. PET 4000/9000

Un resumen de sus capacidades es: 

  • Múltiples tipos de ficheros de código (ensamblador o BASIC) se pueden componer a un solo destino.
  • Ensamblador / Desemsamblador y Depurador integrado para 6502/6510/65816
  • Importación de programas (.prg, .T64 or .D64/.D71/.D81)
  • Exportación de programas (.prg, .p00)
  • Editor de Sprites
  • Editor de juegos de caracteres
  • Diseñador de pantallas 
  • Generador de códidos especuales de impresión
  • Visor de memoria
  • Importación y exportación de binarios
  • Herramienta de creación de discos .D64/.D71/.D81
  • Constantes en BASIC
  • Re-numerado y formateo de código 
  • Formateo automático de código ensamblador
  • Interfaz de usuario tipo MDI
  • Gran cantidad de manuales, ayuda y tutoriales

La verdad que es una herramienta muy completa y funcional. 

Una cosa que no termina de convencerme es que para compilar y ejecutar un proyecto, necesita un emulador externo configurado en la propia herramienta. 

Seguramente con el tiempo y adquiriendo experiencia con el entorno, esta circunstancia se verá justificada. 

En este enlace tenéis más imágenes de la herramienta en acción.