161 lines
4.2 KiB
C
161 lines
4.2 KiB
C
#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]);
|
|
}
|
|
}
|