domingo, 7 de enero de 2018

Preview de 8BP v32

Hola amigos de 8 bits de poder

aunque aun no he publicado la v32, os quiero adelantar algo para que veais como va quedando. Está prácticamente acabada aunque tengo que preparar una buena demo y tambien actualizar el manual de programación, por lo que aun me demoraré un pelín.

Lo que permite la v32 es crear un mundo 2D y recorrerlo en 3D. Es decir, podemos pintar caminos, plantas , arboles, vallas, etc y activar el modo de visualizacion 3D para ver en 3 dimensiones nuestro mapa del mundo. Este sencillo y versátil mecanismo permitirá hacer juegos de tanques, de naves, de carreras etc, casi con la misma sencillez con la que hacemos un juego 2D.

Esto se puede concebir como una especie de nuevo modo de visualizacion 3D, como el "modo 7" de SNES (salvando las distancias), y se puede comprender con el siguiente ejemplo
nuevo modo 3D para recorrer el "mapa del mundo" de 8BP
En este caso hemos definido un mundo con segmentos y con una valla y al activar el modo 3D , las imagenes que conforman el mundo se proyectan en una visualizacion 3D

La detección de colisión de sprites sigue funcionando en 2D, de modo que podemos detectar cuando nuestro coche se sale de la carretera o pisa un charco, pero al imprimir los sprites se calculan coordenadas 3D antes de pintarlos.

ya entrando en mas detalle tenemos las siguientes  nuevas características:


  • Un comando de activación del modo 3D, que nos permite limitar la aplicación de la proyección 3D a un subconjunto de sprites de los 32 disponibles. Además, nos permite definir un offset vertical para proyectar mas arriba o mas abajo de la pantalla.  Por lo demas, las cosas siguen funcionando como hasta ahora para juegos con scroll. El comando MAP2SP calcula qué imágenes del mundo caen dentro de la pantalla y genera una lista de sprites a imprimir. El comando PRINTSPALL los imprime, pero si está activado el modo 3D, entonces primero los proyectará. La porción del mundo que se considera, de 160x200, tras ser proytectada caerá en un rectángulo de la pantalla de dimensiones 160x100. Los sprites no afectados por el modo 3D, se seguirán imprimiendo en cualquier parte de la pantalla y sin ser proyectados


  • Podemos definir imágenes con zoom. Básicamente son imágenes compuestas de varias versiones de la misma (unas mas grandes y otras mas pequeñas) y al proyectarse mas alto o mas bajo se escogerá automáticamente la versión mas adecuada


  • Podemos definir un nuevo tipo de imagen llamados "segmentos":  se definen por repetición de una sola scanline, muy útil para trazar caminos. Ocupan muy poca memoria y se pueden colocar en el mundo torcidos, de modo que nos permiten crear curvas y caminos. En un juego de tanques en el desierto puede que no los usemos pero en un juego de carreras son útiles.


Por último, y puesto que en 3D los juegos avanzan muy deprisa, será util un comando de actualización del mapa del mundo, para poder recorrer largas distancias y no solo la capacidad actual del mapa que es de 82 items. Estoy trabajando en este comando, y pronto estará todo disponible

Os dejo con un vídeo para que podáis ver como va quedando. Espero tenerlo todo publicado muy pronto




hasta la vista!








miércoles, 30 de agosto de 2017

Disponible versión V31 de la librería 8BP

hola amigos de 8 bits de poder

Ya esta disponible la versión v28 de 8BP,  en https://github.com/jjaranda13/8BP la cual incorpora un nuevo comando para imprimir minicaracteres.
la libreria ahora ocupa 1kB mas ( en total 7kB) pero en realidad internamente han quedado 850 bytes para programar nuevas funcionalidades ( la v32 incorporará pseudo 3D sin ocupar mas memoria)
Todo está documentado en el nuevo manual disponible en github


