Added language support to main menu and sign

This commit is contained in:
2024-10-17 07:17:36 -07:00
parent 3baafec9cb
commit 7867076bbe
13 changed files with 162 additions and 85 deletions

View File

@ -1,7 +1,16 @@
{
"general": {
"test": {
"test": "test"
"main_menu": {
"new_game": "New Game",
"load_game": "Load Game",
"options": "Options",
"exit": "Exit"
},
"maps": {
"testmap": {
"sign": {
"text": "This is a sign.",
"name": "Sign"
}
}
}
}

View File

@ -40,7 +40,7 @@
"type": 3,
"x": 3,
"y": 8,
"text": "This is a sign."
"text": "maps.testmap.sign"
},
{
"type": 4,

View File

@ -28,28 +28,17 @@ game_t GAME;
void gameInit() {
memset(&GAME, 0, sizeof(game_t));
timeInit();
inputInit();
displayInit();
assetInit();
assetLanguageLoad("en.json");
textboxInit();
testMenuInit();
mainMenuInit();
assetLanguageLoad("en.json");
char_t buffer[LANGUAGE_STRING_LENGTH_MAX];
languageGet(buffer, "general.test.test");
conversation_t conversation;
conversationInit(
&conversation,
conversationTestInit,
conversationTestUpdate
);
conversationUpdate(&conversation);
conversationInit();
GAME.state = GAME_STATE_INITIAL;
}
@ -57,6 +46,7 @@ void gameInit() {
gameupdateresult_t gameUpdate(const float_t delta) {
timeUpdate(delta);
inputUpdate();
conversationUpdate();
switch(GAME.state) {
case GAME_STATE_INITIAL:

View File

@ -14,23 +14,29 @@ void languageInit() {
memset(&LANGUAGE, 0, sizeof(language_t));
}
int32_t languageGet(
char_t *buffer,
const char_t *key,
...
) {
const char_t * languageGetPointer(const char_t *key) {
assertNotNull(key, "Key cannot be NULL.");
int32_t i;
language_t *lang = &LANGUAGE;
lang->count;
int32_t i = 0;
while(i < LANGUAGE.count) {
if(strcmp(key, LANGUAGE.keys[i]) != 0) {
i++;
continue;
}
if(buffer != NULL) strcpy(buffer, LANGUAGE.strings[i]);
return strlen(LANGUAGE.strings[i]);
return LANGUAGE.strings[i];
}
return -1;
return NULL;
}
int32_t languageGet(char_t *buffer, const char_t *key) {
const char_t *str = languageGetPointer(key);
if(str == NULL) return -1;
if(buffer == NULL) return strlen(str);
strcpy(buffer, str);
return strlen(str);
}

View File

@ -25,16 +25,20 @@ extern language_t LANGUAGE;
*/
void languageInit();
/**
* Gets the pointer to the language string for the given key. Pointer should not
* be modified or freed.
*
* @param key The key to get the string for.
* @return The pointer to the string.
*/
const char_t * languageGetPointer(const char_t *key);
/**
* Returns the language string for the given key.
*
* @param buffer The buffer to write the string to, or NULL to get length.
* @param key The key to get the string for.
* @param ... The arguments to replace in the string.
* @return The length of the string.
*/
int32_t languageGet(
char_t *buffer,
const char_t *key,
...
);
int32_t languageGet(char_t *buffer, const char_t *key);

View File

@ -9,5 +9,6 @@
target_sources(${DAWN_TARGET_NAME}
PRIVATE
conversation.c
conversationsign.c
testconversation.c
)

View File

@ -8,44 +8,48 @@
#include "conversation.h"
#include "assert/assert.h"
void conversationInit(
conversation_t *conversation,
const conversationcallback_t init,
const conversationcallback_t update
) {
assertNotNull(conversation, "Conversation is NULL.");
conversation_t CONVERSATION;
memset(conversation, 0, sizeof(conversation_t));
conversation->init = init;
conversation->update = update;
conversation->index = CONVERSATION_NOT_INITIALIZED;
void conversationInit() {
memset(&CONVERSATION, 0, sizeof(conversation_t));
}
void conversationUpdate(conversation_t *conversation) {
void conversationSet(
const conversationcallback_t init,
const conversationcallback_t update,
void *user
) {
CONVERSATION.init = init;
CONVERSATION.update = update;
CONVERSATION.index = CONVERSATION_NOT_INITIALIZED;
CONVERSATION.user = user;
}
void conversationUpdate() {
if(CONVERSATION.init == NULL || CONVERSATION.update == NULL) return;
uint16_t ret;
assertNotNull(conversation, "Conversation is NULL.");
// Init or update.
switch(conversation->index) {
switch(CONVERSATION.index) {
case CONVERSATION_NOT_INITIALIZED:
conversation->index = 0;
ret = conversation->init(
conversation, conversation->index
CONVERSATION.index = 0;
ret = CONVERSATION.init(
&CONVERSATION, CONVERSATION.index
);
break;
default:
ret = conversation->update(conversation, conversation->index);
ret = CONVERSATION.update(&CONVERSATION, CONVERSATION.index);
break;
}
// Check ret value and update conversation.
switch(ret) {
case CONVERSATION_NEXT:
conversation->index++;
conversation->index = conversation->init(
conversation, conversation->index
CONVERSATION.index++;
CONVERSATION.index = CONVERSATION.init(
&CONVERSATION, CONVERSATION.index
);
break;
@ -53,8 +57,8 @@ void conversationUpdate(conversation_t *conversation) {
return;
case CONVERSATION_RESTART:
conversation->index = 0;
conversation->init(conversation, conversation->index);
CONVERSATION.index = 0;
CONVERSATION.init(&CONVERSATION, CONVERSATION.index);
break;
case CONVERSATION_INVALID:
@ -62,13 +66,12 @@ void conversationUpdate(conversation_t *conversation) {
break;
case CONVERSATION_DONE:
CONVERSATION.init = NULL;
CONVERSATION.update = NULL;
break;
default:
conversation->index = ret;
conversation->index = conversation->init(
conversation, conversation->index
);
CONVERSATION.index = ret;
break;
}
}

View File

@ -28,21 +28,27 @@ typedef struct _conversation_t {
void *user;
} conversation_t;
extern conversation_t CONVERSATION;
/**
* Initializes a conversation object.
*
* @param conversation Conversation to initialize.
* @param update Function to handle conversation updates.
* Initializes the conversation object.
*/
void conversationInit(
conversation_t *conversation,
void conversationInit();
/**
* Sets the conversation object.
*
* @param init The initialization callback.
* @param update The update callback.
* @param user The user data.
*/
void conversationSet(
const conversationcallback_t init,
const conversationcallback_t update
const conversationcallback_t update,
void *user
);
/**
* Update a given conversation.
*
* @param conversastion Conversation to update.
*/
void conversationUpdate(conversation_t *conversation);
void conversationUpdate();

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "conversationsign.h"
#include "assert/assert.h"
#include "rpg/entity/entity.h"
#include "locale/language.h"
uint16_t conversationSignInit(conversation_t *convo, const uint16_t i) {
assertNotNull(convo, "Conversation is NULL!");
assertNotNull(convo->user, "Conversation user is NULL!");
entity_t *e = (entity_t*)convo->user;
assertTrue(e->type == ENTITY_TYPE_SIGN, "Entity is not a sign!");
textboxSetText("maps.testmap.sign.name", "maps.testmap.sign.text");
return 0;
}
uint16_t conversationSignUpdate(conversation_t *convo, const uint16_t i) {
switch(i) {
case 0:
return textboxIsOpen() ? CONVERSATION_CONTINUE : CONVERSATION_DONE;
default:
return CONVERSATION_INVALID;
}
}

View File

@ -0,0 +1,12 @@
/**
* Copyright (c) 2024 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "conversation.h"
uint16_t conversationSignInit(conversation_t *convo, const uint16_t i);
uint16_t conversationSignUpdate(conversation_t *convo, const uint16_t i);

View File

@ -8,6 +8,9 @@
#include "interact.h"
#include "assert/assert.h"
#include "game/game.h"
#include "locale/language.h"
#include "rpg/conversation/conversationsign.h"
void entityInteractEntity(
entity_t *source,
@ -29,7 +32,7 @@ void entityInteractEntity(
return;
case ENTITY_TYPE_SIGN:
textboxSetText("Sign", target->sign.text);
conversationSet(conversationSignInit, conversationSignUpdate, target);
return;
case ENTITY_TYPE_DOOR:

View File

@ -7,15 +7,16 @@
#include "mainmenu.h"
#include "game/game.h"
#include "locale/language.h"
menu_t MAIN_MENU;
void mainMenuInit() {
const char_t* strings[] = {
"New Game",
"Load Game",
"Options",
"Exit"
languageGetPointer("main_menu.new_game"),
languageGetPointer("main_menu.load_game"),
languageGetPointer("main_menu.options"),
languageGetPointer("main_menu.exit")
};
uint16_t columns = 1;
@ -35,21 +36,25 @@ void mainMenuSelectCallback(
const uint16_t y,
const char_t *str
) {
if(strcmp(str, "New Game") == 0) {
// New Game
if(y == 0) {
GAME.mapNext = MAP_LIST_TEST;
GAME.state = GAME_STATE_MAP_CHANGE;
return;
}
if(strcmp(str, "Load Game") == 0) {
// Load Game
if(y == 1) {
return;
}
if(strcmp(str, "Options") == 0) {
// Options
if(y == 2) {
return;
}
if(strcmp(str, "Exit") == 0) {
// Exit
if(y == 3) {
GAME.shouldExit = true;
return;
}

View File

@ -9,6 +9,7 @@
#include "assert/assert.h"
#include "input.h"
#include "game/time.h"
#include "locale/language.h"
textbox_t TEXTBOX;
@ -20,18 +21,23 @@ void textboxSetText(
const char_t *title,
const char_t *text
) {
size_t len;
const char_t *temp;
assertNotNull(text, "Text cannot be NULL.");
// Setup text copies
size_t len = strlen(text);
// Copy translation
temp = languageGetPointer(text);
len = strlen(temp);
assertTrue(len < TEXTBOX_TEXT_MAX, "Text is too long.");
strcpy(TEXTBOX.text, text);
strcpy(TEXTBOX.text, temp);
TEXTBOX.textLength = len;
// Setup title
if(title) {
assertTrue(strlen(title) < TEXTBOX_TITLE_MAX, "Title is too long.");
strcpy(TEXTBOX.title, title);
temp = languageGetPointer(title);
len = strlen(temp);
assertTrue(len < TEXTBOX_TITLE_MAX, "Title is too long.");
strcpy(TEXTBOX.title, temp);
} else {
TEXTBOX.title[0] = '\0';
}