help me to make 8BP better

If you like 8BP, your help is welcome. Help me supporting this initiative (from 1€, whatever you want). Donations will be used for materials and 8BP disemination:
Mostrando entradas con la etiqueta arcade. Mostrar todas las entradas
Mostrando entradas con la etiqueta arcade. Mostrar todas las entradas

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!

domingo, 30 de octubre de 2016

Nuevo videojuego "Nibiru"

Hola amigos de 8 bits de poder

ya esta disponible para descarga el videojuego "Nibiru", programado en BASIC y usando la librería 8BP , versión V26b
Lo encontrarás en la carpeta "GameExamples" de https://github.com/jjaranda13/8BP

El juego funciona en CPC464 y en CPC6128. tanto el archivo ".dsk" como el ".wav" están disponibles.

El juego pone a prueba muchas de las características de 8BP y de la técnica de programación de "lógicas masivas", y tiene detalles como un gráfico de carga lujoso y tres melodías durante el juego, así como una tabla de scores que no se pierde aunque reinicies el juego y otros aspectos técnicos avanzados como scroll paralax, rutas, macrosecuencias, etc. El listado BASIC ocupa poco mas de 16KB, de modo que aun sobrarían 10 KB para hacer un juego mucho mayor (con 8BP los juegos en BASIC pueden ocupar 26KB, sin contar gráficos ni música).



Eres el piloto de una nave destructora y debes vencer al planeta Nibiru y a su lider, "Gorgo", un reptil milenario casi invencible. Debes destruir a los pajaros galácticos que viven en sus lunas y una vez que llegues al planeta te debes enfrentar a sus peligros antes de poder luchar con Gorgo.

El Juego consiste en tres fases y utiliza el mecanismo de scroll de 8BP basado en el comando MAP2SP y también usa enrutamiento de sprites y macrosecuencias de animación. Todo desde BASIC! gracias a 8BP y a la técnica de "lógicas masivas".


Aaunque la impresión con sobreescritura sea mas lenta que la "normal", la segunda fase demuestra que aun así es posible un juego de arcade con sobreescritura. Música, scroll, detección de colisiones, sprites con sobreescritura, enrutamiento de sprites, todo a la vez es posible con 8BP


En la tercera fase podrás ver un scroll paralax, donde las montañas se mueven a diferente velocidad que el mar. impresionante, verdad? piensa que es un juego hecho en BASIC!!!



Pronto publicaré un articulo sobre como lo he programado, explicando algunos detalles técnicos. También actualizaré la documentación con esta información y nuevos consejos.

Os dejo con un vídeo del juego:


Hasta la próxima!!






miércoles, 23 de marzo de 2016

Anunnaki: nuevo videojuego realizado con 8BP

hola amigos de 8BP

Ya esta listo el nuevo videojuego "Anunnaki", realizado en BASIC con la libreria 8BP.
Este es un juego de arcade y hace un uso intensivo de la técnica de lógicas masivas.

Os podéis descargar el videojuego desde https://github.com/jjaranda13/8BP



El juego hace uso de la técnica de lógicas masivas para manejar hasta 30 sprites entre naves y disparos. Todo ha sido posible en BASIC. Además, se utilizan técnicas para simular scroll, descritas en el manual de 8BP (version v21) que podeis encontrar en github






Además, esta disponible la version V21 de la libreria 8BP en github y esta nueva versión incorpora

  • SETUPSP,5,Vy,Vx: con un solo comando ahora actualizamos la Vy y la Vx, ahorrando casi 3 milisegundos
  • STARS: comando mejorado, ahora realiza mejor el calculo cuando una estrella se sale por un limite y debe entrar por el lado opuesto
  • herramienta SPEDIT v5: ahora puedes "espejar" tus sprites sobre un eje central imaginario, una ayuda para dibujar sprites simetricos


  • explicación mas detallada de la tecnica de logicas masivas
  • nuevos consejos de programación eficiente en memoria y velocidad
  • código del videojuego anunnaki
  • nuevos consejos sobre como editar musica para no tener problemas

viernes, 18 de marzo de 2016

Lógicas masivas: controla el tiempo, no el espacio

hola amigos de 8 bits de poder