El juego de caracteres del AMSTRAD es bonito y bien construido. Sin embargo, en mode 0 tan solo disponemos de 20 caracteres de ancho por línea y aparecen demasiado “ensanchados”, por lo que en ocasiones no son adecuados para mostrar ciertos textos o marcadores de un juego. Además, el comando PRINT es muy lento, por lo que es poco recomendable actualizar los marcadores frecuentemente, ya que el juego se “detiene” mientras se está imprimiendo, son pocos milisegundos pero es perceptible.
Por ese motivo, a partir de la versión v31 de 8BP se ha incorporado el comando PRINTAT, el cual puede imprimir una cadena de caracteres usando un nuevo juego de caracteres mas pequeño (los llamo “minicaracteres”). Este nuevo comando permite usar el mecanismo de transparencia de los sprites, de modo que podras imprimir caracteres respetando el fondo. Funciona del siguiente modo:

|PRINTAT,<flag transparencia>, y,x,@string

Ejemplo:
cad$= “Hola”
|PRINTAT,0,100,10, @cad$



El comando |PRINTAT imprime cadenas de caracteres y no variables numéricas, por lo que si quieres imprimir un número (por ejemplo, los puntos en el marcador de tu videojuego) debes hacerlo asi:

puntos=puntos+1
cad$= str$(puntos) 
|PRINTAT,0,100,10, @cad$

A diferencia del comando PRINT del BASIC, el comando |PRINTAT es bastante rápido y puede ser utilizado para actualizar los marcadores de tu videojuego con frecuencia.
PRINTAT usa un alfabeto redefinible, que puede contener una versión reducida o diferente de los caracteres “oficiales” del amstrad. Por defecto 8BP proporciona un pequeño alfabeto compuesto por números, letras mayúsculas y algunos símbolos. No podrás usar un carácter que no se encuentre entre este conjunto, como las letras minúsculas. Los caracteres de dicho alfabeto miden todos lo mismo: 4pixels de ancho x 5 pixels de alto, es decir 2 bytes x 5 lineas.
Esta cadena contiene todos los caracteres que puedes usar con el alfabeto de serie de 8BP. Fíjate que no hay minúsculas y faltan muchos símbolos, aunque puedes crear tu propio alfabeto que los contenga. Fíjate que el último símbolo es el espacio en blanco, es decir, es un símbolo disponible y por lo tanto puedes incluir espacios en blanco en las cadenas que imprimas. ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:! ")



IMPORTANTE: Ten mucho cuidado de no usar caracteres no creados cuando uses PRINTAT.
He creado los caracteres usando las tintas 2 y 4, para que se pueda usar la sobreescritura, ya que los colores de fondo son 0 y 1 y usando sobreescritura la tinta 2 debe ser igual a la 3 y la 4 debe ser igual a la 5 ( consulta el capítulo donde explico la sobreescritura). Para usar la sobreescritura simplemente pon a “1” el flag de transparencia en el comando PRINTAT.


Puedes crear tu propio juego de caracteres, en el manual te indico paso a paso como hacerlo. básicamente consiste en definir una cadena que contiene todos los caracteres que vas a crear y dibujar uno a uno cada carácter.  Los bytes resultantes de cada dibujo de cada carácter los copias en un fichero de alfabeto con el que se ensambla toda la librería. 

a continuación os dejo una pequeña demostración del nuevo comando


hasta pronto amigos!







martes, 11 de julio de 2017

Programando juegos en Amstrad con la libreria 8BP y Locomotive Basic

Hola amigos de 8BP

Últimamente estoy trabajando poco en mejoras a la librería pero tengo ya una nueva versión que publicaré en breve (V31), con un par de nuevas e interesantes mejoras. Además, he empezado un nuevo juego de arcade que espero que os guste.
Una de las mejoras es la posibilidad de tener un juego de minicaracteres redefinibles para mode 0, de modo que podamos imprimir textos, marcadores etc., a un tamaño razonable y a mucha mayor velocidad que el comando PRINT de Basic, permitiendo que, por ejemplo, un texto pueda salir botando por la pantalla, o imprimir puntuaciones de un juego sin provocar esas indeseables pausas que provoca el comando PRINT. También ando trasteando con pseudo3D, a ver hasta donde llegamos.

