From 1a6ed047eab084d41504e15a47ef0b52323fcefe Mon Sep 17 00:00:00 2001 From: mibi88 Date: Sat, 15 Jul 2023 11:43:24 +0200 Subject: [PATCH 01/12] Managing interactive dialogs. Nothing tested yet. --- src/dialogs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index bb2a3e1..a2b77ae 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -151,8 +151,57 @@ void showtext_dialog_end(Game *game, bopti_image_t *face, char *text) { showtext_opt(game, face, text, NULL, false, true); } -char **choices; +#define CHOICE_BOX_HEIGHT 10 +#define CHOICE_BOX_PADDING_TOP 3 -void _choice_call_before_end(void) { - // +char **choices; +int choices_amount, default_choice; + +int _choice_call_before_end(void) { + int i, key; + /* Make a little animation because we looove little animations ;) */ + for(i=0;iframe_duration < 20) sleep(); + game->frame_duration = 0; + } + const int choice_size = DWIDTH/choices_amount; + int arrow_width, selected = default_choice; + dsize(">", FONT_USED, &arrow_width, NULL); + do{ + /* Clear the box. */ + drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, (DWIDTH/8)*(DWIDTH/8), + (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); + for(i=0;i"); + dtext(i*choice_size+arrow_width, + BOX_HEIGHT+PXSIZE*CHOICE_BOX_PADDING_TOP, C_BLACK, + choices[i]); + } + blit(); + key = getkey().key; + if(key == KEY_LEFT && selected > 0) selected--; + else if(key == KEY_RIGHT && selected < choices_amount) selected++; + }while(key != KEY_EXE); + /* Make a little animation because we looove little animations ;) */ + for(i=DWIDTH/8+1;i>0;i++){ + drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), + (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); + drect(i*(DWIDTH/8), 0, i*(DWIDTH/8)+PXSIZE, + (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_BLACK); + drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), + (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); + blit(); + while(game->frame_duration < 20) sleep(); + game->frame_duration = 0; + } + return selected; } From f71121a79ee2760eb15720199c538ffa7f772392 Mon Sep 17 00:00:00 2001 From: mibi88 Date: Sat, 15 Jul 2023 19:26:32 +0200 Subject: [PATCH 02/12] Added interactive dialogs, but they are not working properly yet. --- src/config.h | 2 +- src/dialogs.c | 97 +++++++++++++++++++++++++++++---------------------- src/dialogs.h | 7 +++- src/main.c | 3 ++ 4 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/config.h b/src/config.h index 6afe302..c434419 100644 --- a/src/config.h +++ b/src/config.h @@ -6,6 +6,6 @@ #define GRAYMODEOK 1 #endif -#define USB_FEATURE 1 +#define USB_FEATURE 0 #endif diff --git a/src/dialogs.c b/src/dialogs.c index 392ef73..09dcd87 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -35,26 +35,29 @@ void blit() int showtext_opt(Game *game, bopti_image_t *face, char *text, - int call_before_end(void), bool start_anim, bool end_anim) { + int call_before_end(Game *game), bool start_anim, + bool end_anim) { dfont(&FONT_USED); unsigned int i, n, y = PXSIZE, l = 0; int line_max_chars, return_int = 0; unsigned int max_lines_amount = (BOX_HEIGHT-2)*PXSIZE/ (FONT_USED.line_height+PXSIZE); const char *c; - /* Run a little fancy animation. */ - for(i=0;iframe_duration < 20) sleep(); - game->frame_duration = 0; + while(game->frame_duration < 20) sleep(); + game->frame_duration = 0; + } } /* We should start to drawint the text on the x axis at BOX_HEIGHT to avoid * drawing on the face. */ @@ -86,7 +89,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, */ /* Make a little animation :). */ blit(); - while(game->frame_duration < 1000) sleep(); + while(game->frame_duration < 100) sleep(); game->frame_duration = 0; /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); @@ -103,7 +106,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, l = 0; } else{ - while(game->frame_duration < 1000) sleep(); + while(game->frame_duration < 100) sleep(); game->frame_duration = 0; } } @@ -111,26 +114,28 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* If we have not filled everthing with text at the end. */ /* Make a little animation :). */ blit(); - while(game->frame_duration < 1000) sleep(); + while(game->frame_duration < 100) sleep(); game->frame_duration = 0; /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); blit(); while(getkey().key != KEY_EXE) sleep(); } - if(call_before_end) return_int = call_before_end(); - /* Run another little fancy animation. */ - for(i=40;i>0;i--){ - draw(game); - drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); - drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); - dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, - DIMAGE_NONE); + if(call_before_end) return_int = call_before_end(game); + if(end_anim){ + /* Run another little fancy animation. */ + for(i=40;i>0;i--){ + draw(game); + drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); + drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); + dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, + DIMAGE_NONE); - dupdate(); + dupdate(); - while(game->frame_duration < 20) sleep(); - game->frame_duration = 0; + while(game->frame_duration < 20) sleep(); + game->frame_duration = 0; + } } return return_int; } @@ -154,16 +159,16 @@ void showtext_dialog_end(Game *game, bopti_image_t *face, char *text) { #define CHOICE_BOX_HEIGHT 10 #define CHOICE_BOX_PADDING_TOP 3 -char **choices; -int choices_amount, default_choice; +char *_choices; +int _choices_amount, _default_choice; -int _choice_call_before_end(void) { +int _choice_call_before_end(Game *game) { int i, key; /* Make a little animation because we looove little animations ;) */ for(i=0;iframe_duration < 20) sleep(); game->frame_duration = 0; } - const int choice_size = DWIDTH/choices_amount; - int arrow_width, selected = default_choice; - dsize(">", FONT_USED, &arrow_width, NULL); + const int choice_size = DWIDTH/_choices_amount; + int arrow_width, selected = _default_choice, pos = 0; + dsize(">", &FONT_USED, &arrow_width, NULL); do{ /* Clear the box. */ drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, (DWIDTH/8)*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); - for(i=0;i"); - dtext(i*choice_size+arrow_width, - BOX_HEIGHT+PXSIZE*CHOICE_BOX_PADDING_TOP, C_BLACK, - choices[i]); + pos += strlen(_choices); + dtext(i*choice_size+arrow_width+PXSIZE, + (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, C_BLACK, + &(_choices+pos)[i]); } blit(); key = getkey().key; if(key == KEY_LEFT && selected > 0) selected--; - else if(key == KEY_RIGHT && selected < choices_amount) selected++; + else if(key == KEY_RIGHT && selected < _choices_amount) selected++; }while(key != KEY_EXE); /* Make a little animation because we looove little animations ;) */ - for(i=DWIDTH/8+1;i>0;i++){ + for(i=DWIDTH/8+1;i>0;i--){ drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), 0, i*(DWIDTH/8)+PXSIZE, @@ -205,3 +211,12 @@ int _choice_call_before_end(void) { } return selected; } + +int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, + bool end, char *choices, int choices_amount, + int default_choice) { + _choices = choices; + _choices_amount = choices_amount; + _default_choice = default_choice; + return showtext_opt(game, face, text, _choice_call_before_end, start, end); +} diff --git a/src/dialogs.h b/src/dialogs.h index 62c9a6e..7e9e7e4 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -10,7 +10,8 @@ #define F_HEIGHT (32*PXSIZE) int showtext_opt(Game *game, bopti_image_t *face, char *text, - int call_before_end(void), bool start_anim, bool end_anim); + int call_before_end(Game *game), bool start_anim, + bool end_anim); void showtext(Game *game, bopti_image_t *face, char *text); @@ -20,4 +21,8 @@ void showtext_dialog_mid(Game *game, bopti_image_t *face, char *text); void showtext_dialog_end(Game *game, bopti_image_t *face, char *text); +int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, + bool end, char *choices, int choices_amount, + int default_choice); + #endif diff --git a/src/main.c b/src/main.c index 121a2ee..95397f2 100644 --- a/src/main.c +++ b/src/main.c @@ -100,6 +100,9 @@ int main(void) { #endif showtext(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet."); + int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0ipsum", 2, 0); + if(in) showtext_dialog_end(&game, &player_face_img, "You choosed ipsum"); + else showtext_dialog_end(&game, &player_face_img, "You choosed Lorem"); do{ /* clear screen */ dclear(C_WHITE); From acb859eaa89c02ee3ea9811bf00b2ec0a29b860b Mon Sep 17 00:00:00 2001 From: mibi88 Date: Tue, 18 Jul 2023 19:47:47 +0200 Subject: [PATCH 03/12] Already did some fixes, trying to improve animations. --- src/dialogs.c | 94 ++++++++++++++++++++++++++++++++++++++------------- src/game.c | 2 +- src/main.c | 20 +++++------ src/map.c | 3 -- 4 files changed, 81 insertions(+), 38 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index 09dcd87..1528344 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -2,6 +2,7 @@ #include #include +#include #include @@ -13,7 +14,7 @@ extern font_t fontRPG; #define FONT_USED fontRPG -#if GRAYMODEOK==1 +#if GRAYMODEOK #include uint32_t *lightVRAMnext, *darkVRAMnext; uint32_t *lightVRAMcurrent, *darkVRAMcurrent; @@ -24,7 +25,7 @@ void blit() { dupdate(); - #if GRAYMODEOK==1 + #if GRAYMODEOK dgray_getvram( &lightVRAMnext, &darkVRAMnext ); dgray_getscreen( &lightVRAMcurrent, &darkVRAMcurrent ); @@ -43,11 +44,10 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, unsigned int max_lines_amount = (BOX_HEIGHT-2)*PXSIZE/ (FONT_USED.line_height+PXSIZE); const char *c; + draw(game); if(start_anim){ /* Run a little fancy animation. */ for(i=0;iframe_duration < 20) sleep(); game->frame_duration = 0; } + }else{ + drect(0, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE, C_WHITE); + drect(0, (BOX_HEIGHT-1)*PXSIZE, DWIDTH, BOX_HEIGHT*PXSIZE, C_BLACK); + dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, + (BOX_HEIGHT-7)*PXSIZE, DIMAGE_NONE); + + dupdate(); } - /* We should start to drawint the text on the x axis at BOX_HEIGHT to avoid + /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid * drawing on the face. */ - /* Show a little message that showing text in dialogs is not implemented - * yet. */ for(i=0;i0; n--) { - /* If we found a space, we can draw this line and do the same for - * the next line. */ - if(text[i+n] == ' '){ - dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, - DTEXT_TOP, text+i, n); /* Draw everything. */ - /* Increment y by the line height. */ - y += FONT_USED.line_height+PXSIZE; - i += n; /* We drew everything to i+n */ - l++; /* We drew one more line. */ - break; + if(*(c+1) != '\0'){ + for(n=line_max_chars; n>0; n--) { + /* If we found a space, we can draw this line and do the same for + * the next line. */ + if(text[i+n] == ' '){ + dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, + DTEXT_TOP, text+i, n); /* Draw everything. */ + /* Increment y by the line height. */ + y += FONT_USED.line_height+PXSIZE; + i += n; /* We drew everything to i+n */ + l++; /* We drew one more line. */ + break; + } } + }else{ + dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, + DTEXT_TOP, text+i, line_max_chars); + y += FONT_USED.line_height+PXSIZE; + i += line_max_chars; + l++; } if(l>=max_lines_amount-1){ /* We drew one entire screen, reset everything to draw the next one. @@ -162,9 +175,35 @@ void showtext_dialog_end(Game *game, bopti_image_t *face, char *text) { char *_choices; int _choices_amount, _default_choice; +/* store_vram_part(int x1, int y1, int x2, int y2) and restore_vram_part(int x, + * int y) are needed in the animations of the interaction dialog. */ + +#ifdef FXCG50 + image_t vram_part; +#else + // Really need to code this! +#endif + +void store_vram_part(int x1, int y1, int x2, int y2) { + #ifdef FXCG50 + image_sub(image_create_vram(), x1, y1, x2-x1, y2-y1, &vram_part); + #else + // Really need to code this! + #endif +} +void restore_vram_part(int x, int y) { + #ifdef FXCG50 + dimage(x, y, &vram_part); + #else + // Really need to code this! + #endif +} + int _choice_call_before_end(Game *game) { int i, key; /* Make a little animation because we looove little animations ;) */ + store_vram_part(0, (BOX_HEIGHT+1)*PXSIZE, + DWIDTH, (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE); for(i=0;i", &FONT_USED, &arrow_width, NULL); do{ /* Clear the box. */ - drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, (DWIDTH/8)*(DWIDTH/8), - (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); + drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, DWIDTH, + (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE-1, C_WHITE); + /* Display the diffrent choices. */ for(i=0;i<_choices_amount;i++){ if(i == selected) dtext(i*choice_size+PXSIZE, (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, C_BLACK, ">"); - pos += strlen(_choices); dtext(i*choice_size+arrow_width+PXSIZE, (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, C_BLACK, - &(_choices+pos)[i]); + _choices+pos+i); + pos += strlen(_choices+pos); } blit(); key = getkey().key; @@ -199,9 +239,10 @@ int _choice_call_before_end(Game *game) { }while(key != KEY_EXE); /* Make a little animation because we looove little animations ;) */ for(i=DWIDTH/8+1;i>0;i--){ - drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), + restore_vram_part(0, BOX_HEIGHT*PXSIZE); + drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); - drect(i*(DWIDTH/8), 0, i*(DWIDTH/8)+PXSIZE, + drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_BLACK); drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); @@ -209,6 +250,11 @@ int _choice_call_before_end(Game *game) { while(game->frame_duration < 20) sleep(); game->frame_duration = 0; } + #ifdef FXCG50 + // + #else + // Really need to code this! + #endif return selected; } diff --git a/src/game.c b/src/game.c index eb9df60..74b8e32 100644 --- a/src/game.c +++ b/src/game.c @@ -40,7 +40,7 @@ void get_inputs(Game *game) { /* if USB is enabled - keybinding for screencapture */ -#if USB_FEATURE==1 +#if USB_FEATURE if(keydown(KEY_7)) game->screenshot = true; if(keydown(KEY_8)) game->record = !game->record; diff --git a/src/main.c b/src/main.c index 95397f2..5023ddb 100644 --- a/src/main.c +++ b/src/main.c @@ -12,7 +12,7 @@ #endif //USB_FEATURE -#if GRAYMODEOK==1 +#if GRAYMODEOK #include #endif //GRAYMODEOK @@ -35,14 +35,14 @@ Game game = { /* screen capture management code */ -#if USB_FEATURE==1 +#if USB_FEATURE void USB_feature( void ) { if (game.screenshot && usb_is_open()) { - #if GRAYMODEOK==1 // This is a trick, if GRAYMODEOK is defined then - // we make the code accessible + #if GRAYMODEOK // This is a trick, if GRAYMODEOK is defined then + // we make the code accessible if (dgray_enabled()) usb_fxlink_screenshot_gray(false); @@ -58,7 +58,7 @@ Game game = { if (game.record && usb_is_open()) { - #if GRAYMODEOK==1 + #if GRAYMODEOK if (dgray_enabled()) usb_fxlink_videocapture_gray(false); @@ -87,7 +87,7 @@ int main(void) { } timer_start(timer); - #if USB_FEATURE==1 + #if USB_FEATURE usb_interface_t const *interfaces[] = {&usb_ff_bulk, NULL}; usb_open(interfaces, GINT_CALL_NULL); #endif @@ -95,7 +95,7 @@ int main(void) { /* start grayscale engine */ - #if GRAYMODEOK==1 + #if GRAYMODEOK dgray(DGRAY_ON); #endif @@ -117,7 +117,7 @@ int main(void) { dupdate(); /* Screen capture feature if enabled */ - #if USB_FEATURE==1 + #if USB_FEATURE USB_feature(); #endif @@ -132,13 +132,13 @@ int main(void) { /* shutdown grayengine*/ - #if GRAYMODEOK==1 + #if GRAYMODEOK dgray(DGRAY_OFF); #endif /* close USB */ - #if USB_FEATURE==1 + #if USB_FEATURE usb_close(); #endif diff --git a/src/map.c b/src/map.c index 361e592..dbd0ea5 100644 --- a/src/map.c +++ b/src/map.c @@ -180,9 +180,6 @@ void render_map_by_layer(Player *player, Map *map_level, int layer) { } } - - - short int get_tile(Map *map_level, int x, int y, int l) { /* Get the tile at (x, y) on layer l. Returns the tile ID or MAP_OUTSIDE if * she's not found. */ From ea66f50f444c2009a05602c85a469e1d294c5969 Mon Sep 17 00:00:00 2001 From: mibi88 Date: Tue, 18 Jul 2023 21:08:12 +0200 Subject: [PATCH 04/12] Everything is now working, except the animation after choosing. --- assets-cg/font.png | Bin 15185 -> 1269 bytes assets-fx/font.png | Bin 15187 -> 956 bytes src/dialogs.c | 47 +++++++++++++++++++++++++++++++-------------- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/assets-cg/font.png b/assets-cg/font.png index 148bcb3e85d0c11452cee2744bc18602594e4ded..e661cc425bae1f6621dc548bd6b6137aa979a55d 100644 GIT binary patch delta 1250 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 S-0{CZI4H`h$<#_&g#UjxS|p7C diff --git a/src/dialogs.c b/src/dialogs.c index 1528344..90ed03d 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -2,7 +2,6 @@ #include #include -#include #include @@ -65,6 +64,9 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, (BOX_HEIGHT-7)*PXSIZE, DIMAGE_NONE); dupdate(); + + while(game->frame_duration < 20) sleep(); + game->frame_duration = 0; } /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid * drawing on the face. */ @@ -179,14 +181,17 @@ int _choices_amount, _default_choice; * int y) are needed in the animations of the interaction dialog. */ #ifdef FXCG50 + #include + image_t vram_part_reference; image_t vram_part; #else // Really need to code this! #endif -void store_vram_part(int x1, int y1, int x2, int y2) { +void store_vram_part(int x, int y, int w, int h) { #ifdef FXCG50 - image_sub(image_create_vram(), x1, y1, x2-x1, y2-y1, &vram_part); + image_sub(image_create_vram(), x, y, w, h, &vram_part_reference); + image_copy(&vram_part_reference, &vram_part, true); #else // Really need to code this! #endif @@ -203,25 +208,23 @@ int _choice_call_before_end(Game *game) { int i, key; /* Make a little animation because we looove little animations ;) */ store_vram_part(0, (BOX_HEIGHT+1)*PXSIZE, - DWIDTH, (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE); + DWIDTH, (CHOICE_BOX_HEIGHT+1)*PXSIZE); for(i=0;iframe_duration < 20) sleep(); game->frame_duration = 0; } const int choice_size = DWIDTH/_choices_amount; - int arrow_width, selected = _default_choice, pos = 0; - dsize(">", &FONT_USED, &arrow_width, NULL); + int arrow_width, arrow_height, selected = _default_choice, pos = 0; + dsize(">", &FONT_USED, &arrow_width, &arrow_height); + arrow_width += FONT_USED.char_spacing; do{ - /* Clear the box. */ - drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, DWIDTH, - (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE-1, C_WHITE); /* Display the diffrent choices. */ for(i=0;i<_choices_amount;i++){ if(i == selected) dtext(i*choice_size+PXSIZE, @@ -234,17 +237,33 @@ int _choice_call_before_end(Game *game) { } blit(); key = getkey().key; - if(key == KEY_LEFT && selected > 0) selected--; - else if(key == KEY_RIGHT && selected < _choices_amount) selected++; + if(key == KEY_LEFT && selected > 0){ + /* Remove the old arrow. */ + drect(selected*choice_size+PXSIZE, + (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, + selected*choice_size+PXSIZE+arrow_width, + (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, + C_WHITE); + selected--; + } + else if(key == KEY_RIGHT && selected < _choices_amount){ + /* Remove the old arrow. */ + drect(selected*choice_size+PXSIZE, + (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE, + selected*choice_size+PXSIZE+arrow_width, + (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, + C_WHITE); + selected++; + } }while(key != KEY_EXE); /* Make a little animation because we looove little animations ;) */ for(i=DWIDTH/8+1;i>0;i--){ - restore_vram_part(0, BOX_HEIGHT*PXSIZE); + restore_vram_part(0, (BOX_HEIGHT+1)*PXSIZE+40); drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_BLACK); - drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), + drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE+1, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); blit(); while(game->frame_duration < 20) sleep(); From 5c02111ac26fc8a459e9feec24b4f540d7d49c62 Mon Sep 17 00:00:00 2001 From: mibi88 Date: Wed, 19 Jul 2023 00:17:38 +0200 Subject: [PATCH 05/12] Still trying to fix my image_t problems ... --- src/dialogs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index 90ed03d..cb537fc 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -183,22 +183,26 @@ int _choices_amount, _default_choice; #ifdef FXCG50 #include image_t vram_part_reference; - image_t vram_part; + image_t *vram_part = NULL; #else // Really need to code this! #endif void store_vram_part(int x, int y, int w, int h) { #ifdef FXCG50 + if(image_valid(vram_part)) image_free(vram_part); image_sub(image_create_vram(), x, y, w, h, &vram_part_reference); - image_copy(&vram_part_reference, &vram_part, true); + vram_part = image_create(w, h, IMAGE_RGB565); + if(vram_part){ + image_copy(&vram_part_reference, vram_part, true); + } #else // Really need to code this! #endif } void restore_vram_part(int x, int y) { #ifdef FXCG50 - dimage(x, y, &vram_part); + dimage(x, y, vram_part); #else // Really need to code this! #endif @@ -258,7 +262,7 @@ int _choice_call_before_end(Game *game) { }while(key != KEY_EXE); /* Make a little animation because we looove little animations ;) */ for(i=DWIDTH/8+1;i>0;i--){ - restore_vram_part(0, (BOX_HEIGHT+1)*PXSIZE+40); + restore_vram_part(0, (BOX_HEIGHT+1)*PXSIZE); drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE, @@ -270,7 +274,7 @@ int _choice_call_before_end(Game *game) { game->frame_duration = 0; } #ifdef FXCG50 - // + if(image_valid(vram_part)) image_free(vram_part); #else // Really need to code this! #endif From afc2623ad0b9b33fbb82eb89999ac65646ff6531 Mon Sep 17 00:00:00 2001 From: mibi88 Date: Wed, 19 Jul 2023 16:57:40 +0200 Subject: [PATCH 06/12] Fixed a little bug, animation working on th CG50 (thanks Sly) --- src/dialogs.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index cb537fc..ca523ff 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -192,7 +192,7 @@ void store_vram_part(int x, int y, int w, int h) { #ifdef FXCG50 if(image_valid(vram_part)) image_free(vram_part); image_sub(image_create_vram(), x, y, w, h, &vram_part_reference); - vram_part = image_create(w, h, IMAGE_RGB565); + vram_part = image_alloc(w, h, IMAGE_RGB565); if(vram_part){ image_copy(&vram_part_reference, vram_part, true); } @@ -211,13 +211,13 @@ void restore_vram_part(int x, int y) { int _choice_call_before_end(Game *game) { int i, key; /* Make a little animation because we looove little animations ;) */ - store_vram_part(0, (BOX_HEIGHT+1)*PXSIZE, - DWIDTH, (CHOICE_BOX_HEIGHT+1)*PXSIZE); + store_vram_part(0, BOX_HEIGHT*PXSIZE, + DWIDTH, (CHOICE_BOX_HEIGHT+2)*PXSIZE); for(i=0;i0;i--){ - restore_vram_part(0, (BOX_HEIGHT+1)*PXSIZE); + restore_vram_part(0, BOX_HEIGHT*PXSIZE); drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); - drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE, - (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_BLACK); + drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, + (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE+1, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); blit(); @@ -274,7 +274,7 @@ int _choice_call_before_end(Game *game) { game->frame_duration = 0; } #ifdef FXCG50 - if(image_valid(vram_part)) image_free(vram_part); + if(vram_part) image_free(vram_part); #else // Really need to code this! #endif From aafa52f4aecc96a6b65c3a04191322dc093e89ff Mon Sep 17 00:00:00 2001 From: mibi88 Date: Wed, 19 Jul 2023 17:43:02 +0200 Subject: [PATCH 07/12] =?UTF-8?q?Changed=20showtext=5Fopt=20to=20redraw=20?= =?UTF-8?q?the=20screen=20on=20the=20animation=20at=20the=20end=20of=20an?= =?UTF-8?q?=20interaction,=20like=20Leph=C3=A9=20recommended=20it.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/dialogs.c | 107 +++++++++++++++++--------------------------------- src/dialogs.h | 16 ++++---- src/main.c | 6 +-- 3 files changed, 46 insertions(+), 83 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index ca523ff..0d98047 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -35,8 +35,11 @@ void blit() int showtext_opt(Game *game, bopti_image_t *face, char *text, - int call_before_end(Game *game), bool start_anim, - bool end_anim) { + int call_before_end(Game *game, unsigned int i), + bool start_anim, + bool end_anim, + void for_each_screen(Game *game, unsigned int i), + int line_duration, bool line_anim, unsigned int start_i) { dfont(&FONT_USED); unsigned int i, n, y = PXSIZE, l = 0; int line_max_chars, return_int = 0; @@ -52,8 +55,6 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, DIMAGE_NONE); - dupdate(); - while(game->frame_duration < 20) sleep(); game->frame_duration = 0; } @@ -63,14 +64,15 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (BOX_HEIGHT-7)*PXSIZE, DIMAGE_NONE); - dupdate(); + if(line_anim) dupdate(); while(game->frame_duration < 20) sleep(); game->frame_duration = 0; } /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid * drawing on the face. */ - for(i=0;i0; n--) { - /* If we found a space, we can draw this line and do the same for - * the next line. */ + /* If we found a space, we can draw this line and do the same + * for the next line. */ if(text[i+n] == ' '){ dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, DTEXT_TOP, text+i, n); /* Draw everything. */ @@ -103,14 +105,14 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* We drew one entire screen, reset everything to draw the next one. */ /* Make a little animation :). */ - blit(); - while(game->frame_duration < 100) sleep(); + if(line_anim) blit(); + while(game->frame_duration < line_duration) sleep(); game->frame_duration = 0; /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); } /* Make a little animation :). */ - blit(); + if(line_anim) blit(); if(l>=max_lines_amount-1){ while(getkey().key != KEY_EXE) sleep(); /* Clear the screen. */ @@ -121,22 +123,22 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, l = 0; } else{ - while(game->frame_duration < 100) sleep(); + while(game->frame_duration < line_duration) sleep(); game->frame_duration = 0; } } if(lframe_duration < 100) sleep(); + if(line_anim) blit(); + while(game->frame_duration < line_duration) sleep(); game->frame_duration = 0; /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); - blit(); + if(line_anim) blit(); while(getkey().key != KEY_EXE) sleep(); } - if(call_before_end) return_int = call_before_end(game); + if(call_before_end) return_int = call_before_end(game, i); if(end_anim){ /* Run another little fancy animation. */ for(i=40;i>0;i--){ @@ -155,64 +157,27 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, return return_int; } -void showtext(Game *game, bopti_image_t *face, char *text) { - showtext_opt(game, face, text, NULL, true, true); -} - -void showtext_dialog_start(Game *game, bopti_image_t *face, char *text) { - showtext_opt(game, face, text, NULL, true, false); -} - -void showtext_dialog_mid(Game *game, bopti_image_t *face, char *text) { - showtext_opt(game, face, text, NULL, false, false); -} - -void showtext_dialog_end(Game *game, bopti_image_t *face, char *text) { - showtext_opt(game, face, text, NULL, false, true); +void showtext_dialog(Game *game, bopti_image_t *face, char *text, + bool dialog_start, bool dialog_end) { + showtext_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, + true, 0); } #define CHOICE_BOX_HEIGHT 10 #define CHOICE_BOX_PADDING_TOP 3 -char *_choices; +char *_choices, *_text; int _choices_amount, _default_choice; +bopti_image_t *_face; +unsigned int _i; -/* store_vram_part(int x1, int y1, int x2, int y2) and restore_vram_part(int x, - * int y) are needed in the animations of the interaction dialog. */ - -#ifdef FXCG50 - #include - image_t vram_part_reference; - image_t *vram_part = NULL; -#else - // Really need to code this! -#endif - -void store_vram_part(int x, int y, int w, int h) { - #ifdef FXCG50 - if(image_valid(vram_part)) image_free(vram_part); - image_sub(image_create_vram(), x, y, w, h, &vram_part_reference); - vram_part = image_alloc(w, h, IMAGE_RGB565); - if(vram_part){ - image_copy(&vram_part_reference, vram_part, true); - } - #else - // Really need to code this! - #endif -} -void restore_vram_part(int x, int y) { - #ifdef FXCG50 - dimage(x, y, vram_part); - #else - // Really need to code this! - #endif +void _choice_screen_call(Game *game, unsigned int i) { + _i = i; } -int _choice_call_before_end(Game *game) { +int _choice_call_before_end(Game *game, unsigned int org_i) { int i, key; /* Make a little animation because we looove little animations ;) */ - store_vram_part(0, BOX_HEIGHT*PXSIZE, - DWIDTH, (CHOICE_BOX_HEIGHT+2)*PXSIZE); for(i=0;i0;i--){ - restore_vram_part(0, BOX_HEIGHT*PXSIZE); + draw(game); + showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, + _i); drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE+1, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); - blit(); + dupdate(); while(game->frame_duration < 20) sleep(); game->frame_duration = 0; } - #ifdef FXCG50 - if(vram_part) image_free(vram_part); - #else - // Really need to code this! - #endif return selected; } @@ -287,5 +249,8 @@ int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, _choices = choices; _choices_amount = choices_amount; _default_choice = default_choice; - return showtext_opt(game, face, text, _choice_call_before_end, start, end); + _face = face; + _text = text; + return showtext_opt(game, face, text, _choice_call_before_end, start, end, + _choice_screen_call, 100, true, 0); } diff --git a/src/dialogs.h b/src/dialogs.h index 7e9e7e4..099ef7f 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -10,16 +10,14 @@ #define F_HEIGHT (32*PXSIZE) int showtext_opt(Game *game, bopti_image_t *face, char *text, - int call_before_end(Game *game), bool start_anim, - bool end_anim); + int call_before_end(Game *game, unsigned int i), + bool start_anim, + bool end_anim, + void for_each_screen(Game *game, unsigned int i), + int line_duration, bool line_anim, unsigned int start_i); -void showtext(Game *game, bopti_image_t *face, char *text); - -void showtext_dialog_start(Game *game, bopti_image_t *face, char *text); - -void showtext_dialog_mid(Game *game, bopti_image_t *face, char *text); - -void showtext_dialog_end(Game *game, bopti_image_t *face, char *text); +void showtext_dialog(Game *game, bopti_image_t *face, char *text, + bool dialog_start, bool dialog_end); int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, bool end, char *choices, int choices_amount, diff --git a/src/main.c b/src/main.c index 5023ddb..ca1ac26 100644 --- a/src/main.c +++ b/src/main.c @@ -99,10 +99,10 @@ int main(void) { dgray(DGRAY_ON); #endif - showtext(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet."); + showtext(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0ipsum", 2, 0); - if(in) showtext_dialog_end(&game, &player_face_img, "You choosed ipsum"); - else showtext_dialog_end(&game, &player_face_img, "You choosed Lorem"); + if(in) showtext_dialog(&game, &player_face_img, "You choosed ipsum", false, true); + else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true); do{ /* clear screen */ dclear(C_WHITE); From 65ed14fc37d79e9d3b125991c3f1bf5226eace3e Mon Sep 17 00:00:00 2001 From: mibi88 Date: Wed, 19 Jul 2023 20:06:28 +0200 Subject: [PATCH 08/12] Everything is working now. --- assets-cg/font.png | Bin 1269 -> 1205 bytes assets-fx/font.png | Bin 956 -> 875 bytes src/dialogs.c | 35 +++++++++++++++++++++-------------- src/dialogs.h | 3 ++- src/main.c | 2 +- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/assets-cg/font.png b/assets-cg/font.png index e661cc425bae1f6621dc548bd6b6137aa979a55d..1b1622c91839afc5568547605878ec71630b0220 100644 GIT binary patch delta 1185 zcmZWnZB)`{9M!o-I@6Y7*)cukdeJP~)EP4*P4gv5qr{>YGer(kUjQDQ^ms?a%ty^X)mm``qXL?!885k@L;3fwF{{ zs6!=nI_4mHY=>(s^+?&qvXKuA+K*lm-UiK|x6xO`=_jG%hrfBr^JtmrS~?!1pdc%T zYyx~EEJjaR1NpE@J%bo&@we#zt+|`(q?}(B?IF!W`go##cewg?$L{rEt|{>=oIbhg zMZXvVgh1n+OCZy356IQG{1=5H%j!@e=URC*VW#NSR(VguB1Vc0F#1uh6Gj_u(mVAl zFD~a21w<(ldIn^5bMb%`%4#X#Y^{&yrc;`ROHdy62smHKf*d5C@Wokz2JoED!|5SnCui&?->V)cCD38 z2AFbmOW(tH(*ADrv=*+PEk!400r`fl)dP_@*S|m)B#x?c6va9Bes(5hzU;Mxd?G@j zgcql$)si|Ry#}|tx$vB4rCErB^EwWtU_KDYB2nk)okfV0$VqC|E+)ELO$}W-EP~Ds ztplW}%^v{LQ5b?~PfVSJZ&LgL>KLg{AP8jxPiUALqyRV&YE;$Zk(Df*_XDe#&5G}n zHKX;Su{fRi3YgW9BL*l`n5IK8@;B{M)XD=bI}rtNF$82Bb9;53#Zd;E_?BLF?{h5| z&w>+km8L`Btms>a91t$Bvl zb0M|M7q&-sgO6Cz8drK=QhMfd?88Ji>;zmFcy{^o^wVfHV6SbGUqee&PgUIUIg8xq zcn!}F+Xuh3^fTsY9=q;Q@%^ssB_|;Bi&q_yfp2`d_(%ZgP$@Ja zg_Ak!{)gl>mz0l+#?LnO)|GA`3nuWa%)6~xoq`#p+Q(Mos%`dg_)pk0jQ#6h!4~tt z7RO7UsgoG`3pkTkK2>|ISV}H?N)it+p2`Q}p55qedJhKckc{|=$7dnEx(_i3=D>;wUE9DgeTt&2b2cuPREKTNbbQL;+ zuEJ>L3U{=C94qax2IjBP4q*E#P&T;wyc75~bViz`seTPRve*@Fot|@MG>;lgq~vzn wOh)>w`9Q?J?K!eucaSAxo3HfkTDm<{zX)Zf%D5_T(g8dPvHN2L(I+qe2kcm77XSbN delta 1249 zcmV<71Rndf3H1q(B!9d~L_t(|ob8=kQrs{QMeP*(2&u3t*hv+oNATM#hv4 z9Md6$CYsfnI4FdM4ho^6gF9EP*yzo2<0O&kdU}bv1u}|8e>K_3dw^CJqXrx!Vr`@Q}LZ z!+p+8E#ROK8XOclvgM{eAH_i-G&m@9M9x7SD^kNS;Ghs3926Q;f9IZpgFd(A}fFz->VbnMpz zi+lXUmt+z#%i-SUF+5E`|E_VXlr{$kClPe0OHX@6(QThE#`wsU(b4ho^!nSqOS zet%PJ*>$(GX8OJ}NxFxnrnxBpek-o0++TP;R%)*PnjEF&{%q7C(VW|^l`h+^?t?7O zXN{)T_Wb$8K_N8mJ?iBsPd}G$!O=%jUrjA?M&4;!Ttutq@yvBt)hByLoJQ6>Gfj1* z^J$UZnDqaSgFPVdLHfn3u^6HU~)Y?ANDn}_YI4Fc><)Gd*5_`^{Mbo>U(F(iUrC8c-&*<^y z{=~^l?F|kJq1l;(=CR~;%UPqQBU(8!_oqjR>ddl{=2rj*h0wUOnY5f5OO~gWQ?ui& zj(0fa>Y3NH_?-QYTk7QVi7cdT**atA^i&)aLc>}-nxQpuPzcR`y+*rThL?1;00000 LNkvXXu0mjfM8J>J diff --git a/assets-fx/font.png b/assets-fx/font.png index f7b376a79039938d2b092cc6f9dbe53cf87d3705..b89f3dd94e100b29fc674be57556e5ba99dcd89e 100644 GIT binary patch delta 852 zcmV-a1FQVJ2kQoqB!4nVL_t(&f$dt+k|QAqgsXhz?)Pne(|d4+pg_wQFE?9dKWrsT ztB9yQY`FZ81%DT7EI+)NL*|2s=&OD3WFji9jcbRSIb!~yjiuNDU5p*j#n=H|j0e$i zzII^8wwYrl6WvaE{A%Wd?x#HN$t0@$f|(E6$f1Ukxe2Sq4u9x1sIdAm-2uG@$x#2| z+5ydDxY;WnbU)>BPiEcYJ>M{SSDV%{!)jAi3A#@r;_vfI&HR`teI7gIST>)@YTW_T z9laEi=C7me>vbdBK1(Tbt4NF#25w?gai1Ik4W?=!*N&6^1-4G@0Mwx;>g6PnMhHa{{hF0TfV>;b2E#jy%$_6T6Oba&4j!C$`tbh_-E5ZIU;E8r8$(NrIrfl4a6U zDUBxsrl!ef?Ot;9rpeRQIrVZY{@j};=78SSrnSuarhkMq%Gvnn+0_%4>8hDXc>s-a z{DrzFqh^RcRF`Vb(C%;nr)MM`@Kv)4nJeYr-QyTdKrhYQ)pz)+xrEwPq!~Nq6g8h7 zeHwj+x{hL>K9&x7f%U(lNkBG5``2P9acm&ET+8naye%etTaJ1uwPpQ^r+x<)I8491 zg4N8d?tii5OZqJEb0u?En-(+CZ<}1*^BUu<&E%PReFjw5F_}|KRYMh6)T$X*pGkAA zy1Ka!nR@ijPgER{YK>dk5o4aIjomTY8FinLheJf~;}U%Ut1;|X^5%Z|mm^ZbiKJ+z zdB*5I0tKY573eLqNb*`?jkw{UIAXnb^G-JzI)7^C12WN0>7BF%p67eO%?IT>>%EO~ z9m6g@He$D;K9i8<(Kd3k-lk5}Iq-Ae@{5_f+O(M2SDT9ZKbIB+R`<9}g7qF(dE_<9 zC8izyqt&K&#E@pn+~o6{(nmuE)rVtb)DA2eJ&7Zr(G3tuoVlyUg&UD*bf9MD^yYH( z8BN+fw!T`LP0tA=SAw~#Mh}?N{!9Z^nBX%Fk_@ ecd&2y#mv73O+k8c0iqB90000+ElXF$hSgC~hpacWN zgAk8#oEh%N&6!>T5cpbwPWclg(tDPT`7=#slequ@T=*B)1OS=0rDAY0Tg-1TF%&bQ zgE1327&D=Ru>frQYlWn=O=g>!0A5ac{MXC{UQcaM{}_kEbw~D<29MTe%}?oV5V7Z8p|}RO#qdN3;^kU z|4`(H%|x3iB>>omO=l)D?haG+o-<(goHJE3k9KY|=i-ss+|2Gzv~!qu+GxdTzIx`I zb5=%RGm}yhtAB;^(+1&@9y^v- zhez4htTtiMq-1q#(jX_US5W?9t}lBud0OL;gNW&7*uo`{+Ocv4-8?V;7?;_RN5bnuUwQHUHVfA1Xk z!4i7t$yI&lA2o+iOj(+-QchO)ZtvZwXQ&#eAJfyOLtJ3}t89WJo2>OK(Udqc5!GCa zuMB@#bbrJ)9OY1=dSb_wzJntare0q0)l9GMk>o@A%!qR&b5@%MGriw7m69ru0`>Xl z30b%Gew116xe%qoNSOd|`&b>DSl>OL-jKO{TuHt1k^zW?kF|KG-O)R%8SioWOzORg z)2!HIh`_H@!c$)b%`OL_LgS0HpibGxv+yYr9jARTLwp~AtS9v>rQ!%L_dy*lrB7tfy>jT54LBqz2e@XoS(`paos z!Aqzby);LC&>5=EW!^oM$L6eex?AH%2c8Ys2ctz|tKyue{9xv+HVtMjz}3uSeO$meYO1$dHtg&FAitbNWEhK&wTk@ z&@l#0-K)w=GOc|*0yRyRcU8DpYG#O-J&JmUR*>45{s>L>?Nc-Hj%+dpn0>)~1*UAG z%0o&{syyoC>Nix(X2p~_QWr9ED%~SdydRLjo|oBq$`5A#0dA@c`WGXekpKVy07*qo IM6N<$f^A3EAOHXW diff --git a/src/dialogs.c b/src/dialogs.c index 0d98047..090ecf1 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -8,7 +8,7 @@ #include "config.h" -#define BOX_HEIGHT (F_HEIGHT/PXSIZE+8) +#define BOX_HEIGHT (F_HEIGHT/PXSIZE+9) extern font_t fontRPG; #define FONT_USED fontRPG @@ -39,32 +39,37 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, bool start_anim, bool end_anim, void for_each_screen(Game *game, unsigned int i), - int line_duration, bool line_anim, unsigned int start_i) { + int line_duration, bool line_anim, unsigned int start_i, + bool wait_continue) { dfont(&FONT_USED); unsigned int i, n, y = PXSIZE, l = 0; int line_max_chars, return_int = 0; unsigned int max_lines_amount = (BOX_HEIGHT-2)*PXSIZE/ (FONT_USED.line_height+PXSIZE); const char *c; - draw(game); if(start_anim){ /* Run a little fancy animation. */ for(i=0;iframe_duration < 20) sleep(); game->frame_duration = 0; } }else{ + draw(game); drect(0, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE, C_WHITE); drect(0, (BOX_HEIGHT-1)*PXSIZE, DWIDTH, BOX_HEIGHT*PXSIZE, C_BLACK); dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (BOX_HEIGHT-7)*PXSIZE, DIMAGE_NONE); - if(line_anim) dupdate(); + if(line_anim) blit(); while(game->frame_duration < 20) sleep(); game->frame_duration = 0; @@ -72,15 +77,16 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid * drawing on the face. */ for(i=start_i;i0; n--) { /* If we found a space, we can draw this line and do the same * for the next line. */ @@ -95,6 +101,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, } } }else{ + /* If it is the last line of the text. */ dtext_opt(BOX_HEIGHT*PXSIZE, y, C_BLACK, C_NONE, DTEXT_LEFT, DTEXT_TOP, text+i, line_max_chars); y += FONT_USED.line_height+PXSIZE; @@ -114,9 +121,9 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* Make a little animation :). */ if(line_anim) blit(); if(l>=max_lines_amount-1){ - while(getkey().key != KEY_EXE) sleep(); - /* Clear the screen. */ - drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-1, + if(wait_continue) while(getkey().key != KEY_EXE) sleep(); + /* Clear the text area. */ + drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2, C_WHITE); /* Reset y and l. */ y = PXSIZE; @@ -136,7 +143,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); if(line_anim) blit(); - while(getkey().key != KEY_EXE) sleep(); + if(wait_continue) while(getkey().key != KEY_EXE) sleep(); } if(call_before_end) return_int = call_before_end(game, i); if(end_anim){ @@ -160,7 +167,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, void showtext_dialog(Game *game, bopti_image_t *face, char *text, bool dialog_start, bool dialog_end) { showtext_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, - true, 0); + true, 0, true); } #define CHOICE_BOX_HEIGHT 10 @@ -229,7 +236,7 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { for(i=DWIDTH/8+1;i>0;i--){ draw(game); showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, - _i); + _i, false); drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, @@ -252,5 +259,5 @@ int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, _face = face; _text = text; return showtext_opt(game, face, text, _choice_call_before_end, start, end, - _choice_screen_call, 100, true, 0); + _choice_screen_call, 100, true, 0, true); } diff --git a/src/dialogs.h b/src/dialogs.h index 099ef7f..1f0199f 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -14,7 +14,8 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, bool start_anim, bool end_anim, void for_each_screen(Game *game, unsigned int i), - int line_duration, bool line_anim, unsigned int start_i); + int line_duration, bool line_anim, unsigned int start_i, + bool wait_continue); void showtext_dialog(Game *game, bopti_image_t *face, char *text, bool dialog_start, bool dialog_end); diff --git a/src/main.c b/src/main.c index ca1ac26..cc72975 100644 --- a/src/main.c +++ b/src/main.c @@ -99,7 +99,7 @@ int main(void) { dgray(DGRAY_ON); #endif - showtext(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); + showtext_dialog(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, true); int in = showtext_dialog_ask(&game, &player_face_img, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet.", true, false, "Lorem\0ipsum", 2, 0); if(in) showtext_dialog(&game, &player_face_img, "You choosed ipsum", false, true); else showtext_dialog(&game, &player_face_img, "You choosed Lorem", false, true); From c82a9fc5dacd03534a158d48170d0e04ffd9764f Mon Sep 17 00:00:00 2001 From: mibi88 Date: Wed, 19 Jul 2023 20:53:14 +0200 Subject: [PATCH 09/12] Fixed some graphical issues, only one is still there on mono --- src/dialogs.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index 090ecf1..27f4620 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -8,7 +8,7 @@ #include "config.h" -#define BOX_HEIGHT (F_HEIGHT/PXSIZE+9) +#define BOX_HEIGHT (F_HEIGHT/PXSIZE+8) extern font_t fontRPG; #define FONT_USED fontRPG @@ -49,7 +49,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, const char *c; if(start_anim){ /* Run a little fancy animation. */ - for(i=0;i0;i--){ + for(i=BOX_HEIGHT;i>0;i--){ draw(game); drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); @@ -186,11 +185,11 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { int i, key; /* Make a little animation because we looove little animations ;) */ for(i=0;iframe_duration < 20) sleep(); @@ -237,11 +236,11 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { draw(game); showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, _i, false); - drect(0, BOX_HEIGHT*PXSIZE, i*(DWIDTH/8), + drect(0, (BOX_HEIGHT+1)*PXSIZE+1, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, C_WHITE); drect(i*(DWIDTH/8), BOX_HEIGHT*PXSIZE, i*(DWIDTH/8)+PXSIZE-1, (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); - drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE+1, i*(DWIDTH/8), + drect(0, (BOX_HEIGHT+CHOICE_BOX_HEIGHT)*PXSIZE, i*(DWIDTH/8), (BOX_HEIGHT+CHOICE_BOX_HEIGHT+1)*PXSIZE, C_BLACK); dupdate(); while(game->frame_duration < 20) sleep(); From d1e32de9c5f540f9b1b820f81906dad0d487c129 Mon Sep 17 00:00:00 2001 From: mibi88 Date: Wed, 19 Jul 2023 23:11:00 +0200 Subject: [PATCH 10/12] Started adding comments. Still have this weird bug on the mono calculator --- src/dialogs.c | 31 +++++++++++++++++++++++-------- src/dialogs.h | 2 +- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/dialogs.c b/src/dialogs.c index 27f4620..34c8bc0 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -39,7 +39,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, bool start_anim, bool end_anim, void for_each_screen(Game *game, unsigned int i), - int line_duration, bool line_anim, unsigned int start_i, + int line_duration, bool update_screen, unsigned int start_i, bool wait_continue) { dfont(&FONT_USED); unsigned int i, n, y = PXSIZE, l = 0; @@ -50,10 +50,17 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, if(start_anim){ /* Run a little fancy animation. */ for(i=0;i<=BOX_HEIGHT;i++){ + /* Redrawing the entire screen, because maybe there was no dialog + displayed before. */ draw(game); + /* Fill the dialog box with white */ drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); + /* Draw a thick black line on the bottom of the dialog. */ drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); + + /* Draw the part of the face of the player that can fit correctly in + * the dialog drawn. */ dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, DIMAGE_NONE); @@ -63,15 +70,19 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, game->frame_duration = 0; } }else{ + /* Here I'm drawing the same as if start_anim is true, but whitout + * making an animation. */ draw(game); drect(0, 0, DWIDTH, BOX_HEIGHT*PXSIZE, C_WHITE); drect(0, BOX_HEIGHT*PXSIZE, DWIDTH, (BOX_HEIGHT+1)*PXSIZE, C_BLACK); dimage(4*PXSIZE, 2*PXSIZE, face); - if(line_anim) blit(); + if(update_screen){ + blit(); - while(game->frame_duration < 20) sleep(); - game->frame_duration = 0; + while(game->frame_duration < 20) sleep(); + game->frame_duration = 0; + } } /* We should start to drawing the text on the x axis at BOX_HEIGHT to avoid * drawing on the face. */ @@ -111,15 +122,17 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, /* We drew one entire screen, reset everything to draw the next one. */ /* Make a little animation :). */ - if(line_anim) blit(); + if(update_screen) blit(); while(game->frame_duration < line_duration) sleep(); game->frame_duration = 0; /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); } /* Make a little animation :). */ - if(line_anim) blit(); + if(update_screen) blit(); if(l>=max_lines_amount-1){ + /* If we drew one entire screen. */ + /* Wait that the EXE key is pressed if we should. */ if(wait_continue) while(getkey().key != KEY_EXE) sleep(); /* Clear the text area. */ drect(BOX_HEIGHT*PXSIZE, 0, DWIDTH, (BOX_HEIGHT-1)*PXSIZE-2, @@ -129,6 +142,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, l = 0; } else{ + /* Else, wait a bit for the animation. */ while(game->frame_duration < line_duration) sleep(); game->frame_duration = 0; } @@ -136,12 +150,13 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, if(lframe_duration < line_duration) sleep(); game->frame_duration = 0; /* Ask the user to press EXE to continue. */ dtext(BOX_HEIGHT*PXSIZE, y, C_BLACK, "[EXE] to continue ..."); - if(line_anim) blit(); + /* Update the screen and wait for EXE being pressed, if needed. */ + if(update_screen) blit(); if(wait_continue) while(getkey().key != KEY_EXE) sleep(); } if(call_before_end) return_int = call_before_end(game, i); diff --git a/src/dialogs.h b/src/dialogs.h index 1f0199f..4c6ad99 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -14,7 +14,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, bool start_anim, bool end_anim, void for_each_screen(Game *game, unsigned int i), - int line_duration, bool line_anim, unsigned int start_i, + int line_duration, bool update_screen, unsigned int start_i, bool wait_continue); void showtext_dialog(Game *game, bopti_image_t *face, char *text, From 6acb9ab93bc458823abe5f1a5b10ea72be54aafd Mon Sep 17 00:00:00 2001 From: mibi88 Date: Thu, 20 Jul 2023 11:27:19 +0200 Subject: [PATCH 11/12] Fixed the last graphical issue. --- src/dialogs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialogs.c b/src/dialogs.c index 34c8bc0..19881c4 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -64,7 +64,7 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, dsubimage(4*PXSIZE, 2*PXSIZE, face, 0, 0, F_WIDTH, (i-8)*PXSIZE, DIMAGE_NONE); - dupdate(); + blit(); while(game->frame_duration < 20) sleep(); game->frame_duration = 0; From ea9244ca616ea166250814ea1dcf0d477aaaa680 Mon Sep 17 00:00:00 2001 From: mibi88 Date: Thu, 20 Jul 2023 13:11:36 +0200 Subject: [PATCH 12/12] Finished adding comments to the dialogs code. --- src/dialogs.c | 44 +++++++++++++++++++++++++++++++++- src/dialogs.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/dialogs.c b/src/dialogs.c index 19881c4..e6c313e 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -161,8 +161,9 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, } if(call_before_end) return_int = call_before_end(game, i); if(end_anim){ - /* Run another little fancy animation. */ + /* Run another little fancy animation if we should. */ for(i=BOX_HEIGHT;i>0;i--){ + /* It is the same as the start animation. */ draw(game); drect(0, 0, DWIDTH, i*PXSIZE, C_WHITE); drect(0, i*PXSIZE, DWIDTH, (i+1)*PXSIZE, C_BLACK); @@ -180,6 +181,8 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, void showtext_dialog(Game *game, bopti_image_t *face, char *text, bool dialog_start, bool dialog_end) { + /* Run showtext_opt with some default values. It makes it easier to use in + * simple dialogs. */ showtext_opt(game, face, text, NULL, dialog_start, dialog_end, NULL, 100, true, 0, true); } @@ -187,11 +190,15 @@ void showtext_dialog(Game *game, bopti_image_t *face, char *text, #define CHOICE_BOX_HEIGHT 10 #define CHOICE_BOX_PADDING_TOP 3 +/* Some variables and pointers used to get some arguments passed in + * showtext_dialog_ask in _choice_call_before_end. */ char *_choices, *_text; int _choices_amount, _default_choice; bopti_image_t *_face; unsigned int _i; +/* Get where I started drawing a dialog page, to be able to redraw the last page + * for the end animation in _choice_call_before_end. */ void _choice_screen_call(Game *game, unsigned int i) { _i = i; } @@ -200,19 +207,37 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { int i, key; /* Make a little animation because we looove little animations ;) */ for(i=0;iframe_duration < 20) sleep(); game->frame_duration = 0; } + /* Calculate the maximal size of a choice. */ const int choice_size = DWIDTH/_choices_amount; + /* arrow_width: The space taken by the arrow that shows the selected item. + * arrow_height: The height of the arrow used to show which item is choosen. + * Used to calculate the size of the rectangle used to remove + * him. + * selected: The selected item. + * pos: The position of the item we're drawing in the choice + * string. The choice string is not really a string, it is + * made of multiple '\0' terminated strings, that are in + * memory one after the other. + */ int arrow_width, arrow_height, selected = _default_choice, pos = 0; + /* Calculate the size of the arrow. */ dsize(">", &FONT_USED, &arrow_width, &arrow_height); + /* Add the character spacing of the font to it. */ arrow_width += FONT_USED.char_spacing; do{ /* Display the diffrent choices. */ @@ -227,6 +252,8 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { } blit(); key = getkey().key; + /* If the player pressed the left arrow key and has not already selected + * the first possible choice. */ if(key == KEY_LEFT && selected > 0){ /* Remove the old arrow. */ drect(selected*choice_size+PXSIZE, @@ -234,8 +261,12 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { selected*choice_size+PXSIZE+arrow_width, (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, C_WHITE); + + /* Move the selection arrow and update the selected item. */ selected--; } + /* If the player pressed the right arrow key and has not already + * selected the last possible choice. */ else if(key == KEY_RIGHT && selected < _choices_amount-1){ /* Remove the old arrow. */ drect(selected*choice_size+PXSIZE, @@ -243,11 +274,16 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { selected*choice_size+PXSIZE+arrow_width, (BOX_HEIGHT+CHOICE_BOX_PADDING_TOP)*PXSIZE+arrow_height, C_WHITE); + + /* Move the selection arrow and update the selected item. */ selected++; } + /* If the user has not validated his choice by pressing EXE, we loop one + * more time. */ }while(key != KEY_EXE); /* Make a little animation because we looove little animations ;) */ for(i=DWIDTH/8+1;i>0;i--){ + /* I'm drawing the same box as on the start animation */ draw(game); showtext_opt(game, _face, _text, NULL, false, false, NULL, 0, false, _i, false); @@ -261,17 +297,23 @@ int _choice_call_before_end(Game *game, unsigned int org_i) { while(game->frame_duration < 20) sleep(); game->frame_duration = 0; } + /* Return the selected item because he'll also be returned by showtext_opt. + */ return selected; } int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, bool end, char *choices, int choices_amount, int default_choice) { + /* Put some arguments in global pointers and variables to make them + * accessible by _choice_call_before_end. */ _choices = choices; _choices_amount = choices_amount; _default_choice = default_choice; _face = face; _text = text; + /* Run showtext_opt and return his return value (the return value of + *_choice_call_before_end) */ return showtext_opt(game, face, text, _choice_call_before_end, start, end, _choice_screen_call, 100, true, 0, true); } diff --git a/src/dialogs.h b/src/dialogs.h index 4c6ad99..ccff4be 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -9,6 +9,34 @@ #define F_WIDTH (32*PXSIZE) #define F_HEIGHT (32*PXSIZE) +/* showtext_opt() + * + * Show some text in a box with word wrap for dialogs. + * + * game: The game struct of the current game. + * face: A bopti_image_t of the face of the person who's saying this + * text. This bopti_image_t should have a width of F_WIDTH and + * a height of F_HEIGHT. + * text: The text to display. + * call_before_end: A function called when the end of the text was displayed and + * the user pressed EXE (or wait_continue was true). His + * parameter game is the game struct passed to showtext_opt, + * and i is the current position in text. + * start_anim: A boolean, that, if he's true, makes that a little animation + * is shown at the start of showtext_opt. + * end_anim: A boolean, that, if he's true, makes that a little animation + * is shown at the end of showtext_opt. + * for_each_screen: A function called before a page of the dialog gets drawn. + * His parameter game is the game struct passed to + * showtext_opt, and i is the current position in text. + * line_duration: How many ms showtext_opt will wait after a line has been + * drawn. + * update_screen: When he's true showtext_opt will update the screen after + * drawing a line etc. + * start_i: At which position I start displaying the text. + * wait_continue: If I should wait that EXE is pressed after drawing a page. + */ + int showtext_opt(Game *game, bopti_image_t *face, char *text, int call_before_end(Game *game, unsigned int i), bool start_anim, @@ -17,9 +45,46 @@ int showtext_opt(Game *game, bopti_image_t *face, char *text, int line_duration, bool update_screen, unsigned int start_i, bool wait_continue); +/* showtext_dialog() + * + * Calls showtext_opt with default parameters. + * + * game: The game struct of the current game. + * face: A bopti_image_t of the face of the person who's saying this + * text. This bopti_image_t should have a width of F_WIDTH and a + * height of F_HEIGHT. + * text: The text to display. + * dialog_start: A boolean, that, if he's true, makes that a little animation is + * shown at the start of showtext_opt. + * dialog_end: A boolean, that, if he's true, makes that a little animation is + * shown at the end of showtext_opt. + */ + void showtext_dialog(Game *game, bopti_image_t *face, char *text, bool dialog_start, bool dialog_end); +/* showtext_dialog_ask() + * + * Like showtext_dialog, but lets the user choose between multiple possible + * choices after displaying the text. + * + * game: The game struct of the current game. + * face: A bopti_image_t of the face of the person who's saying this + * text. This bopti_image_t should have a width of F_WIDTH and a + * height of F_HEIGHT. + * text: The text to display. + * start: A boolean, that, if he's true, makes that a little animation + * is shown at the start of showtext_opt. + * end: A boolean, that, if he's true, makes that a little animation + * is shown at the end of showtext_opt. + * choices: A pointer to null-terminated strings that are one after the + * other in memory. They should be one null-terminated string + * for each possible choice. + * choice_amount: The amount of possible choices in the choices zero-terminated + * strings. + * default_choice: The choice choosen by default when the dialog just opened. + */ + int showtext_dialog_ask(Game *game, bopti_image_t *face, char *text, bool start, bool end, char *choices, int choices_amount, int default_choice);