Created a new Spritesheet struct for loading and managing spritesheets - has two SDL_Surfaces, one scaled, the other original. Also has various properties related to scale size, columns in a row, etc.. Changed interfaceDraw() to use the new system. Also, the tile in front of the player is drawn at partial opacity if it is a WALL or a DOOR. Moved the position of the UI around.

master
kts 2013-11-15 18:19:54 -08:00
parent 981e0cd2f2
commit 57a1b46db4
2 changed files with 182 additions and 72 deletions

View File

@ -198,12 +198,15 @@ void interfaceSetScale(float scale_x, float scale_y) {
g_tile_scale_y = scale_y;
g_tile_width = g_tile_scale_x * TILE_WIDTH;
g_tile_height = g_tile_scale_y * TILE_HEIGHT;
player_spritesheet = interfaceScaleSurface(player_spritesheet, scale_x, scale_y);
wall_spritesheet = interfaceScaleSurface(wall_spritesheet, scale_x, scale_y);
npc_spritesheet = interfaceScaleSurface(npc_spritesheet, scale_x, scale_y);
floor_spritesheet = interfaceScaleSurface(floor_spritesheet, scale_x, scale_y);
door_spritesheet = interfaceScaleSurface(door_spritesheet, scale_x, scale_y);
shadow_spritesheet = interfaceScaleSurface(shadow_spritesheet, scale_x, scale_y);
}
void scaleTiles(float scale_x, float scale_y) {
setSpritesheetScale(&player_sprites, scale_x, scale_y);
setSpritesheetScale(&shadow_sprites, scale_x, scale_y);
setSpritesheetScale(&door_sprites, scale_x, scale_y);
setSpritesheetScale(&npc_sprites, scale_x, scale_y);
setSpritesheetScale(&floor_sprites, scale_x, scale_y);
setSpritesheetScale(&wall_sprites, scale_x, scale_y);
}
int interfaceInit() {
@ -238,17 +241,20 @@ int interfaceInit() {
/* tile specific stuff */
/* load our surfaces from memory */
font_spritesheet = IMG_Load_RW(SDL_RWFromMem(&font_images, font_images_length), 1);
// font_mini_spritesheet = IMG_Load_RW(SDL_RWFromMem(&font_mini_images, font_mini_images_length), 1);
loadFontFromMemory(&font_standard, font_images, font_images_length, 16, 32);
setFontScale(&font_standard, 1.0f, 1.0f);
loadFontFromMemory(&font_mini, font_mini_images, font_mini_images_length, 8, 8);
setFontScale(&font_mini, 2.0f, 2.0f);
ui_spritesheet = IMG_Load_RW(SDL_RWFromMem(&ui_images, ui_images_length), 1);
player_spritesheet = IMG_Load_RW(SDL_RWFromMem(&player_images, player_images_length), 1);
npc_spritesheet = IMG_Load_RW(SDL_RWFromMem(&npc_images, npc_images_length), 1);
wall_spritesheet = IMG_Load_RW(SDL_RWFromMem(&wall_images, wall_images_length), 1);
floor_spritesheet = IMG_Load_RW(SDL_RWFromMem(&floor_images, floor_images_length), 1);
door_spritesheet = IMG_Load_RW(SDL_RWFromMem(&door_images, door_images_length), 1);
shadow_spritesheet = IMG_Load_RW(SDL_RWFromMem(&shadow_images, shadow_images_length), 1);
interfaceSetScale(2.0f, 2.0f);
loadSpritesheetFromMemory(&player_sprites, player_images, player_images_length, 16, 32, TOTAL_CLASSES);
loadSpritesheetFromMemory(&shadow_sprites, shadow_images, shadow_images_length, 16, 32, TOTAL_CLASSES);
loadSpritesheetFromMemory(&door_sprites, door_images, door_images_length, 16, 32, 16);
loadSpritesheetFromMemory(&npc_sprites, npc_images, npc_images_length, 16, 32, 16);
loadSpritesheetFromMemory(&floor_sprites, floor_images, floor_images_length, 16, 32, 16);
loadSpritesheetFromMemory(&wall_sprites, wall_images, wall_images_length, 16, 32, 16);
scaleTiles(2.0f, 2.0f);
/* set up our ui */
uiInit();
uiSetScale(2.0f, 2.0f);
@ -293,7 +299,7 @@ int uiInit() {
SDL_BlitSurface(ui_spritesheet, &hotbar_item_rect, ui_hotbar_surface, &hotbar_target_rect);
char label[2]; // max 99 hotbar_count then
itoa(i+1, label, 10);
interfaceDrawString(ui_hotbar_surface, label, i*UI_HOTBAR_ITEM_WIDTH + TILE_WIDTH/2 , 0);
interfaceDrawStringF(&font_standard, ui_hotbar_surface, label, i*UI_HOTBAR_ITEM_WIDTH + TILE_WIDTH/2 , 0);
i++;
}
SDL_SetOpacity(ui_hotbar_surface, 0.75);
@ -328,8 +334,8 @@ void cameraDraw() {
int end_x = player->x + ((struct PlayerTile*)player->data)->vision;
int end_y = player->y + ((struct PlayerTile*)player->data)->vision;
// TODO: The camera's center offset should change based upon distance to the map's width/height!
float camera_offset_x = (player->x+1)*g_tile_width - (camera_rect.w/2);
float camera_offset_y = (player->y+1)*g_tile_width - (camera_rect.h/2);
float camera_offset_x = (player->x+1)*floor_sprites.s_width - (camera_rect.w/2);
float camera_offset_y = (player->y+1)*(floor_sprites.s_height/2) - (camera_rect.h/2);
while (step_x < end_x) {
step_y = player->y - ((struct PlayerTile*)player->data)->vision;
while (step_y < end_y) {
@ -339,42 +345,37 @@ void cameraDraw() {
current_tile = &(current_map)->matrix[step_x][step_y];
int tile_id = current_tile->id;
while(current_tile) {
int y_offset = current_tile->id / 16; // 16 tiles across in spritesheet
int x_offset = current_tile->id - (y_offset*16);
SDL_Rect sprite_offset = { x_offset*g_tile_width, y_offset*g_tile_height, g_tile_width, g_tile_height};
SDL_Rect tile_rect = {(step_x*g_tile_width)-camera_offset_x, (step_y*g_tile_width)-camera_offset_y, g_tile_width, g_tile_height};
switch (current_tile->tid) {
case WALL:
SDL_BlitSurface(wall_spritesheet, &sprite_offset, camera_surface, &tile_rect);
//drawScaledSprite(&wall_sprites, current_tile->id, camera_surface, (step_x*wall_sprites.s_width)-camera_offset_x, (step_y*wall_sprites.s_height/2)-camera_offset_y);
if (step_x == player->x && step_y == player->y+1)
drawScaledTransparentSprite(&wall_sprites, current_tile->id, 0.75f, camera_surface, (step_x*wall_sprites.s_width)-camera_offset_x, (step_y*wall_sprites.s_height/2)-camera_offset_y);
else
drawScaledSprite(&wall_sprites, current_tile->id, camera_surface, (step_x*wall_sprites.s_width)-camera_offset_x, (step_y*wall_sprites.s_height/2)-camera_offset_y);
break;
case FLOOR:
SDL_BlitSurface(floor_spritesheet, &sprite_offset, camera_surface, &tile_rect);
drawScaledSprite(&floor_sprites, current_tile->id, camera_surface, (step_x*floor_sprites.s_width)-camera_offset_x, (step_y*floor_sprites.s_height/2)-camera_offset_y);
break;
case NPC:
SDL_BlitSurface(npc_spritesheet, &sprite_offset, camera_surface, &tile_rect);
drawScaledSprite(&npc_sprites, current_tile->id, camera_surface, (step_x*npc_sprites.s_width)-camera_offset_x, (step_y*npc_sprites.s_height/2)-camera_offset_y);
break;
case DOOR:
tile_id = tile_id*4;
tile_id += ((struct DoorTile*)current_tile->data)->state;
y_offset = tile_id / 16;
x_offset = tile_id - (y_offset*16);
sprite_offset.x = x_offset*g_tile_width;
sprite_offset.y = y_offset*g_tile_height;
SDL_BlitSurface(door_spritesheet, &sprite_offset, camera_surface, &tile_rect);
if (step_x == player->x && step_y == player->y+1)
drawScaledTransparentSprite(&door_sprites, tile_id, 0.75f, camera_surface, (step_x*door_sprites.s_width)-camera_offset_x, (step_y*door_sprites.s_height/2)-camera_offset_y);
else
drawScaledSprite(&door_sprites, tile_id, camera_surface, (step_x*door_sprites.s_width)-camera_offset_x, (step_y*door_sprites.s_height/2)-camera_offset_y);
break;
case PLAYER:
y_offset = current_tile->id / TOTAL_CLASSES;
x_offset = current_tile->id - (y_offset*TOTAL_CLASSES);
sprite_offset.x = x_offset*g_tile_width;
sprite_offset.y = y_offset*g_tile_height;
SDL_BlitSurface(shadow_spritesheet, NULL, camera_surface, &tile_rect);
SDL_BlitSurface(player_spritesheet, &sprite_offset, camera_surface, &tile_rect);
drawScaledSprite(&shadow_sprites, 0, camera_surface, (step_x*shadow_sprites.s_width)-camera_offset_x, (step_y*shadow_sprites.s_height/2)-camera_offset_y);
drawScaledSprite(&player_sprites, current_tile->id, camera_surface, (step_x*player_sprites.s_width)-camera_offset_x, (step_y*player_sprites.s_height/2)-camera_offset_y);
break;
}
current_tile = current_tile->next;
}
} else {
SDL_Rect tile_rect = {(step_x*g_tile_width)-camera_offset_x, (step_y*g_tile_width)-camera_offset_y, g_tile_width, g_tile_height};
SDL_Rect tile_rect = {(step_x*floor_sprites.s_width)-camera_offset_x, (step_y*floor_sprites.s_width)-camera_offset_y, floor_sprites.s_width, floor_sprites.s_height};
SDL_FillRect(camera_surface, &tile_rect, SDL_MapRGB(camera_surface->format, 0, 0, 0));
}
step_y++; // move down
@ -383,26 +384,13 @@ void cameraDraw() {
}
//SDL_BlitSurface(interfaceScaleSurface(camera_surface, camera_surface->w*(camera_surface->w/camera_rect.w), camera_surface->h*(camera_surface->h/camera_rect.h)), NULL, screen, &camera_rect);
SDL_BlitSurface(camera_surface, NULL, screen, &camera_rect);
char test[12];
itoa(tickrate, test, 10);
interfaceDrawString(screen, test, screen->w-strlen(test)*g_tile_width, 0);
}
void uiDraw() {
/* int hotbar_count = 4;
// TODO: move the next line to a uiSetAlpha function (so user can customize).
// TODO: create a Surface in interfaceInit() and simply blit that here.
SDL_SetAlpha(ui_spritesheet, SDL_SRCALPHA, 200);
SDL_Rect hotbar_item_rect = { 0, 0, 32, 32 };
int hotbar_width = hotbar_count*32;
int hotbar_height = 32;
int i = 0;
while (i < hotbar_count) {
SDL_Rect hotbar_target_rect = {(screen->w/2 - hotbar_width/2)+i*32, screen->h-hotbar_height, (screen->w/2 - hotbar_width/2)+32+i*32, screen->h};
SDL_BlitSurface(ui_spritesheet, &hotbar_item_rect, screen, &hotbar_target_rect);
i++;
}*/
SDL_Rect ui_hotbar_target_rect = {(screen->w/2 - ui_hotbar_surface->w/2), screen->h-ui_hotbar_surface->h, (screen->w/2 - ui_hotbar_surface->w/2), screen->h};
// bottom-center:
//SDL_Rect ui_hotbar_target_rect = {(screen->w/2 - ui_hotbar_surface->w/2), screen->h-ui_hotbar_surface->h, (screen->w/2 - ui_hotbar_surface->w/2), screen->h};
// top-center:
SDL_Rect ui_hotbar_target_rect = {(screen->w/2 - ui_hotbar_surface->w/2), 0, (screen->w/2 - ui_hotbar_surface->w/2), NULL};
SDL_BlitSurface(ui_hotbar_surface, NULL, screen, &ui_hotbar_target_rect);
/* TODO: move the ui_messages_surface updating elsewhere and use non-ConsoleEntry system */
int line;
@ -418,8 +406,14 @@ void uiDraw() {
}
//SDL_Rect ui_messages_target_rect = {0, screen->h - (4*font_mini.height) - ui_hotbar_surface->h, font_mini.width * 24, font_mini.height * 4};
SDL_Rect ui_messages_target_rect = {0, screen->h - (5*(font_mini.height+1)*font_mini.scale_y) - ui_hotbar_surface->h, ui_messages_surface->w, 5*(font_mini.height+1)*font_mini.scale_y};
//SDL_Rect ui_messages_target_rect = {0, screen->h - (5*(font_mini.height+1)*font_mini.scale_y) - ui_hotbar_surface->h, ui_messages_surface->w, 5*(font_mini.height+1)*font_mini.scale_y};
SDL_Rect ui_messages_target_rect = {0, screen->h - (5*(font_mini.height+1)*font_mini.scale_y), ui_messages_surface->w, 5*(font_mini.height+1)*font_mini.scale_y};
SDL_BlitSurface(ui_messages_surface, NULL, screen, &ui_messages_target_rect);
/* draw tickrate (temporary) */
char test[12];
itoa(tickrate, test, 10);
interfaceDrawStringF(&font_mini, screen, test, screen->w-(strlen(test)*(font_mini.width*font_mini.scale_x)), 0);
}
int interfaceLoop() {
@ -514,17 +508,17 @@ void interfaceDrawConsole() {
int line;
struct ConsoleEntry *entry;
entry = console_last_entry;
SDL_Rect print_area = {0, 0, screen->w, 9*TILE_HEIGHT};
SDL_Rect print_area = {0, 0, screen->w, 9*font_standard.s_height};
SDL_FillRect(screen, &print_area, SDL_MapRGB(screen->format, 0, 128, 28));
for (line = 7;line >= 0;line--) {
if (entry->size > 0) {
interfaceDrawString(screen, entry->string, 0, line*TILE_HEIGHT);
interfaceDrawStringF(&font_standard, screen, entry->string, 0, line*font_standard.s_height);
}
if (entry->prev != NULL)
entry = entry->prev;
}
interfaceDrawChar(screen, '>', 0, 8*TILE_HEIGHT);
interfaceDrawString(screen, console_cmd, TILE_WIDTH*2, 8*TILE_HEIGHT);
interfaceDrawCharF(&font_standard, screen, '>', 0, 8*font_standard.s_height);
interfaceDrawStringF(&font_standard, screen, console_cmd, font_standard.s_width*2, 8*font_standard.s_height);
}
void interfaceDrawChar(SDL_Surface *to_surface, char ch, int start_x, int start_y) {
@ -720,6 +714,28 @@ void SDL_CopySurface(SDL_Surface *from_surface, SDL_Rect *from_rect, SDL_Surface
SDL_UnlockSurface(to_surface);
}
SDL_Surface *SDL_ScaleSurface(SDL_Surface *surface, float scale_x, float scale_y) {
long x;
long y;
long output_x;
long output_y;
long new_width = (long)((float)surface->w * scale_x+0.5f);
long new_height = (long)((float)surface->h * scale_y+0.5f);
SDL_Surface *new_surface = SDL_CreateRGBSurface(surface->flags, new_width, new_height, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
for (y = 0;y < surface->h;y++) {
for (x = 0;x < surface->w;x++) {
for (output_y = 0;output_y < scale_y; ++output_y) {
for (output_x = 0;output_x < scale_x; ++output_x) {
putpixel(new_surface, (Sint32)(scale_x*x) + output_x, (Sint32)(scale_y*y)+output_y, getpixel(surface, x, y));
}
}
}
}
return new_surface;
}
SDL_Surface *interfaceSmoothScaleSurface(SDL_Surface *surface, float scale_x, float scale_y) {
long x;
long y;
@ -834,8 +850,10 @@ void loadFontFromMemory(struct Font *font, unsigned char *memory, unsigned int l
font->scale_y = 1.0f;
font->width = width;
font->height = height;
font->s_width = width;
font->s_height = height;
font->spritesheet = IMG_Load_RW(SDL_RWFromMem(memory, length), 1);
font->scaled_spritesheet = font->spritesheet;
font->scaled_spritesheet = SDL_ScaleSurface(font->spritesheet, 1.0f, 1.0f);
}
void freeFont(struct Font *font) {
@ -846,7 +864,76 @@ void freeFont(struct Font *font) {
void setFontScale(struct Font *font, float scale_x, float scale_y) {
font->scale_x = scale_x;
font->scale_y = scale_y;
SDL_FreeSurface(font->scaled_spritesheet);
font->scaled_spritesheet = interfaceScaleSurface(font->spritesheet, scale_x, scale_y);
font->s_width = font->width * scale_x;
font->s_height = font->height * scale_y;
}
void loadSpritesheetFromMemory(struct Spritesheet *spritesheet, unsigned char *memory, unsigned int length, int width, int height, int columns) {
spritesheet->width = width;
spritesheet->height = height;
spritesheet->columns = columns;
spritesheet->spritesheet = IMG_Load_RW(SDL_RWFromMem(memory, length), 1);
spritesheet->scale_x = 1.0f;
spritesheet->scale_y = 1.0f;
spritesheet->s_spritesheet = SDL_ScaleSurface(spritesheet->spritesheet, 1.0f, 1.0f);
spritesheet->s_width = width;
spritesheet->s_height = height;
}
void freeSpritesheet(struct Spritesheet *spritesheet) {
SDL_FreeSurface(spritesheet->s_spritesheet);
SDL_FreeSurface(spritesheet->spritesheet);
}
void setSpritesheetScale(struct Spritesheet *spritesheet, float scale_x, float scale_y) {
spritesheet->scale_x = scale_x;
spritesheet->scale_y = scale_y;
SDL_FreeSurface(spritesheet->s_spritesheet);
spritesheet->s_spritesheet = SDL_ScaleSurface(spritesheet->spritesheet, scale_x, scale_y);
spritesheet->s_width = spritesheet->width * scale_x;
spritesheet->s_height = spritesheet->height * scale_y;
}
void drawSprite(struct Spritesheet *spritesheet, int id, SDL_Surface *target_surface, int start_x, int start_y) {
int y_offset = id / spritesheet->columns;
int x_offset = id - (y_offset * spritesheet->columns);
SDL_Rect sprite_offset = { x_offset*spritesheet->width, y_offset*spritesheet->height, spritesheet->width, spritesheet->height};
SDL_Rect render_position = {start_x, start_y, spritesheet->width, spritesheet->height};
SDL_BlitSurface(spritesheet->spritesheet, &sprite_offset, target_surface, &render_position);
}
void drawScaledSprite(struct Spritesheet *spritesheet, int id, SDL_Surface *target_surface, int start_x, int start_y) {
int y_offset = id / spritesheet->columns;
int x_offset = id - (y_offset * spritesheet->columns);
SDL_Rect sprite_offset = { x_offset*spritesheet->s_width, y_offset*spritesheet->s_height, spritesheet->s_width, spritesheet->s_height};
SDL_Rect render_position = {start_x, start_y, spritesheet->s_width, spritesheet->s_height};
SDL_BlitSurface(spritesheet->s_spritesheet, &sprite_offset, target_surface, &render_position);
}
void drawScaledTransparentSprite(struct Spritesheet *spritesheet, int id, double opacity, SDL_Surface *target_surface, int start_x, int start_y) {
int y_offset = id / spritesheet->columns;
int x_offset = id - (y_offset * spritesheet->columns);
SDL_Rect sprite_offset = { x_offset*spritesheet->s_width, y_offset*spritesheet->s_height, spritesheet->s_width, spritesheet->s_height};
SDL_Rect render_position = {start_x, start_y, spritesheet->s_width, spritesheet->s_height};
//SDL_BlitSurface(spritesheet->s_spritesheet, &sprite_offset, target_surface, &render_position);
SDL_Surface *temp_sprite = SDL_CreateRGBSurface(spritesheet->spritesheet->flags, spritesheet->s_width, spritesheet->s_height, spritesheet->spritesheet->format->BitsPerPixel, spritesheet->s_spritesheet->format->Rmask, spritesheet->s_spritesheet->format->Gmask, spritesheet->s_spritesheet->format->Bmask, spritesheet->s_spritesheet->format->Amask);
// Why doesn't the following work:
//SDL_BlitSurface(spritesheet->s_spritesheet, &sprite_offset, temp_sprite, NULL);
// But this does:
SDL_Rect temp_offset = { 0, 0, spritesheet->s_width, spritesheet->s_height };
SDL_CopySurface(spritesheet->s_spritesheet, &sprite_offset, temp_sprite, &temp_offset);
// TODO: do not use copysurface, use blitsurface, as it (should) be faster.
SDL_SetOpacity(temp_sprite, opacity);
SDL_BlitSurface(temp_sprite, NULL, target_surface, &render_position);
//SDL_BlitSurface(spritesheet->s_spritesheet, &sprite_offset, target_surface, &render_position);
}
void interfaceQuit() {
@ -859,12 +946,14 @@ void interfaceClose() {
SDL_FreeSurface(camera_surface);
SDL_FreeSurface(font_spritesheet);
freeFont(&font_mini);
SDL_FreeSurface(player_spritesheet);
SDL_FreeSurface(npc_spritesheet);
SDL_FreeSurface(wall_spritesheet);
SDL_FreeSurface(floor_spritesheet);
SDL_FreeSurface(door_spritesheet);
SDL_FreeSurface(shadow_spritesheet);
freeFont(&font_standard);
freeSpritesheet(&player_sprites);
freeSpritesheet(&shadow_sprites);
freeSpritesheet(&npc_sprites);
freeSpritesheet(&floor_sprites);
freeSpritesheet(&door_sprites);
freeSpritesheet(&wall_sprites);
SDL_Quit();
}

View File

@ -15,23 +15,37 @@
struct Font {
int width;
int height;
int s_width;
int s_height;
float scale_x;
float scale_y;
SDL_Surface *spritesheet;
SDL_Surface *scaled_spritesheet;
};
struct Font font_mini;
struct Font font_standard;
struct Spritesheet {
int width;
int height;
int s_width;
int s_height;
int columns;
float scale_x;
float scale_y;
SDL_Surface *spritesheet;
SDL_Surface *s_spritesheet;
};
struct Spritesheet player_sprites;
struct Spritesheet shadow_sprites;
struct Spritesheet npc_sprites;
struct Spritesheet door_sprites;
struct Spritesheet floor_sprites;
struct Spritesheet wall_sprites;
SDL_Surface* screen;
SDL_Surface* font_spritesheet;
SDL_Surface* ui_spritesheet;
SDL_Surface* player_spritesheet;
SDL_Surface* npc_spritesheet;
SDL_Surface* shadow_spritesheet;
SDL_Surface* wall_spritesheet;
SDL_Surface* floor_spritesheet;
SDL_Surface* door_spritesheet;
SDL_Surface* camera_surface;
SDL_Event event;
@ -53,6 +67,12 @@ Uint32 combinepixels(Uint32 pixel_1, Uint32 pixel_2);
/* --- tile stuff --- */
void interfaceSetScale(float scale_x, float scale_y);
void loadSpritesheetFromMemory(struct Spritesheet *spritesheet, unsigned char *memory, unsigned int length, int width, int height, int columns);
void freeSpritesheet(struct Spritesheet *spritesheet);
void setSpritesheetScale(struct Spritesheet *spritesheet, float scale_x, float scale_y);
void drawSprite(struct Spritesheet *spritesheet, int id, SDL_Surface *target_surface, int start_x, int start_y);
void drawScaledSprite(struct Spritesheet *spritesheet, int id, SDL_Surface *target_surface, int start_x, int start_y);
void drawScaledTransparentSprite(struct Spritesheet *spritesheet, int id, double opacity, SDL_Surface *target_surface, int start_x, int start_y);
/* --- core drawing stuff --- */
void interfaceDrawString(SDL_Surface *to_surface, const char *string, int start_x, int start_y);
@ -65,6 +85,7 @@ SDL_Surface *interfaceSmoothScaleSurface(SDL_Surface *surface, float scale_x, fl
void SDL_CopySurface(SDL_Surface *from_surface, SDL_Rect *from_rect, SDL_Surface *to_surface, SDL_Rect *to_rect);
void SDL_SetOpacity(SDL_Surface *surface, double percent);
SDL_Surface *SDL_ScaleSurface(SDL_Surface *surface, float scale_x, float scale_y);
/* --- ui related stuff --- */
float g_ui_scale_x;