Repository navigation
Sesion: Video Juegos 1
- Sesión CPCRetroDev: Planificación
- Sesión Revisión del proceso de ensamblado y ficheros
- Sesión Convertir y dibujar sprites en ensamblador con cpctelera
- Sesión: Convertir y dibujar mapas de tiles en ensamblador con CPCTelera
Vamos a cambiar el modo de vídeo a 0. Este modo tiene una resolución de 160x200 pixeles, con 16 colores. Ahora se usan 4 bits por pixel, por lo que en cada byte hay 2 pixeles. Los bits 7,5,3 y 1 (impares) contienen el color del pixel izquierdo, y los bits 6,4,2 y 0 (pares) los del pixel derecho
Lo primero que hay que hacer es deshabilitar el firmware, y luego cambiar el modo
El main.s queda así
;;===============================
;; Main program entry
;;===============================
_main::
call cpct_disableFirmware_asm
ld c,#0
call cpct_setVideoMode_asm
;;-- Draw the Ground
ld a, #0xA0 ;;-- yellow pattern
call drawGround
main_loop:
call hero_erase ;; Erase the hero
call obstacle_erase ;; Erase the bullet
call hero_update ;; Update the Hero
call obstacle_update ;; Update the bullet
;;-- Check colision
call hero_getPtrHL
call obstacle_checkCollision
ld (0xC000),a ;;-- Draw collision
ld (0xC001),a
ld (0xC002),a
ld (0xC003),a
call hero_draw ;;-- Draw the hero
call obstacle_draw ;;-- Draw the bullet
;;-- Wait for the raster to finish
call cpct_waitVSYNC_asm
jr main_loop- Resultado:

Vemos como los colores han cambiado
Vamos a pintar un sprite de 8x12 pixeles usando gimp. Abrimos gimp, creamos una imagen nueva (File/New) y le indicamos que tiene un tamaño de 8x12 píxeles. Como la imagen muy pequeña, hacemos zoom:

Activamos el grid (Vies/Show Grid)

Para que el grid se vea como en la imagen hay que configurar para que la distancia entre líneas verticales y horizontales sea de 1 pixel. Esto lo hacemos desde el menú Edit/preferences/Default Image/Default grid

Tambien podemos cambiar el color del grid. Una vez hecho esto, reiniciamos (y volvemos a crear una imagen nueva para que aparezca el grid con los cambios)
Ahora dibujamos nuestro sprite utilizando la brocha. Ponemos un tamaño de 1, y la dureza y fuerza al 100%

Este sprite de prueba lo he exportado a png y está en el fichero smily.png
También es posible dibujar los sprites vectorialmente con inkscape. Desde el menú View/Page grid se activa la rejilla. Es importante activar las opciones de ajuste a la rejilla, en la parte de la derecha

