diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 944f21e..dd51115 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,24 +27,24 @@ if(MINGW) set(LINK_FLAGS -Wl,-subsystem,windows) endif(MINGW) -SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib/radioedit:\$ORIGIN/gamestates:\$ORIGIN:\$ORIGIN/../lib:\$ORIGIN/lib:\$ORIGIN/bin") +SET(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib/ticklemonster:\$ORIGIN/gamestates:\$ORIGIN:\$ORIGIN/../lib:\$ORIGIN/lib:\$ORIGIN/bin") if(APPLE) - set(EXECUTABLE "RadioEdit") + set(EXECUTABLE "TickleMonster") else(APPLE) - set(EXECUTABLE "radioedit") + set(EXECUTABLE "ticklemonster") endif(APPLE) -add_library("libsuperderpy-radioedit" SHARED ${SRC_LIST}) +add_library("libsuperderpy-ticklemonster" SHARED ${SRC_LIST}) add_executable(${EXECUTABLE} WIN32 MACOSX_BUNDLE ${EXECUTABLE_SRC_LIST}) -SET_TARGET_PROPERTIES("libsuperderpy-radioedit" PROPERTIES PREFIX "") +SET_TARGET_PROPERTIES("libsuperderpy-ticklemonster" 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-radioedit) +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-ticklemonster) -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) +target_link_libraries("libsuperderpy-ticklemonster" ${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}) @@ -53,4 +53,4 @@ endif(ALLEGRO5_MAIN_FOUND) add_subdirectory(gamestates) install(TARGETS ${EXECUTABLE} DESTINATION ${BIN_INSTALL_DIR}) -install(TARGETS "libsuperderpy-radioedit" DESTINATION ${LIB_INSTALL_DIR}) +install(TARGETS "libsuperderpy-ticklemonster" DESTINATION ${LIB_INSTALL_DIR}) diff --git a/src/gamestates/CMakeLists.txt b/src/gamestates/CMakeLists.txt index a499123..9f730c7 100644 --- a/src/gamestates/CMakeLists.txt +++ b/src/gamestates/CMakeLists.txt @@ -1,16 +1,18 @@ MACRO(GAMESTATE name) - add_library("libsuperderpy-radioedit-${name}" SHARED "${name}.c") + add_library("libsuperderpy-ticklemonster-${name}" SHARED "${name}.c") - SET_TARGET_PROPERTIES("libsuperderpy-radioedit-${name}" PROPERTIES PREFIX "") + SET_TARGET_PROPERTIES("libsuperderpy-ticklemonster-${name}" PROPERTIES PREFIX "") - 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) + target_link_libraries("libsuperderpy-ticklemonster-${name}" ${ALLEGRO5_LIBRARIES} ${ALLEGRO5_FONT_LIBRARIES} ${ALLEGRO5_TTF_LIBRARIES} ${ALLEGRO5_PRIMITIVES_LIBRARIES} ${ALLEGRO5_AUDIO_LIBRARIES} ${ALLEGRO5_ACODEC_LIBRARIES} ${ALLEGRO5_IMAGE_LIBRARIES} m libsuperderpy-ticklemonster) - install(TARGETS "libsuperderpy-radioedit-${name}" DESTINATION ${LIB_INSTALL_DIR}) + install(TARGETS "libsuperderpy-ticklemonster-${name}" DESTINATION ${LIB_INSTALL_DIR}) ENDMACRO() GAMESTATE("dosowisko") GAMESTATE("menu") +GAMESTATE("info") +GAMESTATE("level") GAMESTATE("loading") diff --git a/src/gamestates/dosowisko.c b/src/gamestates/dosowisko.c index 43c4555..a965198 100644 --- a/src/gamestates/dosowisko.c +++ b/src/gamestates/dosowisko.c @@ -26,7 +26,7 @@ #include "../timeline.h" #include "dosowisko.h" -int Gamestate_ProgressCount = 3; +int Gamestate_ProgressCount = 5; static char* text = "# dosowisko.net"; diff --git a/src/gamestates/info.c b/src/gamestates/info.c new file mode 100644 index 0000000..ba2b5ea --- /dev/null +++ b/src/gamestates/info.c @@ -0,0 +1,199 @@ +/*! \file menu.c + * \brief Main Menu view. + */ +/* + * Copyright (c) Sebastian Krzyszkowiak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include "../config.h" +#include "../utils.h" +#include "../timeline.h" +#include "level.h" + +#define TILE_SIZE 20 +#define MAX_FUN 250.0 + +int Gamestate_ProgressCount = 4; + + +void Gamestate_Draw(struct Game *game, struct LevelResources* data) { + + al_set_target_bitmap(al_get_backbuffer(game->display)); + + al_clear_to_color(al_map_rgb(3, 213, 255)); + + al_draw_bitmap(data->bg,0, 0,0); + al_draw_bitmap(data->buildings,0, 0,0); + + al_draw_filled_rectangle(0, 0, 320, 180, al_map_rgba(0,0,0,64)); + + + DrawCharacter(game, data->monster, al_map_rgb(255,255,255), 0); + + al_draw_bitmap(data->meter,0, 0,0); + + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 19, ALLEGRO_ALIGN_CENTRE, "You're the TICKLE MONSTER!"); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 29, ALLEGRO_ALIGN_CENTRE, "You tickle kids to ensure they "); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 39, ALLEGRO_ALIGN_CENTRE, "are raised with proper amounts of fun!"); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 54, ALLEGRO_ALIGN_CENTRE, "Use ARROWS to move and SPACE to tickle!"); + + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 104, ALLEGRO_ALIGN_CENTRE, "Beware - if you give them wrong amount"); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 114, ALLEGRO_ALIGN_CENTRE, "of fun, they turn into fun hating"); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, 124, ALLEGRO_ALIGN_CENTRE, "grown ups! Don't let them catch you!"); + + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 5, 162, ALLEGRO_ALIGN_LEFT, "Press ENTER to start!"); + +} + + +void Gamestate_Logic(struct Game *game, struct LevelResources* data) { + + AnimateCharacter(game, data->monster, 1); + +} + +void* Gamestate_Load(struct Game *game, void (*progress)(struct Game*)) { + + struct LevelResources *data = malloc(sizeof(struct LevelResources)); + + data->timer = al_create_timer(1); + al_register_event_source(game->_priv.event_queue, al_get_timer_event_source(data->timer)); + + data->timeline = TM_Init(game, "main"); + (*progress)(game); + + data->bg = al_load_bitmap( GetDataFilePath(game, "bg2.png") ); + data->buildings = al_load_bitmap( GetDataFilePath(game, "buildings.png") ); + data->hid = al_load_bitmap( GetDataFilePath(game, "hid.png") ); + data->meter = al_load_bitmap( GetDataFilePath(game, "meter.png") ); + (*progress)(game); + + data->font_title = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"),game->viewport.height*0.16,0 ); + data->font = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"),12,0 ); + (*progress)(game); + + data->monster = CreateCharacter(game, "monster"); + RegisterSpritesheet(game, data->monster, "stand"); + RegisterSpritesheet(game, data->monster, "tickle"); + RegisterSpritesheet(game, data->monster, "ticklefail"); + RegisterSpritesheet(game, data->monster, "fail"); + RegisterSpritesheet(game, data->monster, "jump"); + LoadSpritesheets(game, data->monster); + (*progress)(game); + + al_set_target_backbuffer(game->display); + return data; +} + + +void Gamestate_Stop(struct Game *game, struct LevelResources* data) { + +} + +void Gamestate_Unload(struct Game *game, struct LevelResources* data) { + al_destroy_bitmap(data->bg); + al_destroy_bitmap(data->buildings); + al_destroy_bitmap(data->meter); + al_destroy_font(data->font_title); + al_destroy_font(data->font); + DestroyCharacter(game, data->monster); +} + + +void StartGame(struct Game *game, struct LevelResources *data) { + TM_CleanQueue(data->timeline); + TM_CleanBackgroundQueue(data->timeline); + ChangeSpritesheet(game, data->monster, "stand"); + ChangeSpritesheet(game, data->suit, "stand"); + } + +void Gamestate_Start(struct Game *game, struct LevelResources* data) { + data->cloud_position = 100; + SetCharacterPosition(game, data->monster, 150, 73, 0); + + data->score = 0; + data->time = 0; + + data->lost = false; + data->tickling = false; + data->haskid = false; + + data->movedown = false; + data->moveup = false; + + data->markx = 119; + data->marky = 2; + + data->soloactive = false; + data->soloanim = 0; + data->soloflash = 0; + data->soloready = 0; + + data->keys.key = 0; + data->keys.delay = 0; + data->keys.shift = false; + data->keys.lastkey = -1; + + data->lightanim=0; + + data->kidSpeed = 0.8; + + data->usage = 0; + + SelectSpritesheet(game, data->monster, "stand"); + + //TM_AddQueuedBackgroundAction(data->timeline, &Anim_FixGuitar, TM_AddToArgs(NULL, 1, data), 15*1000, "fix_guitar"); + //TM_AddQueuedBackgroundAction(data->timeline, &Anim_CowLook, TM_AddToArgs(NULL, 1, data), 5*1000, "cow_look"); + + data->kids[0] = NULL; + data->kids[1] = NULL; + data->kids[2] = NULL; + data->kids[3] = NULL; + data->kids[4] = NULL; + data->kids[5] = NULL; + data->destroyQueue = NULL; + + data->kidRate = 100; + data->timeTillNextBadguy = 0; +} + +void Gamestate_ProcessEvent(struct Game *game, struct LevelResources* data, ALLEGRO_EVENT *ev) { + TM_HandleEvent(data->timeline, ev); + + if (ev->type == ALLEGRO_EVENT_KEY_DOWN) { + if (ev->keyboard.keycode == ALLEGRO_KEY_ESCAPE) { + SwitchGamestate(game, "info", "level"); + return; + } + if (ev->keyboard.keycode == ALLEGRO_KEY_ENTER) { + SwitchGamestate(game, "info", "level"); + return; + } + } + +} + +void Gamestate_Pause(struct Game *game, struct LevelResources* data) { + TM_Pause(data->timeline); +} +void Gamestate_Resume(struct Game *game, struct LevelResources* data) { + TM_Resume(data->timeline); +} +void Gamestate_Reload(struct Game *game, struct LevelResources* data) {} diff --git a/src/gamestates/info.h b/src/gamestates/info.h new file mode 100644 index 0000000..301985a --- /dev/null +++ b/src/gamestates/info.h @@ -0,0 +1,84 @@ +/*! \file menu.h + * \brief Main Menu view headers. + */ +/* + * Copyright (c) Sebastian Krzyszkowiak + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +/*! \brief Resources used by Menu state. */ +struct LevelResources { + ALLEGRO_BITMAP *bg; /*!< Bitmap with lower portion of menu landscape. */ + ALLEGRO_BITMAP *buildings; + ALLEGRO_BITMAP *hid; + ALLEGRO_BITMAP *meter; + ALLEGRO_BITMAP *busted; + + ALLEGRO_TIMER *timer; + + float kidSpeed; + + int markx, marky; + + int usage; + int lightx, lighty, lightanim; + + int soloready, soloanim, soloflash; + bool soloactive; + + bool tickling, moveup, movedown, haskid, lost; + + struct Kid { + struct Character *character; + struct Kid *next, *prev; + float speed; + bool tickled; + bool grownup; + int fun; + bool happy; + bool right; + } *kids[6], *destroyQueue, *tickledKid; + + int timeTillNextBadguy, kidRate; + + struct Character *monster; + struct Character *suit; + struct Character *kid; + struct Timeline *timeline; + float cloud_position; /*!< Position of bigger cloud. */ + ALLEGRO_SAMPLE *sample; /*!< Music sample. */ + ALLEGRO_SAMPLE *click_sample; /*!< Click sound sample. */ + ALLEGRO_SAMPLE_INSTANCE *laughter; /*!< Sample instance with music sound. */ + ALLEGRO_SAMPLE_INSTANCE *click; /*!< Sample instance with click sound. */ + ALLEGRO_FONT *font_title; /*!< Font of "Super Derpy" text. */ + ALLEGRO_FONT *font; /*!< Font of standard menu item. */ + int selected; /*!< Number of selected menu item. */ + + struct { + int key; + bool shift; + int delay; + // workaround for random bogus UP/DOWN events + int lastkey; + int lastdelay; + } keys; + + int score, time; +}; diff --git a/src/gamestates/level.c b/src/gamestates/level.c index 27fdbec..98fa804 100644 --- a/src/gamestates/level.c +++ b/src/gamestates/level.c @@ -1,5 +1,5 @@ -/*! \file level.c - * \brief Playable Level code. +/*! \file menu.c + * \brief Main Menu view. */ /* * Copyright (c) Sebastian Krzyszkowiak @@ -18,435 +18,692 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include +#include +#include +#include +#include "../config.h" #include "../utils.h" #include "../timeline.h" -#include "../config.h" #include "level.h" -#include +#define TILE_SIZE 20 +#define MAX_FUN 250.0 +#define FLOOR_OF_FUN 0.68 +#define CEIL_OF_FUN 0.88 -// TODO: move this file to better place -// it's now a place for level related utilities - certainly not a gamestate +int Gamestate_ProgressCount = 8; -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); +void SaveScore(struct Game *game, struct LevelResources *data) { + + if (((data->score / (double)(data->time / 10)) > (data->savedScore / (double)data->savedTime)) || ((data->score / (double)(data->time / 10)) == (data->savedScore / (double)data->savedTime) && (data->score > data->savedScore))) { + char *text = malloc(255*sizeof(char)); + snprintf(text, 255, "%d", data->score); + SetConfigOption(game, "TickleMonster", "score", text); + snprintf(text, 255, "%d", data->time / 10); + SetConfigOption(game, "TickleMonster", "time", text); + } + +} + +void AnimateBadguys(struct Game *game, struct LevelResources *data, int i) { + struct Kid *tmp = data->kids[i]; + while (tmp) { + AnimateCharacter(game, tmp->character, tmp->tickled ? 1 : tmp->speed * data->kidSpeed); + tmp=tmp->next; + } +} + +void MoveBadguys(struct Game *game, struct LevelResources *data, int i, float dx) { + struct Kid *tmp = data->kids[i]; + while (tmp) { + + if (!tmp->grownup) { + if ((!tmp->character->spritesheet->kill) && (!tmp->tickled)) { + MoveCharacter(game, tmp->character, dx * tmp->speed * data->kidSpeed, 0, 0); + } + + if (tmp->character->x < 30) { + if (tmp->fun > FLOOR_OF_FUN * MAX_FUN && tmp->fun < CEIL_OF_FUN * MAX_FUN) { + tmp->happy = true; + al_set_sample_instance_playing(data->click, true); + data->score++; + } else { + if (rand() % 3 == 0) { + tmp->grownup = true; + tmp->right = true; + tmp->character->spritesheets = data->suit->spritesheets; + SelectSpritesheet(game, tmp->character, "walk"); + MoveCharacter(game, tmp->character, 0, -8, 0); + } + } + } + } else { + // grownup + MoveCharacter(game, tmp->character, (tmp->right ? -1 : 1) * dx * tmp->speed * data->kidSpeed / 2, 0, 0); + if (tmp->character->x > 270) { + tmp->right = false; + } else if (tmp->character->x < 42) { + if (rand() % 2) { // 50% chance for getting rid + tmp->right = true; + } else { + if (!tmp->right) { + tmp->happy = true; + } + } + } + } + + if (tmp->grownup) { + if ((tmp->character->x > data->monster->x) && (tmp->character->x + 10 < data->monster->x + 20) && (abs(tmp->character->y - data->monster->y) < 5)) { + data->lost = true; + al_stop_sample_instance(data->laughter); + al_stop_timer(data->timer); + SaveScore(game, data); + } + } + + if (tmp->happy) { + if (tmp->prev) { + tmp->prev->next = tmp->next; + if (tmp->next) tmp->next->prev = tmp->prev; + } else { + data->kids[i] = tmp->next; + if (tmp->next) tmp->next->prev = NULL; + } + struct Kid *old = tmp; + tmp = tmp->next; + old->character->dead = true; + old->prev = NULL; + old->next = data->destroyQueue; + if (data->destroyQueue) data->destroyQueue->prev = old; + data->destroyQueue = old; + } else { + tmp = tmp->next; + } + + } +} + +void CheckForEnd(struct Game *game, struct LevelResources *data) { + return; + + int i; + bool lost = false; + for (i=0; i<6; i++) { + struct Kid *tmp = data->kids[i]; + while (tmp) { + if (tmp->character->x <= (139-(i*10))-10) { + lost = true; + break; + } + tmp=tmp->next; + } + if (lost) break; + } + + if (lost) { + + data->soloactive=false; + data->soloanim=0; + data->soloflash=0; + data->soloready=0; + + SelectSpritesheet(game, data->monster, "cry"); + } +} + +void DrawBadguys(struct Game *game, struct LevelResources *data, int i) { + struct Kid *tmp = data->kids[i]; + while (tmp) { + if (!tmp->happy) { + DrawCharacter(game, tmp->character, al_map_rgb(255,255,255), (tmp->grownup && !tmp->right) ? ALLEGRO_FLIP_HORIZONTAL : 0); + } + tmp=tmp->next; + } +} + +void Gamestate_Draw(struct Game *game, struct LevelResources* data) { + + al_set_target_bitmap(al_get_backbuffer(game->display)); + + al_clear_to_color(al_map_rgb(3, 213, 255)); + + al_draw_bitmap(data->bg,0, 0,0); + + for (int i=0; i<6; i++) { + DrawBadguys(game, data, i); + if ((int)((data->monster->y + 18) / 20) > i) { + DrawCharacter(game, data->monster, al_map_rgb(255,255,255), 0); + } + } + + al_draw_bitmap(data->buildings,0, 0,0); + if (data->savedScore) { + al_draw_bitmap(data->hid2,0, 0,0); + } else { + al_draw_bitmap(data->hid,0, 0,0); + } + + if (data->tickling && data->haskid) { + al_draw_bitmap(data->meter,0, 0,0); + int length = (data->tickledKid->fun / MAX_FUN) * 151; + al_draw_filled_rectangle(160, 163, 160 + ((length > 151) ? 151 : length), 173, al_map_rgb(255,255,255)); + if ((data->tickledKid->fun / MAX_FUN) > FLOOR_OF_FUN) { + al_draw_filled_rectangle(160 + 151 * FLOOR_OF_FUN, 163, 160 + ((length > 151 * CEIL_OF_FUN) ? (151 * CEIL_OF_FUN) : length), 173, al_map_rgb(192, 255, 192)); + } + } + + if (data->soloflash) { + al_draw_filled_rectangle(0, 0, 320, 180, al_map_rgb(255,255,255)); + } + + char *text = malloc(255*sizeof(char)); + snprintf(text, 255, "%d", data->score); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 21, 162, 0, text); + snprintf(text, 255, "%d", data->time / 10); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 61, 162, 0, text); + if (data->savedScore) { + snprintf(text, 255, "%d / %d", data->savedScore, data->savedTime); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 106, 162, 0, text); + } + free(text); + + if (data->lost) { + al_draw_filled_rectangle(0, 0, 320, 180, al_map_rgba(0,0,0,128)); + al_draw_bitmap(data->busted,0, 0,0); + + char *text = malloc(255*sizeof(char)); + snprintf(text, 255, "Score: %d", data->score); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 200, 118, 0, text); + snprintf(text, 255, "Time: %d", data->time / 10); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 200, 128, 0, text); + free(text); + } + + if (data->paused) { + al_draw_filled_rectangle(0, 0, 320, 180, al_map_rgba(0,0,0,128)); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5 - 25, ALLEGRO_ALIGN_CENTRE, "Game paused!"); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5 + 5, ALLEGRO_ALIGN_CENTRE, "SPACE to resume"); + DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5 + 15, ALLEGRO_ALIGN_CENTRE, "ESCAPE to leave"); + } +} + +void AddBadguy(struct Game *game, struct LevelResources* data, int i) { + struct Kid *n = malloc(sizeof(struct Kid)); + n->next = NULL; + n->prev = NULL; + n->speed = (rand() % 3) * 0.25 + 1; + n->tickled = false; + n->grownup = false; + n->happy = false; + n->fun = 0; + n->character = CreateCharacter(game, "kid"); + n->character->spritesheets = data->kid->spritesheets; + n->character->shared = true; + SelectSpritesheet(game, n->character, "walk"); + SetCharacterPosition(game, n->character, 280, 20+(i*TILE_SIZE), 0); + + if (data->kids[i]) { + struct Kid *tmp = data->kids[i]; + while (tmp->next) { + tmp=tmp->next; + } + tmp->next = n; + n->prev = tmp; + } else { + data->kids[i] = n; + } +} + +void Fire(struct Game *game, struct LevelResources *data) { + + if (data->movedown || data->moveup) return; + + if (data->tickling) { + + if (data->haskid) { + data->tickledKid->tickled = false; + SelectSpritesheet(game, data->tickledKid->character, "walk"); + data->haskid = false; + al_set_sample_instance_playing(data->laughter, false); + MoveCharacter(game, data->tickledKid->character, 0, 3, 0); + data->tickledKid = NULL; + } + + SelectSpritesheet(game, data->monster, "stand"); + MoveCharacter(game, data->monster, 2, -2, 0); + data->tickling = false; return; } - while (tmp) { - if (!strcmp(tmp->name, name)) { - character->spritesheet = tmp; - //game->level.sheet_rows = tmp->rows; - //game->level.sheet_cols = tmp->cols; - //game->level.sheet_blanks = tmp->blanks; - //game->level.sheet_speed_modifier = tmp->speed; - character->pos = 0; - //game->level.sheet_scale = tmp->scale; - //game->level.sheet_successor = tmp->successor; - if (character->bitmap) al_destroy_bitmap(character->bitmap); - character->bitmap = al_create_bitmap((game->viewport.height*0.25)*tmp->aspect*tmp->scale, (game->viewport.height*0.25)*tmp->scale); // FIXME: dimensions! - PrintConsole(game, "SUCCESS: Spritesheet for %s activated: %s (%dx%d)", character->name, 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; + + SelectSpritesheet(game, data->monster, "ticklefail"); + MoveCharacter(game, data->monster, -2, 2, 0); + + data->tickling = true; + + //PrintConsole(game, "MONSTAH %f", data->monster->x); } -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, "levels/%s/%s.png", character->name, tmp->name); - tmp->bitmap = LoadScaledBitmap(game, filename, (int)(game->viewport.height*0.25*tmp->aspect*tmp->scale)*tmp->cols, (int)(game->viewport.height*0.25*tmp->scale)*tmp->rows); - } - tmp = tmp->next; - } -} +void Gamestate_Logic(struct Game *game, struct LevelResources* data) { -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; - } -} + if ((data->lost) || (data->paused)) return; -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, "levels/%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->speed = atof(al_get_config_value(config, "", "speed")); - s->aspect = atof(al_get_config_value(config, "", "aspect")); - s->scale = atof(al_get_config_value(config, "", "scale")); - 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; - return character; -} - -void DestroyCharacter(struct Game *game, struct Character *character) { - PrintConsole(game, "Destroying character %s...", character->name); - UnloadSpritesheets(game, character); - struct Spritesheet *tmp, *s = character->spritesheets; - tmp = s; - while (s) { - tmp = s; - s = s->next; - free(tmp); + if (strcmp(data->monster->spritesheet->name, "fail") == 0) { + data->tickling = false; + MoveCharacter(game, data->monster, 2, -2, 0); + SelectSpritesheet(game, data->monster, "stand"); } - if (character->bitmap) al_destroy_bitmap(character->bitmap); - free(character->name); - free(character); -} - -void AnimateCharacter(struct Game *game, struct Character *character, float speed_modifier) { - if ((character->spritesheet->speed) && (speed_modifier)) { - character->pos_tmp+=character->spritesheet->speed*speed_modifier; - while (character->pos_tmp >= 1) { - character->pos++; - character->pos_tmp--; - } - if (character->pos>=character->spritesheet->cols*character->spritesheet->rows-character->spritesheet->blanks) { - character->pos=0; - if (character->spritesheet->successor) { - SelectSpritesheet(game, character, character->spritesheet->successor); + if (data->tickling) { + if (!data->haskid) { + struct Kid *tmp = data->kids[(int)((data->monster->y - 15) / 20)]; + while (tmp) { + if ((tmp->character->x > data->monster->x + 16) && (tmp->character->x < data->monster->x + 23)) { + if (tmp->grownup) { + data->lost = true; + al_stop_sample_instance(data->laughter); + al_stop_timer(data->timer); + SaveScore(game, data); + } else { + tmp->tickled = true; + SelectSpritesheet(game, data->monster, "tickle"); + SelectSpritesheet(game, tmp->character, "laugh"); + data->haskid = true; + data->tickledKid = tmp; + SetCharacterPosition(game, tmp->character, data->monster->x + 22, tmp->character->y - 3, 0); + al_set_sample_instance_playing(data->laughter, true); + } + break; + } + tmp=tmp->next; } } - } -} -void MoveCharacter(struct Game *game, struct Character *character, float x, float y, float angle) { - character->x += x; - character->y += y; - character->angle += angle; -} - -void SetCharacterPosition(struct Game *game, struct Character *character, float x, float y, float angle) { - character->x = x; - character->y = y; - character->angle = angle; -} - -void AdvanceLevel(struct Game *game, int current_level, bool last) { - if (!last) { - int available = atoi(GetConfigOptionDefault(game, "MuffinAttack", "level", "1")); - available++; - if ((available<2) || (available>7)) available=1; - if (available==(current_level+1)) { - char* text = malloc(255*sizeof(char)); - snprintf(text, 255, "%d", available); - SetConfigOption(game, "MuffinAttack", "level", text); - free(text); + if (data->haskid) { + data->tickledKid->fun++; } - } else { - SetConfigOption(game, "MuffinAttack", "completed", "1"); } -} -/*char* GetLevelFilename(struct Game *game, char* filename) { - // FIXME: it should work with larger numbers too - char* name = strdup(filename); - char* ch = strchr(name, '?'); - ch[0] = '0' + game->level.current_level; - return name; -}*/ -void DrawCharacter(struct Game *game, struct Character *character, ALLEGRO_COLOR tilt, int flags) { - al_set_target_bitmap(character->bitmap); - al_clear_to_color(al_map_rgba(0,0,0,0)); - al_draw_bitmap_region(character->spritesheet->bitmap, 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),0,0,0); - al_set_target_bitmap(al_get_backbuffer(game->display)); + if (data->keys.lastkey == data->keys.key) { + data->keys.delay = data->keys.lastdelay; // workaround for random bugus UP/DOWN events + } - al_draw_tinted_rotated_bitmap(character->bitmap, tilt, al_get_bitmap_width(character->bitmap), al_get_bitmap_height(character->bitmap)/2, character->x*game->viewport.width + al_get_bitmap_width(character->bitmap), character->y*game->viewport.height + al_get_bitmap_height(character->bitmap)/2, character->angle, flags); // FIXME: viewport height? omg character should have its dimensions ;_; + if (data->moveup && data->monster->y < 14) { + data->moveup = false; + } + if (data->movedown && data->monster->y > 112) { + data->movedown = false; + } -} + if (data->moveup) { + MoveCharacter(game, data->monster, 0, -1, 0); + } else if (data->movedown) { + MoveCharacter(game, data->monster, 0, 1, 0); + } -/* -void Level_Logic(struct Game *game) { - LEVELS(Logic, game); + if ((int)(data->monster->y + 7) % TILE_SIZE == 0) { + data->moveup = false; + data->movedown = false; + } - if ((game->level.sheet_speed) && (game->level.sheet_speed_modifier)) { - game->level.sheet_tmp+=1; - if (game->level.sheet_tmp >= (game->level.sheet_speed/game->level.speed_modifier)/game->level.sheet_speed_modifier) { - game->level.sheet_pos++; - game->level.sheet_tmp -= (game->level.sheet_speed/game->level.speed_modifier)/game->level.sheet_speed_modifier; + data->cloud_position-=0.1; + if (data->cloud_position<-40) { data->cloud_position=100; PrintConsole(game, "cloud_position"); } + AnimateCharacter(game, data->monster, 1); + + if ((data->keys.key) && (data->keys.delay < 3)) { + + if (!data->tickling) { + if (data->keys.key==ALLEGRO_KEY_LEFT) { + if (data->monster->x > 42) { + MoveCharacter(game, data->monster, -1, 0, 0); + } + } + + if (data->keys.key==ALLEGRO_KEY_RIGHT) { + if (data->monster->x < 256) { + MoveCharacter(game, data->monster, 1, 0, 0); + } + } + } + + if (data->keys.delay == INT_MIN) data->keys.delay = 3; + else data->keys.delay += 3; + + } else if (data->keys.key) { + data->keys.delay-=3; } - if (game->level.sheet_pos>=game->level.sheet_cols*game->level.sheet_rows-game->level.sheet_blanks) { - game->level.sheet_pos=0; - if (game->level.sheet_successor) { - SelectDerpySpritesheet(game, game->level.sheet_successor); + + AnimateBadguys(game, data, 0); + AnimateBadguys(game, data, 1); + AnimateBadguys(game, data, 2); + AnimateBadguys(game, data, 3); + AnimateBadguys(game, data, 4); + AnimateBadguys(game, data, 5); + + MoveBadguys(game, data, 0, -0.17); + MoveBadguys(game, data, 1, -0.18); + MoveBadguys(game, data, 2, -0.19); + MoveBadguys(game, data, 3, -0.2); + MoveBadguys(game, data, 4, -0.21); + MoveBadguys(game, data, 5, -0.22); + + data->timeTillNextBadguy--; + if (data->timeTillNextBadguy <= 0) { + data->timeTillNextBadguy = data->kidRate * 2; + data->kidRate -= data->kidRate * 0.005; + if (data->kidRate < 50) { + data->kidRate = 50; + } + + data->kidSpeed+= 0.0005; + AddBadguy(game, data, rand() % 6); + } + + if (data->usage) { data->usage--; } + if (data->lightanim) { data->lightanim++;} + if (data->lightanim > 25) { data->lightanim = 0; } + + CheckForEnd(game, data); + + data->soloanim++; + if (data->soloanim >= 60) data->soloanim=0; + + if (data->soloflash) data->soloflash--; + + data->keys.lastkey = data->keys.key; + data->keys.lastdelay = data->keys.delay; + + TM_Process(data->timeline); +} + +void* Gamestate_Load(struct Game *game, void (*progress)(struct Game*)) { + + struct LevelResources *data = malloc(sizeof(struct LevelResources)); + + data->timer = al_create_timer(0.1); + al_register_event_source(game->_priv.event_queue, al_get_timer_event_source(data->timer)); + + data->timeline = TM_Init(game, "main"); + (*progress)(game); + + data->bg = al_load_bitmap( GetDataFilePath(game, "bg2.png") ); + data->buildings = al_load_bitmap( GetDataFilePath(game, "buildings.png") ); + data->hid = al_load_bitmap( GetDataFilePath(game, "hid.png") ); + data->hid2 = al_load_bitmap( GetDataFilePath(game, "hid2.png") ); + data->meter = al_load_bitmap( GetDataFilePath(game, "meter.png") ); + data->busted = al_load_bitmap( GetDataFilePath(game, "busted.png") ); + data->click_sample = al_load_sample( GetDataFilePath(game, "point.flac") ); + (*progress)(game); + + data->click = al_create_sample_instance(data->click_sample); + al_attach_sample_instance_to_mixer(data->click, game->audio.fx); + al_set_sample_instance_playmode(data->click, ALLEGRO_PLAYMODE_ONCE); + (*progress)(game); + + + data->sample = al_load_sample( GetDataFilePath(game, "laughter.flac") ); + (*progress)(game); + + data->laughter = al_create_sample_instance(data->sample); + al_attach_sample_instance_to_mixer(data->laughter, game->audio.fx); + al_set_sample_instance_playmode(data->laughter, ALLEGRO_PLAYMODE_LOOP); + (*progress)(game); + + data->font_title = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"),game->viewport.height*0.16,0 ); + data->font = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"),12,0 ); + (*progress)(game); + + data->monster = CreateCharacter(game, "monster"); + RegisterSpritesheet(game, data->monster, "stand"); + RegisterSpritesheet(game, data->monster, "tickle"); + RegisterSpritesheet(game, data->monster, "ticklefail"); + RegisterSpritesheet(game, data->monster, "fail"); + RegisterSpritesheet(game, data->monster, "jump"); + LoadSpritesheets(game, data->monster); + (*progress)(game); + + data->suit = CreateCharacter(game, "suit"); + RegisterSpritesheet(game, data->suit, "walk"); + LoadSpritesheets(game, data->suit); + (*progress)(game); + + data->kid = CreateCharacter(game, "kid"); + RegisterSpritesheet(game, data->kid, "walk"); + RegisterSpritesheet(game, data->kid, "laugh"); + LoadSpritesheets(game, data->kid); + + al_set_target_backbuffer(game->display); + return data; +} + +void DestroyBadguys(struct Game *game, struct LevelResources* data, int i) { + struct Kid *tmp = data->kids[i]; + if (!tmp) { + tmp = data->destroyQueue; + data->destroyQueue = NULL; + } + while (tmp) { + DestroyCharacter(game, tmp->character); + struct Kid *old = tmp; + tmp = tmp->next; + free(old); + if ((!tmp) && (data->destroyQueue)) { + tmp = data->destroyQueue; + data->destroyQueue = NULL; + } + } + data->kids[i] = NULL; +} + +void Gamestate_Stop(struct Game *game, struct LevelResources* data) { + int i; + for (i=0; i<6; i++) { + DestroyBadguys(game, data, i); + } + al_set_sample_instance_playing(data->laughter, false); +} + +void Gamestate_Unload(struct Game *game, struct LevelResources* data) { + al_destroy_bitmap(data->bg); + al_destroy_bitmap(data->buildings); + al_destroy_bitmap(data->hid); + al_destroy_bitmap(data->hid2); + al_destroy_bitmap(data->meter); + al_destroy_bitmap(data->busted); + al_destroy_font(data->font_title); + al_destroy_font(data->font); + al_destroy_sample_instance(data->laughter); + al_destroy_sample_instance(data->click); + al_destroy_sample(data->sample); + al_destroy_sample(data->click_sample); + DestroyCharacter(game, data->monster); + DestroyCharacter(game, data->suit); + DestroyCharacter(game, data->kid); + TM_Destroy(data->timeline); +} + +// TODO: refactor to single Enqueue_Anim +bool Anim_CowLook(struct Game *game, struct TM_Action *action, enum TM_ActionState state) { + struct LevelResources *data = action->arguments->value; + if (state == TM_ACTIONSTATE_START) { + ChangeSpritesheet(game, data->suit, "look"); + TM_AddQueuedBackgroundAction(data->timeline, &Anim_CowLook, TM_AddToArgs(NULL, 1, data), 54*1000, "cow_look"); + } + return true; +} + +bool Anim_FixGuitar(struct Game *game, struct TM_Action *action, enum TM_ActionState state) { + struct LevelResources *data = action->arguments->value; + if (state == TM_ACTIONSTATE_START) { + ChangeSpritesheet(game, data->monster, "fix"); + TM_AddQueuedBackgroundAction(data->timeline, &Anim_FixGuitar, TM_AddToArgs(NULL, 1, data), 30*1000, "fix_guitar"); + } + return true; +} + +void StartGame(struct Game *game, struct LevelResources *data) { + TM_CleanQueue(data->timeline); + TM_CleanBackgroundQueue(data->timeline); + ChangeSpritesheet(game, data->monster, "stand"); + } + +void Gamestate_Start(struct Game *game, struct LevelResources* data) { + data->cloud_position = 100; + SetCharacterPosition(game, data->monster, 150, 73, 0); + SetCharacterPosition(game, data->suit, 65, 88, 0); + + al_start_timer(data->timer); + + data->score = 0; + data->time = 0; + data->paused = false; + + data->lost = false; + data->tickling = false; + data->haskid = false; + + data->movedown = false; + data->moveup = false; + + data->markx = 119; + data->marky = 2; + + data->soloactive = false; + data->soloanim = 0; + data->soloflash = 0; + data->soloready = 0; + + data->keys.key = 0; + data->keys.delay = 0; + data->keys.shift = false; + data->keys.lastkey = -1; + + data->lightanim=0; + + data->kidSpeed = 0.8; + + data->usage = 0; + + SelectSpritesheet(game, data->monster, "stand"); + //TM_AddQueuedBackgroundAction(data->timeline, &Anim_FixGuitar, TM_AddToArgs(NULL, 1, data), 15*1000, "fix_guitar"); + //TM_AddQueuedBackgroundAction(data->timeline, &Anim_CowLook, TM_AddToArgs(NULL, 1, data), 5*1000, "cow_look"); + + data->kids[0] = NULL; + data->kids[1] = NULL; + data->kids[2] = NULL; + data->kids[3] = NULL; + data->kids[4] = NULL; + data->kids[5] = NULL; + data->destroyQueue = NULL; + + data->kidRate = 100; + data->timeTillNextBadguy = 0; + + char *end = ""; + + data->savedScore = strtol(GetConfigOptionDefault(game, "TickleMonster", "score", "0"), &end, 10); + data->savedTime = strtol(GetConfigOptionDefault(game, "TickleMonster", "time", "-1"), &end, 10); + +} + +void Gamestate_ProcessEvent(struct Game *game, struct LevelResources* data, ALLEGRO_EVENT *ev) { + TM_HandleEvent(data->timeline, ev); + + if (ev->type == ALLEGRO_EVENT_TIMER) { + if (ev->timer.source == data->timer) { + data->time++; + } + } + + if (ev->type == ALLEGRO_EVENT_KEY_DOWN) { + if (ev->keyboard.keycode == ALLEGRO_KEY_ESCAPE) { + if ((data->paused) || (data->lost)) { + SwitchGamestate(game, "level", "menu"); + } + al_stop_timer(data->timer); + data->paused = true; + return; + } + if (data->lost && ev->keyboard.keycode == ALLEGRO_KEY_ENTER) { + SwitchGamestate(game, "level", "menu"); + return; + } + } + if (data->lost) return; + + if (ev->type == ALLEGRO_EVENT_KEY_DOWN) { + + switch (ev->keyboard.keycode) { + case ALLEGRO_KEY_LEFT: + case ALLEGRO_KEY_RIGHT: + if (!data->tickling) { + if (data->keys.key != ev->keyboard.keycode) { + data->keys.key = ev->keyboard.keycode; + data->keys.delay = INT_MIN; + } + } + break; + case ALLEGRO_KEY_UP: + if (!data->tickling) { + if (!data->moveup && !data->movedown) { + SelectSpritesheet(game, data->monster, "jump"); + } + data->moveup = true; + data->movedown = false; + } + break; + case ALLEGRO_KEY_DOWN: + if (!data->tickling) { + if (!data->moveup && !data->movedown) { + SelectSpritesheet(game, data->monster, "jump"); + } + data->moveup = false; + data->movedown = true; + } + break; + case ALLEGRO_KEY_SPACE: + if (data->paused) { + al_start_timer(data->timer); + data->paused = false; + } else { + Fire(game, data); + } + break; + case ALLEGRO_KEY_LSHIFT: + case ALLEGRO_KEY_RSHIFT: + data->keys.shift = true; + break; + case ALLEGRO_KEY_ENTER: + break; + default: + data->keys.key = 0; + break; + } + } else if (ev->type == ALLEGRO_EVENT_KEY_UP) { + switch (ev->keyboard.keycode) { + case ALLEGRO_KEY_LSHIFT: + case ALLEGRO_KEY_RSHIFT: + data->keys.shift = false; + break; + default: + if (ev->keyboard.keycode == data->keys.key) { + data->keys.key = 0; + } + break; } } - } - if (game->level.speed > 0) { - game->level.cl_pos += game->level.speed*game->level.speed_modifier * 0.2; - game->level.bg_pos += game->level.speed*game->level.speed_modifier * 0.6; - game->level.st_pos += game->level.speed*game->level.speed_modifier * 1; - game->level.fg_pos += game->level.speed*game->level.speed_modifier * 1.75; - if (game->level.bg_pos >= 1) game->level.bg_pos=game->level.bg_pos-1; - if (game->level.st_pos >= 1) game->level.st_pos=game->level.st_pos-1; - if (game->level.fg_pos >= 1) game->level.fg_pos=game->level.fg_pos-1; - } - game->level.cl_pos += 0.00005; - if (game->level.cl_pos >= 1) game->level.cl_pos=game->level.cl_pos-1; - - TM_Process(); -} - -void Level_Resume(struct Game *game) { - al_set_sample_instance_position(game->level.music, game->level.music_pos); - al_set_sample_instance_playing(game->level.music, true); - LEVELS(Resume, game); - TM_Resume(); -} - -void Level_Pause(struct Game *game) { - game->level.music_pos = al_get_sample_instance_position(game->level.music); - al_set_sample_instance_playing(game->level.music, false); - LEVELS(Pause, game); - TM_Pause(); -} - -void Level_Draw(struct Game *game) { - al_draw_bitmap(game->level.clouds, (-game->level.cl_pos)*al_get_bitmap_width(game->level.clouds), 0, 0); - al_draw_bitmap(game->level.clouds, (1+(-game->level.cl_pos))*al_get_bitmap_width(game->level.clouds), 0, 0); - al_draw_bitmap(game->level.background, (-game->level.bg_pos)*al_get_bitmap_width(game->level.background), 0, 0); - al_draw_bitmap(game->level.background, (1+(-game->level.bg_pos))*al_get_bitmap_width(game->level.background), 0, 0); - al_draw_bitmap(game->level.stage, (-game->level.st_pos)*al_get_bitmap_width(game->level.stage), 0 ,0); - al_draw_bitmap(game->level.stage, (1+(-game->level.st_pos))*al_get_bitmap_width(game->level.stage), 0 ,0); - - LEVELS(Draw, game); - - if (!game->level.foreground) return; - - al_draw_bitmap(game->level.foreground, (-game->level.fg_pos)*al_get_bitmap_width(game->level.foreground), 0 ,0); - al_draw_bitmap(game->level.foreground, (1+(-game->level.fg_pos))*al_get_bitmap_width(game->level.foreground), 0 ,0); - - al_set_target_bitmap(game->level.meter_bmp); - al_clear_to_color(al_map_rgba(0,0,0,0)); - al_draw_filled_rounded_rectangle(al_get_bitmap_width(game->level.meter_bmp)*0.1, al_get_bitmap_height(game->level.meter_bmp)*0.34, al_get_bitmap_width(game->level.meter_bmp)*0.993, al_get_bitmap_height(game->level.meter_bmp)*0.66, 6,6, al_map_rgb(232,234,239)); - al_draw_horizontal_gradient_rect(al_get_bitmap_width(game->level.meter_bmp)-game->viewportHeight*1.6*0.215, (al_get_bitmap_height(game->level.meter_bmp)-game->viewportHeight*0.025)/2, game->viewportHeight*1.6*0.215*0.975, game->viewportHeight*0.025, al_map_rgb(150,159,182), al_map_rgb(130,139,162)); - al_draw_filled_rectangle(al_get_bitmap_width(game->level.meter_bmp)-game->viewportHeight*1.6*0.215, (al_get_bitmap_height(game->level.meter_bmp)-game->viewportHeight*0.025)/2, al_get_bitmap_width(game->level.meter_bmp)-game->viewportHeight*1.6*0.215+(game->viewportHeight*1.6*0.215*0.975)*game->level.hp, (al_get_bitmap_height(game->level.meter_bmp)-game->viewportHeight*0.025)/2+game->viewportHeight*0.025, al_map_rgb(214,172,55)); - al_draw_bitmap(game->level.meter_image, 0, 0, 0); - al_set_target_bitmap(al_get_backbuffer(game->display)); - - al_draw_tinted_bitmap(game->level.meter_bmp, al_map_rgba(game->level.meter_alpha,game->level.meter_alpha,game->level.meter_alpha,game->level.meter_alpha), game->viewportWidth-al_get_bitmap_width(game->level.meter_bmp)*1.1, game->viewportHeight*0.975-al_get_bitmap_height(game->level.meter_bmp), 0); - - TM_Draw(); -} - - -void Level_Load(struct Game *game) { - game->level.failed=false; - game->level.hp=1; - game->level.cl_pos=0; - game->level.bg_pos=0; - game->level.fg_pos=0.2; - game->level.st_pos=0.1; - game->level.speed = 0; - game->level.speed_modifier = 1; - game->level.derpy_x = -0.2; - game->level.derpy_y = 0.6; - game->level.derpy_angle = 0; - game->level.sheet_speed = 2.4; - game->level.sheet_tmp = 0; - game->level.handle_input = false; - game->level.meter_alpha=0; - game->level.debug_show_sprite_frames=false; - al_clear_to_color(al_map_rgb(0,0,0)); - TM_Init(game); - LEVELS(Load, game); -} - -int Level_Keydown(struct Game *game, ALLEGRO_EVENT *ev) { - if ((game->debug) && (ev->keyboard.keycode==ALLEGRO_KEY_F2)) { - game->level.hp -= 0.1; - if (game->level.hp <= 0) game->level.hp=0.001; - } else if ((game->debug) && (ev->keyboard.keycode==ALLEGRO_KEY_F3)) { - game->level.hp += 0.1; - if (game->level.hp > 1) game->level.hp=1; - } else if ((game->debug) && (ev->keyboard.keycode==ALLEGRO_KEY_F4)) { - game->level.debug_show_sprite_frames = !game->level.debug_show_sprite_frames; - } - LEVELS(Keydown, game, ev); - if (ev->keyboard.keycode==ALLEGRO_KEY_ESCAPE) { - game->gamestate = GAMESTATE_PAUSE; - game->loadstate = GAMESTATE_LEVEL; - PauseGameState(game); - Pause_Load(game); - } - return 0; -} - -void Level_ProcessEvent(struct Game *game, ALLEGRO_EVENT *ev) { - LEVELS(ProcessEvent, game, ev); - TM_HandleEvent(ev); -} - -void Level_Preload(struct Game *game, void (*progress)(struct Game*, float)) { - PrintConsole(game, "Initializing level %d...", game->level.input.current_level); - - game->level.current_level = game->level.input.current_level; - game->level.derpy_sheets = NULL; - game->level.derpy = NULL; - game->level.unloading = false; - Pause_Preload(game); - RegisterDerpySpritesheet(game, "stand"); // default - - game->level.sample = al_load_sample( GetDataFilePath(GetLevelFilename(game, "levels/?/music.flac")) ); - - LEVELS(Preload, game); - - Level_PreloadBitmaps(game, progress); - - game->level.music = al_create_sample_instance(game->level.sample); - al_attach_sample_instance_to_mixer(game->level.music, game->audio.music); - al_set_sample_instance_playmode(game->level.music, ALLEGRO_PLAYMODE_LOOP); - - if (!game->level.sample){ - fprintf(stderr, "Audio clip sample not loaded!\n" ); - exit(-1); - } } -void Level_Unload(struct Game *game) { - if (game->level.unloading) return; - game->level.unloading = true; - Pause_Unload_Real(game); - FadeGameState(game, false); - al_destroy_sample_instance(game->level.music); - al_destroy_sample(game->level.sample); - Level_UnloadBitmaps(game); - LEVELS(Unload, game); - TM_Destroy(); +void Gamestate_Pause(struct Game *game, struct LevelResources* data) { + data->paused = true; + TM_Pause(data->timeline); } - - -void Level_UnloadBitmaps(struct Game *game) { - al_destroy_bitmap(game->level.derpy); - struct Spritesheet *tmp = game->level.derpy_sheets; - while (tmp) { - al_destroy_bitmap(tmp->bitmap); - tmp = tmp->next; - } - LEVELS(UnloadBitmaps, game); - al_destroy_bitmap(game->level.foreground); - al_destroy_bitmap(game->level.background); - al_destroy_bitmap(game->level.clouds); - al_destroy_bitmap(game->level.stage); - al_destroy_bitmap(game->level.meter_bmp); - al_destroy_bitmap(game->level.meter_image); - al_destroy_bitmap(game->level.welcome); - game->level.foreground = NULL; +void Gamestate_Resume(struct Game *game, struct LevelResources* data) { + data->paused = false; + TM_Resume(data->timeline); } - -int Level_PreloadSteps(struct Game *game) { - switch (game->level.current_level) { - case 1: - return Level1_PreloadSteps(); break; - case 2: - return Level2_PreloadSteps(); break; - case 3: - return Level3_PreloadSteps(); break; - case 4: - return Level4_PreloadSteps(); break; - case 5: - return Level5_PreloadSteps(); break; - case 6: - return Level6_PreloadSteps(); break; - } - return 0; -} - -void Level_PreloadBitmaps(struct Game *game, void (*progress)(struct Game*, float)) { - int x = 0; - - struct Spritesheet *tmp = game->level.derpy_sheets; - while (tmp) { - x++; - tmp = tmp->next; - } - - PROGRESS_INIT(8+x+Level_PreloadSteps(game)); - - tmp = game->level.derpy_sheets; - while (tmp) { - char filename[255] = { }; - sprintf(filename, "levels/derpy/%s.png", tmp->name); - tmp->bitmap = LoadScaledBitmap(filename, (int)(game->viewportHeight*0.25*tmp->aspect*tmp->scale)*tmp->cols, (int)(game->viewportHeight*0.25*tmp->scale)*tmp->rows); - PROGRESS; - tmp = tmp->next; - } - PROGRESS; - if (!game->level.derpy) SelectDerpySpritesheet(game, "stand"); - - game->level.derpy = al_create_bitmap(al_get_bitmap_width(*(game->level.derpy_sheet))/game->level.sheet_cols, al_get_bitmap_height(*(game->level.derpy_sheet))/game->level.sheet_rows); - - game->level.clouds = LoadScaledBitmap(GetLevelFilename(game, "levels/?/clouds.png"), game->viewportHeight*4.73307291666666666667, game->viewportHeight); - PROGRESS; - game->level.foreground = LoadScaledBitmap(GetLevelFilename(game, "levels/?/foreground.png"), game->viewportHeight*4.73307291666666666667, game->viewportHeight); - PROGRESS; - game->level.background = LoadScaledBitmap(GetLevelFilename(game, "levels/?/background.png"), game->viewportHeight*4.73307291666666666667, game->viewportHeight); - PROGRESS; - game->level.stage = LoadScaledBitmap(GetLevelFilename(game, "levels/?/stage.png"), game->viewportHeight*4.73307291666666666667, game->viewportHeight); - PROGRESS; - game->level.meter_image = LoadScaledBitmap("levels/meter.png", game->viewportHeight*1.6*0.075, game->viewportHeight*1.6*0.075*0.96470588235294117647); - PROGRESS; - game->level.meter_bmp = al_create_bitmap(game->viewportHeight*1.6*0.2+al_get_bitmap_width(game->level.meter_image), al_get_bitmap_height(game->level.meter_image)); - PROGRESS; - game->level.welcome = al_create_bitmap(game->viewportWidth, game->viewportHeight/2); - PROGRESS; - - void ChildProgress(struct Game* game, float p) { - if (progress) (*progress)(game, load_p+=1/load_a); - } - LEVELS(PreloadBitmaps, game, &ChildProgress); -} -*/ +void Gamestate_Reload(struct Game *game, struct LevelResources* data) {} diff --git a/src/gamestates/level.h b/src/gamestates/level.h index 9522a69..1696cf5 100644 --- a/src/gamestates/level.h +++ b/src/gamestates/level.h @@ -1,5 +1,5 @@ -/*! \file level.h - * \brief Playable Level headers. +/*! \file menu.h + * \brief Main Menu view headers. */ /* * Copyright (c) Sebastian Krzyszkowiak @@ -18,66 +18,69 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "../main.h" +#include +#include +#include -/*! \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. */ - float speed; /*!< Speed modifier of spritesheet animation. */ - float aspect; /*!< Aspect ratio of the frame. */ - 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 Resources used by Menu state. */ +struct LevelResources { + ALLEGRO_BITMAP *bg; /*!< Bitmap with lower portion of menu landscape. */ + ALLEGRO_BITMAP *buildings; + ALLEGRO_BITMAP *hid; + ALLEGRO_BITMAP *hid2; + ALLEGRO_BITMAP *meter; + ALLEGRO_BITMAP *busted; + + ALLEGRO_TIMER *timer; + + float kidSpeed; + + int markx, marky; + + int usage; + int lightx, lighty, lightanim; + + int soloready, soloanim, soloflash; + bool soloactive; + + bool tickling, moveup, movedown, haskid, lost, paused; + + struct Kid { + struct Character *character; + struct Kid *next, *prev; + float speed; + bool tickled; + bool grownup; + int fun; + bool happy; + bool right; + } *kids[6], *destroyQueue, *tickledKid; + + int timeTillNextBadguy, kidRate; + + struct Character *monster; + struct Character *suit; + struct Character *kid; + struct Timeline *timeline; + float cloud_position; /*!< Position of bigger cloud. */ + ALLEGRO_SAMPLE *sample; /*!< Music sample. */ + ALLEGRO_SAMPLE *click_sample; /*!< Click sound sample. */ + ALLEGRO_SAMPLE_INSTANCE *laughter; /*!< Sample instance with music sound. */ + ALLEGRO_SAMPLE_INSTANCE *click; /*!< Sample instance with click sound. */ + ALLEGRO_FONT *font_title; /*!< Font of "Super Derpy" text. */ + ALLEGRO_FONT *font; /*!< Font of standard menu item. */ + int selected; /*!< Number of selected menu item. */ + + struct { + int key; + bool shift; + int delay; + // workaround for random bogus UP/DOWN events + int lastkey; + int lastdelay; + } keys; + + int savedScore, savedTime; + int score, time; }; - -/*! \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. */ - ALLEGRO_BITMAP* bitmap; - int pos; /*!< Current spritesheet position. */ - float pos_tmp; /*!< A counter used to slow down spritesheet animation. */ - float x; /*!< Horizontal position of character (0 - left, 1 - right side of maximal square). */ - float y; /*!< Vertical position of character (0 - top, 1 - bottom). */ - float angle; /*!< Characters display angle (radians). */ - void* data; /*!< Additional, custom character data (HP etc.). */ -}; - - -void SelectSpritesheet(struct Game *game, struct Character *character, char* name); -void RegisterSpritesheet(struct Game *game, struct Character *character, char* name); -void AdvanceLevel(struct Game *game, int current_level, bool last); -/*! \brief Replaces first '?' char in filename with current level number. */ -char* GetLevelFilename(struct Game *game, char* filename); - -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, float x, float y, float angle); - -/*void Level_Passed(struct Game *game); -void Level_Pause(struct Game *game); -void Level_Resume(struct Game *game); -void Level_Draw(struct Game *game); -void Level_Logic(struct Game *game); -void Level_Preload(struct Game *game, void (*progress)(struct Game*, float)); -void Level_Unload(struct Game *game); -void Level_Load(struct Game *game); -void Level_ProcessEvent(struct Game *game, ALLEGRO_EVENT *ev); -int Level_Keydown(struct Game *game, ALLEGRO_EVENT *ev); -void Level_UnloadBitmaps(struct Game *game); -void Level_PreloadBitmaps(struct Game *game, void (*progress)(struct Game*, float)); -*/ diff --git a/src/gamestates/loading.c b/src/gamestates/loading.c index f35e6f0..a90e2b2 100644 --- a/src/gamestates/loading.c +++ b/src/gamestates/loading.c @@ -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-1, p*game->viewport.width, game->viewport.height, al_map_rgba(128,128,128,128)); + al_draw_filled_rectangle(0, game->viewport.height/2 - 1, p*game->viewport.width, game->viewport.height/2 + 1, al_map_rgba(128,128,128,128)); } void Draw(struct Game *game, struct LoadingResources *data, float p) { @@ -38,10 +38,12 @@ void* Load(struct Game *game) { al_clear_to_color(al_map_rgb(0,0,0)); data->loading_bitmap = al_create_bitmap(game->viewport.width, game->viewport.height); + data->bg = al_load_bitmap( GetDataFilePath(game, "bg.png") ); al_set_target_bitmap(data->loading_bitmap); 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_draw_bitmap(data->bg, 0, 0, 0); + al_draw_filled_rectangle(0, game->viewport.height/2 - 1, game->viewport.width, game->viewport.height/2 + 1, al_map_rgba(32,32,32,32)); al_set_target_bitmap(al_get_backbuffer(game->display)); return data; } @@ -50,5 +52,6 @@ void Start(struct Game *game, struct LoadingResources *data) {} void Stop(struct Game *game, struct LoadingResources *data) {} void Unload(struct Game *game, struct LoadingResources *data) { al_destroy_bitmap(data->loading_bitmap); + al_destroy_bitmap(data->bg); free(data); } diff --git a/src/gamestates/loading.h b/src/gamestates/loading.h index 0abcdd5..810c448 100644 --- a/src/gamestates/loading.h +++ b/src/gamestates/loading.h @@ -26,4 +26,5 @@ /*! \brief Resources used by Loading state. */ struct LoadingResources { ALLEGRO_BITMAP *loading_bitmap; /*!< Rendered loading bitmap. */ + ALLEGRO_BITMAP *bg; }; diff --git a/src/gamestates/menu.c b/src/gamestates/menu.c index 7267070..2228bf3 100644 --- a/src/gamestates/menu.c +++ b/src/gamestates/menu.c @@ -27,9 +27,7 @@ #include "../timeline.h" #include "menu.h" -#define SOLO_MIN 20 - -int Gamestate_ProgressCount = 5; +int Gamestate_ProgressCount = 4; void About(struct Game *game, struct MenuResources* data) { ALLEGRO_TRANSFORM trans; @@ -43,7 +41,7 @@ void About(struct Game *game, struct MenuResources* data) { al_set_target_backbuffer(game->display); al_clear_to_color(al_map_rgb(0,0,170)); - char *header = "RADIO EDIT"; + char *header = "TICKLE MONSTER"; 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)); @@ -55,8 +53,8 @@ void About(struct Game *game, struct MenuResources* data) { 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.", (void*)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+5*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "About screen not implemented!"); - 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+6*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "See http://dosowisko.net/radioedit/"); - 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+7*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "Made for Ludum Dare 32"); + 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+6*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "See http://dosowisko.net/ticklemonster/"); + 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+7*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_CENTRE, "Made for Ludum Dare 33 by Sebastian Krzyszkowiak"); 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, "* 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+10*al_get_font_line_height(game->_priv.font_bsod)*1.25), ALLEGRO_ALIGN_LEFT, "* Press any key to destroy all muffins in the world."); @@ -68,31 +66,43 @@ void About(struct Game *game, struct MenuResources* data) { } void DrawMenuState(struct Game *game, struct MenuResources *data) { + + const ALLEGRO_TRANSFORM *tmp_trans = al_get_current_transform(); + ALLEGRO_TRANSFORM trans, cur_trans; + al_copy_transform(&trans, tmp_trans); + al_copy_transform(&cur_trans, tmp_trans); + al_translate_transform(&trans, (al_get_display_width(game->display) / 320.0) * 100, (al_get_display_height(game->display) / 260.0) * ((180-data->screen_pos) - 48)); + al_use_transform(&trans); + ALLEGRO_FONT *font = data->font; char* text = malloc(255*sizeof(char)); struct ALLEGRO_COLOR color; switch (data->menustate) { case MENUSTATE_MAIN: - DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Start game"); - DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Options"); - DrawTextWithShadow(font, data->selected==2 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.7, ALLEGRO_ALIGN_CENTRE, "About"); - DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Exit"); + case MENUSTATE_HIDDEN: + if (!data->invisible) { + DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Start game"); + DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Options"); + DrawTextWithShadow(font, data->selected==2 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.7, ALLEGRO_ALIGN_CENTRE, "About"); + DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Exit"); + } break; case MENUSTATE_OPTIONS: - DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Video settings"); - DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Audio settings"); - DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); + DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Video settings"); + DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Audio settings"); + DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); break; case MENUSTATE_AUDIO: if (game->config.music) snprintf(text, 255, "Music volume: %d0%%", game->config.music); else sprintf(text, "Music disabled"); - DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, text); + DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, text); if (game->config.fx) snprintf(text, 255, "Effects volume: %d0%%", game->config.fx); else sprintf(text, "Effects disabled"); - DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, text); - DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); + DrawTextWithShadow(font, data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, text); + DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); break; case MENUSTATE_ABOUT: + al_use_transform(&cur_trans); About(game, data); break; case MENUSTATE_VIDEO: @@ -102,77 +112,24 @@ void DrawMenuState(struct Game *game, struct MenuResources *data) { } else { sprintf(text, "Fullscreen: no"); - color = data->selected==1 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255); + color = data->selected==1 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255); } - DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, text); + DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, text); sprintf(text, "Resolution: %dx", data->options.resolution); DrawTextWithShadow(font, color, game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, text); - DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); - break; - case MENUSTATE_HIDDEN: - break; - case MENUSTATE_LOST: - DrawTextWithShadow(font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "You lost!"); - sprintf(text, "Score: %d", data->score); - DrawTextWithShadow(font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, text); - DrawTextWithShadow(font, al_map_rgb(255,255,128), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back to menu"); - break; - case MENUSTATE_INTRO: - DrawTextWithShadow(font, al_map_rgba(0,0,0,64), 46, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Evi"); - DrawTextWithShadow(font, al_map_rgba(0,0,0,64), 51, game->viewport.height*0.5-1, ALLEGRO_ALIGN_CENTRE, "vi"); - DrawTextWithShadow(font, al_map_rgb(255,255,128), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Evil record label representatives want"); - DrawTextWithShadow(font, al_map_rgba(0,0,0,64), 47, game->viewport.height*0.55, ALLEGRO_ALIGN_CENTRE, "tu"); - DrawTextWithShadow(font, al_map_rgba(0,0,0,64), 48, game->viewport.height*0.55 - 1, ALLEGRO_ALIGN_CENTRE, "tu"); - DrawTextWithShadow(font, al_map_rgb(255,255,128), game->viewport.width*0.5, game->viewport.height*0.55, ALLEGRO_ALIGN_CENTRE, "to turn your awesome single into radio edit."); - DrawTextWithShadow(font, al_map_rgb(255,255,128), game->viewport.width*0.5, game->viewport.height*0.6, ALLEGRO_ALIGN_CENTRE, "Thankfully, with your facemelting guitar"); - DrawTextWithShadow(font, al_map_rgb(255,255,128), game->viewport.width*0.5, game->viewport.height*0.65, ALLEGRO_ALIGN_CENTRE, "skills you don't have to give up so easily!"); - DrawTextWithShadow(font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Press ENTER to continue..."); + DrawTextWithShadow(font, data->selected==3 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.8, ALLEGRO_ALIGN_CENTRE, "Back"); break; default: data->selected=0; - DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(255,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Not implemented yet"); + DrawTextWithShadow(font, data->selected==0 ? al_map_rgb(128,255,128) : al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.5, ALLEGRO_ALIGN_CENTRE, "Not implemented yet"); break; } free(text); + + al_use_transform(&cur_trans); } -void AnimateBadguys(struct Game *game, struct MenuResources *data, int i) { - struct Badguy *tmp = data->badguys[i]; - while (tmp) { - AnimateCharacter(game, tmp->character, tmp->melting ? 1 : tmp->speed * data->badguySpeed); - tmp=tmp->next; - } -} -void MoveBadguys(struct Game *game, struct MenuResources *data, int i, float dx) { - struct Badguy *tmp = data->badguys[i]; - while (tmp) { - - if (!tmp->character->spritesheet->kill) { - MoveCharacter(game, tmp->character, dx * tmp->speed * data->badguySpeed, 0, 0); - } - - if (tmp->character->dead) { - if (tmp->prev) { - tmp->prev->next = tmp->next; - if (tmp->next) tmp->next->prev = tmp->prev; - } else { - data->badguys[i] = tmp->next; - if (tmp->next) tmp->next->prev = NULL; - } - struct Badguy *old = tmp; - tmp = tmp->next; - old->character->dead = true; - old->prev = NULL; - old->next = data->destroyQueue; - if (data->destroyQueue) data->destroyQueue->prev = old; - data->destroyQueue = old; - } else { - tmp = tmp->next; - } - - } -} void ChangeMenuState(struct Game *game, struct MenuResources* data, enum menustate_enum state) { data->menustate=state; @@ -180,327 +137,78 @@ void ChangeMenuState(struct Game *game, struct MenuResources* data, enum menusta PrintConsole(game, "menu state changed %d", state); } -void CheckForEnd(struct Game *game, struct MenuResources *data) { - int i; - bool lost = false; - for (i=0; i<4; i++) { - struct Badguy *tmp = data->badguys[i]; - while (tmp) { - if (tmp->character->x <= (139-(i*10))-10) { - lost = true; - break; - } - tmp=tmp->next; - } - if (lost) break; - } - - if (lost) { - - al_stop_sample_instance(data->solo); - data->soloactive=false; - data->soloanim=0; - data->soloflash=0; - data->soloready=0; - - al_stop_sample_instance(data->music); - al_play_sample_instance(data->end); - SelectSpritesheet(game, data->ego, "cry"); - ChangeMenuState(game, data, MENUSTATE_LOST); - } -} - -void DrawBadguys(struct Game *game, struct MenuResources *data, int i) { - struct Badguy *tmp = data->badguys[i]; - while (tmp) { - DrawCharacter(game, tmp->character, al_map_rgb(255,255,255), 0); - tmp=tmp->next; - } -} - void Gamestate_Draw(struct Game *game, struct MenuResources* data) { al_set_target_bitmap(al_get_backbuffer(game->display)); al_clear_to_color(al_map_rgb(3, 213, 255)); - al_draw_bitmap(data->bg,0, 0,0); - - al_draw_bitmap(data->cloud,game->viewport.width*data->cloud_position/100, 10 ,0); - - al_draw_bitmap(data->forest,0, 0,0); - - al_draw_bitmap(data->grass,0, 0,0); - - DrawCharacter(game, data->cow, al_map_rgb(255,255,255), 0); - - al_draw_bitmap(data->speaker,104, 19,0); - - al_draw_bitmap(data->stage,0, 0,0); - - al_draw_bitmap(data->lines, 100, 136,0); - - al_draw_bitmap(data->cable,0,151,0); - - DrawCharacter(game, data->ego, al_map_rgb(255,255,255), 0); - - if (data->menustate == MENUSTATE_HIDDEN) { - - if (!data->soloactive) { - if (data->marky == 0) { - al_draw_bitmap(data->marksmall, data->markx, 128, 0); - } else if (data->marky == 1) { - al_draw_bitmap(data->marksmall, data->markx, 140, 0); - } else if (data->marky == 2) { - al_draw_bitmap(data->markbig, data->markx, 152, 0); - } else if (data->marky == 3) { - al_draw_bitmap(data->markbig, data->markx, 166, 0); - } - } - - if (data->lightanim) { - int offset = -5; - if (data->lighty == 1) offset = -3; - if (data->lighty == 2) offset = 0; - if (data->lighty == 3) offset = 4; - al_draw_tinted_bitmap(data->light, al_map_rgba(255, 255, 255,rand() % 256 / 50 * 50) , data->lightx - 171 - (data->lighty < 2 ? 1 : 0), 109+(data->lighty*10) - 143 + offset, 0); - } - + al_draw_bitmap(data->bg, 0, 0, 0); + al_draw_bitmap(data->monster, data->monster_pos, 10, 0); + if (!data->starting) { + al_draw_bitmap(data->title, 123, 25 - (pow(sin(data->title_pos), 2) * 16) - data->screen_pos, 0); } - DrawBadguys(game, data, 0); - DrawBadguys(game, data, 1); - DrawBadguys(game, data, 2); - DrawBadguys(game, data, 3); - - if (data->menustate != MENUSTATE_HIDDEN) { - DrawTextWithShadow(data->font_title, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.15, ALLEGRO_ALIGN_CENTRE, data->menustate == MENUSTATE_LOST ? "Radio Edited!" : "Radio Edit"); - DrawMenuState(game, data); - } else { - char score[255]; - snprintf(score, 255, "Score: %d", data->score); - DrawTextWithShadow(data->font, al_map_rgb(255,255,255), 2, game->viewport.height - 10, ALLEGRO_ALIGN_LEFT, score); - - if ((data->soloready >= SOLO_MIN) && (data->soloanim <= 30)) { - DrawTextWithShadow(data->font, al_map_rgb(255,255,255), game->viewport.width*0.5, game->viewport.height*0.15, ALLEGRO_ALIGN_CENTRE, "Press ENTER to play a solo!"); - } - } - - if (data->soloflash) { - al_draw_filled_rectangle(0, 0, 320, 180, al_map_rgb(255,255,255)); - } + DrawMenuState(game, data); } -void AddBadguy(struct Game *game, struct MenuResources* data, int i) { - struct Badguy *n = malloc(sizeof(struct Badguy)); - n->next = NULL; - n->prev = NULL; - n->speed = (rand() % 3) * 0.25 + 1; - n->melting = false; - n->character = CreateCharacter(game, "badguy"); - n->character->spritesheets = data->badguy->spritesheets; - n->character->shared = true; - SelectSpritesheet(game, n->character, "walk"); - SetCharacterPosition(game, n->character, 320, 108+(i*13), 0); - - if (data->badguys[i]) { - struct Badguy *tmp = data->badguys[i]; - while (tmp->next) { - tmp=tmp->next; - } - tmp->next = n; - n->prev = tmp; - } else { - data->badguys[i] = n; - } -} - -void Fire(struct Game *game, struct MenuResources *data) { - - if (data->soloactive) return; - - data->lightx = data->markx; - data->lighty = data->marky; - data->lightanim=1; - data->usage=30; - - int num = rand() % 3; - if (((al_get_sample_instance_position(data->music) + 20000) / 44118) % 2 == 1) { - num += 3; - } - al_stop_sample_instance(data->chords[num]); - al_play_sample_instance(data->chords[num]); - PrintConsole(game, "playing chord nr %d", num); - - struct Badguy *tmp = data->badguys[data->marky]; - while (tmp) { - if (!tmp->melting) { - if ((data->markx >= tmp->character->x - 9) && (data->markx <= tmp->character->x + 1)) { - data->score += 100 * tmp->speed; - SelectSpritesheet(game, tmp->character, "melt"); - data->soloready++; - tmp->melting = true; - } - } - tmp=tmp->next; - } -} void Gamestate_Logic(struct Game *game, struct MenuResources* data) { - if (data->keys.lastkey == data->keys.key) { - data->keys.delay = data->keys.lastdelay; // workaround for random bugus UP/DOWN events - } + data->title_pos += 0.05; - data->cloud_position-=0.1; - if (data->cloud_position<-40) { data->cloud_position=100; PrintConsole(game, "cloud_position"); } - AnimateCharacter(game, data->ego, 1); - AnimateCharacter(game, data->cow, 1); + if (data->starting) { + data->monster_pos -= 6; + + if (data->monster_pos < -202) { + data->starting = false; + LoadGamestate(game, "info"); + LoadGamestate(game, "level"); + StartGamestate(game, "info"); + StopGamestate(game, "menu"); + } + + } else { + data->monster_pos += 6; + if (data->monster_pos > 0) { + data->monster_pos = 0; + } + } if (data->menustate == MENUSTATE_HIDDEN) { - - if ((data->keys.key) && (data->keys.delay < 3)) { - - if (data->keys.key==ALLEGRO_KEY_UP) { - data->marky--; - int min = 139-(data->marky*10); - int step = 10 - (data->markx - min) / ((320-min)/10); - data->markx+= step; - if (data->marky < 0) { - data->markx-=4*step; - data->marky = 3; - } - } - - if (data->keys.key==ALLEGRO_KEY_DOWN) { - data->marky++; - int min = 139-(data->marky*10); - int step = 10 - (data->markx - min) / ((320-min)/10); - data->markx-= step; - if (data->marky > 3) { - data->markx+=4*step; - data->marky = 0; - } - } - - if (data->keys.key==ALLEGRO_KEY_LEFT) { - int min = 139-(data->marky*10); - data->markx-= data->keys.shift ? 5 : 2; - if (data->markx < min) data->markx=min; - } - - if (data->keys.key==ALLEGRO_KEY_RIGHT) { - int max = 320 - al_get_bitmap_width(data->markbig); - if (data->marky < 2) max = 320 - al_get_bitmap_width(data->marksmall); - data->markx+= data->keys.shift ? 5 : 2; - if (data->markx > max) data->markx=max; - } - - if ((data->keys.key==ALLEGRO_KEY_SPACE) && (data->usage==0)) { - Fire(game, data); - } - - if (data->keys.delay == INT_MIN) data->keys.delay = 45; - else data->keys.delay += 4; - - } else if (data->keys.key) { - data->keys.delay-=3; + data->screen_pos -= (180 - data->screen_pos) / 4 + 1; + if (data->screen_pos < 0) { + data->screen_pos = 0; + data->invisible = false; } - - AnimateBadguys(game, data, 0); - AnimateBadguys(game, data, 1); - AnimateBadguys(game, data, 2); - AnimateBadguys(game, data, 3); - - MoveBadguys(game, data, 0, -0.17); - MoveBadguys(game, data, 1, -0.18); - MoveBadguys(game, data, 2, -0.19); - MoveBadguys(game, data, 3, -0.2); - - data->timeTillNextBadguy--; - if (data->timeTillNextBadguy <= 0) { - data->timeTillNextBadguy = data->badguyRate; - data->badguyRate -= data->badguyRate * 0.02; - if (data->badguyRate < 20) { - data->badguyRate = 20; - } - - data->badguySpeed+= 0.001; - AddBadguy(game, data, rand() % 4); - } - - if (data->usage) { data->usage--; } - if (data->lightanim) { data->lightanim++;} - if (data->lightanim > 25) { data->lightanim = 0; } - - CheckForEnd(game, data); - } - - data->soloanim++; - if (data->soloanim >= 60) data->soloanim=0; - - if (data->soloactive) { - if (al_get_sample_instance_position(data->solo) >= 163840) { - PrintConsole(game, "BLAAAST"); - data->soloflash = 6; - data->soloactive=false; - data->badguySpeed+=0.5; - data->badguyRate += 20; - - int i; - for (i=0; i<4; i++) { - struct Badguy *tmp = data->badguys[i]; - while (tmp) { - if ((!tmp->melting) && (!tmp->character->dead)) { - data->score += 100 * tmp->speed; - SelectSpritesheet(game, tmp->character, "melt"); - tmp->melting = true; - } - tmp=tmp->next; - } - } - + } else { + data->screen_pos += (data->screen_pos) / 4 + 1; + if (data->screen_pos > 180) { + data->screen_pos = 180; } } - if (data->soloflash) data->soloflash--; - - data->keys.lastkey = data->keys.key; - data->keys.lastdelay = data->keys.delay; - - TM_Process(data->timeline); } void* Gamestate_Load(struct Game *game, void (*progress)(struct Game*)) { struct MenuResources *data = malloc(sizeof(struct MenuResources)); - data->timeline = TM_Init(game, "main"); - (*progress)(game); - data->options.fullscreen = game->config.fullscreen; data->options.fps = game->config.fps; data->options.width = game->config.width; data->options.height = game->config.height; data->options.resolution = game->config.width / 320; if (game->config.height / 180 < data->options.resolution) data->options.resolution = game->config.height / 180; + (*progress)(game); data->bg = al_load_bitmap( GetDataFilePath(game, "bg.png") ); - data->forest = al_load_bitmap( GetDataFilePath(game, "forest.png") ); - data->grass = al_load_bitmap( GetDataFilePath(game, "grass.png") ); - data->speaker = al_load_bitmap( GetDataFilePath(game, "speaker.png") ); - data->stage = al_load_bitmap( GetDataFilePath(game, "stage.png") ); - data->cloud = al_load_bitmap( GetDataFilePath(game, "cloud.png") ); - data->lines = al_load_bitmap( GetDataFilePath(game, "lines.png") ); - data->cable = al_load_bitmap( GetDataFilePath(game, "cable.png") ); - data->marksmall = al_load_bitmap( GetDataFilePath(game, "mark-small.png") ); - data->markbig = al_load_bitmap( GetDataFilePath(game, "mark-big.png") ); - data->light = al_load_bitmap( GetDataFilePath(game, "light.png") ); - data->sample = al_load_sample( GetDataFilePath(game, "menu.flac") ); + data->monster = al_load_bitmap( GetDataFilePath(game, "monster.png") ); + data->title = al_load_bitmap( GetDataFilePath(game, "title.png") ); + (*progress)(game); + + data->sample = al_load_sample( GetDataFilePath(game, "monster.flac") ); data->click_sample = al_load_sample( GetDataFilePath(game, "click.flac") ); - data->quit_sample = al_load_sample( GetDataFilePath(game, "quit.flac") ); - data->end_sample = al_load_sample( GetDataFilePath(game, "end.flac") ); - data->solo_sample = al_load_sample( GetDataFilePath(game, "solo.flac") ); (*progress)(game); data->music = al_create_sample_instance(data->sample); @@ -511,277 +219,66 @@ void* Gamestate_Load(struct Game *game, void (*progress)(struct Game*)) { al_attach_sample_instance_to_mixer(data->click, game->audio.fx); al_set_sample_instance_playmode(data->click, ALLEGRO_PLAYMODE_ONCE); - data->quit = al_create_sample_instance(data->quit_sample); - al_attach_sample_instance_to_mixer(data->quit, game->audio.fx); - al_set_sample_instance_playmode(data->quit, ALLEGRO_PLAYMODE_ONCE); - - data->solo = al_create_sample_instance(data->solo_sample); - al_attach_sample_instance_to_mixer(data->solo, game->audio.fx); - al_set_sample_instance_playmode(data->solo, ALLEGRO_PLAYMODE_ONCE); - - data->end = al_create_sample_instance(data->end_sample); - al_attach_sample_instance_to_mixer(data->end, game->audio.fx); - al_set_sample_instance_playmode(data->end, ALLEGRO_PLAYMODE_ONCE); - - int i; - for (i=0; i<6; i++) { - char name[] = "chords/0.flac"; - name[7] = '1' + i; - data->chord_samples[i] = al_load_sample( GetDataFilePath(game, name) ); - - data->chords[i] = al_create_sample_instance(data->chord_samples[i]); - al_attach_sample_instance_to_mixer(data->chords[i], game->audio.fx); - al_set_sample_instance_playmode(data->chords[i], ALLEGRO_PLAYMODE_ONCE); - } - if (!data->click_sample){ fprintf(stderr, "Audio clip sample not loaded!\n" ); exit(-1); } (*progress)(game); - data->font_title = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"),game->viewport.height*0.16,0 ); data->font = al_load_ttf_font(GetDataFilePath(game, "fonts/MonkeyIsland.ttf"),game->viewport.height*0.05,0 ); - (*progress)(game); - - data->ego = CreateCharacter(game, "ego"); - RegisterSpritesheet(game, data->ego, "stand"); - RegisterSpritesheet(game, data->ego, "fix"); - RegisterSpritesheet(game, data->ego, "fix2"); - RegisterSpritesheet(game, data->ego, "fix3"); - RegisterSpritesheet(game, data->ego, "play"); - RegisterSpritesheet(game, data->ego, "cry"); - LoadSpritesheets(game, data->ego); - - data->cow = CreateCharacter(game, "cow"); - RegisterSpritesheet(game, data->cow, "stand"); - RegisterSpritesheet(game, data->cow, "chew"); - RegisterSpritesheet(game, data->cow, "look"); - LoadSpritesheets(game, data->cow); - - data->badguy = CreateCharacter(game, "badguy"); - RegisterSpritesheet(game, data->badguy, "walk"); - RegisterSpritesheet(game, data->badguy, "melt"); - LoadSpritesheets(game, data->badguy); - (*progress)(game); al_set_target_backbuffer(game->display); return data; } -void DestroyBadguys(struct Game *game, struct MenuResources* data, int i) { - struct Badguy *tmp = data->badguys[i]; - if (!tmp) { - tmp = data->destroyQueue; - data->destroyQueue = NULL; - } - while (tmp) { - DestroyCharacter(game, tmp->character); - struct Badguy *old = tmp; - tmp = tmp->next; - free(old); - if ((!tmp) && (data->destroyQueue)) { - tmp = data->destroyQueue; - data->destroyQueue = NULL; - } - } - data->badguys[i] = NULL; -} void Gamestate_Stop(struct Game *game, struct MenuResources* data) { - al_stop_sample_instance(data->music); - - int i; - for (i=0; i<4; i++) { - DestroyBadguys(game, data, i); - } + //al_stop_sample_instance(data->music); } void Gamestate_Unload(struct Game *game, struct MenuResources* data) { - if (game->config.fx) { - al_clear_to_color(al_map_rgb(0,0,0)); - DrawConsole(game); - al_flip_display(); - al_play_sample_instance(data->quit); - al_rest(0.3); - int i; - for (i=0;i<50; i++) { - al_rest(0.05); - ALLEGRO_KEYBOARD_STATE kb; - al_get_keyboard_state(&kb); - if (al_key_down(&kb, ALLEGRO_KEY_ESCAPE)) return; - } - } - + al_stop_sample_instance(data->music); al_destroy_bitmap(data->bg); - al_destroy_bitmap(data->cloud); - al_destroy_bitmap(data->grass); - al_destroy_bitmap(data->forest); - al_destroy_bitmap(data->stage); - al_destroy_bitmap(data->speaker); - al_destroy_bitmap(data->lines); - al_destroy_bitmap(data->cable); - al_destroy_bitmap(data->light); - al_destroy_bitmap(data->marksmall); - al_destroy_bitmap(data->markbig); - al_destroy_font(data->font_title); + al_destroy_bitmap(data->title); + al_destroy_bitmap(data->monster); al_destroy_font(data->font); - al_destroy_sample_instance(data->music); + //al_destroy_sample_instance(data->music); al_destroy_sample_instance(data->click); - al_destroy_sample_instance(data->end); - al_destroy_sample_instance(data->quit); - al_destroy_sample_instance(data->solo); - al_destroy_sample(data->sample); + //al_destroy_sample(data->sample); al_destroy_sample(data->click_sample); - al_destroy_sample(data->quit_sample); - al_destroy_sample(data->end_sample); - al_destroy_sample(data->solo_sample); - int i; - for (i=0; i<6; i++) { - al_destroy_sample_instance(data->chords[i]); - al_destroy_sample(data->chord_samples[i]); - } - DestroyCharacter(game, data->ego); - DestroyCharacter(game, data->cow); - DestroyCharacter(game, data->badguy); - TM_Destroy(data->timeline); } -// TODO: refactor to single Enqueue_Anim -bool Anim_CowLook(struct Game *game, struct TM_Action *action, enum TM_ActionState state) { - struct MenuResources *data = action->arguments->value; - if (state == TM_ACTIONSTATE_START) { - ChangeSpritesheet(game, data->cow, "look"); - TM_AddQueuedBackgroundAction(data->timeline, &Anim_CowLook, TM_AddToArgs(NULL, 1, data), 54*1000, "cow_look"); - } - return true; -} void StartGame(struct Game *game, struct MenuResources *data) { - TM_CleanQueue(data->timeline); - TM_CleanBackgroundQueue(data->timeline); - ChangeSpritesheet(game, data->ego, "play"); - ChangeSpritesheet(game, data->cow, "chew"); ChangeMenuState(game,data,MENUSTATE_HIDDEN); - al_play_sample_instance(data->chords[0]); -} - -bool Anim_FixGuitar(struct Game *game, struct TM_Action *action, enum TM_ActionState state) { - struct MenuResources *data = action->arguments->value; - if (state == TM_ACTIONSTATE_START) { - ChangeSpritesheet(game, data->ego, "fix"); - TM_AddQueuedBackgroundAction(data->timeline, &Anim_FixGuitar, TM_AddToArgs(NULL, 1, data), 30*1000, "fix_guitar"); - } - return true; + data->starting = true; } void Gamestate_Start(struct Game *game, struct MenuResources* data) { - data->cloud_position = 100; - SetCharacterPosition(game, data->ego, 22, 107, 0); - SetCharacterPosition(game, data->cow, 35, 88, 0); - data->score = 0; + data->title_pos = 0; + data->screen_pos = 180; + data->invisible = true; + data->monster_pos = -202; + data->starting = false; - data->markx = 119; - data->marky = 2; - - data->soloactive = false; - data->soloanim = 0; - data->soloflash = 0; - data->soloready = 0; - - data->keys.key = 0; - data->keys.delay = 0; - data->keys.shift = false; - data->keys.lastkey = -1; - - data->lightanim=0; - - data->badguySpeed = 1.2; - - data->usage = 0; - - SelectSpritesheet(game, data->ego, "stand"); - SelectSpritesheet(game, data->cow, "chew"); - ChangeMenuState(game,data,MENUSTATE_MAIN); - TM_AddQueuedBackgroundAction(data->timeline, &Anim_FixGuitar, TM_AddToArgs(NULL, 1, data), 15*1000, "fix_guitar"); - TM_AddQueuedBackgroundAction(data->timeline, &Anim_CowLook, TM_AddToArgs(NULL, 1, data), 5*1000, "cow_look"); + ChangeMenuState(game,data,MENUSTATE_HIDDEN); al_play_sample_instance(data->music); - al_rest(0.01); // poor man's synchronization - data->badguys[0] = NULL; - data->badguys[1] = NULL; - data->badguys[2] = NULL; - data->badguys[3] = NULL; - data->destroyQueue = NULL; - - data->badguyRate = 100; - data->timeTillNextBadguy = 0; } void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEGRO_EVENT *ev) { - TM_HandleEvent(data->timeline, ev); if ((data->menustate == MENUSTATE_ABOUT) && (ev->type == ALLEGRO_EVENT_KEY_DOWN)) { ChangeMenuState(game, data, MENUSTATE_MAIN); return; } - if (data->menustate == MENUSTATE_HIDDEN) { - - if (ev->type == ALLEGRO_EVENT_KEY_DOWN) { - - switch (ev->keyboard.keycode) { - case ALLEGRO_KEY_UP: - case ALLEGRO_KEY_DOWN: - case ALLEGRO_KEY_LEFT: - case ALLEGRO_KEY_RIGHT: - case ALLEGRO_KEY_SPACE: - if (data->keys.key != ev->keyboard.keycode) { - data->keys.key = ev->keyboard.keycode; - data->keys.delay = INT_MIN; - } - break; - case ALLEGRO_KEY_ESCAPE: - Gamestate_Stop(game, data); - Gamestate_Start(game, data); - break; - case ALLEGRO_KEY_LSHIFT: - case ALLEGRO_KEY_RSHIFT: - data->keys.shift = true; - break; - case ALLEGRO_KEY_ENTER: - if ((!data->soloactive) && (data->soloready >= SOLO_MIN)) { - data->soloready = 0; - al_play_sample_instance(data->solo); - data->soloactive = true; - data->badguySpeed-=0.5; - } - break; - default: - data->keys.key = 0; - break; - } - } else if (ev->type == ALLEGRO_EVENT_KEY_UP) { - switch (ev->keyboard.keycode) { - case ALLEGRO_KEY_LSHIFT: - case ALLEGRO_KEY_RSHIFT: - data->keys.shift = false; - break; - default: - if (ev->keyboard.keycode == data->keys.key) { - data->keys.key = 0; - } - break; - } - } - - return; - } - if (ev->type != ALLEGRO_EVENT_KEY_DOWN) return; + if (data->starting) return; + if (ev->keyboard.keycode==ALLEGRO_KEY_UP) { data->selected--; if ((data->selected == 2) && ((data->menustate==MENUSTATE_VIDEO) || (data->menustate==MENUSTATE_OPTIONS) || (data->menustate==MENUSTATE_AUDIO))) { @@ -807,7 +304,7 @@ void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEG case MENUSTATE_MAIN: switch (data->selected) { case 0: - ChangeMenuState(game,data,MENUSTATE_INTRO); + StartGame(game, data); break; case 1: ChangeMenuState(game,data,MENUSTATE_OPTIONS); @@ -820,6 +317,9 @@ void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEG break; } break; + case MENUSTATE_HIDDEN: + ChangeMenuState(game,data,MENUSTATE_MAIN); + break; case MENUSTATE_AUDIO: text = malloc(255*sizeof(char)); switch (data->selected) { @@ -921,13 +421,6 @@ void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEG break; case MENUSTATE_ABOUT: break; - case MENUSTATE_INTRO: - StartGame(game, data); - break; - case MENUSTATE_LOST: - Gamestate_Stop(game,data); - Gamestate_Start(game,data); - break; default: UnloadGamestate(game, "menu"); return; @@ -942,8 +435,7 @@ void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEG ChangeMenuState(game,data,MENUSTATE_MAIN); break; case MENUSTATE_HIDDEN: - Gamestate_Stop(game,data); - Gamestate_Start(game,data); + UnloadGamestate(game, "menu"); break; case MENUSTATE_VIDEO: ChangeMenuState(game,data,MENUSTATE_OPTIONS); @@ -951,15 +443,10 @@ void Gamestate_ProcessEvent(struct Game *game, struct MenuResources* data, ALLEG case MENUSTATE_AUDIO: ChangeMenuState(game,data,MENUSTATE_OPTIONS); break; - case MENUSTATE_INTRO: - ChangeMenuState(game,data,MENUSTATE_MAIN); - break; - case MENUSTATE_LOST: - Gamestate_Stop(game,data); - Gamestate_Start(game,data); - break; default: - UnloadGamestate(game, "menu"); + ChangeMenuState(game,data,MENUSTATE_HIDDEN); + data->selected = -1; + data->title_pos = 0; return; } } diff --git a/src/gamestates/menu.h b/src/gamestates/menu.h index 5e9663e..ed34aea 100644 --- a/src/gamestates/menu.h +++ b/src/gamestates/menu.h @@ -25,70 +25,30 @@ /*! \brief Enum of menu states in Menu and Pause game states. */ enum menustate_enum { + MENUSTATE_HIDDEN, MENUSTATE_MAIN, MENUSTATE_OPTIONS, MENUSTATE_VIDEO, MENUSTATE_AUDIO, - MENUSTATE_HIDDEN, - MENUSTATE_ABOUT, - MENUSTATE_LOST, - MENUSTATE_INTRO, - // FIXME: menustate abuse eeeeew + MENUSTATE_ABOUT }; /*! \brief Resources used by Menu state. */ struct MenuResources { - ALLEGRO_BITMAP *bg; /*!< Bitmap with lower portion of menu landscape. */ - ALLEGRO_BITMAP *cloud; /*!< Bitmap with bigger cloud. */ - ALLEGRO_BITMAP *grass; - ALLEGRO_BITMAP *forest; - ALLEGRO_BITMAP *stage; - ALLEGRO_BITMAP *speaker; - ALLEGRO_BITMAP *lines; - ALLEGRO_BITMAP *cable; - ALLEGRO_BITMAP *light; + ALLEGRO_BITMAP *bg; + ALLEGRO_BITMAP *monster; /*!< Bitmap with bigger cloud. */ + ALLEGRO_BITMAP *title; - ALLEGRO_BITMAP *marksmall; - ALLEGRO_BITMAP *markbig; - int markx, marky; + double title_pos; + int screen_pos; + bool invisible; + int monster_pos; + bool starting; - 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. */ ALLEGRO_SAMPLE *sample; /*!< Music sample. */ ALLEGRO_SAMPLE *click_sample; /*!< Click sound sample. */ - 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; /*!< Font of standard menu item. */ int selected; /*!< Number of selected menu item. */ enum menustate_enum menustate; /*!< Current menu page. */ @@ -100,14 +60,4 @@ struct MenuResources { int resolution; } options; /*!< Options which can be changed in menu. */ - struct { - int key; - bool shift; - int delay; - // workaround for random bogus UP/DOWN events - int lastkey; - int lastdelay; - } keys; - - int score; }; diff --git a/src/main.c b/src/main.c index d7c1f6a..3687331 100644 --- a/src/main.c +++ b/src/main.c @@ -78,7 +78,7 @@ int main(int argc, char **argv){ srand(time(NULL)); al_set_org_name("Super Derpy"); - al_set_app_name("Radio Edit"); + al_set_app_name("Tickle Monster"); if(!al_init()) { fprintf(stderr, "failed to initialize allegro!\n"); @@ -158,8 +158,8 @@ int main(int argc, char **argv){ PrintConsole(&game, "Viewport %dx%d", game.viewport.width, game.viewport.height); - ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/radioedit.png")); - al_set_window_title(game.display, "Radio Edit"); + ALLEGRO_BITMAP *icon = al_load_bitmap(GetDataFilePath(&game, "icons/ticklemonster.png")); + al_set_window_title(game.display, "Tickle Monster vs Suits"); al_set_display_icon(game.display, icon); al_destroy_bitmap(icon); @@ -233,7 +233,7 @@ int main(int argc, char **argv){ free(gamestate); char libname[1024] = {}; - snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENTION, "radioedit"); + snprintf(libname, 1024, "libsuperderpy-%s-loading" LIBRARY_EXTENTION, "ticklemonster"); void *handle = dlopen(libname, RTLD_NOW); if (!handle) { FatalError(&game, true, "Error while initializing loading screen %s", dlerror()); @@ -293,11 +293,11 @@ 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" LIBRARY_EXTENTION, "radioedit", tmp->name); + snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENTION, "ticklemonster", tmp->name); tmp->handle = dlopen(libname,RTLD_NOW); if (!tmp->handle) { //PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror()); - FatalError(&game, true, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror()); + FatalError(&game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror()); tmp->pending_load = false; tmp->pending_start = false; @@ -423,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, "RadioEdit_%ld_%ld.png", time(NULL), clock()); + snprintf(filename, 255, "TickleMonster_%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)); diff --git a/src/utils.c b/src/utils.c index 867a219..ec13bf0 100644 --- a/src/utils.c +++ b/src/utils.c @@ -237,7 +237,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)); - char *header = "RADIO EDIT"; + char *header = "TICKLE MONSTER"; 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)); @@ -271,7 +271,7 @@ void FatalError(struct Game *game, bool fatal, char* format, ...) { al_get_keyboard_state(&kb); int i; - for (i=0; i