Hacemos un PACMAN con 8BP

¡Hola amigos de 8 Bits de Poder! En el artículo de hoy sobre la librería 8BP, avanzamos un poco más en el uso del comando layout. Para ello, haremos uso de un juego comecocos al estilo PacMan con 8BP, que nos permitirá visualizar claramente esta funcionalidad de la librería.

Pero espera… ¿Es posible que no sepas nada de 8 Bits de Poder? Puedes leer el primer artículo del curso de programación en Amstrad CPC de 8BP.
Ejemplo de juego con layout
Vamos a evolucionar un poco el juego presentado en capítulos anteriores, en lo que respecta al control del personaje. Esta vez vamos a usar a Montoya como ejemplo, el cual tiene 8 secuencias de animación, cada una para moverse en una dirección diferente. A las secuencias de animación les hemos asignado un número que va del 1 al 8.


En la rutina de control del personaje hemos incluido colisión con el layout. En función de la dirección en la que avanzamos, modificamos las coordenadas “nuevas” (yn , xn) e invocamos a la función de colisión con layout |COLAY,0 para chequear si el sprite 0 (nuestro personaje) ha colisionado. Si ha colisionado, corregimos las coordenadas (una o las dos) para dejarle en una posición sin colisión antes de imprimirle de nuevo.
10 MEMORY 23999 20 MODE 0: DEFINT A-Z: CALL &6B78:' install RSX 25 call &bc02:'restaura paleta por defecto por si acaso 26 ink 0,0:'fondo negro 30 FOR j=0 TO 31:|SETUPSP,j,0,&X0:NEXT:'reset sprites 40 |SETLIMITS,0,80,0,200: ' establecemos los limites de la pantalla de juego 50 dim c$(25):for i=0 to 24:c$(i)=" ":next 100 c$(1)= "ZZZZZZZZZZZZZZZZZZZZ" 110 c$(2)= "Z Z" 120 c$(3)= "Z Z" 125 c$(4)= "Z Z" 130 c$(5)= "Z ZZZ ZZZZ ZZZ Z" 140 c$(6)= "Z ZZZ ZZZZ ZZZ Z" 150 c$(7)= "Z ZZZ ZZZZ ZZZ Z" 160 c$(8)= "Z Z" 170 c$(9)= "Z Z" 190 c$(10)="Z Z" 195 c$(11)="Z ZZZZZ ZZZZZZZ Z" 200 c$(12)="Z ZZZZZ ZZZZZZZ Z" 210 c$(13)="Z Z" 220 c$(14)="Z Z" 230 c$(15)="Z Z" 240 c$(16)="ZZZZZZZZZZZZZZ ZZZZ" 250 c$(17)="Z Z" 260 c$(18)="Z Z" 270 c$(19)="Z Z" 271 c$(20)="Z Z" 272 c$(21)="Z Z" 273 c$(22)="Z Z" 274 c$(23)="ZZZZZZZZZZZZZZZZZZZZ" 300 gosub 550: ' imprime el layout 310 xa=40:xn=xa:ya=150:yn=ya:' coordenadas del personaje 311|SETUPSP,0,0,&x111:' deteccion de colision con sprites y layout 312|SETUPSP,0,7,1: ' secuencia = 1 320 |LOCATESP,0,ya,xa: 'colocamos al personaje (sin imprimirlo) 325 cl%=0:'declaramos la variable de colision, explicitamente entera (%) 330 '--- – ciclo de juego – -------------------- 340 gosub 1500:'rutina de lectura teclado y movimiento de personaje 350|PRINTSPALL,0,0 360 goto 340 550 'rutina print layout----------------------------------------- 560 FOR i=0 TO 23:|LAYOUT,i,0,@c$(i):NEXT 570 RETURN 1500 ' rutina movimiento personaje – ----------- 1510 IF INKEY(27)<0 GOTO 1520 1511 IF INKEY(67)=0 THEN IF dir<>2 THEN |SETUPSP,0,7,2:dir=2:GOTO 1533 ELSE |ANIMA,0:xn=xa+1:yn=ya-2:GOTO 1533 1512 IF INKEY(69)=0 THEN IF dir<>8 THEN |SETUPSP,0,7,8:dir=8:GOTO 1533 ELSE |ANIMA,0:xn=xa+1:yn=ya+2:GOTO 1533 1513 IF dir<>1 THEN |SETUPSP,0,7,1:dir=1:GOTO 1533 ELSE |ANIMA,0:xn=xa+1:GOTO 1533 1520 IF INKEY(34)<0 GOTO 1530 1521 IF INKEY(67)=0 THEN IF dir<>4 THEN |SETUPSP,0,7,4:dir=4:GOTO 1533 ELSE |ANIMA,0:xn=xa-1:yn=ya-2:GOTO 1533 1522 IF INKEY(69)=0 THEN IF dir<>6 THEN |SETUPSP,0,7,6:dir=6:GOTO 1533 ELSE |ANIMA,0:xn=xa-1:yn=ya+2:GOTO 1533 1523 IF dir<>5 THEN |SETUPSP,0,7,5:dir=5:GOTO 1533 ELSE |ANIMA,0:xn=xa-1:GOTO 1533 1530 IF INKEY(67)=0 THEN IF dir<>3 THEN |SETUPSP,0,7,3:dir=3:GOTO 1533 ELSE |ANIMA,0:yn=ya-4:GOTO 1533 1531 IF INKEY(69)=0 THEN IF dir<>7 THEN |SETUPSP,0,7,7:dir=7:GOTO 1533 ELSE |ANIMA,0:yn=ya+4:GOTO 1533 1532 RETURN 1533 |LOCATESP,0,yn,xn:ynn=yn:|COLAY,@cl%,0:IF cl%=0 THEN 1536 1534 yn=ya:|POKE, 27001,yn:|COLAY,@cl%,0:IF cl%=0 THEN 1536 1535 xn=xa: yn=ynn:|POKE, 27001,yn:|POKE, 27003,xn:|COLAY,@cl%,0:IF cl%=1 THEN yn=ya:|POKE,27001,yn 1536 ya=yn:xa=xn 1537 RETURN
Cómo abrir una compuerta en el layout
Si deseas que tu personaje pueda coger una llave y abrir una compuerta o en general eliminar una parte del layout para permitir el acceso, lo que tienes que hacer son dos cosas:
- Tener definido un sprite de borrado de 8×8 donde todo sean ceros. Usando |LAYOUT lo imprimes en las posiciones que deseas
- A continuación, usando nuevamente |LAYOUT, imprimes espacios donde has borrado. Así el map layout quedará con el carácter “ “ en esas posiciones y la función de colisión con el layout resultará cero.
En el juego “mutante montoya” se utiliza esta técnica para abrir la puerta del castillo, así como para abrir las compuertas que conducen a la princesa.

