import Radio Edit codebase

This commit is contained in:
Sebastian Krzyszkowiak 2016-06-27 21:20:02 +02:00
parent e92e4b6bec
commit 46827594b4
16 changed files with 1368 additions and 668 deletions

View file

@ -69,9 +69,9 @@
if (WIN32)
# use relative install prefix to avoid hardcoded install paths in cmake_install.cmake files
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" ) # The subdirectory relative to the install prefix where libraries will be installed (default is ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX})
set(LIB_INSTALL_DIR "bin" ) # The subdirectory relative to the install prefix where libraries will be installed (default is ${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX})
set(EXEC_INSTALL_PREFIX "" ) # Base directory for executables and libraries
set(EXEC_INSTALL_PREFIX "${EXEC_INSTALL_PREFIX}" ) # Base directory for executables and libraries
set(SHARE_INSTALL_PREFIX "share" ) # Base directory for files which go to share/
set(BIN_INSTALL_DIR "bin" ) # The install dir for executables (default ${EXEC_INSTALL_PREFIX}/bin)
set(SBIN_INSTALL_DIR "sbin" ) # The install dir for system executables (default ${EXEC_INSTALL_PREFIX}/sbin)

View file

@ -5,6 +5,10 @@ SET(SRC_LIST
gamestate.c
)
SET(EXECUTABLE_SRC_LIST
main.c
)
find_package(Allegro5 REQUIRED)
find_package(Allegro5Font REQUIRED)
find_package(Allegro5TTF REQUIRED)
@ -17,42 +21,36 @@ if(APPLE)
endif(APPLE)
if(MINGW)
# resource compilation for MinGW
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icon.o COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_SOURCE_DIR} -i${CMAKE_SOURCE_DIR}/data/icons/icon.rc -o ${CMAKE_CURRENT_BINARY_DIR}/icon.o )
set(SRC_LIST ${SRC_LIST} ${CMAKE_CURRENT_BINARY_DIR}/icon.o)
set(LINK_FLAGS -Wl,-subsystem,windows)
# resource compilation for MinGW
add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/icon.o COMMAND ${CMAKE_RC_COMPILER} -I${CMAKE_SOURCE_DIR} -i${CMAKE_SOURCE_DIR}/data/icons/icon.rc -o ${CMAKE_CURRENT_BINARY_DIR}/icon.o )
set(EXECUTABLE_SRC_LIST ${EXECUTABLE_SRC_LIST} ${CMAKE_CURRENT_BINARY_DIR}/icon.o)
set(LINK_FLAGS -Wl,-subsystem,windows)
endif(MINGW)
SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib/superderpy:\$ORIGIN/gamestates:\$ORIGIN/levels:\$ORIGIN:\$ORIGIN/../lib")
#IF(${PACKAGE_BUILD})
# SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
# SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib/superderpy:\$ORIGIN")
#ENDIF(${PACKAGE_BUILD})
SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib/radioedit:\$ORIGIN/gamestates:\$ORIGIN:\$ORIGIN/../lib:\$ORIGIN/lib:\$ORIGIN/bin")
if(APPLE)
set(EXECUTABLE "SuperDerpy")
set(EXECUTABLE "RadioEdit")
else(APPLE)
set(EXECUTABLE "superderpy")
set(EXECUTABLE "radioedit")
endif(APPLE)
add_library("libsuperderpy" SHARED ${SRC_LIST})
add_executable(${EXECUTABLE} WIN32 MACOSX_BUNDLE "main.c")
add_library("libsuperderpy-radioedit" SHARED ${SRC_LIST})
add_executable(${EXECUTABLE} WIN32 MACOSX_BUNDLE ${EXECUTABLE_SRC_LIST})
SET_TARGET_PROPERTIES("libsuperderpy" PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES("libsuperderpy-radioedit" PROPERTIES PREFIX "")
include_directories(${ALLEGRO5_INCLUDE_DIR} ${ALLEGRO5_FONT_INCLUDE_DIR} ${ALLEGRO5_TTF_INCLUDE_DIR} ${ALLEGRO5_PRIMITIVES_INCLUDE_DIR} ${ALLEGRO5_AUDIO_INCLUDE_DIR} ${ALLEGRO5_ACODEC_INCLUDE_DIR} ${ALLEGRO5_IMAGE_INCLUDE_DIR})
target_link_libraries(${EXECUTABLE} ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} ${ALLEGRO5_MAIN_LIBRARIES} m dl libsuperderpy)
target_link_libraries(${EXECUTABLE} ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} ${ALLEGRO5_MAIN_LIBRARIES} m dl libsuperderpy-radioedit)
target_link_libraries("libsuperderpy" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} ${ALLEGRO5_MAIN_LIBRARIES} m)
target_link_libraries("libsuperderpy-radioedit" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} ${ALLEGRO5_MAIN_LIBRARIES} m)
if(ALLEGRO5_MAIN_FOUND)
target_link_libraries(${EXECUTABLE} ${ALLEGRO5_MAIN_LIBRARIES})
endif(ALLEGRO5_MAIN_FOUND)
add_subdirectory(gamestates)
add_subdirectory(levels)
install(TARGETS ${EXECUTABLE} DESTINATION ${BIN_INSTALL_DIR})
install(TARGETS "libsuperderpy" DESTINATION ${LIB_INSTALL_DIR})
install(TARGETS "libsuperderpy-radioedit" DESTINATION ${LIB_INSTALL_DIR})

View file

@ -26,33 +26,33 @@
struct Game;
struct Gamestate {
char* name;
void* handle;
bool loaded, pending_load;
bool started, pending_start;
bool showLoading;
bool paused;
bool fade; // TODO: or maybe should it be in API?
unsigned char fade_counter;
char** after; // TODO: and this one too?
struct Gamestate* next;
void* data;
struct {
void (*Gamestate_Draw)(struct Game *game, void* data);
void (*Gamestate_Logic)(struct Game *game, void* data);
char* name;
void* handle;
bool loaded, pending_load;
bool started, pending_start;
bool showLoading;
bool paused;
bool fade; // TODO: or maybe should it be in API?
unsigned char fade_counter;
char** after; // TODO: and this one too?
struct Gamestate* next;
void* data;
struct {
void (*Gamestate_Draw)(struct Game *game, void* data);
void (*Gamestate_Logic)(struct Game *game, void* data);
void* (*Gamestate_Load)(struct Game *game, void (*progress)(struct Game *game));
void (*Gamestate_Start)(struct Game *game, void* data);
void (*Gamestate_Pause)(struct Game *game, void* data);
void (*Gamestate_Resume)(struct Game *game, void* data);
void (*Gamestate_Stop)(struct Game *game, void* data);
void (*Gamestate_Unload)(struct Game *game, void* data);
void* (*Gamestate_Load)(struct Game *game, void (*progress)(struct Game *game));
void (*Gamestate_Start)(struct Game *game, void* data);
void (*Gamestate_Pause)(struct Game *game, void* data);
void (*Gamestate_Resume)(struct Game *game, void* data);
void (*Gamestate_Stop)(struct Game *game, void* data);
void (*Gamestate_Unload)(struct Game *game, void* data);
void (*Gamestate_ProcessEvent)(struct Game *game, void* data, ALLEGRO_EVENT *ev);
void (*Gamestate_Reload)(struct Game *game, void* data);
void (*Gamestate_ProcessEvent)(struct Game *game, void* data, ALLEGRO_EVENT *ev);
void (*Gamestate_Reload)(struct Game *game, void* data);
int *Gamestate_ProgressCount;
} api;
int *Gamestate_ProgressCount;
} api;
};
void LoadGamestate(struct Game *game, const char* name);

View file