Hoy voy a tratar de explicar en profundidad como funciona la técnica de lógicas masivas en el caso mas complejo: hileras de naves con trayectorias. Espero que esta detallada explicación os ayude a construir vuestras propias lógicas masivas.

Comencemos imaginando una trayectoria para una hilera de 8 naves enemigas. las naves pasarán una a una por una serie de "nodos de control", que son lugares en el espacio donde deben cambiar su dirección, definida por sus velocidades en X, e Y, es decir (Vx,Vy)

Trayectoria definida con "nodos de control"
Una forma de controlar que las 8 naves cambien de dirección en dichos lugares sería comparar sus coordenadas X,Y con la de cada uno de los nodos de control y si coinciden con alguno de ellos, entonces aplicamos las velocidades nuevas asociadas al cambio en ese nodo. Puesto que hablamos de 2 coordenadas, 8 naves y 4 nodos, estamos ante:

2 x 8 x 4 = 64 comprobaciones en cada fotograma

Esto no es viable si queremos velocidad desde BASIC. Y es que no es una estrategia eficiente computacionalmente. Puesto que estamos ante un escenario "determinista", podríamos estar seguros en cada instante de tiempo donde van a encontrase cada una de las naves y por lo tanto en lugar de hacer comprobaciones en el espacio, podemos únicamente centrarnos en la coordenada temporal (que es el número de fotograma del juego o el también llamado número de "ciclo de juego")

Puesto que conocemos a la velocidad a la que se mueven las naves, podemos saber cuando la primera de ellas pasará por el primer nodo. A ese instante lo llamaremos t(1). También asumiremos que debido a la separación entre las naves, la segunda de las naves pasará por el nodo en el instante t(1)+10. la tercera en t(1)+20 y la octava en t(1)+70

Sabiendo esto podemos controlar el tiempo con dos variables: una contará las decenas (i) y otra las unidades(j). Para controlar el cambio de las 8 naves en el primer nodo podemos escribir:

j=j+1: IF j=10 THEN j=0: i=i+1
IF i>=t(1) AND i<t(1) +8 THEN [actualiza velocidad de nave  i-t(1) con los valores de velocidad del nodo 1]

Como vemos con una sola linea podemos ir cambiando las velocidades de cada nave a medida que van pasando cada una de ellas por el nodo 1. Durante los 8 instantes de tiempo posteriores a t(1) se van actualizando cada una de las naves, justo cuando pasan por el nodo de control

Ahora vamos a aplicar lo mismo a los 4 nodos. Podríamos ejecutar 4 comprobaciones en lugar de una, pero sería ineficiente. Además si tuviésemos muchos nodos esto supondría muchas comprobaciones. Podemos hacerlo solo con una, teniendo en cuenta que la primera nave pasa por un nodo en un instante t(n) y la ultima nave pasa por ese nodo en t(n)+7

Cuando la primera nave pasa por el primer nodo, tiene sentido pensar en empezar a comprobar el nodo 2, pero no el nodo 3 ni el 4. Ya tenemos el nodo mayor que vamos a controlar.
En cuanto al nodo menor, podemos asumir que aunque tengamos 20 nodos, estén lo suficientemente separados como para que no haya naves atravesando mas de 3 nodos a la vez (vamos a suponer eso y usaremos ese "3" como parámetro). Por lo tanto el nodo menor a comprobar es el mayor - 3. Al nodo menor lo vamos a llamar "nmin" y al mayor "nmax".  ( nmin = nmax-3 ). El caso que queramos tener plena libertad para poder definir cualquier trayectoria,  nmin debe ser nmax menos el número de naves de la hilera.



j=j+1: IF j=10 THEN j=0: i=i+1: n=nmax
IF n<nmin THEN 50:' no hay que actualizar mas naves
IF i>=t(n) AND i<t(n)+8 THEN [actualiza i-t(n)]:IF i-t(n)=0 THEN nmax=nmax+1: nmin=nmax-3
n=n-1

50 ' mas instrucciones del juego

Como veis cuando se incrementa en 1 la decena de tiempo, se comprueban los nodos desde "nmax" hasta "nmin" Y en cada nodo actualizamos la nave i-t(n). Pensad que si t(3) es, por ejemplo, 23, entonces cuando llegamos al nodo 3 en el instante i=23, actualizamos la nave i-23 =0, con los valores de velocidad del nodo 3.