Hoy os traigo un vídeo recientemente publicado por Retromadrid. Se trata de la conferencia que hice el día 29 de abril titulada "programando juegos en Amstrad con la librería 8BP y Locomotive Basic".

Además, he subido la presentación (powerpoint y pdf) de la conferencia a github (https://github.com/jjaranda13/8BP). La encontraréis en la carpeta de "documentacion", así como el folleto. De este modo podréis seguir y entender con mas claridad la conferencia. La presentación es un fichero muy pesado, de unos 72MB, porque incluye vídeos embebidos. Es muy completa, pero no es larga ni complicada.

Agradezco desde aquí a los amigos y organizadores de Retromadrid la oportunidad brindada para compartir esta iniciativa con los amantes de lo retro.





un abrazo y feliz verano!


lunes, 1 de mayo de 2017

8 BITS DE PODER estuvo en Retromadrid 2017

Hola amigos de 8 bits de poder


Así es, 8BP estuvo en Retromadrid. Una experiencia inolvidable. Un reencuentro con el significado de la palabra "juego", desprovista del gran poder computacional actual. Donde la palabra "jugabilidad" no se mezcla con gráficos en alta resolución ni sonido de alta fidelidad ni memorias gigantescas. Una vuelta a los orígenes. A la esencia de lo que significa "jugar"

Sistemas retro de toda clase, expositores de altísimo nivel, pasión desbordada, aroma a Z80, 6502 y 68000, emoción y calidad. Encuentros con representantes de la escena retro y con un público entrañable que daba una gran energía al acontecimiento. Gracias a Javy, Atila, Jose, Cesar...y tantos que nos habéis dado esta acogida tan cálida.  En una palabra, Retromadrid ha sido magnífico.



El Sábado, presenté una conferencia sobre 8BP en la que se mostraron los fundamentos y posibilidades de esta herramienta, ejemplos y explicaciones sobre lógicas masivas, manejo de sprites, layout, sobreescritura, técnicas de scroll y recomendaciones de programación.



La conferencia se apoyó en una presentación y diversos vídeos. La presentación la subiré al repositorio github de 8bp , para complementar el manual. Me consta que fue grabada en vídeo, de modo que cuando sea publicado dicho vídeo os lo haré saber.

Agenda de la conferencia sobre 8BP

Folleto que fue repartido entre los visitantes
El folleto lo podéis encontrar en este link : folleto_8BP_retromadrid
Y en primicia, se presentó sobre un CPC464 real, el nuevo juego "fresh fruits & vegetables". Un juego de plataformas, donde tu misión consiste en recoger todas las frutas para dejar a la población sin nada que comer, de modo que tengan que sacrificar a un pobre cerdo para alimentarse. Tanto "fresh fruits & vegetables" como "Nibiru" fueron expuestos para el disfrute de grandes y pequeños durante todo el dia
juegos hechos con 8BP sobre un CPC464 real durante Retromadrid


Os dejo con el video del nuevo juego "Fresh fruits & vegetables" que encontrareis en el directorio "gameExamples" del repositorio GitHub de 8BP, en https://github.com/jjaranda13/8BP





hasta la vista!!!



martes, 31 de enero de 2017

Disponible versión V28 de la librería 8BP

hola amigos de 8 bits de poder

Ya esta disponible la versión v28 de 8BP,  en https://github.com/jjaranda13/8BP la cual sigue ocupando lo mismo, 6KB y trae nuevas funcionalidades para la definición de rutas de sprites
(todo está documentado en el nuevo manual disponible en github):

estos nuevos mecanismos los estoy usando para programar un nuevo juego de plataformas:


Para empezar os recordaré lo que es una ruta: básicamente es un conjunto de segmentos que definen la trayectoria de un sprite. Cada segmento posee un numero de pasos , una Vy y una Vx, es decir una ruta es algo asi:

ROUTE0
    db 10,2,1 ; diez pasos con Vy=2, Vx=1
    db 5,1,-1; cinco pasos con Vy=1, Vx=-1
    db 0: fin de la ruta, al llegar aqui se empieza de nuevo

En mitad de una ruta, o al final nos puede interesar cambiar el estado del sprite. Por ejemplo eso es útil en un disparo que queremos que se desactive "solo" tras avanzar suficiente como para estar seguros de que se ha salido de la pantalla. Pues bien, también puede ser interesante hacer mas cambios en un sprite durante la ruta. Las cosas que ahora podemos hacer son 3

- Cambio de estado del sprite
- Cambio de secuencia de animación del sprite
- Cambio de imagen (útil si no tiene secuencia asociada)

Cambio de estado forzado desde una ruta
Consiste en que podemos forzar un cambio de estado en mitad de una ruta. Para
ello indicaremos que deseamos un cambio de estado indicando como valor de número de pasos del segmento = 255.
El cambio de estado es un segmento más y es importante que mantengas el mismo número de parámetros por segmento, es decir, 3 bytes. Un cambio de estado a status=13 podria escribirse como:

    255,13,0

El tercer parámetro (el cero) no significa nada, es solo un “relleno” para que el segmento mida 3 bytes, pero es imprescindible.
El valor 255 le indicará al comando ROUTEALL que lo que debe hacer esta vez es cambiar el estado del sprite, asignándole el que se indique a continuación. El cambio de estado se ejecuta sin consumir un paso, por lo que siempre se ejecutará el siguiente paso al cambio de estado. Si no queremos que el sprite se mueva mas, simplemente definiremos un segmento de un paso sin movimiento en X ni en Y justo después del cambio de estado. Veamos un ejemplo:

ROUTE3; disparo_dere
;-----------------
db 40,0,2; cuarenta pasos a la derecha con Vx=2
db 255,0,0; cambio de estado a cero
db 1,0,0; quieto Vy=0, Vx=0
db 0
ROUTE4; disparo_izq
;-----------------
db 40,0,-2; cuarenta pasos a la izquierda con Vx=-2
db 255,0,0; cambio de estado a cero
db 1,0,0; quieto Vy=0, Vx=0
db 0

Estas dos rutas las vamos a usar para disparar con nuestro personaje. La primera de ellas, tras recorrer 40 pasos en los que avanza 2 bytes en X, sufre un cambio de estado y el sprite pasa a estado 0, es decir, desactivado. El siguiente segmento solo tiene un paso y no hay movimiento (vy=0, vx=0).
Con este mecanismo podemos disparar y que los disparos se desactiven solos cuando se salen de la pantalla. Ello ahorra lógica de BASIC y acelera nuestros juegos.

Los cambios de estado se pueden forzar en cualquier segmento de la ruta, no necesariamente al final, aunque en el caso de un disparo es muy lógico hacerlo al final de la ruta.


Cambios de secuencia de animación forzados desde rutas
Podemos cambiar la secuencia de animación de un sprite usando un segmento especial. Cuando pongamos 254 en el valor del número de pasos, el comando ROUTEALL interpretará que se debe realizar un cambio de secuencia de animación en el sprite. Ejemplo:
254,10,0
Este segmento cambia la secuencia de animación del sprite, estableciendo la secuencia número 10. El tercer parámetro (el cero) no significa nada, es solo un “relleno” para que el segmento mida 3 bytes, pero es imprescindible.
Al igual que con el cambio de estado, el cambio de secuencia se ejecuta sin consumir un paso, por lo que siempre se ejecutará el siguiente paso al cambio de secuencia.


Cambios de imagen forzados desde rutas: boing, boing!!!
Hemos visto como enrutar sprites con ROUTEALL o aun mejor, con AUTOALL,1
A menudo no queremos enrutar un sprite a través de una trayectoria sino algo más cotidiano: dar un salto con un personaje


Para no tener que controlar si el personaje ha llegado al punto cenital del salto, podemos usar un segmento especial que indica cambio de imagen. Al igual que cualquier otro segmento, consume 3 bytes, pero en este caso el primero es el indicador de cambio de imagen (un valor 253) y los dos siguientes se corresponden con la dirección de memoria de la imagen. MUCHA ATENCION, deberás usar “dw” antes del nombre de la imagen que quieres asignar, por lo que este segmento de cambio de imagen lo tendrás que escribir en dos líneas. Un “db” para el 253 y un “dw” para la dirección de memoria de la imagen.

  db 253
  dw SOLDADO_R1_UP

En el ejemplo siguiente tenemos un muñeco que salta. Al subir el muñeco que se borra a sí mismo por abajo mientras que al bajar se borra a sí mismo por arriba. Para que no haya discontinuidad en el movimiento, justo al cambiar una imagen por otra es necesario realinear verticalmente al soldado, subiendo la imagen de bajada exactamente 5 lineas, para hacerla coincidir con el soldado que estaba subiendo.


Usaremos dos rutas, una para saltar a la derecha y otra a la izquierda. Este sería el fichero routes_mygame.asm
;
; LISTA DE RUTAS
;================
;pon aqui los nombres de todas las rutas que hagas
ROUTE_LIST
dw ROUTE0
dw ROUTE1
dw ROUTE2
dw ROUTE3
dw ROUTE4
; DEFINICION DE CADA RUTA
;==========================
ROUTE0; jump_right
db 253
dw SOLDADO_R1_UP
db 1,-5,1
db 2,-4,1
db 2,-3,1
db 2,-2,1
db 2,-1,1
db 253
dw SOLDADO_R1_DOWN
db 1,-5,1; subo para que UP y down encajen
db 2,1,1
db 2,2,1
db 2,3,1
db 2,4,1
db 1,5,1
db 253
dw SOLDADO_R1
db 1,5,1; baja una mas
db 255,13,0; nuevo estado, ya sin flag de ruta y con flag de animacion
db 254,32,0; macrosecuencia 32
db 1,0,0; quietooo.!!!!
db 0

Y esto es todo. Os dejo con un video de preview del juego que estoy haciendo




Cuando tenga avances en el juego de plataformas publicaré mas
hasta pronto!



martes, 3 de enero de 2017

Análisis del uso combinado de CPCBASIC compiler y 8BP

hola amigos de 8BP

Hoy os traigo una curiosidad interesante. Existe un compilador de BASIC para amstrad CPC que corre bajo windows, llamado "BASIC3" o "CPC basic compiler". lo podéis encontrar en http://www.cpcbasic.tk/


Esta herramienta es útil en dos casos:
- tanto si quieres compilar tu juego para no mostrar el listado de tu programa
 -como si quieres ganar algo de velocidad (sobre todo tiene sentido en arcade)


Dicho compilador no es compatible 100% con locomotive BASIC pero con pocos cambios se puede hacer funcionar un programa. Es parecido a la herramienta "fabacom", que compila locomotive BASIC, pero a diferencia de esta, no genera un ejecutable gigante (fabacom mete una sobrecarga de 10KB)

He compilado el mini-invaders y aqui tenéis el resultado. Va mas deprisa como era de esperar. ten en cuenta que al compilar, se esta ejecutando el juego en código máquina. ya no es interpretado. Como puedes ver en el vídeo, la mejora es perceptible.
Yo seguiré programando en BASIC intepretado y compartiré el código fuente de mis juegos pero esta opción no es mala ya que a diferencia de fabacom, no consume mucha RAM. El binario que ha generado son 4KB, mientras que el listado BASIC ocupa 3KB.  Es algo más pero es razonable. Posteriormente he compilado Nibiru (el cual no compila si no se hacen muchos cambios), de 17KB y ha generado un binario de 22kB, es decir, una sobrecarga de 5KB. Probablemente cuanta mas variedad de instrucciones de BASIC se usen, mayor es la sobrecarga pero 5KB sigue siendo razonable.


Es realmente importante la ganancia? hablamos de un 50% de aumento de la velocidad como mucho, en el mejor caso. Es decir que es como pasar de 100Km/h a 150Km/h. Esto no esta mal, pero piensa que hemos pasado del BASIC interpretado al código máquina y normalmente se dice que la velocidad se debe multiplicar al menos por 100  (hablaríamos de un incremento del 10000% ). Sin embargo  sólo hemos ganado un 50%. El motivo de tan "pobre" ganancia es que las instrucciones de 8BP ya hacen todo el trabajo duro y en realidad el compilador solo ha traducido a código máquina la parte menos pesada, la lógica del juego.

En resumen, está bien, pero no esperes un milagro. Sólo tiene sentido si a tu juego le falta velocidad. Cuando necesites mas velocidad, hay estrategias explicadas en el manual de 8BP para acelerar tu juego en BASIC, como la técnica de lógicas masivas, o sencillos ajustes finales tales como eliminar lineas REM o sustituir las invocaciones RSX por CALL XXXX, o eliminar las invocaciones a RND y cambiarlas por un array pseudoaleatorio, etc. Es decir, hay cierto margen para aumentar la velocidad y sólo si aun así es insuficiente, tendrá sentido compilar, ya que lo que vas a ganar es "sólo" un 50%


hasta la vista!

miércoles, 28 de diciembre de 2016

Cómo hacer un juego tipo "space invaders" en BASIC para Amstrad usando la librería 8BP

Hola amigos de 8 bits de poder

Esta vez os traigo un pequeño tutorial de introducción para hacer un juego tipo "space invaders" en unos minutos. El tutorial está disponible en el canal de vídeos de 8BP https://www.youtube.com/watch?v=6OcB_hjuYiU




Y el juego "mini-invaders" lo encontrareis en la carpeta "Game Examples" del proyecto Github en https://github.com/jjaranda13/8BP


Os adjunto aquí el listado del juego. Como complemento a las explicaciones del vídeo os daré algunas pinceladas sobre el listado BASIC del juego que adjunto.

- el juego usa 32 sprites
- la nave es el sprite 31 
- los disparos que puedes lanzar con la nave son el 29 y el 30
- los invaders disparan usando el sprite 28 
- los invaders usan los sprites del 0 al 27 (28 invaders en total)
los sprites 31,30 y 29 tienen flag de colisionador activo
- el resto de sprites son "colisionados" y tienen flag de colisionado activo
- los invasores tienen flag de movimiento automatico activo y se les asocia la ruta "0" que los mueve de derecha a izquierda y hacia abajo, lo típico de los invasores
- los disparos de la nave y de los invaders usan una característica de la V27. recorren la pantalla y al salir se desactivan automáticamente con un cambio de estado definido al final de su ruta, simplificando de este modo la lógica de BASIC y por consiguiente acelerando el juego

a continuación teneis el listado

10 MEMORY 25999
20 dir=42540:FOR star=0 TO 40
30 POKE dir+star*2,RND*200
40 POKE dir+star*2+1,RND*80
50 NEXT
60 DEFINT A-Z: CALL &6B78:' install RSX
70 |PRINTSPALL,0,1,0:|AUTOALL,1:MODE 0
80 ON BREAK GOSUB 810
90 CALL &BC02:'restaura paleta por defecto     
100 INK 0,0:BORDER 1: vidas=3: puntos=0
110 CLS: |STARS,0,10,4,2,0: ciclo=0:counter=0
120 ENT -5,7,10,1,7,-10,1:ENV 1,1,15,1,15,-1,1:
130 'nave
140 |SETUPSP,31,9,16:|SETUPSP,31,0,33:|SETUPSP,31,7,0
150 x=40:y=192:|LOCATESP,31,192,40

160 'fire [29,30]
170 FOR i=29 TO 30:|SETUPSP,i,9,18:|SETUPSP,i,0,0:NEXT
180 disp=0

190 'fire invaders [28]
200 |SETUPSP,28,9,19:|SETUPSP,28,0,0

210 ' invaders [0..27]
220 i=0:FOR yi=0 TO 3
230 FOR xi=0 TO 6
240 |SETUPSP,i,7,1
250 |LOCATESP,i,yi*16+10,xi*8
260 |SETUPSP,i,0,143
270 |SETUPSP,i,15,0
280 i=i+1:NEXT:NEXT

290 'setup colision ------------
300 collider=0:collided=0:|COLSP,34,4,0
310 |COLSPALL,@collider,@collided:|COLSP,32,0,28

320 'WAIT SPACE TO START --------
330 PLOT 1,382:DRAW 640,382:|SETLIMITS,1,80,10,200:|PRINTSPALL
340 LOCATE 1,1:PRINT "SCORE";puntos:LOCATE 12,1:PRINT "LIVES:";vidas
350 SOUND 1,25,80,12,,5
360 IF INKEY(47)<>0 THEN  360
370 SOUND 1,100,7,15

380 'ciclo de juego ------------

390 GOSUB 520:'lectura teclado y movimiento nave y/o disparo
400 GOSUB 630:'disparo invaders
410 ciclo=ciclo+1: IF ciclo>=1048 THEN 110
420 |STARS,0,10,4,1,0
430 |AUTOALL:|PRINTSPALL:|COLSPALL
440 IF collided=32 THEN 390
450 IF collider=31 THEN vidas=vidas-1: IF vidas=0 THEN 690 ELSE 730
460 |SETUPSP,collided,7,2:puntos=puntos+1
470 |SETUPSP,collider,9,17:'borrado del disparo
480 |SETUPSP,collider,15,3
490 SOUND 7,1000,20,15,,,15:LOCATE 7,1:PRINT puntos
500 GOTO 390

510 ' rutina de movimiento nave -----
520 IF INKEY(27)=0 THEN x=x+1:GOTO 540
530 IF INKEY(34)=0 THEN x=x-1
540 IF counter+8<=ciclo THEN IF INKEY(47)=0 THEN counter=ciclo:GOSUB 580
550 |LOCATESP,31,y,x
560 RETURN

570 ' disparo nave ---------------
580 disp=1+disp MOD 2
590 |LOCATESP,28+disp,y,x+2:|SETUPSP,28+disp,0,169:|SETUPSP,28+disp,15,1:|SETUPSP,28+disp,9,18
600 SOUND 1,25,20,12,,5
610 RETURN

620 ' rutina disparo invaders ----
630 IF PEEK(27448)<>0 THEN RETURN
640 invader=RND*28:dirinvader=invader*16+27000
650 IF PEEK (dirinvader)=0 THEN RETURN
660 |LOCATESP,28,PEEK(dirinvader+1),PEEK(dirinvader+3):|SETUPSP,28,0,139:|SETUPSP,28,15,2
670 SOUND 1,250,20,12,,5
680 RETURN

690 ' GAME OVER
695 |SETUPSP,31,7,3:|SETUPSP,31,0,143:|LOCATESP,31,186,x
700 LOCATE 7,12:PEN 7:PRINT "GAME OVER"
701 for i=0 to 27:|setupsp,i,0,0:next
702 |PRINTSPALL
710 IF INKEY(47)<>0 THEN  702 ELSE RUN

730 ' rutina muerte nave
740 SOUND 7,1000,20,15,,,15
750 BORDER 7,0
760 |SETUPSP,31,7,3:|SETUPSP,31,0,143:|LOCATESP,31,186,x
770 |PRINTSPALL
780 IF INKEY(47)<>0 THEN  770
790 BORDER 1
800 GOTO 110


810 MODE 2: INK 0,0:PEN 1:BORDER 0: END


Por último os adjunto un video tutorial de programación del juego



hasta la vista!