@ -1,21 +1,16 @@
MACRO(GAMESTATE name)
add_library("libsuperderpy-muffinattack-${name}" SHARED "${name}.c")
add_library("libsuperderpy-radioedit-${name}" SHARED "${name}.c")
SET_TARGET_PROPERTIES("libsuperderpy-muffinattack-${name}" PROPERTIES PREFIX "")
SET_TARGET_PROPERTIES("libsuperderpy-radioedit-${name}" PROPERTIES PREFIX "")
target_link_libraries("libsuperderpy-muffinattack-${name}" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} m libsuperderpy)
target_link_libraries("libsuperderpy-radioedit-${name}" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} m libsuperderpy-radioedit)
install(TARGETS "libsuperderpy-muffinattack-${name}" DESTINATION ${LIB_INSTALL_DIR})
install(TARGETS "libsuperderpy-radioedit-${name}" DESTINATION ${LIB_INSTALL_DIR})
ENDMACRO()
GAMESTATE("dosowisko")
GAMESTATE("menu")
GAMESTATE("disclaimer")
GAMESTATE("intro")
GAMESTATE("map")
GAMESTATE("about")
#GAMESTATE("pause")
GAMESTATE("loading")

View file

@ -106,18 +106,22 @@ void Gamestate_Draw(struct Game *game, struct dosowiskoResources* data) {
al_clear_to_color(al_map_rgba(0,0,0,0));
al_draw_text(data->font, al_map_rgba(255,255,255,10), game->viewport.width/2, game->viewport.height*0.4167, ALLEGRO_ALIGN_CENTRE, t);
al_set_target_backbuffer(game->display);
al_clear_to_color(al_map_rgb(35, 31, 32));
double tg = tan(-data->tan/384.0 * ALLEGRO_PI - ALLEGRO_PI/2);
int fade = data->fadeout ? 255 : data->fade;
al_set_target_bitmap(data->pixelator);
al_clear_to_color(al_map_rgb(35, 31, 32));
al_draw_tinted_scaled_bitmap(data->bitmap, al_map_rgba(fade, fade, fade, fade), 0, 0, al_get_bitmap_width(data->bitmap), al_get_bitmap_height(data->bitmap), -tg*al_get_bitmap_width(data->bitmap)*0.05, -tg*al_get_bitmap_height(data->bitmap)*0.05, al_get_bitmap_width(data->bitmap)+tg*0.1*al_get_bitmap_width(data->bitmap), al_get_bitmap_height(data->bitmap)+tg*0.1*al_get_bitmap_height(data->bitmap), 0);
al_draw_bitmap(data->checkerboard, 0, 0, 0);
al_set_target_backbuffer(game->display);
al_draw_bitmap(data->pixelator, 0, 0, 0);
}
}
@ -155,13 +159,14 @@ void* Gamestate_Load(struct Game *game, void (*progress)(struct Game*)) {
data->timeline = TM_Init(game, "main");
data->bitmap = al_create_bitmap(game->viewport.width, game->viewport.height);
data->checkerboard = al_create_bitmap(game->viewport.width, game->viewport.height);
data->pixelator = al_create_bitmap(game->viewport.width, game->viewport.height);
al_set_target_bitmap(data->checkerboard);
al_lock_bitmap(data->checkerboard, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);
int x, y;
for (x = 0; x < al_get_bitmap_width(data->checkerboard); x=x+2) {
for (y = 0; y < al_get_bitmap_height(data->checkerboard); y=y+2) {
al_put_pixel(x, y, al_map_rgb(0,0,0));
al_put_pixel(x, y, al_map_rgba(0,0,0,64));
al_put_pixel(x+1, y, al_map_rgba(0,0,0,0));
al_put_pixel(x, y+1, al_map_rgba(0,0,0,0));
al_put_pixel(x+1, y+1, al_map_rgba(0,0,0,0));
@ -211,6 +216,7 @@ void Gamestate_Unload(struct Game *game, struct dosowiskoResources* data) {
al_destroy_sample(data->key_sample);
al_destroy_bitmap(data->bitmap);
al_destroy_bitmap(data->checkerboard);
al_destroy_bitmap(data->pixelator);
TM_Destroy(data->timeline);
free(data);
}

View file

@ -23,7 +23,7 @@ struct dosowiskoResources {
ALLEGRO_FONT *font;
ALLEGRO_SAMPLE *sample, *kbd_sample, *key_sample;
ALLEGRO_SAMPLE_INSTANCE *sound, *kbd, *key;
ALLEGRO_BITMAP *bitmap, *checkerboard;
ALLEGRO_BITMAP *bitmap, *checkerboard, *pixelator;
int pos, fade, tick, tan;
char text[255];
bool underscore, fadeout;

View file

@ -25,7 +25,7 @@
void Progress(struct Game *game, struct LoadingResources *data, float p) {
al_set_target_bitmap(al_get_backbuffer(game->display));
al_draw_bitmap(data->loading_bitmap,0,0,0);
al_draw_filled_rectangle(0, game->viewport.height*0.985, p*game->viewport.width, game->viewport.height, al_map_rgba(255,255,255,255));
al_draw_filled_rectangle(0, game->viewport.height-1, p*game->viewport.width, game->viewport.height, al_map_rgba(128,128,128,128));
}
void Draw(struct Game *game, struct LoadingResources *data, float p) {
@ -39,15 +39,10 @@ void* Load(struct Game *game) {
data->loading_bitmap = al_create_bitmap(game->viewport.width, game->viewport.height);
data->image = LoadScaledBitmap(game, "loading.png", game->viewport.height*2, game->viewport.height);
al_set_target_bitmap(data->loading_bitmap);
al_clear_to_color(al_map_rgb(193,225,218));
al_draw_bitmap(data->image, game->viewport.width-al_get_bitmap_width(data->image), 0, 0);
DrawTextWithShadow(game->_priv.font, al_map_rgb(255,255,255), game->viewport.width*0.0234, game->viewport.height*0.84, ALLEGRO_ALIGN_LEFT, "Loading...");
al_draw_filled_rectangle(0, game->viewport.height*0.985, game->viewport.width, game->viewport.height, al_map_rgba(128,128,128,128));
al_clear_to_color(al_map_rgb(0,0,0));
al_draw_filled_rectangle(0, game->viewport.height-1, game->viewport.width, game->viewport.height, al_map_rgba(32,32,32,32));
al_set_target_bitmap(al_get_backbuffer(game->display));
al_destroy_bitmap(data->image);
return data;
}

View file

@ -25,6 +25,5 @@
/*! \brief Resources used by Loading state. */
struct LoadingResources {
ALLEGRO_BITMAP *loading_bitmap; /*!< Rendered loading bitmap. */
ALLEGRO_BITMAP *image; /*!< Loading background. */
ALLEGRO_BITMAP *loading_bitmap; /*!< Rendered loading bitmap. */
};

File diff suppressed because it is too large Load diff

View file

@ -27,43 +27,69 @@
enum menustate_enum {
MENUSTATE_MAIN,
MENUSTATE_OPTIONS,
MENUSTATE_CONTROLS,
MENUSTATE_VIDEO,
MENUSTATE_PAUSE,
MENUSTATE_AUDIO
MENUSTATE_AUDIO,
MENUSTATE_HIDDEN,
MENUSTATE_ABOUT,
MENUSTATE_LOST,
MENUSTATE_INTRO,
// FIXME: menustate abuse eeeeew
};
/*! \brief Resources used by Menu state. */
struct MenuResources {
ALLEGRO_BITMAP *image; /*!< Bitmap with lower portion of menu landscape. */
ALLEGRO_BITMAP *bg; /*!< Bitmap with lower portion of menu landscape. */
ALLEGRO_BITMAP *cloud; /*!< Bitmap with bigger cloud. */
ALLEGRO_BITMAP *cloud2; /*!< Bitmap with small cloud. */
ALLEGRO_BITMAP *pie; /*!< Unscaled bitmap with pie. */
ALLEGRO_BITMAP *pie_bitmap; /*!< Scaled and "rendered" bitmap with pies. */
ALLEGRO_BITMAP *pinkcloud_bitmap; /*!< Scaled bitmap with pinkcloud and home. */
ALLEGRO_BITMAP *pinkcloud; /*!< Unscaled bitmap with pinkcloud and home. */
ALLEGRO_BITMAP *rain; /*!< Unscaled bitmap with rain drop. */
ALLEGRO_BITMAP *rain_bitmap; /*!< Scaled and "rendered" bitmap with rain drops. */
ALLEGRO_BITMAP *mountain; /*!< Flashing mountain in background bitmap. */
ALLEGRO_BITMAP *logo; /*!< Logo displayed in the background. */
ALLEGRO_BITMAP *logoblur; /*!< Prerendered blurred logo. */
ALLEGRO_BITMAP *glass; /*!< Texture used for glass effect in the logo. */
ALLEGRO_BITMAP *blurbg; /*!< Temporary bitmap used for blur effect in glass logo. */
ALLEGRO_BITMAP *blurbg2; /*!< Temporary bitmap used for blur effect in glass logo. */
ALLEGRO_BITMAP *grass;
ALLEGRO_BITMAP *forest;
ALLEGRO_BITMAP *stage;
ALLEGRO_BITMAP *speaker;
ALLEGRO_BITMAP *lines;
ALLEGRO_BITMAP *cable;
ALLEGRO_BITMAP *light;
ALLEGRO_BITMAP *marksmall;
ALLEGRO_BITMAP *markbig;
int markx, marky;
float badguySpeed;
ALLEGRO_SAMPLE *chord_samples[6];
ALLEGRO_SAMPLE_INSTANCE *chords[6];
// 0-2: low; 3-5: high
int usage;
int lightx, lighty, lightanim;
int soloready, soloanim, soloflash;
bool soloactive;
struct Badguy {
struct Character *character;
struct Badguy *next, *prev;
float speed;
bool melting;
} *badguys[4], *destroyQueue;
int timeTillNextBadguy, badguyRate;
struct Character *ego;
struct Character *cow;
struct Character *badguy;
struct Timeline *timeline;
float cloud_position; /*!< Position of bigger cloud. */
float cloud2_position; /*!< Position of small cloud. */
int mountain_position; /*!< Position of flashing mountain. */
float tint; /*!< Opacity of flashing mountain. */
ALLEGRO_SAMPLE *sample; /*!< Background music sample. */
ALLEGRO_SAMPLE *rain_sample; /*!< Rain sound sample. */
ALLEGRO_SAMPLE *sample; /*!< Music sample. */
ALLEGRO_SAMPLE *click_sample; /*!< Click sound sample. */
ALLEGRO_SAMPLE_INSTANCE *music; /*!< Sample instance with background music. */
ALLEGRO_SAMPLE_INSTANCE *rain_sound; /*!< Sample instance with rain sound. */
ALLEGRO_SAMPLE *quit_sample;
ALLEGRO_SAMPLE *end_sample;
ALLEGRO_SAMPLE *solo_sample;
ALLEGRO_SAMPLE_INSTANCE *music; /*!< Sample instance with music sound. */
ALLEGRO_SAMPLE_INSTANCE *click; /*!< Sample instance with click sound. */
ALLEGRO_SAMPLE_INSTANCE *quit;
ALLEGRO_SAMPLE_INSTANCE *solo;
ALLEGRO_SAMPLE_INSTANCE *end;
ALLEGRO_FONT *font_title; /*!< Font of "Super Derpy" text. */
ALLEGRO_FONT *font_subtitle; /*!< Font of "Muffin Attack" text. */
ALLEGRO_FONT *font; /*!< Font of standard menu item. */
ALLEGRO_FONT *font_selected; /*!< Font of selected menu item. */
int selected; /*!< Number of selected menu item. */
enum menustate_enum menustate; /*!< Current menu page. */
struct {
@ -71,8 +97,17 @@ struct MenuResources {
int fps;
int width;
int height;
int resolution;
} options; /*!< Options which can be changed in menu. */
};
//void DrawMenuState(struct Game *game);
//void ChangeMenuState(struct Game *game, enum menustate_enum state);
struct {
int key;
bool shift;
int delay;
// workaround for random bogus UP/DOWN events
int lastkey;
int lastdelay;
} keys;
int score;
};

View file

@ -35,23 +35,6 @@
#include "config.h"
#include "main.h"
void DrawConsole(struct Game *game) {
if (game->_priv.showconsole) {
al_draw_bitmap(game->_priv.console, 0, 0, 0);
double game_time = al_get_time();
if(game_time - game->_priv.fps_count.old_time >= 1.0) {
game->_priv.fps_count.fps = game->_priv.fps_count.frames_done / (game_time - game->_priv.fps_count.old_time);
game->_priv.fps_count.frames_done = 0;
game->_priv.fps_count.old_time = game_time;
}
char sfps[6] = { };
snprintf(sfps, 6, "%.0f", game->_priv.fps_count.fps);
DrawTextWithShadow(game->_priv.font, al_map_rgb(255,255,255), game->viewport.width*0.99, 0, ALLEGRO_ALIGN_RIGHT, sfps);
}
game->_priv.fps_count.frames_done++;
}
void DrawGamestates(struct Game *game) {
al_set_target_backbuffer(game->display);
al_clear_to_color(al_map_rgb(0,0,0));
@ -84,64 +67,8 @@ void EventGamestates(struct Game *game, ALLEGRO_EVENT *ev) {
}
}
void SetupViewport(struct Game *game) {
game->viewport.width = al_get_display_width(game->display);
game->viewport.height = al_get_display_height(game->display);
if (atoi(GetConfigOptionDefault(game, "SuperDerpy", "letterbox", "0"))) {
float const aspectRatio = (float)1920 / (float)1080; // full HD
int clipWidth = game->viewport.width, clipHeight = game->viewport.width / aspectRatio;
int clipX = 0, clipY = (game->viewport.height - clipHeight) / 2;
if (clipY <= 0) {
clipHeight = game->viewport.height;
clipWidth = game->viewport.height * aspectRatio;
clipX = (game->viewport.width - clipWidth) / 2;
clipY = 0;
}
al_set_clipping_rectangle(clipX, clipY, clipWidth, clipHeight);
ALLEGRO_TRANSFORM projection;
al_build_transform(&projection, clipX, clipY, 1, 1, 0.0f);
al_use_transform(&projection);
game->viewport.width = clipWidth;
game->viewport.height = clipHeight;
} else if ((atoi(GetConfigOptionDefault(game, "SuperDerpy", "rotate", "1"))) && (game->viewport.height > game->viewport.width)) {
ALLEGRO_TRANSFORM projection;
al_identity_transform(&projection);
al_rotate_transform(&projection, 0.5*ALLEGRO_PI);
al_translate_transform(&projection, game->viewport.width, 0);
al_use_transform(&projection);
int temp = game->viewport.height;
game->viewport.height = game->viewport.width;
game->viewport.width = temp;
}
}
int Console_Load(struct Game *game) {
game->_priv.font_console = NULL;
game->_priv.console = NULL;
game->_priv.font_console = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"),game->viewport.height*0.018,0 );
if (game->viewport.height*0.022 >= 16) {
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/PerfectDOSVGA437.ttf"),16,0 );
} else {
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"),game->viewport.height*0.022,0 );
}
game->_priv.font = al_load_ttf_font(GetDataFilePath(game, "fonts/ShadowsIntoLight.ttf"),game->viewport.height*0.09,0 );
game->_priv.console = al_create_bitmap(game->viewport.width, game->viewport.height*0.12);
al_set_target_bitmap(game->_priv.console);
al_clear_to_color(al_map_rgba(0,0,0,80));
al_set_target_bitmap(al_get_backbuffer(game->display));
return 0;
}
void Console_Unload(struct Game *game) {
al_destroy_font(game->_priv.font);
al_destroy_font(game->_priv.font_console);
al_destroy_bitmap(game->_priv.console);
}
void derp(int sig) {
write(STDERR_FILENO, "Segmentation fault\n", 19);
write(STDERR_FILENO, "I just don't know what went wrong!\n", 35);
int __attribute__((unused)) n = write(STDERR_FILENO, "Segmentation fault\nI just don't know what went wrong!\n", 54);
abort();
}
@ -151,7 +78,7 @@ int main(int argc, char **argv){
srand(time(NULL));
al_set_org_name("Super Derpy");
al_set_app_name("Muffin Attack");
al_set_app_name("Radio Edit");
if(!al_init()) {
fprintf(stderr, "failed to initialize allegro!\n");
@ -169,14 +96,14 @@ int main(int argc, char **argv){
game._priv.font_bsod = NULL;
game._priv.console = NULL;
game.config.fullscreen = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fullscreen", "1"));
game.config.music = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "music", "7"));
game.config.fullscreen = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fullscreen", "0"));
game.config.music = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "music", "10"));
game.config.voice = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "voice", "10"));
game.config.fx = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "fx", "10"));
game.config.debug = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "debug", "0"));
game.config.width = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "width", "800"));
game.config.width = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "width", "1280"));
if (game.config.width<320) game.config.width=320;
game.config.height = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "height", "450"));
game.config.height = atoi(GetConfigOptionDefault(&game, "SuperDerpy", "height", "720"));
if (game.config.height<180) game.config.height=180;
if(!al_init_image_addon()) {
@ -217,6 +144,9 @@ int main(int argc, char **argv){
else al_set_new_display_flags(ALLEGRO_WINDOWED);
al_set_new_display_option(ALLEGRO_VSYNC, 2-atoi(GetConfigOptionDefault(&game, "SuperDerpy", "vsync", "1")), ALLEGRO_SUGGEST);
al_set_new_display_option(ALLEGRO_OPENGL, atoi(GetConfigOptionDefault(&game, "SuperDerpy", "opengl", "1")), ALLEGRO_SUGGEST);
#ifdef ALLEGRO_WINDOWS
al_set_new_window_position(20, 40); // workaround nasty Windows bug with window being created off-screen
#endif
game.display = al_create_display(game.config.width, game.config.height);
if(!game.display) {
@ -226,20 +156,17 @@ int main(int argc, char **argv){
SetupViewport(&game);
int ret = Console_Load(&game);
if (ret!=0) return ret;
PrintConsole(&game, "Viewport %dx%d", game.viewport.width, game.viewport.height);
ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/superderpy.png"));
al_set_window_title(game.display, "Super Derpy: Muffin Attack");
ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/radioedit.png"));
al_set_window_title(game.display, "Radio Edit");
al_set_display_icon(game.display, icon);
al_destroy_bitmap(icon);
if (game.config.fullscreen) al_hide_mouse_cursor(game.display);
al_inhibit_screensaver(true);
al_set_new_bitmap_flags(ALLEGRO_MAG_LINEAR | ALLEGRO_MIN_LINEAR);
al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR);
game._priv.gamestates = NULL;
@ -250,7 +177,7 @@ int main(int argc, char **argv){
return -1;
}
game.audio.v = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
game.audio.v = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
game.audio.mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
game.audio.fx = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
game.audio.music = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
@ -268,15 +195,15 @@ int main(int argc, char **argv){
game._priv.showconsole = game.config.debug;
al_flip_display();
al_clear_to_color(al_map_rgb(0,0,0));
al_wait_for_vsync();
game._priv.timer = al_create_timer(ALLEGRO_BPS_TO_SECS(60)); // logic timer
if(!game._priv.timer) {
FatalError(&game, true, "Failed to create logic timer.");
return -1;
}
al_register_event_source(game._priv.event_queue, al_get_timer_event_source(game._priv.timer));
al_flip_display();
al_start_timer(game._priv.timer);
setlocale(LC_NUMERIC, "C");
@ -306,24 +233,20 @@ int main(int argc, char **argv){
free(gamestate);
char libname[1024] = {};
snprintf(libname, 1024, "libsuperderpy-%s-loading.so", "muffinattack");
snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENTION, "radioedit");
void *handle = dlopen(libname, RTLD_NOW);
if (!handle) {
FatalError(&game, true, "Error while initializing loading screen %s", dlerror());
exit(1);
} else {
void gs_error() {
FatalError(&game, true, "Error on resolving loading symbol: %s", dlerror());
exit(1);
}
#define GS_LOADINGERROR FatalError(&game, true, "Error on resolving loading symbol: %s", dlerror()); exit(1);
if (!(game._priv.loading.Draw = dlsym(handle, "Draw"))) { gs_error(); }
if (!(game._priv.loading.Load = dlsym(handle, "Load"))) { gs_error(); }
if (!(game._priv.loading.Start = dlsym(handle, "Start"))) { gs_error(); }
if (!(game._priv.loading.Stop = dlsym(handle, "Stop"))) { gs_error(); }
if (!(game._priv.loading.Unload = dlsym(handle, "Unload"))) { gs_error(); }
if (!(game._priv.loading.Draw = dlsym(handle, "Draw"))) { GS_LOADINGERROR; }
if (!(game._priv.loading.Load = dlsym(handle, "Load"))) { GS_LOADINGERROR; }
if (!(game._priv.loading.Start = dlsym(handle, "Start"))) { GS_LOADINGERROR; }
if (!(game._priv.loading.Stop = dlsym(handle, "Stop"))) { GS_LOADINGERROR; }
if (!(game._priv.loading.Unload = dlsym(handle, "Unload"))) { GS_LOADINGERROR; }
}
game._priv.loading.data = (*game._priv.loading.Load)(&game);
@ -370,7 +293,7 @@ int main(int argc, char **argv){
al_stop_timer(game._priv.timer);
// TODO: take proper game name
char libname[1024];
snprintf(libname, 1024, "libsuperderpy-%s-%s.so", "muffinattack", tmp->name);
snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENTION, "radioedit", tmp->name);
tmp->handle = dlopen(libname,RTLD_NOW);
if (!tmp->handle) {
//PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror());
@ -380,27 +303,22 @@ int main(int argc, char **argv){
tmp->pending_start = false;
} else {
void gs_error() {
FatalError(&game, true, "Error on resolving gamestate symbol: %s", dlerror());
tmp->pending_load = false;
tmp->pending_start = false;
tmp=tmp->next;
}
#define GS_ERROR FatalError(&game, false, "Error on resolving gamestate symbol: %s", dlerror()); tmp->pending_load = false; tmp->pending_start = false; tmp=tmp->next; continue;
if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; }
if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { gs_error(); continue; }
if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; }
int p = 0;
void progress(struct Game *game) {
@ -420,7 +338,7 @@ int main(int argc, char **argv){
}
DrawConsole(&game);
al_flip_display();
tmp->data = (*tmp->api.Gamestate_Load)(&game, &progress);
tmp->data = (*tmp->api.Gamestate_Load)(&game, &progress); // feel free to replace "progress" with empty function if you want to compile with clang
loaded++;
tmp->loaded = true;
@ -437,7 +355,7 @@ int main(int argc, char **argv){
while (tmp) {
if ((tmp->pending_start) && (!tmp->started) && (tmp->loaded)) {
if ((tmp->pending_start) && (!tmp->started) && (tmp->loaded)) {
PrintConsole(&game, "Starting gamestate \"%s\"...", tmp->name);
al_stop_timer(game._priv.timer);
(*tmp->api.Gamestate_Start)(&game, tmp->data);
@ -471,11 +389,14 @@ int main(int argc, char **argv){
else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {
break;
}
#ifdef ALLEGRO_MACOSX
else if(ev.type == ALLEGRO_EVENT_DISPLAY_FOUND) {
SetupViewport(&game);
}
#ifdef ALLEGRO_MACOSX
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == 104)) { //TODO: report to upstream
#else
#else
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == ALLEGRO_KEY_TILDE)) {
#endif
#endif
game._priv.showconsole = !game._priv.showconsole;
}
else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game.config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F1)) {
@ -502,7 +423,7 @@ int main(int argc, char **argv){
} else if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (game.config.debug) && (ev.keyboard.keycode == ALLEGRO_KEY_F12)) {
ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_USER_DOCUMENTS_PATH);
char filename[255] = { };
snprintf(filename, 255, "SuperDerpy_%ld_%ld.png", time(NULL), clock());
snprintf(filename, 255, "RadioEdit_%ld_%ld.png", time(NULL), clock());
al_set_path_filename(path, filename);
al_save_bitmap(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP), al_get_backbuffer(game.display));
PrintConsole(&game, "Screenshot stored in %s", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));

View file

@ -35,6 +35,8 @@ struct Gamestate;
struct Game {
ALLEGRO_DISPLAY *display; /*!< Main Allegro display. */
ALLEGRO_TRANSFORM projection;
struct {
int width; /*!< Actual available width of viewport. */
int height; /*!< Actual available height of viewport. */

View file

@ -226,6 +226,7 @@ struct TM_Action* TM_AddAction(struct Timeline* timeline, bool (*func)(struct Ga
}
struct TM_Action* TM_AddBackgroundAction(struct Timeline* timeline, bool (*func)(struct Game*, struct TM_Action*, enum TM_ActionState), struct TM_Arguments* args, int delay, char* name) {
// FIXME: some action wasn't freed!
struct TM_Action *action = malloc(sizeof(struct TM_Action));
if (timeline->background) {
struct TM_Action *pom = timeline->background;
@ -297,8 +298,9 @@ void TM_CleanQueue(struct Timeline* timeline) {
while (pom!=NULL) {
if (pom->active) {
if (*pom->function) (*pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY);
else {
if (pom->timer) al_destroy_timer(pom->timer);
if (pom->timer) {
al_stop_timer(pom->timer);
al_destroy_timer(pom->timer);
}
} else {
TM_DestroyArgs(pom->arguments);
@ -311,23 +313,25 @@ void TM_CleanQueue(struct Timeline* timeline) {
free(pom->name);
free(pom);
tmp2 = tmp;
if (!tmp) pom=timeline->background->next;
if (!tmp) pom=timeline->queue->next;
else pom=tmp->next;
tmp = tmp2;
}
}
// TODO: it shouldn't be needed, but is. Debug!
timeline->queue = NULL;
}
void TM_CleanBackgroundQueue(struct Timeline* timeline) {
PrintConsole(timeline->game, "Timeline Manager[%s]: cleaning background queue", timeline->name);
struct TM_Action *tmp, *tmp2, *pom = timeline->queue;
struct TM_Action *tmp, *tmp2, *pom = timeline->background;
tmp = NULL;
pom=timeline->background;
while (pom!=NULL) {
if (pom->active) {
if (*pom->function) (*pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY);
else {
if (pom->timer) al_destroy_timer(pom->timer);
if (pom->timer) {
al_stop_timer(pom->timer);
al_destroy_timer(pom->timer);
}
} else {
TM_DestroyArgs(pom->arguments);
@ -345,6 +349,8 @@ void TM_CleanBackgroundQueue(struct Timeline* timeline) {
tmp = tmp2;
}
}
// TODO: it shouldn't be needed, but is. Debug!
timeline->background = NULL;
}
void TM_Destroy(struct Timeline* timeline) {
@ -363,6 +369,8 @@ struct TM_Arguments* TM_AddToArgs(struct TM_Arguments* args, int num, ...) {
struct TM_Arguments* tmp = args;
for(i = 0; i < num; i++) {
if (!tmp) {
//FIXME: on some occasions some arguments weren't freed. Check it out.
// TM_AddQueuedBackgroundAction? possibly not only.
tmp = malloc(sizeof(struct TM_Arguments));
tmp->value = va_arg(ap, void*);
tmp->next = NULL;

View file

@ -39,11 +39,11 @@ enum TM_ActionState {
/*! \brief Timeline structure. */
struct Timeline {
struct TM_Action *queue; /*!< Main timeline queue. */
struct TM_Action *background; /*!< Background queue. */
char* name; /*!< Name of the timeline. */
unsigned int lastid; /*!< Last ID given to timeline action. */
struct Game* game; /*!< Reference to the game object. */
struct TM_Action *queue; /*!< Main timeline queue. */
struct TM_Action *background; /*!< Background queue. */
char* name; /*!< Name of the timeline. */
unsigned int lastid; /*!< Last ID given to timeline action. */
struct Game* game; /*!< Reference to the game object. */
};
/*! \brief Arguments for TM_Action. */

View file

@ -20,11 +20,98 @@
*/
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_ttf.h>
#include "stdio.h"
#include "config.h"
#include "string.h"
#include "math.h"
#include "utils.h"
char* strdup(const char *str) {
int n = strlen(str) + 1;
char *dup = malloc(n);
if (dup) { strcpy(dup, str); }
return dup;
}
void DrawConsole(struct Game *game) {
if (game->_priv.showconsole) {
ALLEGRO_TRANSFORM trans;
al_identity_transform(&trans);
int clipX, clipY, clipWidth, clipHeight;
al_get_clipping_rectangle(&clipX, &clipY, &clipWidth, &clipHeight);
al_use_transform(&trans);
al_draw_bitmap(game->_priv.console, clipX, clipY, 0);
double game_time = al_get_time();
if(game_time - game->_priv.fps_count.old_time >= 1.0) {
game->_priv.fps_count.fps = game->_priv.fps_count.frames_done / (game_time - game->_priv.fps_count.old_time);
game->_priv.fps_count.frames_done = 0;
game->_priv.fps_count.old_time = game_time;
}
char sfps[6] = { };
snprintf(sfps, 6, "%.0f", game->_priv.fps_count.fps);
al_use_transform(&game->projection);
DrawTextWithShadow(game->_priv.font, al_map_rgb(255,255,255), game->viewport.width*0.99, 0, ALLEGRO_ALIGN_RIGHT, sfps);
}
game->_priv.fps_count.frames_done++;
}
void Console_Load(struct Game *game) {
game->_priv.font_console = NULL;
game->_priv.console = NULL;
game->_priv.font_console = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"),al_get_display_height(game->display)*0.025,0 );
if (al_get_display_height(game->display)*0.025 >= 16) {
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/PerfectDOSVGA437.ttf"),16,0 );
} else {
game->_priv.font_bsod = al_load_ttf_font(GetDataFilePath(game, "fonts/DejaVuSansMono.ttf"), al_get_display_height(game->display)*0.025,0 );
}
game->_priv.console = al_create_bitmap((al_get_display_width(game->display) / 320) * 320, al_get_font_line_height(game->_priv.font_console)*5);
game->_priv.font = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"), 0 ,0 );
al_set_target_bitmap(game->_priv.console);
al_clear_to_color(al_map_rgba(0,0,0,80));
al_set_target_bitmap(al_get_backbuffer(game->display));
}
void Console_Unload(struct Game *game) {
al_destroy_font(game->_priv.font);
al_destroy_font(game->_priv.font_console);
al_destroy_bitmap(game->_priv.console);
}
void SetupViewport(struct Game *game) {
game->viewport.width = 320;
game->viewport.height = 180;
int resolution = al_get_display_width(game->display) / 320;
if (al_get_display_height(game->display) / 180 < resolution) resolution = al_get_display_height(game->display) / 180;
if (resolution < 1) resolution = 1;
if (atoi(GetConfigOptionDefault(game, "SuperDerpy", "letterbox", "1"))) {
int clipWidth = 320 * resolution, clipHeight = 180 * resolution;
int clipX = (al_get_display_width(game->display) - clipWidth) / 2, clipY = (al_get_display_height(game->display) - clipHeight) / 2;
al_set_clipping_rectangle(clipX, clipY, clipWidth, clipHeight);
al_build_transform(&game->projection, clipX, clipY, resolution, resolution, 0.0f);
al_use_transform(&game->projection);
} else if ((atoi(GetConfigOptionDefault(game, "SuperDerpy", "rotate", "1"))) && (game->viewport.height > game->viewport.width)) {
al_identity_transform(&game->projection);
al_rotate_transform(&game->projection, 0.5*ALLEGRO_PI);
al_translate_transform(&game->projection, game->viewport.width, 0);
al_scale_transform(&game->projection, resolution, resolution);
al_use_transform(&game->projection);
int temp = game->viewport.height;
game->viewport.height = game->viewport.width;
game->viewport.width = temp;
}
if (game->_priv.console) Console_Unload(game);
Console_Load(game);
}
void DrawVerticalGradientRect(float x, float y, float w, float h, ALLEGRO_COLOR top, ALLEGRO_COLOR bottom) {
ALLEGRO_VERTEX v[] = {
{.x = x, .y = y, .z = 0, .color = top},
@ -48,41 +135,12 @@ void DrawTextWithShadow(ALLEGRO_FONT *font, ALLEGRO_COLOR color, float x, float
al_draw_text(font, color, (int)x, (int)y, flags, text);
}
void FadeGamestate(struct Game *game, bool in) {
//TODO: reimplement
/* ALLEGRO_BITMAP* bitmap = al_create_bitmap(game->viewportWidth, game->viewportHeight);
al_set_target_bitmap(bitmap);
al_clear_to_color(al_map_rgb(0,0,0));
al_set_target_bitmap(al_get_backbuffer(game->display));
float fadeloop;
if (in) {
fadeloop = 255;
} else {
fadeloop = 0;
}
while ((in && fadeloop>=0) || (!in && fadeloop<255)) {
ALLEGRO_EVENT ev;
al_wait_for_event(game->event_queue, &ev);
if ((ev.type == ALLEGRO_EVENT_TIMER) && (ev.timer.source == game->timer)) {
LogicGamestates(game);
if (in) {
fadeloop-=10;
} else {
fadeloop+=10;
}
}
if (al_is_event_queue_empty(game->event_queue)) {
DrawGamestates(game);
al_draw_tinted_bitmap(bitmap,al_map_rgba_f(1,1,1,fadeloop/255.0),0,0,0);
DrawConsole(game);
al_flip_display();
}
}
al_destroy_bitmap(bitmap);
al_clear_to_color(al_map_rgb(0,0,0));
if (in) {
DrawGamestates(game);
}*/
/* linear filtering code written by SiegeLord */
ALLEGRO_COLOR interpolate(ALLEGRO_COLOR c1, ALLEGRO_COLOR c2, float frac) {
return al_map_rgba_f(c1.r + frac * (c2.r - c1.r),
c1.g + frac * (c2.g - c1.g),
c1.b + frac * (c2.b - c1.b),
c1.a + frac * (c2.a - c1.a));
}
/*! \brief Scales bitmap using software linear filtering method to current target. */
@ -95,15 +153,6 @@ void ScaleBitmap(ALLEGRO_BITMAP* source, int width, int height) {
al_lock_bitmap(al_get_target_bitmap(), ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_WRITEONLY);
al_lock_bitmap(source, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY);
/* linear filtering code written by SiegeLord */
ALLEGRO_COLOR interpolate(ALLEGRO_COLOR c1, ALLEGRO_COLOR c2, float frac) {
return al_map_rgba_f(c1.r + frac * (c2.r - c1.r),
c1.g + frac * (c2.g - c1.g),
c1.b + frac * (c2.b - c1.b),
c1.a + frac * (c2.a - c1.a));
}
for (y = 0; y < height; y++) {
float pixy = ((float)y / height) * ((float)al_get_bitmap_height(source) - 1);
float pixy_f = floor(pixy);
@ -133,33 +182,23 @@ ALLEGRO_BITMAP* LoadScaledBitmap(struct Game *game, char* filename, int width, i
al_set_target_bitmap(target);
al_clear_to_color(al_map_rgba(0,0,0,0));
char* origfn = GetDataFilePath(game, filename);
void GenerateBitmap() {
if (memoryscale) al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
source = al_load_bitmap( origfn );
if (memoryscale) {
al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR);
ScaleBitmap(source, width, height);
}
else {
al_draw_scaled_bitmap(source, 0, 0, al_get_bitmap_width(source), al_get_bitmap_height(source), 0, 0, width, height, 0);
}
/*al_save_bitmap(cachefn, target);
PrintConsole(game, "Cache bitmap %s generated.", filename);*/
al_destroy_bitmap(source);
if (memoryscale) al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
source = al_load_bitmap( origfn );
if (memoryscale) {
al_set_new_bitmap_flags(ALLEGRO_MIN_LINEAR);
ScaleBitmap(source, width, height);
}
else {
al_draw_scaled_bitmap(source, 0, 0, al_get_bitmap_width(source), al_get_bitmap_height(source), 0, 0, width, height, 0);
}
/*source = al_load_bitmap( cachefn );
if (source) {
if ((al_get_bitmap_width(source)!=width) || (al_get_bitmap_height(source)!=height)) {
al_destroy_bitmap(source);*/
GenerateBitmap();
al_destroy_bitmap(source);
free(origfn);
return target;
/* }
return source;
} else GenerateBitmap();
return target;*/
}
void FatalError(struct Game *game, bool fatal, char* format, ...) {
@ -179,6 +218,10 @@ void FatalError(struct Game *game, bool fatal, char* format, ...) {
PrintConsole(game, text);
}
ALLEGRO_TRANSFORM trans;
al_identity_transform(&trans);
al_use_transform(&trans);
if (!game->_priv.font_bsod) {
game->_priv.font_bsod = al_create_builtin_font();
}
@ -186,7 +229,7 @@ void FatalError(struct Game *game, bool fatal, char* format, ...) {
al_set_target_backbuffer(game->display);
al_clear_to_color(al_map_rgb(0,0,170));
al_flip_display();
al_rest(1.1);
al_rest(0.6);
bool done = false;
while (!done) {
@ -194,32 +237,32 @@ void FatalError(struct Game *game, bool fatal, char* format, ...) {
al_set_target_backbuffer(game->display);
al_clear_to_color(al_map_rgb(0,0,170));
char *header = "SUPER DERPY";
char *header = "RADIO EDIT";
al_draw_filled_rectangle(game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header)/2 - 4, (int)(game->viewport.height * 0.32), 4 + game->viewport.width/2 + al_get_text_width(game->_priv.font_bsod, header)/2, (int)(game->viewport.height * 0.32) + al_get_font_line_height(game->_priv.font_bsod), al_map_rgb(170,170,170));
al_draw_filled_rectangle(al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header)/2 - 4, (int)(al_get_display_height(game->display) * 0.32), 4 + al_get_display_width(game->display)/2 + al_get_text_width(game->_priv.font_bsod, header)/2, (int)(al_get_display_height(game->display) * 0.32) + al_get_font_line_height(game->_priv.font_bsod), al_map_rgb(170,170,170));
al_draw_text(game->_priv.font_bsod, al_map_rgb(0, 0, 170), game->viewport.width/2, (int)(game->viewport.height * 0.32), ALLEGRO_ALIGN_CENTRE, header);
al_draw_text(game->_priv.font_bsod, al_map_rgb(0, 0, 170), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32), ALLEGRO_ALIGN_CENTRE, header);
char *header2 = "A fatal exception 0xD3RP has occured at 0028:M00F11NZ in GST SD(01) +";
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2, (int)(game->viewport.height * 0.32+2*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, header2);
al_draw_textf(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(game->viewport.height * 0.32+3*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "%p and system just doesn't know what went wrong.", game);
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32+2*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, header2);
al_draw_textf(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+3*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "%p and system just doesn't know what went wrong.", game);
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2, (int)(game->viewport.height * 0.32+5*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, text);
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32+5*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, text);
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(game->viewport.height * 0.32+7*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Press any key to terminate this error.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(game->viewport.height * 0.32+8*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Press any key to destroy all muffins in the world.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(game->viewport.height * 0.32+9*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Just kidding, please press any key anyway.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+7*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Press any key to terminate this error.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+8*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Press any key to destroy all muffins in the world.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+9*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Just kidding, please press any key anyway.");
if (fatal) {
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(game->viewport.height * 0.32+11*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "This is fatal error. My bad.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+11*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "This is fatal error. My bad.");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2, (int)(game->viewport.height * 0.32+13*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "Press any key to quit _");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32+13*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "Press any key to quit _");
} else {
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(game->viewport.height * 0.32+11*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "Anything I can do to help?");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2 - al_get_text_width(game->_priv.font_bsod, header2)/2, (int)(al_get_display_height(game->display) * 0.32+11*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "Anything I can do to help?");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), game->viewport.width/2, (int)(game->viewport.height * 0.32+13*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "Press any key to continue _");
al_draw_text(game->_priv.font_bsod, al_map_rgb(255,255,255), al_get_display_width(game->display)/2, (int)(al_get_display_height(game->display) * 0.32+13*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "Press any key to continue _");
}
al_flip_display();
@ -235,12 +278,31 @@ void FatalError(struct Game *game, bool fatal, char* format, ...) {
}
}
}
al_use_transform(&game->projection);
}
void TestPath(char* filename, char* subpath, char** result) {
if (*result) return; //already found
ALLEGRO_PATH *tail = al_create_path(filename);
ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_RESOURCES_PATH);
ALLEGRO_PATH *data = al_create_path(subpath);
al_join_paths(path, data);
al_join_paths(path, tail);
//printf("Testing for %s\n", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
if (al_filename_exists(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP))) {
*result = strdup(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
}
al_destroy_path(tail);
al_destroy_path(data);
al_destroy_path(path);
}
char* GetDataFilePath(struct Game *game, char* filename) {
//TODO: support for current game
//FIXME: strdups result in memory leaks!
char *result = 0;
if (al_filename_exists(filename)) {
@ -254,24 +316,13 @@ char* GetDataFilePath(struct Game *game, char* filename) {
return strdup(origfn);
}
void TestPath(char* subpath) {
ALLEGRO_PATH *tail = al_create_path(filename);
ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_RESOURCES_PATH);
ALLEGRO_PATH *data = al_create_path(subpath);
al_join_paths(path, data);
al_join_paths(path, tail);
//printf("Testing for %s\n", al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
if (al_filename_exists(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP))) {
result = strdup(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP));
}
al_destroy_path(tail);
al_destroy_path(data);
al_destroy_path(path);
}
TestPath("../share/superderpy/data/");
TestPath("../data/");
TestPath("../Resources/data/");
TestPath("data/");
TestPath(filename, "data/", &result);
TestPath(filename, "../share/radioedit/data/", &result);
TestPath(filename, "../data/", &result);
#ifdef ALLEGRO_MACOSX
TestPath(filename, "../Resources/data/", &result);
TestPath(filename, "../Resources/gamestates/", &result);
#endif
if (!result) {
FatalError(game, true, "Could not find data file: %s!", filename);
@ -280,7 +331,6 @@ char* GetDataFilePath(struct Game *game, char* filename) {
return result;
}
void PrintConsole(struct Game *game, char* format, ...) {
va_list vl;
va_start(vl, format);
@ -288,6 +338,8 @@ void PrintConsole(struct Game *game, char* format, ...) {
vsnprintf(text, 1024, format, vl);
va_end(vl);
if (game->config.debug) { printf("%s\n", text); fflush(stdout); }
if (!game->_priv.console) return;
if ((!game->config.debug) && (!game->_priv.showconsole)) return;
ALLEGRO_BITMAP *con = al_create_bitmap(al_get_bitmap_width(game->_priv.console), al_get_bitmap_height(game->_priv.console));
al_set_target_bitmap(con);
al_clear_to_color(al_map_rgba(0,0,0,80));
@ -299,3 +351,180 @@ void PrintConsole(struct Game *game, char* format, ...) {
al_set_target_bitmap(al_get_backbuffer(game->display));
al_destroy_bitmap(con);
}
void SelectSpritesheet(struct Game *game, struct Character *character, char *name) {
struct Spritesheet *tmp = character->spritesheets;
PrintConsole(game, "Selecting spritesheet for %s: %s", character->name, name);
if (!tmp) {
PrintConsole(game, "ERROR: No spritesheets registered for %s!", character->name);
return;
}
while (tmp) {
if (!strcmp(tmp->name, name)) {
character->spritesheet = tmp;
if (character->successor) free(character->successor);
if (tmp->successor) {
character->successor = strdup(tmp->successor);
} else {
character->successor = NULL;
}
character->pos = 0;
if (character->bitmap) {
if ((al_get_bitmap_width(character->bitmap) != tmp->width / tmp->cols) || (al_get_bitmap_height(character->bitmap) != tmp->height / tmp->rows)) {
al_destroy_bitmap(character->bitmap);
character->bitmap = al_create_bitmap(tmp->width / tmp->cols, tmp->height / tmp->rows);
}
} else {
character->bitmap = al_create_bitmap(tmp->width / tmp->cols, tmp->height / tmp->rows);
}
PrintConsole(game, "SUCCESS: Spritesheet for %s activated: %s (%dx%d)", character->name, character->spritesheet->name, al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap));
return;
}
tmp = tmp->next;
}
PrintConsole(game, "ERROR: No spritesheets registered for %s with given name: %s", character->name, name);
return;
}
void ChangeSpritesheet(struct Game *game, struct Character *character, char* name) {
if (character->successor) free(character->successor);
character->successor = strdup(name);
}
void LoadSpritesheets(struct Game *game, struct Character *character) {
PrintConsole(game, "Loading spritesheets for character %s...", character->name);
struct Spritesheet *tmp = character->spritesheets;
while (tmp) {
if (!tmp->bitmap) {
char filename[255] = { };
snprintf(filename, 255, "sprites/%s/%s.png", character->name, tmp->name);
tmp->bitmap = al_load_bitmap(GetDataFilePath(game, filename));
tmp->width = al_get_bitmap_width(tmp->bitmap);
tmp->height = al_get_bitmap_height(tmp->bitmap);
}
tmp = tmp->next;
}
}
void UnloadSpritesheets(struct Game *game, struct Character *character) {
PrintConsole(game, "Unloading spritesheets for character %s...", character->name);
struct Spritesheet *tmp = character->spritesheets;
while (tmp) {
if (tmp->bitmap) al_destroy_bitmap(tmp->bitmap);
tmp->bitmap = NULL;
tmp = tmp->next;
}
}
void RegisterSpritesheet(struct Game *game, struct Character *character, char* name) {
struct Spritesheet *s = character->spritesheets;
while (s) {
if (!strcmp(s->name, name)) {
//PrintConsole(game, "%s spritesheet %s already registered!", character->name, name);
return;
}
s = s->next;
}
PrintConsole(game, "Registering %s spritesheet: %s", character->name, name);
char filename[255] = { };
snprintf(filename, 255, "sprites/%s/%s.ini", character->name, name);
ALLEGRO_CONFIG *config = al_load_config_file(GetDataFilePath(game, filename));
s = malloc(sizeof(struct Spritesheet));
s->name = strdup(name);
s->bitmap = NULL;
s->cols = atoi(al_get_config_value(config, "", "cols"));
s->rows = atoi(al_get_config_value(config, "", "rows"));
s->blanks = atoi(al_get_config_value(config, "", "blanks"));
s->delay = atof(al_get_config_value(config, "", "delay"));
s->kill = false;
const char *kill = al_get_config_value(config, "", "kill");
if (kill) s->kill = atoi(kill);
s->successor=NULL;
const char* successor = al_get_config_value(config, "", "successor");
if (successor) {
s->successor = malloc(255*sizeof(char));
strncpy(s->successor, successor, 255);
}
s->next = character->spritesheets;
character->spritesheets = s;
al_destroy_config(config);
}
struct Character* CreateCharacter(struct Game *game, char* name) {
PrintConsole(game, "Creating character %s...", name);
struct Character *character = malloc(sizeof(struct Character));
character->name = strdup(name);
character->angle = 0;
character->bitmap = NULL;
character->data = NULL;
character->pos = 0;
character->pos_tmp = 0;
character->x = -1;
character->y = -1;
character->spritesheets = NULL;
character->spritesheet = NULL;
character->successor = NULL;
character->shared = false;
character->dead = false;
return character;
}
void DestroyCharacter(struct Game *game, struct Character *character) {
PrintConsole(game, "Destroying character %s...", character->name);
if (!character->shared) {
struct Spritesheet *tmp, *s = character->spritesheets;
tmp = s;
while (s) {
tmp = s;
s = s->next;
if (tmp->bitmap) al_destroy_bitmap(tmp->bitmap);
if (tmp->successor) free(tmp->successor);
free(tmp->name);
free(tmp);
}
}
if (character->bitmap) al_destroy_bitmap(character->bitmap);
if (character->successor) free(character->successor);
free(character->name);
free(character);
}
void AnimateCharacter(struct Game *game, struct Character *character, float speed_modifier) {
if (character->dead) return;
if (speed_modifier) {
character->pos_tmp++;
if (character->pos_tmp >= character->spritesheet->delay / speed_modifier) {
character->pos_tmp = 0;
character->pos++;
}
if (character->pos>=character->spritesheet->cols*character->spritesheet->rows-character->spritesheet->blanks) {
character->pos=0;
if (character->spritesheet->kill) {
character->dead = true;
} else if (character->successor) {
SelectSpritesheet(game, character, character->successor);
}
}
}
}
void MoveCharacter(struct Game *game, struct Character *character, float x, float y, float angle) {
if (character->dead) return;
character->x += x;
character->y += y;
character->angle += angle;
}
void SetCharacterPosition(struct Game *game, struct Character *character, int x, int y, float angle) {
if (character->dead) return;
character->x = x;
character->y = y;
character->angle = angle;
}
void DrawCharacter(struct Game *game, struct Character *character, ALLEGRO_COLOR tilt, int flags) {
if (character->dead) return;
al_draw_tinted_bitmap_region(character->spritesheet->bitmap, tilt, al_get_bitmap_width(character->bitmap)*(character->pos%character->spritesheet->cols),al_get_bitmap_height(character->bitmap)*(character->pos/character->spritesheet->cols),al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap), character->x, character->y, flags);
}

View file

@ -22,6 +22,32 @@
#include <allegro5/allegro_font.h>
#include "main.h"
#ifdef ALLEGRO_WINDOWS
#define LIBRARY_EXTENTION ".dll"
#else
#define LIBRARY_EXTENTION ".so"
#endif
// hacks for "pixelness"
#define al_draw_bitmap(a,b,c,d) al_draw_bitmap(a,(int)(b), (int)(c), d)
#define al_draw_scaled_bitmap(a,b,c,d,e,f,g,h,i,j) al_draw_scaled_bitmap(a,b,c,d,e,(int)(f), (int)(g), (int)(h), (int)(i), j)
//#define al_draw_tinted_scaled_bitmap(a,tint,b,c,d,e,f,g,h,i,j) al_draw_tinted_scaled_bitmap(a,tint,(int)(b),(int)(c),(int)(d),(int)(e),(int)(f), (int)(g), (int)(h), (int)(i), j)
#define al_draw_rotated_bitmap(a,b,c,d,e,f,g) al_draw_rotated_bitmap(a,(int)(b),(int)(c),(int)(d),(int)(e), f, g)
#define al_draw_bitmap_region(a, b, c, d, e, f, g, h) al_draw_bitmap_region(a,(int)(b),(int)(c),(int)(d),(int)(e),(int)(f), (int)(g), h)
#define al_draw_tinted_bitmap_region(a, tint, b, c, d, e, f, g, h) al_draw_tinted_bitmap_region(a,tint,(int)(b),(int)(c),(int)(d),(int)(e),(int)(f), (int)(g), h)
#define al_draw_tinted_rotated_bitmap(a,tint,b,c,d,e,f,g) al_draw_tinted_rotated_bitmap(a,tint,(int)(b),(int)(c),(int)(d),(int)(e), f, g)
//#define al_draw_filled_rectangle
//#define al_draw_prim()
#define al_load_ttf_font(a,b,c) al_load_ttf_font(a, (int)(b / 8)*8 == 0 ? 8 : (int)(b / 8)*8, c)
#define al_draw_text(a,b,c,d,e,f) al_draw_text(a, b, (int)(c), (int)(d), e, f)
char* strdup(const char *str);
void SetupViewport(struct Game *game);
void Console_Unload(struct Game *game);
void DrawConsole(struct Game *game);
/*! \brief Draws rectangle filled with vertical gradient. */
void DrawVerticalGradientRect(float x, float y, float w, float h, ALLEGRO_COLOR top, ALLEGRO_COLOR bottom);
/*! \brief Draws rectangle filled with horizontal gradient. */
@ -36,12 +62,11 @@ void DrawTextWithShadow(ALLEGRO_FONT *font, ALLEGRO_COLOR color, float x, float
/*! \brief Loads bitmap into memory and scales it with software linear filtering. */
ALLEGRO_BITMAP* LoadScaledBitmap(struct Game *game, char* filename, int width, int height);
/*! \brief Displays fade in or fade out animation on current gamestate. */
void FadeGamestate(struct Game *game, bool in);
/*! \brief Finds path for data file. */
char* GetDataFilePath(struct Game *game, char* filename);
char* GetLibFilePath(struct Game *game, char* filename);
/*! \brief Print some message on game console.
*
* Draws message on console bitmap, so it'll be displayed when calling DrawConsole.
@ -51,3 +76,53 @@ char* GetDataFilePath(struct Game *game, char* filename);
void PrintConsole(struct Game *game, char* format, ...);
void FatalError(struct Game *game, bool exit, char* format, ...);
/*! \brief Structure representing one spritesheet for character animation. */
struct Spritesheet {
char* name; /*!< Name of the spritesheet (used in file paths). */
ALLEGRO_BITMAP* bitmap; /*!< Spritesheet bitmap. */
int rows; /*!< Number of rows in the spritesheet. */
int cols; /*!< Number of columns in the spritesheet. */
int blanks; /*!< Number of blank frames at the end of the spritesheet. */
int width;
int height;
int delay;
bool kill;
float scale; /*!< Scale modifier of the frame. */
char* successor; /*!< Name of animation successor. If it's not blank, then animation will be played only once. */
struct Spritesheet* next; /*!< Next spritesheet in the queue. */
};
/*! \brief Structure representing one visible character. */
struct Character {
char* name; /*!< Name of the character (used in file paths). */
struct Spritesheet *spritesheet; /*!< Current spritesheet used by character. */
struct Spritesheet *spritesheets; /*!< List of all spritesheets registered to character. */
char* successor;
ALLEGRO_BITMAP* bitmap;
int pos; /*!< Current spritesheet position. */
int pos_tmp; /*!< A counter used to slow down spritesheet animation. */
float x; /*!< Horizontal position of character. */
float y; /*!< Vertical position of character. */
float angle; /*!< Characters display angle (radians). */
void* data; /*!< Additional, custom character data (HP etc.). */
bool shared;
bool dead;
};
void SelectSpritesheet(struct Game *game, struct Character *character, char* name);
void ChangeSpritesheet(struct Game *game, struct Character *character, char* name);
void RegisterSpritesheet(struct Game *game, struct Character *character, char* name);
void DrawCharacter(struct Game *game, struct Character *character, ALLEGRO_COLOR tilt, int flags);
struct Character* CreateCharacter(struct Game *game, char* name);
void DestroyCharacter(struct Game *game, struct Character *character);
void LoadSpritesheets(struct Game *game, struct Character *character);
void UnloadSpritesheets(struct Game *game, struct Character *character);
void AnimateCharacter(struct Game *game, struct Character *character, float speed_modifier);
void MoveCharacter(struct Game *game, struct Character *character, float x, float y, float angle);
void SetCharacterPosition(struct Game *game, struct Character *character, int x, int y, float angle);