From f39f66a539e635e389623884438af10b8c760d91 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Sun, 5 Mar 2023 22:27:35 -0800 Subject: [PATCH] Input handling fixes, max char limit --- main.c | 95 ++++++++++++++++++++++++++++++++--------------- todo.txt | 20 ++++++---- web_template.html | 21 +++++++++-- 3 files changed, 96 insertions(+), 40 deletions(-) diff --git a/main.c b/main.c index d9c64db..fb381b3 100644 --- a/main.c +++ b/main.c @@ -121,15 +121,20 @@ typedef enum EntityKind #endif // null terminator always built into buffers so can read properly from data +#define BUFF_VALID(buff_ptr) assert((buff_ptr)->cur_index <= ARRLEN((buff_ptr)->data)) #define BUFF(type, max_size) struct { int cur_index; type data[max_size]; char null_terminator; } #define BUFF_HAS_SPACE(buff_ptr) ( (buff_ptr)->cur_index < ARRLEN((buff_ptr)->data) ) -#define BUFF_APPEND(buff_ptr, element) { (buff_ptr)->data[(buff_ptr)->cur_index++] = element; assert((buff_ptr)->cur_index <= ARRLEN((buff_ptr)->data)); } +#define BUFF_EMPTY(buff_ptr) ((buff_ptr)->cur_index == 0) +#define BUFF_APPEND(buff_ptr, element) { (buff_ptr)->data[(buff_ptr)->cur_index++] = element; BUFF_VALID(buff_ptr); } //#define BUFF_ITER(type, buff_ptr) for(type *it = &((buff_ptr)->data[0]); it < (buff_ptr)->data + (buff_ptr)->cur_index; it++) #define BUFF_ITER_EX(type, buff_ptr, begin_ind, cond, movement) for(type *it = &((buff_ptr)->data[begin_ind]); cond; movement) #define BUFF_ITER(type, buff_ptr) BUFF_ITER_EX(type, (buff_ptr), 0, it < (buff_ptr)->data + (buff_ptr)->cur_index, it++) +#define BUFF_PUSH_FRONT(buff_ptr, value) { (buff_ptr)->cur_index++; BUFF_VALID(buff_ptr); for(int i = (buff_ptr)->cur_index - 1; i > 0; i--) { (buff_ptr)->data[i] = (buff_ptr)->data[i - 1]; }; (buff_ptr)->data[0] = value; } +#define BUFF_REMOVE_FRONT(buff_ptr) {if((buff_ptr)->cur_index > 0) {for(int i = 0; i < (buff_ptr)->cur_index - 1; i++) { (buff_ptr)->data[i] = (buff_ptr)->data[i+1]; }; (buff_ptr)->cur_index--;}} #define BUFF_CLEAR(buff_ptr) {memset((buff_ptr), 0, sizeof(*(buff_ptr))); ((buff_ptr)->cur_index = 0);} -#define MAX_SENTENCE_LENGTH 400 +// REFACTORING:: also have to update in javascript!!!!!!!! +#define MAX_SENTENCE_LENGTH 400 // LOOOK AT AGBOVE COMMENT GBEFORE CHANGING typedef BUFF(char, MAX_SENTENCE_LENGTH) Sentence; #define SENTENCE_CONST(txt) (Sentence){.data=txt, .cur_index=sizeof(txt)} @@ -157,9 +162,10 @@ typedef struct Entity // npcs bool is_npc; + double character_say_timer; NpcKind npc_kind; + Sentence sentence_to_say; Dialog player_dialog; - Sentence to_say; #ifdef WEB int gen_request_id; #endif @@ -236,21 +242,29 @@ void make_space_and_append(Dialog *d, Sentence *s) BUFF_APPEND(d, *s); } -void add_new_npc_sentence(Entity *npc, char *sentence) +void say_characters(Entity *npc, int num_characters) { - size_t sentence_len = strlen(sentence); - assert(sentence_len < MAX_SENTENCE_LENGTH); - Sentence new_sentence = {0}; - BUFF(char, MAX_SENTENCE_LENGTH) match_buffer = {0}; - bool inside_star = false; - for(int i = 0; i < sentence_len; i++) + Sentence *sentence_to_append_to = &npc->player_dialog.data[npc->player_dialog.cur_index-1]; + for(int i = 0; i < num_characters; i++) { - if(sentence[i] == '"') break; - if(sentence[i] == '\n') continue; - - if(inside_star) + if(!BUFF_EMPTY(&npc->player_dialog) && !BUFF_EMPTY(&npc->sentence_to_say)) { - if(sentence[i] == '*') + char new_character = npc->sentence_to_say.data[0]; + bool found_matching_star = false; + BUFF(char, MAX_SENTENCE_LENGTH) match_buffer = {0}; + if(new_character == '*') + { + for(int ii = sentence_to_append_to->cur_index-1; ii >= 0; ii--) + { + if(sentence_to_append_to->data[ii] == '*') + { + found_matching_star = true; + break; + } + BUFF_PUSH_FRONT(&match_buffer, sentence_to_append_to->data[ii]); + } + } + if(found_matching_star) { if(strcmp(match_buffer.data, "fights player") == 0 && npc->npc_kind == OLD_MAN) { @@ -261,24 +275,29 @@ void add_new_npc_sentence(Entity *npc, char *sentence) npc->going_to_target = true; npc->target_goto = AddV2(npc->pos, V2(0.0, -TILE_SIZE*1.5f)); } - BUFF_CLEAR(&match_buffer); - inside_star = false; - } - else - { - BUFF_APPEND(&match_buffer, sentence[i]); } + BUFF_APPEND(sentence_to_append_to, new_character); + BUFF_REMOVE_FRONT(&npc->sentence_to_say); } - else - { - if(sentence[i] == '*') inside_star = true; - } - + } +} +void add_new_npc_sentence(Entity *npc, char *sentence) +{ + size_t sentence_len = strlen(sentence); + assert(sentence_len < MAX_SENTENCE_LENGTH); + Sentence new_sentence = {0}; + bool inside_star = false; + for(int i = 0; i < sentence_len; i++) + { + if(sentence[i] == '"') break; + if(sentence[i] == '\n') continue; BUFF_APPEND(&new_sentence, sentence[i]); } - make_space_and_append(&npc->player_dialog, &new_sentence); - + Sentence empty_sentence = {0}; + say_characters(npc, npc->sentence_to_say.cur_index); + make_space_and_append(&npc->player_dialog, &empty_sentence); + npc->sentence_to_say = new_sentence; } // from_point is for knockback @@ -397,7 +416,15 @@ void end_text_input(char *what_player_said) player->talking_to->gen_request_id = req_id; #endif #ifdef DESKTOP - add_new_npc_sentence(player->talking_to, "......"); + if(player->talking_to->npc_kind == DEATH) + { + add_new_npc_sentence(player->talking_to, "test *moves* I am death, destroyer of games. Come join me in the afterlife, or continue onwards *moves*"); + //add_new_npc_sentence(player->talking_to, "test"); + } + if(player->talking_to->npc_kind == OLD_MAN) + { + add_new_npc_sentence(player->talking_to, "If it's a fight you're looking for! *fights player*"); + } #endif } } @@ -1906,6 +1933,16 @@ void frame(void) if(it->is_npc) { + if(!BUFF_EMPTY(&it->sentence_to_say)) + { + it->character_say_timer += dt; + const float character_say_time = 0.05f; + while(it->character_say_timer > character_say_time) + { + say_characters(it, 1); + it->character_say_timer -= character_say_time; + } + } if(it->npc_kind == DEATH && it->going_to_target) { it->pos = LerpV2(it->pos, dt*5.0f, it->target_goto); diff --git a/todo.txt b/todo.txt index 17e8889..1ff4a07 100644 --- a/todo.txt +++ b/todo.txt @@ -1,18 +1,22 @@ -Marketing: - - Mailing list - -Making the game: - - Skeleton enemy - - Animate text characters coming in - - Escape exits typing +Happening: +DONE - Animate text characters coming in +DONE - Escape exits typing +DONE - Get rid of enters and stars in javascript input box - Space and e for attack and roll, tooltip + - Skeleton enemy + - Shopkeep character - Don't flip player direction when you walk vertically - - Get rid of enters and stars in javascript input box - Sword improvements, deflect bullets, player knockback - Save every request and response (server logs) - Portal at end, exit level - Drop shadow on text, or outline. Something - Sound + +Later + +Marketing: + - Mailing list + - Ask death to come help you fight, new action - Perfect dodge roll just after you roll, sound effect and particles. Lets you keep momentum. Each dodge roll diff --git a/web_template.html b/web_template.html index 35687b2..61512e3 100644 --- a/web_template.html +++ b/web_template.html @@ -103,7 +103,7 @@ body {
-
@@ -148,8 +148,23 @@ function end_dialog() { Module.ccall('end_text_input', 'void', ['string'], [document.getElementById("inputtext").value]); } -function textarea_key_up() { - end_dialog(); +function on_textarea_key(event) { + let final_textarea_string = ""; + let cur_textarea_string = document.getElementById("inputtext").value; + for(let i = 0; i < Math.min(cur_textarea_string.length, 250); i++) + { + let cur = cur_textarea_string[i]; + if(cur === "\n") continue; + if(cur.charCodeAt(0) >= 255) continue; // non ascii gtfo + final_textarea_string += cur_textarea_string[i]; + } + document.getElementById("inputtext").value = final_textarea_string; + if(event.key === "Enter") end_dialog(); + if(event.key === "Escape") + { + document.getElementById("inputtext").value = ""; + end_dialog(); + } } const max_retries = 5;