Luego se exporta, indicando que el tamaño de la imagen es (en este caso) de 8x8. Este es el fichero resultante: chess.png
El amstrad CPC puede mostrar un total de 27 colores, pero solo se pueden utilizar los que están disponibles en la paleta. En el modo 1 tenemos una paleta de 4 colores, que por defecto son: azul(0), cyan(1), amarillo(2) y rojo(3). Estos cuatro colores se pueden cambiar por otros 4 diferentes, dentro de la gama de colores disponibles
En el modo 0 se tienen un total de 16 colores en la paleta por defecto (0-15), donde el 0 es el negro y el 15 el blanco brillante
En este enlace: Amstrad CPC palette está la información sobre las paletas de colores
En la carpeta cfg de nuestro proyecto se encuentran los ficheros de configuración. Uno de ellos es el image_conversion.mk. Es una macro para convertir automáticamente las imágenes en datos.En este archivo se define la paleta. Es una lista con los valores firmware asignados a cada color de la paleta
PALETTE={0 1 3 4 7 9 10 12 13 16 19 20 21 24 25 26}
Los colores asinados son los siguientes:
| Numero | Numero firmware | Color |
|---|---|---|
| 0 | 0 | Negro |
| 1 | 1 | Azul |
| 2 | 3 | Rojo |
| 3 | 4 | Magenta |
| 4 | 7 | Purple |
| 5 | 9 | Verde |
| 6 | 10 | Cyan |
| 7 | 12 | Amarillo |
| 8 | 13 | Blanco |
| 9 | 16 | Rosa |
| 10 | 19 | Verde marino |
| 11 | 20 | Cyan claro |
| 12 | 21 | Lima |
| 13 | 24 | Amarillo brillante |
| 14 | 25 | Amarillo pastel |
| 15 | 26 | Blanco brillante |
Así, el color 4 de la paleta es el purpura (por defecto) Esto lo podemos cambiar y definir los 16 colores que nosotros queramos
A continuación se encuentra la llamada a la macro IMG2SPRITES para realizar automáticamente la conversión de la imagen a datos:
PALETTE={0 1 3 4 7 9 10 12 13 16 19 20 21 24 25 26}
$(eval $(call IMG2SPRITES,assets/smily.png,0,sprite,8,12,$(PALETTE),,src/sprites/,hwpalette))Esta macro toma el fichero smily.png con nuestro sprite. La conversión la queremos para el modo 0. El prefijo asignado es sprite. El tamaño es de 8x12 y se le indica que use la paleta definida PALETTE. El resultado (los datos) los generará en el directorio src/sprites. Este directorio lo tenemos que crear a mano (si no está ya creado)
Los ficheros fuente con los sprites los metemos en la carpeta assets (que hay que crear). Este es el arbol de proyectos tal cual lo tenemos inicialmente:
$ tree
.
├── assets
│ ├── chess.png
│ ├── chess.svg
│ ├── smily.png
│ └── smily.xcf
├── cfg
│ ├── build_config.mk
│ ├── image_conversion.mk
│ ├── music_conversion.mk
│ └── tilemap_conversion.mk
├── Makefile
└── src
├── bullet.h.s
├── bullet.s
├── cpctelera.h.s
├── hero.h.s
├── hero.s
├── main.s
├── obstacle.h.s
├── obstacle.s
└── spritesAhora ejecutamos make. Suceden muchas cosas. Las vemos poco a poco:

Se invoca a la herramienta cpct_img2tileset para convertir el fichero assets/smily.png. Se generan los ficheros src/sprite/smily.c y src/sprite/smily.h
-
src/sprite/smily.h: Se definen las constantes globales
sprite_paletteysprite_smily
// Data created with Img2CPC - (c) Retroworks - 2007-2015
#ifndef _ASSETS_SMILY_H_
#define _ASSETS_SMILY_H_
#include <types.h>
extern const u8 sprite_palette[16];
#define SPRITE_SMILY_W 4
#define SPRITE_SMILY_H 12
extern const u8 sprite_smily[4 * 12];
#endif- src/sprite/smily.c: Y aquí sus contenidos (En C)
#include "smily.h"
// Data created with Img2CPC - (c) Retroworks - 2007-2015
// Palette uses hardware values.
const u8 sprite_palette[16] = { 0x54, 0x44, 0x5c, 0x58, 0x45, 0x56, 0x46, 0x5e, 0x40, 0x47, 0x42, 0x53, 0x5a, 0x4a, 0x43, 0x4b };
// Tile sprite_smily: 8x12 pixels, 4x12 bytes.
const u8 sprite_smily[4 * 12] = {
0x00, 0x51, 0xa2, 0x00,
0x00, 0xf3, 0xf3, 0x00,
0x51, 0xf3, 0xf3, 0xa2,
0xf3, 0x51, 0xa2, 0xf3,
0xf3, 0x51, 0xa2, 0xf3,
0xf3, 0x51, 0xa2, 0xf3,
0xf3, 0xf3, 0xf3, 0xf3,
0xf3, 0xf3, 0xf3, 0xf3,
0x51, 0x51, 0xa2, 0xa2,
0x51, 0xa2, 0x51, 0xa2,
0x00, 0xf3, 0xf3, 0x00,
0x00, 0x51, 0xa2, 0x00
};Este es el árbol de proyecto con los nuevos cambios:
.
├── assets
│ ├── ...
├── cfg
│ ├── build_config.mkimage_conversion.mk
│ ├── ...
├── obj
│ └── sprites
│ ├── smily.asm
│ ├── smily.lst
│ ├── smily.rel
│ ├── smily.rst
│ └── smily.sym
└── src
├── ...
└── sprites
├── smily.c
└── smily.hEl proceso se resume así:
assets/smily.png --> src/sprites/smily.c --> obj/sprites/smily.asm
Hemos obtenido un fichero en ensamblador: smily.asm que contiene la paleta y los sprites para usarlos directamente en nuestras funciones de ensamblador. Las etiquetas que están disponibles para usarse son: _sprite_palette y _sprite_smily
...
;--------------------------------------------------------
; code
;--------------------------------------------------------
.area _CODE
.area _CODE
_sprite_palette:
.db #0x54 ; 84 'T'
.db #0x44 ; 68 'D'
.db #0x5c ; 92
.db #0x58 ; 88 'X'
.db #0x45 ; 69 'E'
.db #0x56 ; 86 'V'
.db #0x46 ; 70 'F'
.db #0x5e ; 94
.db #0x40 ; 64
.db #0x47 ; 71 'G'
.db #0x42 ; 66 'B'
.db #0x53 ; 83 'S'
.db #0x5a ; 90 'Z'
.db #0x4a ; 74 'J'
.db #0x43 ; 67 'C'
.db #0x4b ; 75 'K'
_sprite_smily:
.db #0x00 ; 0
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0x00 ; 0
.db #0x00 ; 0
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0x00 ; 0
.db #0x51 ; 81 'Q'
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xa2 ; 162
.db #0xf3 ; 243
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0x51 ; 81 'Q'
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0xa2 ; 162
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0x00 ; 0
.db #0xf3 ; 243
.db #0xf3 ; 243
.db #0x00 ; 0
.db #0x00 ; 0
.db #0x51 ; 81 'Q'
.db #0xa2 ; 162
.db #0x00 ; 0
.area _INITIALIZER
.area _CABS (ABS)Ya lo tenemos todo listo para pintar nuestro nuevo sprite. En el fichero hero.s tendremos que usar los datos del sprite, por lo que añadimos la etiqueta global _sprite_smily. Es un puntero a los datos del sprite
.area _DATA
.area _CODE
;;==============================================
;;==============================================
;; PRIVATE DATA
;;==============================================
;;==============================================
;;-- Data for drawing the sprite
.globl _sprite_smily
;;-- HERO DATA
hero_x: .db #39 ;;-- x position (in bytes [0-79])
...Para pintar el sprite utilizamos la función de cpctelera drawSprite
La nueva función de dibujado la metemos en hero_draw (pública):
;;======================
;; Draw the hero
;; DESTROYS: AF, BC, HL
;;=======================
hero_draw::
;;-- Convert the hero_x, hero_y variables into
;;-- the corresponding address in the Video memory
ld de, #0xC000 ;;-- Video initial address
ld a,(hero_x)
ld c,a ;;-- Hero x position
ld a,(hero_y)
ld b,a ;;-- Hero y position
call cpct_getScreenPtr_asm
;; HL contains the video address
;; move it to the DE register
ex de, hl
;; Draw our hero
ld hl, #_sprite_smily
ld bc, #0x0C04 ;; Height, Width: 8x12 pixels
call cpct_drawSprite_asm
retLa función de borrado hero_erase también la modificamos. Y hacemos que el tamaño del sprite lo tome de las variables:
;;======================
;; Erase the hero
;; DESTROYS: AF, BC, HL
;;=======================
hero_erase::
;;-- Convert the hero_x, hero_y variables into
;;-- the corresponding address in the Video memory
ld de, #0xC000 ;;-- Video initial address
ld a,(hero_x)
ld c,a ;;-- Hero x position
ld a,(hero_y)
ld b,a ;;-- Hero y position
call cpct_getScreenPtr_asm
;; HL contains the video address
;; move it to the DE register
ex de, hl
;; Draw a Box (our hero!)
ld a, (hero_w)
ld c, a ;; c = Hero width
ld a, (hero_h)
ld b, a ;; b = Hero height
ld a, #0x00 ;; Color pattern: 0 (Black!)
call cpct_drawSolidBox_asm
retLas variables del tamaño del personaje las actualizamos (ahora son de 8x12). La altura es de 12 y la anchura de 4 (bytes, y hay 2 pixeles por byte)
;;-- HERO DATA
...
hero_w: .db #4 ;;-- Width in bytes
hero_h: .db #12 ;;-- Height in bytes
...Modificamos la tabla de saltos también para que el personal salta más alto y dure un poco más:
;;-- Jump table
jumptable:
.db #-3, #-3, #-2, #-2, #-1, #-1
.db #0, #0, #0, #0
.db #1, #1, #2, #2, #3, #3
.db #0x80También tenemos que establecer la nueva paleta. Eso lo hacemos con la función cpct_setPalette-asm.html
Esto lo hacemos en el main.s, antes de entrar en el bucle principal
...
;;-- Change the color palette
ld hl, #_sprite_palette
ld de, #16
call cpct_setPalette_asm
...Por último, modificamos la rutina del personaje para que compruebe la colisión con la posición derecha, que ahora el tamaño es de 4 bytes. Sin embargo, en vez de cablearlo, vamos a hacer una rutina más genérica, que tenga en cuenta la variable hero_w
;;=============================================
;; moveHeroRight: Move the hero to the right
;; (inside the line limits)
;;
;; DESTROYS:
;;=============================================
moveHeroRight:
;;- Check if the hero_x has reached its maximum value
;;-- We should check the possition 80 - hero.width
ld a, (hero_w)
ld b,a
ld a, #80
sub b ;;-- A = 80 - hero_w
ld b,a ;;-- B = 80 - hero_w
ld a, (hero_x) ;;-- A = hero_x
cp b ;; hero_x == 80-hero_w?
jr z,do_not_move_r
;;- No max reached: increase the hero_x by 1
inc a ;;-- A = A + 1
ld (hero_x),a ;;-- hero_x = A
do_not_move_r:
retAl ejecutarlo vemos esto, ¡¡Se nos ha dibujado el personaje!!

