spaceshooter/game/lib/screen.c

191 lines
6.3 KiB
C

#include "screen.h"
#include "message.h"
CLIENT_SCREEN* cl_create_screen(CLIENT_SCREEN* screen, float scale_factor, bool fullscreen, bool resolution, int w, int h, int FPS, int num_adapter)
{
if(!screen)
{
screen = (CLIENT_SCREEN*)malloc(sizeof(CLIENT_SCREEN));
show_message_error(screen, "Failed to allocate space for CLIENT_SCREEN");
}
CLIENT_ADAPTER adapter = cl_get_info_adapter(num_adapter);
screen->FPS = FPS;
screen->monitor_width = adapter.width;
screen->monitor_height = adapter.height;
screen->display_diagonal = (float)adapter.width / adapter.height;
screen->fullscreen = fullscreen;
if(resolution)
{
if(w < 640 || h < 400 || ((float)w / h) < 1.0)
{
screen->width = screen->buffer_width = 640;
screen->height = screen->buffer_height = 400;
}
else
{
screen->width = screen->buffer_width = w;
screen->height = screen->buffer_height = h;
}
screen->buffer_diagonal = (float)screen->buffer_width / screen->buffer_height;
if(screen->fullscreen)
{
if(screen->display_diagonal > screen->buffer_diagonal)
{
screen->own_diagonal = true;
screen->scale_factor = (float)screen->buffer_width / screen->monitor_width;
screen->display_width = screen->monitor_width * ((float)screen->buffer_height / screen->monitor_height);
screen->display_height = screen->buffer_height;
screen->pos_x = (screen->display_width / 2) - (screen->buffer_width / 2);
screen->pos_y = 0;
}
else if(screen->display_diagonal < screen->buffer_diagonal)
{
screen->own_diagonal = false;
screen->scale_factor = (float)screen->buffer_height / screen->monitor_height;
screen->display_width = screen->buffer_width;
screen->display_height = screen->monitor_height * ((float)screen->buffer_width / screen->monitor_width);
screen->pos_x = 0;
screen->pos_y = (screen->display_height / 2) - (screen->buffer_height / 2);
}
else
{
screen->own_diagonal = true;
screen->scale_factor = (float)screen->buffer_width / screen->monitor_width;
screen->display_width = screen->buffer_width;
screen->display_height = screen->buffer_height;
screen->pos_x = 0;
screen->pos_y = 0;
}
}
else
{
if(screen->display_diagonal >= screen->buffer_diagonal)
screen->scale_factor = (float)screen->buffer_width / screen->monitor_width;
else if(screen->display_diagonal < screen->buffer_diagonal)
screen->scale_factor = (float)screen->buffer_height / screen->monitor_height;
screen->own_diagonal = true;
screen->pos_x = 0;
screen->pos_y = 0;
screen->display_width = screen->buffer_width;
screen->display_height = screen->buffer_height;
}
}
else
{
if((float)scale_factor >= 0.1 && (float)scale_factor < 1.0)
screen->scale_factor = scale_factor;
else if((float)scale_factor >= 1.0)
{
screen->fullscreen = true;
screen->scale_factor = 1.0;
}
else
screen->scale_factor = 0.5;
screen->own_diagonal = true;
screen->width = screen->buffer_width = screen->display_width = screen->monitor_width * screen->scale_factor;
screen->height = screen->buffer_height = screen->display_height = screen->monitor_height * screen->scale_factor;
screen->pos_x = 0;
screen->pos_y = 0;
}
if(screen->fullscreen)
{
screen->scale_factor_x = (float)screen->monitor_width / screen->display_width;
screen->scale_factor_y = (float)screen->monitor_height / screen->display_height;
}
// Create allegro display
al_set_new_display_option(ALLEGRO_SAMPLE_BUFFERS, 1, ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_SAMPLES, 8, ALLEGRO_SUGGEST);
if(screen->fullscreen)
al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
screen->display = al_create_display(screen->display_width, screen->display_height);
show_message_error(screen->display, "Failed to create Allegro display");
screen->buffer = al_create_bitmap(screen->buffer_width, screen->buffer_height);
show_message_error(screen->buffer, "Failed to create Allegro buffer");
if(screen->fullscreen)
{
ALLEGRO_TRANSFORM t;
al_identity_transform(&t);
al_scale_transform(&t, screen->scale_factor_x, screen->scale_factor_y);
al_use_transform(&t);
}
cl_get_screen(screen);
return screen;
}
static CLIENT_ADAPTER cl_get_info_adapter(int num_adapter)
{
CLIENT_ADAPTER adapter;
const int num_monitor = al_get_num_video_adapters();
ALLEGRO_MONITOR_INFO m_i;
int cur_adapter;
show_message_error(num_monitor, "Could not find connected monitors");
if(num_adapter != -1 && num_adapter <= num_monitor - 1)
cur_adapter = num_adapter;
else
cur_adapter = 0;
al_get_monitor_info(cur_adapter, &m_i);
adapter.width = m_i.x2 - m_i.x1;
adapter.height = m_i.y2 - m_i.y1;
return adapter;
}
void cl_free_screen(CLIENT_SCREEN* screen)
{
cl_destroy_screen(screen);
free(screen);
}
void cl_destroy_screen(CLIENT_SCREEN* screen)
{
al_destroy_bitmap(screen->buffer);
al_destroy_display(screen->display);
}
CLIENT_SCREEN cl_get_screen(CLIENT_SCREEN* screen)
{
static CLIENT_SCREEN screen_info;
if(screen)
{
screen_info = *screen;
}
return screen_info;
}
void cl_pre_draw()
{
CLIENT_SCREEN screen = cl_get_screen(NULL);
al_set_target_bitmap(screen.buffer);
al_clear_to_color(al_map_rgb(0, 0, 0));
}
void cl_post_draw()
{
CLIENT_SCREEN screen = cl_get_screen(NULL);
al_set_target_backbuffer(screen.display);
al_draw_scaled_bitmap(screen.buffer, 0, 0, screen.buffer_width, screen.buffer_height, screen.pos_x, screen.pos_y, screen.buffer_width, screen.buffer_height, 0);
al_flip_display();
}