Ejercicio obligatorio 3
Fecha de entrega: Martes 3 de noviembre
Introducción
Formato de archivo
Un juego maneja geometrías, assets y niveles. Se tiene un formato de archivo binario para representar estas tres entidades.
Dado que tenemos tres entidades nuestro formato consiste de tres capítulos: El primero para las geometrías, el segundo para los assets y el tercero para los niveles.
Sección
Tamaño
Geometrías
--
Assets
--
Niveles
--
Cada una de estas secciones tiene un formato específico y su tamaño dependerá de las entidades representadas.
Sección de geometrías
La sección de geometrías iniciará con la cantidad de geometrías y luego habrá un registro por cada geometría contenida.
Entonces la sección tendrá esta estructura:
Campo
Tipo
Valor
n_geom
int16_tLa cantidad de geometrías
geom[0]
geometría
La primera geometría
...
...
...
geom[n-1]
geometría
La última geometría
A su vez cada geometría tendrá el siguiente formato:
Campo
Tipo
Valor
Nombre
char[15]El nombre de la geometría
Ancho
int16_tEl ancho de la geometría
Alto
int16_tEl alto de la geometría
n_coords
int16_tLa cantidad de coordenadas
cs[0]
vector_tLa primera coordenada
...
...
...
cs[n-1]
vector_tLa última coordenada
Siendo un vector_t una secuencia de dos float como en el EJ2.
Sección de assets
La sección de assets dirá cómo se graficará una geometría particular para un determinado material.
La misma posee la misma estructura general que la sección de geometrías: Una cantidad de assets seguida de una sucesión de assets. (Ver tabla de la sección anterior.)
Cada uno de los assets tendrá el siguiente formato:
Campo
Tipo
Valor
Geometría
char[15]La geometría que representa
Material
int8_tEl material que representa
Versión
int8_tLa versión de ese asset
Archivo
char[50]El nombre del archivo
Posición
int16_t[2]La posición del asset en el archivo
Tamaño
int16_t[2]El tamaño del asset en el archivo
En este caso cada asset tiene un tamaño fijo de 75 bytes.
El material será uno de la siguiente tabla:
Valor
Material
0
Madera
1
Vidrio
2
Piedra
3
Fijo
4
Personaje
Sección de niveles
A diferencia de las secciones anteriores, no hay un indicador de cuántos niveles posee el archivo. Habrá niveles hasta consumir el archivo completo.
Cada nivel será una sucesión de n_bloques bloques:
Campo
Tipo
Valor
n_bloques
int16_tLa cantidad de bloques del nivel
bloque[0]
bloque
El primer bloque del nivel
...
...
...
bloque[n-1]
bloque
El último bloque del nivel
Cada bloque tendrá el siguiente formato:
Campo
Tipo
Valor
Geometría
char[15]La geometría del bloque
Material
int8_tEl material del bloque
CM
vector_tEl centro de masa del bloque
Angulo
doubleEl ángulo del bloque
Cada bloque tiene un tamaño fijo de 32 bytes.
SDL2 en 5 minutos
Para representar gráficamente nuestros niveles se utilizará la biblioteca gráfica SDL2.
Una aplicación gráfica tiene un pseudocódigo más o menos de este estilo:
main() {
inicializar;
while(1) {
leer la entrada del usuario;
procesar lo que haya que procesar;
dibujar la pantalla;
esperar un ratito para cumplir con los FPS;
}
destruir;
}
Se provee un esqueleto completo con esta lógica, donde se indica dónde el alumno tiene que completar con su código. De SDL2 sólo habrá que aprender a leer el teclado, a dibujar líneas y a cambiar el color. El resto ya está hecho.
Se proveen ejemplos tanto de teclado, como del dibujado de cosas.
Sistema de referencia
En SDL2 el origen está en la esquina superior izquierda de la pantalla. La pantalla tiene un determinado ancho \(W\) y un alto \(H\).
Nuestros objetos viven en el mundo, con coordenadas cartesianas \((x, y)\), y queremos dibujar eso en la pantalla. Ahora bien, la idea es que la pantalla esté centrada en una coordenada \(c = \left(c_x, c_y\right)\) y además no utilizar un pixel de pantalla para cada unidad del mundo si no tener un factor de escala \(e\):
Para transformar coordenadas del mundo en coordenadas de pantalla, entonces tendremos que transformar así:
Siendo \((u, v)\) las coordenadas de pantalla.
Trabajo
Materiales
Declarar un tipo enumerativo materiales_t para los posibles materiales.
Estructuras
Declarar sendas estructuras para una geometría, para un asset, para un bloque y
para un nivel consistentes con lo presentado en la introducción. Todos los
vectores que dependan de un n variable deberán ser arreglos dinámicos.
Lectura
Implementar una función
struct geometria *leer_geometrias(FILE *f, size_t *n); que lea del
archivo f la sección de geometría completa. La función debe retornar un
arreglo dinámico de struct geometria y su longitud n o NULL en caso de
falla de memoria o de corrupción en el archivo.
Implementar una función
struct asset *leer_assets(FILE *f, size_t *n); que lea del archivo f
la sección de assets completa. La función debe retornar un arreglo dinámico de
struct asset y su longitud n o NULL en caso de falla de memoria o de
corrupción del archivo.
Implementar una función:
struct nivel *leer_nivel(FILE *f); que lea del archivo f un nivel.
La función debe retornar el nivel leído o NULL en caso de falla de memoria,
corrupción o terminarse el archivo.
Programa
Utilizando la plantilla dada implementar un programa que se invoque como:
$ ./20262_ej3 <archivo>
que dado un archivo binario como el ya descripto grafique en la pantalla los
bloques que componen un nivel.
El programa iniciará con centro en \((0, 0)\) y escala en \(5\). Cuando
se presione la tecla arriba se incrementará en 10 la componente \(y\) del
centro. De forma análoga abajo, izquierda derecha 10 unidades en el sentido que
corresponda. Cuando se apriete la tecla + se incrementará la escala en un
10%, mientras que cuando se presione - se reducirá en un 10%. Cada vez que el
usuario apriete la barra espaciadora se deberá mostrar el nivel siguiente del
archivo hasta terminar.
Archivo de ejemplo
Se provee un archivo binario de ejemplo que contiene 2 niveles. Para simplicar
las geometrías de ese archivo están centradas en el origen y las rotaciones de
los bloque son todas o \(0\) o \(\frac\pi2\), por lo que puede
prescindirse de utilizar el poligono_t ya implementado en el EJ2.
Las siguientes son capturas de los dos niveles, en ambos casos el centro está puesto en \((20, 30)\) y la escala en \(6.655\).
El archivo de ejemplo y la plantilla de SDL2 se descarga de acá:
archivos_20262_ej3.tar.gz
Entrega
Se deben entregar el programa desarrollado, no es obligatorio modularizar pero
es deseable. En caso de modularizar entregar además de los archivos .c y .h
el Makefile para compilar el proyecto.
El programa debe:
Compilar correctamente con los flags:
-Wall -Werror -std=c99 -pedantic -fno-extended-identifiers
pasar Valgrind correctamente,
La entrega se realiza a través del sistema de entregas.
El ejercicio es de entrega individual.