- Resultado: En esta animación vemos el juego tal cual está ahora:

Tiled es una herramienta libre que nos permite crear mapas y escenarios para nuestros juegos. Se instala muy fácil en Linux. Sólo hay que bajarse el appimage desde el github: Tiled github. Yo tengo instalada la versión 1.7.2
El primer paso es aprender a manejarlo. Hay documentación aquí: Tiled: User manual
Los mapas se construyen a partir de un conjunto de sprites simples que se llaman tilesets (conjunto de tiles). Por ejemplo, para construir un laberinto necesitamos sprites para las paredes vertical, para las horizontales, para las esquinas, para el fondo, etc... Para practicar vamos a crear un tileset super simplificado, son sólo 4 tiles: pared vertical central, pared horizontal central, nudo y fondo
Estos 4 tiles los creamos con Gimp, y los metemos un único fichero donde están los 4 tiles agrupados, formando por ejemplo un array 2x2, pero los podríamos poner también en fila (un array de 1x4). Cada tile es de 4x4

Ahora arrancamos Tiled. Para crear un mapa nuevo le damos a File/New/New Map.... Ahora establecemos el tamaños de nuestras tiles (en nuestro caso son de 4x4) y el tamaño del mapa en tiles

Le damos a Save as y lo guardamos como level1.tmx. Se nos abre el editor de mapas:

Ahora creamos el Tileset. Pinchamos en File/New/New Tileset:

Le damos un nombre, por ejemplo tileset-1. Le indicamos el archivo donde está los tiles, que en nuestro caso era tiles8x8.png y el tamaño de los tiles que contiene: 4x4 en nuestro caso. Pinchamos en Save as y lo guardamos en el fichero tileset-1.tsx
En la parte de la derecha del editor de mapas veremos los 4 tiles de nuestro tileset (si se ven muy pequeños hay que hacer zoom)

Ahora ya podemos dibujar nuestro mapa. Este es el que he hecho de prueba:

Lo guardamos. Ya está todo listo para usarlo desde nuestro programa en ensamblador
Ya tenemos nuestros dos ficheros: level1.tmx y tileset-1.tsx, con el mapa y los tiles respectivamente. Estos son ficheros en xml, por lo que podemos ver lo que tienen:
- level1.txm:
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.7.2" orientation="orthogonal" renderorder="right-down" width="40" height="32" tilewidth="4" tileheight="4" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="tileset-1.tsx"/>
<layer id="1" name="Tile Layer 1" width="40" height="32">
<data encoding="csv">
2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,4,4,4,2,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,2,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
2,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,2,4,4,4,4,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,4,4,4,4,2,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,4,4,4,4,4,4,2,2,2,1,1,1,1,1,1,1,3,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,3,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,3,1,1,1,3,1,1,1,4,4,4,4,2,
3,1,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,3,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,4,4,4,1,1,1,3,
3,1,1,1,1,1,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,4,4,4,4,2,
2,4,4,4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
2,4,4,1,1,1,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,2,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,3,
3,1,4,4,4,4,4,4,1,1,1,1,4,4,4,4,4,1,1,1,4,4,4,4,4,4,4,4,4,4,4,4,4,2,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,
2,4,4,4,4,4,4,4,2,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2
</data>
</layer>
</map>Cada uno de los números 1-4 representa uno de los 4 tiles disponibles
- tileset-1.tsx
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.5" tiledversion="1.7.2" name="tileset-1" tilewidth="4" tileheight="4" tilecount="4" columns="2">
<image source="tiles8x8.png" width="8" height="8"/>
</tileset>Este fichero de tileset no son más que metadatos donde se indica el nombre del fichero fuente que contiene los tiles (tiles8x8.png), las dimensiones en píxeles, y el tamaño de los tiles
Necesitamos convertir estos archivos en datos, para poderlos utilizar desde nuestros programas
A partir del tileset tenemos que generar los datos de los sprites de los 4 tiles. Esto lo hacemos en el archivo cfg/image_conversion.mk, a continuación de lo que habíamos hecho antes:
#-- Tiles generation
$(eval $(call IMG2SPRITES,assets/tiles8x8.png,0,g,4,4,$(PALETTE),tileset,src/sprites/,))
Con esto se generan los ficheros tiles8x8.c y tiles8x8.h con los datos de estos sprites. El símbolo global en c es g_tileset
#include "tiles8x8.h"
// Data created with Img2CPC - (c) Retroworks - 2007-2015
u8* const g_tileset[4] = {
g_tiles8x8_0, g_tiles8x8_1, g_tiles8x8_2, g_tiles8x8_3
};
// Tile g_tiles8x8_0: 4x4 pixels, 2x4 bytes.
const u8 g_tiles8x8_0[2 * 4] = {
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00
};
// Tile g_tiles8x8_1: 4x4 pixels, 2x4 bytes.
const u8 g_tiles8x8_1[2 * 4] = {
0x04, 0x08,
0x0c, 0x0c,
0x0c, 0x0c,
0x04, 0x08
};
// Tile g_tiles8x8_2: 4x4 pixels, 2x4 bytes.
const u8 g_tiles8x8_2[2 * 4] = {
0x04, 0x08,
0x04, 0x08,
0x04, 0x08,
0x04, 0x08
};
// Tile g_tiles8x8_3: 4x4 pixels, 2x4 bytes.
const u8 g_tiles8x8_3[2 * 4] = {
0x00, 0x00,
0x0c, 0x0c,
0x0c, 0x0c,
0x00, 0x00
};El símbolo correspondiente en ensamblador es _g_tileset. Lo incluimos como símbolo global en nuestro main.s para usarlo. Para dejarlo configuado y listo para pintarse, usamos la función cpct_etm_setTileset2x4-s.html
...
.globl _g_tileset
...
__main::
...
;;-- Configure the tileset
ld hl,#_g_tileset
call cpct_etm_setTileset2x4_asmAhora hay que generar los datos del mapa. Esto lo hacemos desde el fichero tilemap_conversion.mk, con la siguiente línea:
$(eval $(call TMX2C,assets/level1.tmx,level0,src/niveles/,))
Creamos el directorio src/niveles y ejecutamos make. Se nos generan los ficheros level1.c y level1.h con el mapa en C:
//
// File assets/level1.tmx converted to csv using cpct_tmx2csv [20211016 16:24:41 CEST]
// * Width: 40 columns (40 bytes, 8 bits per column)
// * Height: 32 rows
// * Bytes: 1280 bytes (40 x 32)
//
#include <types.h>
// Generated CSV tilemap from assets/level1.tmx
const u8 level0[40*32] = {
1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,3,3,3,1,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,1,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
1,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,3,3,3,3,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,3,3,3,3,1,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,1,1,1,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,3,3,3,3,1,
2,0,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,3,3,3,0,0,0,2,
2,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,3,3,3,1,
1,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
1,3,3,0,0,0,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,3,3,3,3,3,1,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,2,
2,0,3,3,3,3,3,3,0,0,0,0,3,3,3,3,3,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,1,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,
1,3,3,3,3,3,3,3,1,3,3,3,3,3,3,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,
};El puntero al mapa lo tenemos en la etiqueta: _level0. Esta etiqueta la importamos en el main.s (como global). Usamos la función cpct_etm_drawTileBox2x4 para dibujar el mapa
.area _DATA
.area _CODE
.include "hero.h.s"
.include "obstacle.h.s"
.include "cpctelera.h.s"
.globl _sprite_palette
.globl _g_tileset
.globl _level0
;;===============================
;; Main program entry
;;===============================
_main::
;;-- Disable Amstrad firmware. Needed for changing
;;-- the video mode
call cpct_disableFirmware_asm
;;-- Change the video modeo to 0 (160x200 16 colors)
ld c,#0
call cpct_setVideoMode_asm
;;-- Change the color palette
ld hl, #_sprite_palette
ld de, #16
call cpct_setPalette_asm
;;-- Configure the tileset
ld hl,#_g_tileset
call cpct_etm_setTileset2x4_asm
;;-- Draw the level0
ld hl, #_level0
push hl
ld hl,#0xC000
push hl
ld bc,#0x0000 ;;-- Tile 0,0
ld de,#0x2028 ;;-- Height/Width in tiles (of the map)
ld a,#0x28 ;;-- Number of tiles in the row
call cpct_etm_drawTileBox2x4_asm ;; Draw the map!!
main_loop:
call hero_erase ;; Erase the hero
call obstacle_erase ;; Erase the bullet
call hero_update ;; Update the Hero
call obstacle_update ;; Update the bullet
;;-- Check colision
call hero_getPtrHL
call obstacle_checkCollision
ld (0xC000),a ;;-- Draw collision
ld (0xC001),a
ld (0xC002),a
ld (0xC003),a
call hero_draw ;;-- Draw the hero
call obstacle_draw ;;-- Draw the bullet
;;-- Wait for the raster to finish
call cpct_waitVSYNC_asm
jr main_loopEsto es lo que se ve ahora:

- Resultado:




