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_t

La 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_t

El ancho de la geometría

Alto

int16_t

El alto de la geometría

n_coords

int16_t

La cantidad de coordenadas

cs[0]

vector_t

La primera coordenada

...

...

...

cs[n-1]

vector_t

La ú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_t

El material que representa

Versión

int8_t

La 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_t

La 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_t

El material del bloque

CM

vector_t

El centro de masa del bloque

Angulo

double

El á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\):

../_images/20262_ej3_transformacion.png

Para transformar coordenadas del mundo en coordenadas de pantalla, entonces tendremos que transformar así:

\[u = \frac W2 + \left(x - c_x\right) e,\]
\[v = \frac H2 - \left(y - c_y\right) e.\]

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\).

../_images/20262_ej3_nivel1.png ../_images/20262_ej3_nivel2.png

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:

  1. Compilar correctamente con los flags:

    -Wall -Werror -std=c99 -pedantic -fno-extended-identifiers
    
  2. pasar Valgrind correctamente,

La entrega se realiza a través del sistema de entregas.

El ejercicio es de entrega individual.