En el siguiente ciclo de juego comprobamos si aun sigue "vigente" el intervalo de tiempo del nodo 2, y actualizamos la nave 1 con los valores de velocidad del nodo 2,

y en el siguiente ciclo comprobamos el nodo 1 y si sigue vigente actualizamos la nave 2, y asi sucesivamente, siempre teniendo en cuenta que la primera nave puede haber llegado a nmax, mientras que la siguiente nave puede estar en nmax-1 y la siguiente en nmax-2, etc.

En resumen, hemos transformado 64 comprobaciones en solo 1, usando "Lógicas masivas". Y si la trayectoria tuviese 40 en lugar de 4 nodos, habríamos transformado 640 operaciones en una sola!

Vale, es algo dificilillo de entender, pero si lo lees despacito otra vez, seguro que lo pillas....y si no, tu pregunta y trato de aclarar más. En la próxima versión de la librería incluiré una buena descripción en el manual sobre este asunto (quizás este mismo post) . Es algo fundamental.



martes, 8 de marzo de 2016

Disponible nueva version v20 de la libreria 8BP (retrocompatible)

hola amigos de 8BP

Ya esta disponible la versión v20 de la libreria 8BP, totalmente retrocompatible

He actualizado el repositorio de github https://github.com/jjaranda13/8BP con los siguientes cambios (coherentes entre la documentación y la librería). Con estas mejoras los juegos arcade ahora funcionan aun más rapido. Se incluye la demo de annunaki donde podéis comprobar el uso de estas mejoras.
Las mejoras son:

  • posibilidad de definir la sensibilidad de la colisión entre sprites
  • nuevo comando COLSPALL que acelera la detección de colisión


Posibilidad de definir la sensibilidad de la colisión entre sprites
COLSP : ahora puedes definir la sensibilidad de la colision (grado de solape entre sprites)

Es posible ajustar la sensibilidad del comando COLSP, decidiendo si el solape entre sprites debe ser de varios pixels o de uno solo, para considerar que ha habido colisión.
Para ello se puede configurar el número de pixels (pixels en dirección Y, bytes en dirección X) de solape necesario tanto en la dirección Y como en la dirección X, usando el comando COLSP y especificando el sprite 34 (que no existe)

|COLSP, 34, dy, dx

La librería 8BP no usa “pixels” en la coordenada X, sino bytes, de modo que debes tener en cuenta que una colisión de 1 byte, en realidad son 2 pixels y esa es la mínima colisión posible cuando ajustas dx=0.
En la coordenada Y, la librería trabaja con líneas de modo que dy=0 significa una colisión de un solo pixel.
Una colisión estricta, útil para disparos sería aquella que no tolera ningún margen, considerando colisión en cuanto hay un mínimo solape entre sprites (1 pixel en dirección Y o un byte en dirección X)

|COLSP, 34, 0, 0: rem colision en cuanto hay un mínimo solape



Sin embargo, si estamos haciendo un juego en MODE 0, donde los pixels son mas anchos que altos, es quizás mas adecuado dar algo de margen en Y y nada en X. Por ejemplo

|COLSP, 34, 2, 0 : rem colision con 3 pix en Y y 1 byte en X

Mi recomendación es que si hay disparos estrechos o pequeños, ajustes la colision con (dy=1, dx=0) mientras que si solo hay personajes grandes puedes dejarla con mas margen (dy=2, dx=1). También debes considerar que si tus sprites tienen un “margen” de borrado alrededor para desplazarse borrándose a si mismos, dicho margen no debería formar parte de la consideración de colisión por lo que tiene sentido que tanto dy como dx no sean cero. En cualquier caso es algo que decidirás en función del tipo de juego que hagas

Nuevo comando COLSPALL que acelera la colisión entre sprites y simplifica tu programa BASIC

Con la funcion COLSP que hemos visto hasta ahora, es posible la detección de colisión de un sprite con todos los demás. Sin embargo si tenemos un disparo múltiple, donde por ejemplo nuestra nave puede disparar hasta 3 disparos simultáneamente, tendríamos que detectar la colisión de cada uno de ellos y adicionalmente la de nuestra nave, resultando en 4 invocaciones a COLSP.
Debemos tener presente que cada invocación atraviesa la capa de análisis sintáctico, por lo que 4 invocaciones resulta costoso. Para ello disponemos de un comando adicional: COLSPALL
Esta funcion funciona en dos pasos, primero debemos especificar que variables van a almacenar el sprite colisionador y el colisionado

|COLSPALL, @colisionador%, @colisionado%

Y posteriormente, en cada ciclo de juego simplemente invocamos la funcion sin parámetros:

|COLSPALL

La función va a considerar como sprites “colisionadores” aquellos que tengan el flag de colisionador a “1” en el byte de estado (es el bit 5), y como “colisionados” aquellos sprites que tengan a “1” el flag de colision (bit 1) del byte de estado. Los sprites colisionadores deberán ser nuestra nave y nuestros disparos




La función COLSPALL empieza comprobando el sprite 31 (si es colisionador) y va descendiendo hasta el sprite 0, invocando internamente a COLSP para cada sprite colisionador. En cuanto detecta una colisión, interrumpe su ejecución y retorna el valor del colisionador y el colisionado. Por ello es importante que nuestra nave tenga un sprite superior a nuestros disparos. De ese modo, si nos alcanzan, lo detectaremos aunque hayamos alcanzado a un enemigo con un disparo en el mismo instante.
En cada ciclo de juego solo se podrá detectar una colisión, pero es suficiente. No es una limitación importante que en cada fotograma solo pueda empezar a “explotar” un enemigo. Si, por ejemplo, tiras una granada y hay un grupo de 5 soldados afectados, cada soldado comenzará a morir en un fotograma distinto, y en 5 fotogramas estarán todos explotando. Usando COLSPALL no explotarán todos a la vez, pero tu juego será más rápido y en un arcade es algo muy importante.


Espero que os gusten estas mejoras. Yo voy a intentar centrarme en avanzar en el videojuego "Annunaki",el cual hace uso de estas mejoras por ser un arcade espacial.   En cuanto lo tenga listo lo compartiré con todos vosotros

  

sábado, 5 de marzo de 2016

Cómo programar un disparo múltiple

Hola amigos de 8 bits de poder

Hoy os voy a contar como programar un disparo múltiple de un modo eficiente.
Lo primero de todo, para evitar el paso de parámetros (es decir, col,<sprite>,@variable%) haremos

col%=0
|COLSP,33,@col%: ' el sprite 33 no existe, se usa para indicar la variable de trabajo

De este modo sucesivas invocaciones a COLSP,<sprite> dejarán el resultado (número de sprite que colisiona) en la variable col%

Primer caso : un personaje que no dispara
Cuando no queremos hacer que nuestro personaje dispare pero simplemente que le puedan matar los enemigos al colisionar, ejecutamos una instrucción como esta en nuestro ciclo de juego

|COLSP,31 : ' suponemos que el sprite 31 es nuestro personaje.

Segundo caso : un personaje que dispara un solo proyectil
En ocasiones queremos que nuestro personaje dispare un solo disparo. En ese caso incorporaremos
una invocación adicional a la colisión del disparo si ha sido lanzado, es decir

|COLSP,7 : ' suponemos que el sprite 7 es nuestro disparo. 

Tercer caso : un personaje que dispara hasta 3 proyectiles a la vez
pero y si queremos colisionar hasta 3 disparos?  vamos a suponer que tenemos hasta 3 disparos con los sprites 7,8 y 9

La solución mas efectiva se basa en uno de los casos más sencillos de aplicación de la técnica de "lógicas masivas". restringiendo a contemplar solo una de las siguientes cosas a la vez:

  • o colisiona uno de los 3 disparos (solo uno), y mata a un enemigo
  • o un disparo sale del área de pantalla (solo uno)


La rutina seria algo así (dentro de cada ciclo de juego haríamos un gosub 750)

744 ' RUTINA DE COLISION DE DISPAROS
745 ' -------------------------------------------------------  

746 ' CASO 1 comprobamos si hay alguna colision
747 '-------------------------------------------
750 if peek(27112)>0 then |colsp,7: if col%<32 then dir=27113:goto 820
760 if peek(27128)>0 then |colsp,8: if col%<32 then dir=27129:goto 820
770 if peek(27144)>0 then |colsp,9: if col<32 then dir=27145:goto 820

780 ' CASO 2 comprobamos si el disparo se ha salido de pantalla
790 ' ----------------------------------------------------------
800 dc=dc mod 3 +1:dir=ddisp(dc):|peek,dir,@yd%: if yd%<-10 then poke dir-1,0: |POKE,dir,200:nd=nd-1
810 return: 

820 ' continuacion del caso 1 en caso de colision
825 ' ------------------------------------------------------------
830 ' desactivo el disparo
840 poke dir-1,0: nd=nd-1:|PRINTSP,6,peek(dir),peek(dir+2): poke dir,255
850 ' ahora proceso al enemigo segun sea duro o blando
860 if col>=duros then return
870 ' alcance de enemigo tipo blando. lo matamos, asignandole una secuencia de muerte y poniendo su estado a no colisionar mas
880 if col>=blandos then |SETUPSP,col,7,4:|SETUPSP,col,0,&x101:return 
890 return


Y aquí tenéis el resultado. En una nueva versión de la librería podréis ajustar la sensibilidad del comando COLSP, decidiendo si el solape entre sprites debe ser de varios pixels o de uno solo, para considerar que ha habido colisión. Y también alguna cosa mas muy interesante relacionada con el comando COLSP. Y como siempre, serán mejoras retrocompatibles.

https://www.youtube.com/watch?v=QDUZmM6AEZ4




viernes, 26 de febrero de 2016

ANNUNAKI: nuestro pasado alien

Hola amigos de 8 bits de poder (8BP)

He avanzado un poco en el videojuego "Annunaki" (hecho en BASIC usando 8BP) y quiero compartir avances y un consejo de programación.

Os quiero contar la diferencia entre:

c = c + 1: IF c=4 THEN c=1

y

c = c mod 3 +1


A primera vista parecen lo mismo, pero si estamos programando en BASIC debemos ser muy cuidadosos. La primera opción consume 2.6 milisegundos  mientras que la segunda consume solo 1.84 ms
Un buen programador debe elegir la segunda opción. Pensad que vuestro videojuego esta lleno de instrucciones y si cada buena elección representa un ahorro de 1 ms o medio milisegundo , cuando se acumulan instrucciones puede haber una gran diferencia, sobre todo en juegos de arcade que requieren velocidad. Intentad siempre reducir complejidad computacional (número de instrucciones) y elegirlas bien (las que consuman menor tiempo). Programar es un arte.
Para medir el tiempo que consume un comando usad un programa como este:

10 MEMORY 26999
11 DEFINT a-z
12 c%=0: a=2
40 a!= TIME
50 FOR i=1 TO 1000
60 AQUI PONEIS LA INSTRUCCION QUE QUEREIS MEDIR
70 NEXT
80 b!=TIME
90 PRINT (b!-a!)
100 c!=1000/((b!-a!)*1/300)
110 PRINT c, "fps"
120 d!=c!/60
130 PRINT "puedes ejecutar ",d!, "comandos por barrido (1/50 seg)"
140 PRINT "el comando tarda ";((b!-a!)/300 -0.47);"milisegundos"

y ahora, un aperitivo, de lo que se puede hacer con 8BP y un poco de BASIC (imagen y video)








jueves, 25 de febrero de 2016

Como hacer un juego de naves con 8BP

hola amigos de 8 bits de poder

Os voy a dar alguna orientación para programar un juego de naves. Estoy realizando un juego que lleva por título "Annunaki", y de momento he hecho la nave y el disparo.







A continuación os doy algunas pistas de como esta hecho, y adjunto el listado
básicamente, hasta la linea 200 solo es la presentación, con un scroll de estrellas de 4 planos, que está construido con el comando STARS

En la linea 1000 se encuentra la primera fase, que no es mas que nuestra nave volando en un cielo estrellado, de nuevo hecho con el comando STARS. tras las inicializaciones se entra en el bucle del "ciclo de juego", que incluye:
gosub 500: en la linea 500 se encuentra la rutina de movimiento de la nave y de lanzamiento de un disparo. fiajos que he dejado un tiempo de guarda entre disparo y disparo. ademas, antes de activar el sprite correspondiente al disparo, elijo entre 3 sprites posibles, de modo que solo puede haber 3 disparos simultáneos.  La variable "nd" es el número de disparos que hay en pantalla

