Предисловие.
По просьбе англо-говорящего читателя Relde, выкладываю свой старый скрипт который печатает текст последовательно.
Разбираем код.
Скачайте проект с github.
Откройте main.c, там разберем функцию printMessageBase которая отвечает за печать текста.
printMessageBase(char* str, Image* img_msg_sign, u8 msg_sign_pal)
Она принимает:
- текст, который будем последовательно печатать
- изображение плитки
- палитру плитки.
Первым делом, включили WINDOW слой, и сказали что он будет отнимать 10 тайлов сверху от BG_A
VDP_setWindowVPos(FALSE, 10);
И нарисовали картинку плитки на этом слое.
VDP_setWindowVPos(FALSE, 10);
VDP_drawImageEx(WINDOW, img_msg_sign, TILE_ATTR_FULL(msg_sign_pal, 255, FALSE, FALSE, VDPTilesFilled), 0, 0, FALSE, FALSE);
Далее:
u32 str_len = strlen(str); //Получаем длину строки
char str_char[1]; //Создаем буффер для текущего символа
char str_line[35]; //Создаем буффер для текущей строки
u8 start_pos_x = 10; //Задаем смещение позиции 1-ой строки
u8 start_pos_y = 2;
bool skip = FALSE;
u8 cur_y = 0; //Позиция текущего символа текущая и максимальная
u8 max_y = 6;
u8 cur_x = 0;
u8 max_x = 27;
//К текущей позиции прибавляется смещение cur_x+start_pos_x
u8 max_x_line = max_x;
Если кнопка пропуска была нажата до выполнения печати, то игнорируем пропуск. Это сделано для того, чтобы при последовательном запуске printMessageBase, строка не пропускалась автоматически если зажата кнопка.
if (joy_value & BUTTON_A || joy_value & BUTTON_B || joy_value & BUTTON_C || joy_value & BUTTON_START) {
can_skip = FALSE;
}
Копируем часть строки в буффер str_line
strncpy(&str_line, 0, max_x);
Проходящимся по всем символам текста, проверяем нажатие кнопки пропуска
for(u32 i=0;i<str_len;i++) {
strncpy(&str_char, str+i, 1);
joy_value = JOY_readJoypad(JOY_1);
if (joy_value & BUTTON_A || joy_value & BUTTON_B || joy_value & BUTTON_C || joy_value & BUTTON_START) {
joy_pressed = TRUE;
if(joy_pressed && !prev_joy_pressed && can_skip) {
skip = TRUE;
} else {
joy_pressed = FALSE;
}
} else {
can_skip = TRUE;
}
Если символ дошел до конца строки, то переходим на следующую строку
if(i != 0 && (cur_x > max_x_line)) {
cur_x = 0;
cur_y += 2;
Если это последняя строка, то ждем нажатия кнопки действия, чтобы перейти на следующую страницу.
if(cur_y >= max_y) { //if text doesn't fit in the rectangle, then
while(1) {
joy_value = JOY_readJoypad(JOY_1);
SYS_doVBlankProcess();
//waiting for just_pressed action from player
if (joy_value & BUTTON_A || joy_value & BUTTON_B || joy_value & BUTTON_C || joy_value & BUTTON_START)
{
joy_pressed = TRUE;
if(joy_pressed && !prev_joy_pressed) {
cur_x = 0;
cur_y = 0;
skip = FALSE;
can_skip = FALSE;
VDP_drawImageEx(WINDOW, &img_message_sign, TILE_ATTR_FULL(msg_sign_pal, 255, FALSE, FALSE, VDPTilesFilled), 0, 0, FALSE, FALSE);
break;
}
} else {
joy_pressed = FALSE;
}
prev_joy_pressed = joy_pressed;
}
}
Печатаем текущий символ со смещением по координатам.
VDP_drawTextBG(WINDOW, str_char, start_pos_x+cur_x, start_pos_y+cur_y);
Если, это начало текущей строки, то
if(cur_x == 0) {
//Обновляем буфер текущей строки и её длину
strncpy(&str_line, str+i, max_x);
u8 str_line_len = strlen(str_line);
//Если оставшийся текст влезает в стоку для печати, то максимальное_кол_символов_в_строке = осталось_символов
if(str_line_len < max_x) {
max_x_line = max_x;
}
else {
//Иначе, ищем последний символ пробела и по нему делим строку.
for(u8 j=0; j<max_x; j++)
{
if(str_line[j] == ' '){
max_x_line = j;
}
}
}
strncpy(&str_line, str+i, max_x_line);
KDebug_Alert(str_line);
}
Если не пропуск ( skip), то ждем после печати каждого символа.
if (!skip) {
waitMs(20);
SYS_doVBlankProcess();
}
И, в конце, ждем нажатия кнопки действия, чтобы выйти из диалога.
//waiting for last press
while(1) {
joy_value = JOY_readJoypad(JOY_1);
if (joy_value & BUTTON_A || joy_value & BUTTON_B || joy_value & BUTTON_C || joy_value & BUTTON_START) {
joy_pressed = TRUE;
if(joy_pressed && !prev_joy_pressed) {
break;
}
} else {
joy_pressed = FALSE;
}
prev_joy_pressed = joy_pressed;
SYS_doVBlankProcess();
}
И выходим из WINDOW режима.
VDP_setWindowVPos(FALSE, 0);
Теперь, скомпилируйте и запустите rom.
Итоговый результат.