En el siguiente ejemplo se ilustra el concepto, abriendo una compuerta situada en las coordenadas (10, 12) de un tamaño de 2 bloques, al coger una llave que está definida con el sprite 16.
Nada más coger la llave se abre la compuerta y la llave queda desactivada para no evaluar más veces la colisión con ella, es decir, el comando |COLSP retornará un 32 a partir del momento que cojas la llave si vuelves a colisionar con ella.
Tras abrir la compuerta, si desplazas el personaje hasta el lugar que ocupaba dicha compuerta, la colisión con layout dará como resultado 0.
'--- – esta parte esta dentro del bucle de logica – -- 6410 |PRINTSPALL,1,0 6411 |COLSP,@cs%,0:IF cs%<32 THEN IF cs%>=15 then gosub 6500 (... mas instrucciones . . .) '------ – rutina de apertura de compuerta----------------- 6499 ' comprueba que tu colision sea con la llave, que es el sprite 16 6500 borra$="MM":spaces$=" ":' el sprite de borrado se ha definido como "M" (M es el sprite 18 en el "idioma" del comando |LAYOUT) 6501 if cs%=16 then|LAYOUT,10,12,@borra$ : |LAYOUT,10,12,@spaces$: |SETUPSP,16,0,0 6502 return
Un pacman con 8bp: LAYOUT con fondo
A continuación, vamos a ver un ejemplo que usa layout y sobrescritura, para lo cual establece un umbral ASCII que permite que el comando |COLAY no considere colisión con los elementos de fondo. Concretamente como elemento de fondo se usa la letra “Y”, la cual se corresponde con el sprite id= 30, y el ASCII de la “Y” es el 89.

Como puedes ver en el ejemplo, tan solo hace falta invocar a COLAY con el parámetro de umbral una vez, ya que las sucesivas invocaciones tienen ya en cuenta dicho umbral
Otro de los aspectos interesantes es la gestión del teclado de este ejemplo. Es óptima para ejecutar el menor número de operaciones |COLAY y a la vez da una sensación muy agradable al avanzar por un pasillo y conectar con otro teniendo dos teclas pulsadas a la vez.
10 MEMORY 23999 20 MODE 0: DEFINT A-Z: CALL &6B78:' install RSX 21 on break gosub 5000 25 call &bc02:'restaura paleta por defecto por si acaso 26 gosub 2300:' paleta con sobreescritura 30 FOR j=0 TO 31:|SETUPSP,j,0,&X0:NEXT:'reset sprites 40 |SETLIMITS,0,80,0,200: ' limites de la pantalla de juego 45 |SETUPSP,30,9,&84d0:' rejilla de fondo ("Y") 46 |SETUPSP,31,9,&84f2:' ladrillo ("Z") 50 dim c$(25):for i=0 to 24:c$(i)=" ":next 100 c$(1)= "ZZZZZZZZZZZZZZZZZZZZ" 110 c$(2)= "ZYYYYYYYYYYYYYYYYYYZ" 120 c$(3)= "ZYYYYYYYYYYYYYYYYYYZ" 125 c$(4)= "ZYZZZYZZZZZZZZYZZZYZ" 130 c$(5)= "ZYZZZYZZZZZZZZYZZZYZ" 140 c$(6)= "ZYYYYYYYYYYYYYYYYYYZ" 150 c$(7)= "ZYYYYYYYYYYYYYYYYYYZ" 160 c$(8)= "ZYZZZZZZZYZZZZZZZZYZ" 170 c$(9)= "ZYZ ZYZ ZYZ" 190 c$(10)="ZYZ ZYZ ZYZ" 195 c$(11)="ZYZZZZZZZYZZZZZZZZYZ" 200 c$(12)="ZYYYYYYYYYYYYYYYYYYZ" 210 c$(13)="ZYYYYYYYYYYYYYYYYYYZ" 220 c$(14)="ZYZZZYZZZZZZZYZZZZYZ" 230 c$(15)="ZYYYYYYYZ ZYYYYYYYYZ" 240 c$(16)="ZYYYYYYYZ ZYYYYYYYYZ" 250 c$(17)="ZYZZZZZYZZZYZZZZZZYZ" 260 c$(18)="ZYYYYYYYYYYYYYYYYYYZ" 270 c$(19)="ZYYYYYYYYYYYYYYYYYYZ" 271 c$(20)="ZZZZZZZZZZZZZZZZZZZZ" 272 c$(21)="" 273 c$(22)="" 274 c$(23)="" 300 'imprimimos el layout 310 FOR i=0 TO 20:|LAYOUT,i,0,@c$(i):NEXT 311 locate 1,1:pen 9:print "DEMO SOBREESCRITURA" 312 locate 3,23:pen 11:print "BASIC usando 8BP" 320 |SETUPSP,0,0,&x01000111:' deteccion colision con sprites y layout 330 |SETUPSP,0,7,1:dir=1: ' secuencia = 1 (coco derecha) 340 xa=20*2:xn=xa:ya=12*8:yn=ya:' coordenadas del personaje 350 |LOCATESP,0,ya,xa: 'colocamos al personaje (sin imprimirlo) 360 |PRINTSPALL,0,1,0:' imprime sprites 361 cl%=0:' variable colision 362 |COLAY,89,cl%,0:'umbral chr$("Y") es 89 400 ' COMIENZA EL JUEGO 401 |MUSIC,0,5 402 ' lectura teclado y colisiones. si vamos en direccion H (o p), primero chequeamos si hay pulsada tecla direccion V (q a) y viceversa 404 if dirn <3 then gosub 450: gosub 410 else gosub 410:gosub 450 405 |LOCATESP,0,yn,xn:|PRINTSPALL 406 ya=yn:xa=xn 407 goto 404 409 ' teclado direccion horizontal – - 410 if INKEY(27)<0 then 430 420 xn=xa+1:poke 27003,xn:|COLAY: IF cl%=0 then if dir<>1 then |SETUPSP,0,7,1:DIR=1:xn=xa:return else dirn=1:return 421 xn=xa:poke 27003,xn:return:'hay colision 430 if INKEY(34)<0 then return 440 xn=xa-1:poke 27003,xn:|COLAY: IF cl%=0 then if dir<>2 then |SETUPSP,0,7,2:DIR=2:xn=xa:return else dirn=2:return 441 xn=xa:poke 27003,xn:'hay colision 442 return 449 'teclado direccion vertical 450 if INKEY(67)<0 then 480 460 yn=ya-2:poke 27001,yn:|COLAY: IF cl%=0 then if dir<>3 then |SETUPSP,0,7,3:DIR=3:yn=ya:return else dirn=3:return 461 yn=ya:poke 27001,yn:'hay colision 480 if INKEY(69)<0 then return 490 yn=ya+2:poke 27001,yn:|COLAY: IF cl%=0 then if dir<>4 then |SETUPSP,0,7,4:DIR=4:yn=ya:return else dirn=4:return 491 yn=ya:poke 27001,yn:'hay colision 492 return 2300 REM – ------ – PALETA sprites transparentes MODE 0------------ 2301 INK 0,11: REM azul claro 2302 INK 1,15: REM naranja 2303 INK 2,0 : INK 3,0: REM negro 2305 INK 4,26: INK 5,26: REM blanco 2307 INK 6,6: INK 7,6: REM rojo 2309 INK 8,18: INK 9,18: REM verde 2311 INK 10,24: INK 11,24: REM amarillo 2313 INK 12,4: INK 13,4 :REM magenta 2315 INK 14,16 : INK 15, 16:REM naranja 2317 AMARILLO=10 2420 RETURN 5000 |musicoff 5010 end
En el siguiente artículo de esta serie veremos como ahorrar memoria haciendo uso del comando layout de 8 Bits de Poder. Si tu juego tiene muchas pantallas, será necesario ahorrar memoria.
Hasta aquí hemos llegado por hoy con el curso de programación en Amstrad CPC de 8 bits de poder Si tienes alguna duda puedes escribir en comentarios y te contestaré lo antes posible.
Todos los recursos, como manuales, ejemplos y juegos compilados de este curso los puedes encontrar en el repositorio Github de 8BP.
Hasta la semana que viene amigos 😄
Con esta librería se puede hacer de todo … válgame !!!