en la 750 se encuentra la rutina que libera el sprite del disparo cuando este sobrepasa el área de la pantalla. simplemente compruebo su coordenada Y con el comando |PEEK. fijaos que uso el PEEK de 8BP y no el PEEK del basic, ya que el de basic no puede leer números negativos. Otra estrategia que uso aqui es chequear solo un disparo en cada ciclo de juego, de ese modo reducimos instrucciones. consulta la técnica de lógicas masivas, es precisamente eso. Cuando un disparo sobrepasa la pantalla, se le desactiva, poniendo a cero su byte de status

por ultimo uso AUTOALL para mover todos los disparos activos y PRINTSPALL para imprimir los sprites (nave y disparos)


Espero que estas notas os sirvan y ayuden a comenzar vuestro propio juego.



10 CALL &6B78
20 dir=&A62C: '42540
30 FOR star=0 TO 40
40 POKE dir+star*2,RND*200
50 POKE dir+star*2+1,RND*80
60 NEXT
61 defint a-z
62 FOR j=0 TO 31:|SETUPSP,j,0,&X0:NEXT:' reset sprites
70 MODE 0: INK 0,0
80 |SETLIMITS,0,80,0,200
81 LOCATE 7,5:PEN 11:PRINT "ANNUNAKI"
82 LOCATE 2,9:PEN 13:PRINT "nuestro pasado alien"
83 LOCATE 2,22:PEN 7:PRINT "pulsa S para empezar"
84 LOCATE 10,25:PEN 11:PRINT "JJGA 2016"
85 |SETUPSP,31,9,34000: |PRINTSP,31,11*8,36
90 |STARS,0,10,3,1,0
100 |STARS,10,10,2,2,0
110 |STARS,20,10,1,1,0
120 |STARS,30,10,4,4,0
131 IF INKEY(60)=0 THEN 150
140 GOTO 90

150 ' empieza el juego-----------------------------
160 gosub 1000:' fase 1
170 gosub 2000:' fase 2
180 gosub 3000:' fase 3
190 gosub 4000:' fase 4
200 goto 20:'vuelta a empezar

499' rutina movimiento nave y disparo-------------------------
500 if inkey(27)=0 then x=x+1:POKE 27499,x:goto 520
510 if inkey(34)=0 then x=x-1:POKE 27499,x
520 if inkey(67)=0 then y=y-3:POKE 27497,y:goto 540
530 if inkey(69)=0 then y=y+3:POKE 27497,y
540 if timer >0 then timer =timer-1:return
700 if inkey(47)<>0 then return
701 if nd=3 then return
702 nd=nd+1:
703 if peek (27480)=0 then libre =30:goto 710
704 if peek (27464)=0 then libre =29:goto 710
705 if peek (27448)=0 then libre =28:goto 710
710 |LOCATESP,libre,y-8,x+4:|SETUPSP,libre,0,&x1001
715 timer=4:'separo disparos en el tiempo con un tiempo de guarda
720 return

749' logica fin disparo-----------------------------
750 dc=dc+1:if dc=4 then dc=1
751 if peek(27496-dc*16)=0 then return
770 |peek,(27497-dc*16),@yd%: if yd%<-4 then |SETUPSP,31-dc,0,0:nd=nd-1
790 return

799 'inicializacion----------------------------
800 FOR j=0 TO 31:|SETUPSP,j,0,&X0:NEXT:' reset sprites
801 nd=0:'num disparos activos. como mucho 3
802 disparo=&871a:yd%=0: dc=0:nd=0:libre=30
803 |SETUPSP,30,9,disparo: |SETUPSP,29,9,disparo: |SETUPSP,28,9,disparo
804 |SETUPSP,30,5,-4: |SETUPSP,29,5,-4: |SETUPSP,28,5,-4:'vy
805 x=40:y=180:|LOCATESP,31,y,x: |SETUPSP,31,0,&x1
806 cls
900 return

999' fase 1---------------------------
1000 gosub 800: 'init generico
1010:'aqui preparo la fase
1500 gosub 500:'mov nave y disparo
1510 if nd>0 then gosub 750:'logica fin disparo
1520 |AUTOALL
1530 |PRINTSPALL,0,0
1532 |STARS,0,20,4,4,0
1540 goto 1500