First demo for dialogs

This commit is contained in:
Darks 2020-10-27 00:34:08 +01:00
parent 48a1c0a121
commit bd16f89b30
Signed by: Darks
GPG Key ID: 7515644268BE1433
9 changed files with 185 additions and 17 deletions

View File

@ -145,7 +145,7 @@ build-cg/assets/img/%.o: assets-cg/img/%
@ mkdir -p $(dir $@)
fxconv --image $< -o $@ $(FXCONVCG) name:img_$(notdir $(basename $*)) $(IMG.$*) profile:p4
# Images
# Images libimg
build-fx/assets/limg/%.o: assets-fx/limg/%
@ mkdir -p $(dir $@)
fxconv --libimg-image $< -o $@ $(FXCONVFX) name:limg_$(notdir $(basename $*)) $(IMG.$*)

View File

@ -53,3 +53,7 @@ There are 2 kinds of powerups: small ones and big ones. Small ones increase powe
### Object updater
An object updater is a function applied to an object. Its protoype must follow this: `void f(object_t*)`. Due to the complexity of the game, it may use `frame`, `us_elapsed`; but it could also use `player`, `difficulty` or other global variables.
## Graphics
Graphics are designed for color calcs. However, I try to be the most responsible possible to facilitate a port to monochrome calcs. Thus, code may be quite verbose when displaying sprites.

Binary file not shown.

View File

@ -1,6 +1,9 @@
#ifndef _CONFIG_H
#define _CONFIG_H
// #define DWIDTH 396
// #define DHEIGHT 224
#define SCREEN_X 270
#define SCREEN_Y 224

View File

@ -7,10 +7,15 @@
#include <gint/keyboard.h>
#include <libimg.h>
#include <libprof.h>
#include <openlibm.h>
/* Define some structures used for dialogs */
typedef struct {
img_t *character;
img_t *characters[2];
char **text;
} dialog_t;
void dialog(dialog_t *dialog);
void display_text(const char *src, int chars);
#endif // _DIALOG_H

View File

@ -60,8 +60,8 @@ INCLUDE := -I include
# Libraries. Add one -l option for each library you are using, and also
# suitable -L options if you have library files in custom folders. To use
# fxlib, add libfx.a to the project directory and use "-L . -lfx".
LIBS_FX := -lprof -limg-fx
LIBS_CG := -lprof -limg-cg
LIBS_FX := -lprof -limg-fx -lopenlibm
LIBS_CG := -lprof -limg-cg -lopenlibm
# Base linker flags for the fxSDK, you usually want to keep these.
LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS_FX) -lgint-fx -lgcc

View File

@ -1,23 +1,162 @@
#include "dialog.h"
// Debug purposes
int _strlen(const char *str) { int i = 0; while (str[i++]); return i; }
void dialog(dialog_t *dialog)
{
img_t chars_img[1][2] = {
{ img_copy(*(dialog->character)), img_darken_create(*(dialog->character))}
// 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 tmp = img_hflip_create(*(dialog->characters[1]));
img_t chars_img[2][2] = {
{ img_copy(*(dialog->characters[0])),
img_darken_create(*(dialog->characters[0])) },
{ img_copy(tmp),
img_darken_create(tmp)}
};
img_destroy(tmp);
dclear(C_BLACK);
// Init text properties
int current_replica = 0;
float current_chars = 0, text_speed = 0.000012; // Chars per us
char wait_change = 0;
img_render_vram(chars_img[0][0], 15, 20);
// Entering main loop
prof_enter(prof_fps);
dupdate();
getkey();
while(!(e.type == KEYEV_UP && e.key == KEY_EXIT)
&& dialog->text[current_replica])
{
// Get last keyboard event
e = pollevent();
// Manage events
if(e.type == KEYEV_UP && e.key == KEY_EXIT) break;
if(e.type == KEYEV_DOWN && e.key == KEY_SHIFT && wait_change == 1)
{
// Reset current chars
current_chars = 0;
// Waiting for key up
wait_change = 2;
}
if(e.type == KEYEV_UP && e.key == 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 * cos(time * 0.000005)));
img_render_vram(chars_img[1][!talking],
DWIDTH * 0.85 - chars_img[1][0].width,
DHEIGHT * (0.15 + 0.04 * sin(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 < 1; i++)
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++)
{
for(int j = 0; j < 2; j++) {
img_destroy(chars_img[i][j]);
// 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]);
}
}

View File

@ -98,6 +98,7 @@ void engine(void)
// Update FPS & frame
prof_leave(prof_fps);
us_elapsed = prof_time(prof_fps);
prof_fps.elapsed = 0;
frame++;
}
}

View File

@ -7,16 +7,32 @@
#include "dialog.h"
// Dev
void dialog(dialog_t*);
int main(void)
{
extern img_t limg_hina;
extern img_t limg_hina, limg_sariel;
prof_init();
dialog_t d = {&limg_hina};
char *text[] = {
"Hey Sariel! How are you?",
"I was fine until an unpleasant witche entered my garden.",
"You're not pleased to see me tonight?",
"Should I recall you stole my scepter yesterday?",
"It was a joke...",
"But I did not enjoy it!",
"You're not fun, Sariel.",
"Are you kidding me?",
"Hey, if you're so sensitive, go home!",
"You've gone too far. I'll take you down!",
"Ok, let's have a fight then. But I won't do you any favours.",
NULL
};
dialog_t d = {
{&limg_hina, &limg_sariel},
text
};
dialog(&d);