render layers other than the background

This commit is contained in:
Andre Leiradella 2015-05-05 16:42:36 -03:00
parent 9188a67cc5
commit 36b6251546
2 changed files with 176 additions and 54 deletions

View File

@ -2,28 +2,52 @@
#include <rl_memory.h>
#include <rl_backgrnd.h>
#include <string.h>
#include <rl_endian.c>
static rl_map_t* destroy( rl_map_t* map )
static rl_map_t* destroy( const rl_map_t* map )
{
if ( map )
{
if ( map->tileset )
for ( int i = map->num_layers - 1; i >= 0; --i )
{
rl_tileset_destroy( map->tileset );
rl_free( (void*)map->layers[ i ] );
}
if ( map->layer0 )
{
rl_free( map->layer0 );
rl_free( (void*)map->layer0 );
}
rl_free( map );
if ( map->imageset )
{
rl_imageset_destroy( (void*)map->imageset );
}
if ( map->tileset )
{
rl_tileset_destroy( (void*)map->tileset );
}
rl_free( (void*)map );
}
return NULL;
}
static void* alloc_zero( size_t size )
{
void* ptr = rl_malloc( size );
if ( ptr )
{
memset( ptr, 0, size );
}
return ptr;
}
rl_map_t* rl_map_create( const void* data, size_t size )
{
union
@ -40,69 +64,162 @@ rl_map_t* rl_map_create( const void* data, size_t size )
int width = ne16( *ptr.u16++ );
int height = ne16( *ptr.u16++ );
int num_layers = ne16( *ptr.u16++ );
ptr.u16++; /* padding */
rl_map_t* map = (rl_map_t*)rl_malloc( sizeof( rl_map_t ) );
rl_map_t* map = (rl_map_t*)alloc_zero( sizeof( rl_map_t ) + ( num_layers - 1 ) * sizeof( rl_layern_t ) );
if ( map )
if ( !map )
{
map->width = width;
map->height = height;
map->num_layers = num_layers;
return NULL;
}
map->width = width;
map->height = height;
map->num_layers = num_layers;
size_t tileset_size = ne32( *ptr.u32++ );
map->tileset = rl_tileset_create( ptr.v, tileset_size );
if ( !map->tileset )
{
return destroy( map );
}
ptr.u8 += tileset_size;
size_t imageset_size = ne32( *ptr.u32++ );
map->imageset = rl_imageset_create( ptr.v, imageset_size );
if ( !map->imageset )
{
return destroy( map );
}
ptr.u8 += imageset_size;
map->layer0 = (rl_layer0_t*)alloc_zero( width * height * sizeof( uint16_t ) );
if ( !map->layer0 )
{
return destroy( map );
}
uint16_t* restrict ndx = (uint16_t*)( (uint8_t*)map->layer0 + sizeof( rl_layer0_t ) );
const uint16_t* restrict end = ndx + width * height;
while ( ndx < end )
{
*ndx++ = ne16( *ptr.u16++ );
}
for ( int i = 1; i < num_layers; i++ )
{
map->layers[ i - 1 ] = (rl_layern_t*)alloc_zero( width * height * sizeof( uint16_t ) );
size_t tileset_size = ne32( *ptr.u32++ );
map->tileset = rl_tileset_create( ptr.v, tileset_size );
if ( map->tileset )
if ( !map->layers[ i - 1 ] )
{
ptr.u8 += tileset_size;
map->layer0 = (rl_layer0_t*)rl_malloc( width * height * sizeof( uint16_t ) );
if ( map->layer0 )
{
uint16_t* restrict ndx = map->layer0->indices;
const uint16_t* restrict end = ndx + width * height;
while ( ndx < end )
{
*ndx++ = ne16( *ptr.u16++ );
}
return map;
}
return destroy( map );
}
ndx = (uint16_t*)( (uint8_t*)map->layers[ i - 1 ] + sizeof( rl_layern_t ) );
end = ndx + width * height;
while ( ndx < end )
{
*ndx++ = ne16( *ptr.u16++ );
}
}
return destroy( map );
return map;
}
void rl_map_destroy( rl_map_t* map )
void rl_map_destroy( const rl_map_t* map )
{
destroy( map );
}
void rl_map_render_layer( rl_map_t* map, int ndx, int x, int y )
static void render_layer0( const rl_map_t* map, int x, int y )
{
int width, height;
rl_backgrnd_fb( &width, &height );
int bg_width, bg_height;
rl_backgrnd_fb( &bg_width, &bg_height );
if ( ndx == 0 )
const rl_tileset_t* tileset = map->tileset;
int ts_width = tileset->width;
int ts_height = tileset->height;
int dx = -( x % ts_width );
int dy = -( y % ts_height );
int max_x = dx + bg_width + ts_width;
int max_y = dy + bg_height + ts_height;
x /= ts_width;
y /= ts_height;
int pitch = map->width;
const uint16_t* restrict ndx = map->layer0->indices + y * pitch + x;
for ( y = dy; y < max_y; y += ts_height )
{
int wt = ( width + map->tileset->width - 1 ) / map->tileset->width + 1;
int ht = ( width + map->tileset->height - 1 ) / map->tileset->height;
const uint16_t* restrict next = ndx + pitch;
int dx = -( x % map->tileset->width );
int dy = -( y % map->tileset->height );
x /= map->tileset->width;
y /= map->tileset->height;
for ( int yy = 0; yy < ht; yy++ )
for ( x = dx; x < max_x; x += ts_width )
{
for ( int xx = 0; xx < wt; xx++ )
{
rl_tileset_blit_nobg( map->tileset, map->layer0->indices[ ( y + yy ) * map->width + ( x + xx ) ], dx + xx * map->tileset->width, dy + yy * map->tileset->height );
}
rl_tileset_blit_nobg( tileset, *ndx++, x, y );
}
ndx = next;
}
}
static void render_layern( const rl_map_t* map, int index, int x, int y )
{
int bg_width, bg_height;
rl_backgrnd_fb( &bg_width, &bg_height );
const rl_imageset_t* imageset = map->imageset;
int ts_width = map->tileset->width;
int ts_height = map->tileset->height;
int dx = -( x % ts_width );
int dy = -( y % ts_height );
int max_x = dx + bg_width + ts_width;
int max_y = dy + bg_height + ts_height;
x /= ts_width;
y /= ts_height;
int pitch = map->width;
const uint16_t* restrict ndx = map->layers[ --index ]->indices + y * pitch + x;
for ( y = dy; y < max_y; y += ts_height )
{
const uint16_t* restrict next = ndx + pitch;
for ( x = dx; x < max_x; x += ts_width )
{
index = *ndx++;
if ( index )
{
rl_image_blit_nobg( imageset->images[ index - 1 ], x, y );
}
}
ndx = next;
}
}
void rl_map_render_layer( const rl_map_t* map, int index, int x, int y )
{
if ( index )
{
render_layern( map, index, x, y );
}
else
{
render_layer0( map, x, y );
}
}

View File

@ -2,6 +2,7 @@
#define RL_MAP_H
#include <rl_userdata.h>
#include <rl_image.h>
#include <rl_tile.h>
#include <stdint.h>
@ -13,6 +14,9 @@ typedef struct
}
rl_layer0_t;
/* layern indices are *image* indices. */
typedef rl_layer0_t rl_layern_t;
typedef struct
{
rl_userdata_t ud;
@ -21,16 +25,17 @@ typedef struct
int height;
int num_layers;
rl_tileset_t* tileset;
rl_layer0_t* layer0;
const rl_tileset_t* tileset;
const rl_imageset_t* imageset;
const rl_layer0_t* layer0;
//rl_layern_t* layers[ 0 ];
rl_layern_t* layers[ 0 ];
}
rl_map_t;
rl_map_t* rl_map_create( const void* data, size_t size );
void rl_map_destroy( rl_map_t* map );
void rl_map_destroy( const rl_map_t* map );
void rl_map_render_layer( rl_map_t* map, int ndx, int x, int y );
void rl_map_render_layer( const rl_map_t* map, int index, int x, int y );
#endif /* RL_MAP_H */