Hoennwalker
Usuario de platino
¡Muy buenas! Bueno con este código que voy a explicar vamos a conseguir printear texto tal y como se hace con msgbox normal PERO sin cargar los gráficos del textbox. También vas a aprender a cambiar la fuente del texto, su color y el color de la sombra de las letras. Espero que os pueda ayudar con vuestras ideas en interfaces.
Lo primero de todo es que doy por sentado que sabes configurar y cargar backgrounds y que además sabes organizar la interfaz en tasks. Esto lo comento porque, aunque este tutorial requiera esas bases de conocimiento, el código está comentado para que puedas comprenderlo una vez tengas esas bases.
El WindowTemplate configura los window que pueden contener un msgbox, en este caso usaremos el primero. WindowTemplate (que lo he llamado "gTextWindows") es un array que en este caso solo contiene dos elementos por mi elección, podrían ser más o incluso solo uno. Esos elementos son el 0 y el 1 (NO 1 y 2... NO) pero como se puede observar el elemento 0 del array se llama "WINDOW" y para ello lo declaramos de antemano con "enum". De esta forma, al primer elemento lo podemos llamar 0 o WINDOW, en cambio, al elemento 1 solo lo podemos llamar 1, ahora lo vemos más adelante. El segundo window no lo vamos a usar, me sirve para haber explicado lo anterior.
La función de abajo, AddText, recibirá como parámetro nuestro texto como se verá más adelante. Realmente podría incluso colocar estas dos funciones (el StringExpandPlaceholders y el printer), que contiene AddText, dentro de CreateTextBox junto a esas 3, pero lo dividimos así para manejarnos mejor. Lo explico ahora mismo en el siguiente párrafo.
Como se ha podido observar, AddText necesita un "text" que es un "const u8", es decir, nuestro texto nombrado "gText". Además ese "text" se pasará a StringExpandPlaceholders, el cual también necesita un const u8. Por tanto, sin necesidad de AddText, tendríamos las dos funciones libres de la siguiente manera: (Y como ya dije, se podrían introducir dentro de CreateTextBox sin ningún problema, o llamarlas sin más desde fuera. Pero es opcional.).
¿Y qué pasa con AddTextPrinterForMessage(1)? Bien, lo primero es que el printer se encarga de dar color al texto y a su sombra, establece la fuente del texto, y lo más importante ¿Por qué (1)? AddTextPrinterForMessage necesita que demos un valor al booleano llamado "allowSkippingDelayWithButtonPress", o sea, permitir o no que al pulsar un botón el texto printee más rápido ¿Os suena no? Si le decimos 0, no lo permite, en cambio con 1 sí. También haremos al final del tutorial una pequeña modificación en la definición de esta función, porque de momento esto carga las letras dentro de un recuadro blanco preparado para el textbox original.
CreateTextBox, Esta función recibirá como parámetro "u8 windowId" nuestro window, su nombre en este caso WINDOW ó 0. De esta forma todas las funciones que contiene CreateTextBox se les pasará el windowId sin necesidad de especificarlo en cada una.
Con InitTexts englobamos en una sola función a las otra dos que hemos creado anteriormente.
Literalmente este siguiente task contiene todo lo necesario que hemos creado para que cargue el mensaje, sí, es en este momento cuando lanzas el mensaje.
A la hora de cerrar el mensaje hay que saber qué es esto "RunTextPrintersAndIsPrinter0Active". Lo usamos mediante un "if" para comprbar si NO se está imprimiendo texto (por eso el signo: !). Y claro, eso es necesario para que el mensaje no se cierre hasta que se haya printeado totalmente y pulses un botón. ¿Recuerdas esto en la declaración del texto "\p"? El printer, es la flechita roja que aparece al final y DEBES PONERLA, porque si no, el mensaje se cerrará automáticamente cuando haya terminado de aparecer ya que no habría ningún printer.
Bueno ClearDialogWindowAndFrame recibe como segundo parámetro un "bool8 copyToVram", esto es lo más importante, hay que ponerlo en valor 1 para que sea TRUE y por tanto pasemos esta info a la Vram por medio del modo 3 "CopyWindowToVram(windowId, 3);". Esto se debe a que en la definición de la función encontramos esto:
ADVERTENCIA, ClearDialogWindowAndFrame no elimina el window del Bg, sino el textbox y el texto. Para liberar el Bg completamente usamos FreeAllWindowBuffers.
Ahora hagamos esa modificación de la que hablé para que las letras carguen sin ese recuadro y también vamos a cambiar la fuente y los colores del texto y su sombra. Ve a "menu.c" y encuentra esta función: (Mi recomendación es que la copies y crees una nueva y hagas modificaciones en esa y, que sea con la que hagas las pruebas).
En AddTextPrinterParameterized2, el penúltimo parámetro que vale 1, lo ponemos en 0 y así las letras ya tendrán fondo transparente. Pues ahora ya sí que tenemos un texto que carga perfectamente sin textbox. El resto de cosas:
- El segundo parámetro es la fuente, puedes escoger entre 0, 1 y 2.
- El sexto es el color del texto.
- El último es el color de la sombra.
Aquí tienes una demostración del resultado:
Lo primero de todo es que doy por sentado que sabes configurar y cargar backgrounds y que además sabes organizar la interfaz en tasks. Esto lo comento porque, aunque este tutorial requiera esas bases de conocimiento, el código está comentado para que puedas comprenderlo una vez tengas esas bases.
El WindowTemplate configura los window que pueden contener un msgbox, en este caso usaremos el primero. WindowTemplate (que lo he llamado "gTextWindows") es un array que en este caso solo contiene dos elementos por mi elección, podrían ser más o incluso solo uno. Esos elementos son el 0 y el 1 (NO 1 y 2... NO) pero como se puede observar el elemento 0 del array se llama "WINDOW" y para ello lo declaramos de antemano con "enum". De esta forma, al primer elemento lo podemos llamar 0 o WINDOW, en cambio, al elemento 1 solo lo podemos llamar 1, ahora lo vemos más adelante. El segundo window no lo vamos a usar, me sirve para haber explicado lo anterior.
C:
enum {WINDOW};
static const struct WindowTemplate gTextWindows[] =
{
[WINDOW] = { // nombre del window
.bg = 0, // El bg donde se colocará el window
.tilemapLeft = 2, // x position
.tilemapTop = 15, // y position
.width = 27, //ancho
.height = 4, //alto
.paletteNum = 15, // Paleta que va a ocupar
.baseBlock = 1,
},
{
.bg = 1, // El bg donde se colocará el window
.tilemapLeft = 2, // x position
.tilemapTop = 10, // y position
.width = 27, //ancho
.height = 4, //alto
.paletteNum = 15, // Paleta que va a ocupar
.baseBlock = 109,
},
}
C:
const u8 gText[] = _("Prueba de texto.\p");
static void AddText(const u8* text)
{
StringExpandPlaceholders(gStringVar4, text);
AddTextPrinterForMessage(1);
}
C:
StringExpandPlaceholders(gStringVar4, gText);
AddTextPrinterForMessage(1);
CreateTextBox, Esta función recibirá como parámetro "u8 windowId" nuestro window, su nombre en este caso WINDOW ó 0. De esta forma todas las funciones que contiene CreateTextBox se les pasará el windowId sin necesidad de especificarlo en cada una.
C:
static void CreateTextBox(u8 windowId)
{
//Estas 3 funciones son predefinidas de pokeemerald (muy importante para los que están empezando diferenciar cuáles creamos y cúales no)
FillWindowPixelBuffer(windowId, 0);//color 0 para los píxeles(transparente), de no hacerlo veríamos el texto acompañado de unas líneas verticales, muy bug.
PutWindowTilemap(windowId); // Colocamos el tilemap, OJO sus gráficos no los estamos colocando ni lo vamos a hacer. Sin el tilemap no se pueden mostrar textos.
CopyWindowToVram(windowId, 3);// Evidentemente, si no mandamos el window a la ram de video tampoco podemos mostrar texto. Generalmente se usa el modo 3.
}
static void InitTextWindows()
{
//Estas 3 funciones son predefinidas de pokeemerald
InitWindows(gTextWindows); //Inicializa los window, para que podamos colocar nuestro texto.
DeactivateAllTextPrinters(); //Desactiva printers anteriores que hubiese, para que no haya contradicciones.
LoadPalette(GetOverworldTextboxPalettePtr(), 0xf0, 0x20); /*Carga la paleta del texto por defecto del juego en el slot 15 de las paletas para backgrounds,
esto claramente afecta si quieres cargar un bg de 224 colores, porque necesitas 16 colores para el
texto y otros 16 para el textbox(si lo tuviera, que en este caso no lo cargamos, por tanto podrías usar
un fondo de 240 colores). Así que si indexas tu tileset en 255 colores, con CMP debes eliminar
en la paleta los 16 colores de la fila 15 y los 16 colores de la última fila. CMP adaptará el tileset perfectamente.*/
}
C:
static void InitTexts()
{
CreateTextBox(WINDOW); // ó CreateTextBox(0);
AddText(gText);
}
C:
static void Task_mensaje(u8 taskId){
InitTextWindows();
InitTexts();
gTasks[taskId].func = Task_cerraMensaje;
}
C:
static void Task_cerraMensaje(u8 taskId){
if(!RunTextPrintersAndIsPrinter0Active()){
ClearDialogWindowAndFrame(WINDOW, 1);
FreeAllWindowBuffers();
}
}
C:
if (copyToVram == TRUE)
CopyWindowToVram(windowId, 3);
/* También podrías haberlo encontrado de esta otra forma, pero la primera manera
sólo es válida cuando el IF contiene una sola línea de código, eso sí, tabulada
para indicar que está dentro del IF*/
if (copyToVram == TRUE){
CopyWindowToVram(windowId, 3);
}
Ahora hagamos esa modificación de la que hablé para que las letras carguen sin ese recuadro y también vamos a cambiar la fuente y los colores del texto y su sombra. Ve a "menu.c" y encuentra esta función: (Mi recomendación es que la copies y crees una nueva y hagas modificaciones en esa y, que sea con la que hagas las pruebas).
C:
void AddTextPrinterForMessage(bool8 allowSkippingDelayWithButtonPress)
{
void (*callback)(struct TextPrinterTemplate *, u16) = NULL;
gTextFlags.canABSpeedUpPrint = allowSkippingDelayWithButtonPress;
AddTextPrinterParameterized2(0, 1, gStringVar4, GetPlayerTextSpeedDelay(), callback, 2, 1, 3);
}
- El segundo parámetro es la fuente, puedes escoger entre 0, 1 y 2.
- El sexto es el color del texto.
- El último es el color de la sombra.
C:
#define TEXT_COLOR_TRANSPARENT 0x0
#define TEXT_COLOR_WHITE 0x1
#define TEXT_COLOR_DARK_GREY 0x2
#define TEXT_COLOR_LIGHT_GREY 0x3
#define TEXT_COLOR_RED 0x4
#define TEXT_COLOR_LIGHT_RED 0x5
#define TEXT_COLOR_GREEN 0x6
#define TEXT_COLOR_LIGHT_GREEN 0x7
#define TEXT_COLOR_BLUE 0x8
#define TEXT_COLOR_LIGHT_BLUE 0x9
#define TEXT_DYNAMIC_COLOR_1 0xA // Usually white
#define TEXT_DYNAMIC_COLOR_2 0xB // Usually white w/ tinge of green
#define TEXT_DYNAMIC_COLOR_3 0xC // Usually white
#define TEXT_DYNAMIC_COLOR_4 0xD // Usually aquamarine
#define TEXT_DYNAMIC_COLOR_5 0xE // Usually blue-green
#define TEXT_DYNAMIC_COLOR_6 0xF // Usually cerulean
Última edición: