#include "dialog.h" // Debug purposes int _strlen(const char *str) { int i = 0; while (str[i++]); return i; } void dialog(dialog_t *dialog) { // Init profiler prof_t prof_fps = prof_make(); uint32_t time = 0; uint32_t us_elapsed = 1; // Init key event key_event_t e; // Init characters metadata (who's talking, etc.) int talking = 0; // Init dialog characters pictures img_t char_flipped = img_hflip_create(*(dialog->characters[1])); img_t chars_img[2][2] = { { img_copy(*(dialog->characters[0])), img_darken_create(*(dialog->characters[0])) }, { char_flipped, img_darken_create(char_flipped)} }; // Init text properties int current_replica = 0; float current_chars = 0, text_speed = 0.000012; // Chars per us char wait_change = 0; // Entering main loop prof_enter(prof_fps); while(dialog->text[current_replica]) { // Get last keyboard event clearevents(); // Manage events if(keydown(KEY_EXIT)) break; if(keydown(KEY_SHIFT) && wait_change == 1) { // Reset current chars current_chars = 0; // Waiting for key up wait_change = 2; } if(!keydown(KEY_SHIFT) && wait_change == 2) { // Change who's speaking talking = !talking; // Update current replica current_replica++; // We're not waiting anymore wait_change = 0; } // Manage states if(keydown(KEY_SHIFT)) { text_speed = 0.000028; } else { text_speed = 0.000012; } // Move text if(!wait_change) current_chars += us_elapsed * text_speed; if(current_chars > _strlen(dialog->text[current_replica])) { current_chars = _strlen(dialog->text[current_replica]); // This may be dirty (mixing engine and inputs) but who cares? if(!keydown(KEY_SHIFT)) wait_change = 1; } // Clear vram before drawing dclear(C_BLACK); // Display everything img_render_vram(chars_img[0][talking], DWIDTH * 0.15, DHEIGHT * (0.15 + 0.04 * fcos(time * 0.000005))); img_render_vram(chars_img[1][!talking], DWIDTH * 0.85 - chars_img[1][0].width, DHEIGHT * (0.15 + 0.04 * fsin(time * 0.000005))); display_text(dialog->text[current_replica], (int)current_chars); dprint_opt(DWIDTH-1, DHEIGHT-1, C_WHITE, C_NONE, DTEXT_RIGHT, DTEXT_BOTTOM, "%i FPS", 1000000 / us_elapsed); // Update VRAM dupdate(); // Get elapsed time, reset profiler and start it again prof_leave(prof_fps); us_elapsed = prof_time(prof_fps); prof_fps.elapsed = 0; prof_enter(prof_fps); // Update global time time += us_elapsed; } /* Destroy temporary images */ for(int i = 0; i < 2; i++) img_destroy(chars_img[i][i]); } // TODO: optimize this naive algorithm. Soft breaks are not implemented void display_text(const char *src, int chars) { // If no chars, nothing to do here if(chars == 0) return; // Init font const font_t *current_font = dfont(NULL); // Init dialog text buffers static char lines[4][50]; // TODO: do not hardcode these sizes // Init width, height for line size int w, h; // Init line and position on line int l = 0, p = 0; // For each char to be displayed for(int i = 0; i < chars; i++) { // Copy char into a line lines[l][p] = src[i]; lines[l][p+1] = '\0'; // Get line size dsize(lines[l], current_font, &w, &h); // If it's too long, move to a new line if(w > 0.7 * DWIDTH) { lines[l][p] = '\0'; l++; p = 0; lines[l][p] = src[i]; lines[l][p+1] = '\0'; } // Move to next char on the line p++; } // Draw all lines for(int i = 0; i < l+1; i++) { dtext(0.15 * DWIDTH, 0.6 * DHEIGHT + (current_font->line_height + 4) * i, C_WHITE, lines[i]); } }