refactor: add game state abstraction
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
#include "game_state.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
char *word_bank[] = {
|
||||||
|
"hypothesis",
|
||||||
|
"science",
|
||||||
|
"usurp",
|
||||||
|
"conditional",
|
||||||
|
"passionate",
|
||||||
|
"orion",
|
||||||
|
NULL // sentinel value marking end
|
||||||
|
};
|
||||||
|
|
||||||
|
struct game_state {
|
||||||
|
char **curr_el;
|
||||||
|
unsigned short curr_letter_index;
|
||||||
|
unsigned short wins;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct game_state state;
|
||||||
|
|
||||||
|
void init_game_state() {
|
||||||
|
state.curr_el = word_bank;
|
||||||
|
state.curr_letter_index = 0;
|
||||||
|
state.wins = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the word at the current element. Will always return a valid non-null pointer to first char of the word
|
||||||
|
char *get_curr_word() {
|
||||||
|
assert(state.curr_el != NULL);
|
||||||
|
assert((*state.curr_el) != NULL);
|
||||||
|
return *state.curr_el;
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_curr_letter() {
|
||||||
|
char *word = get_curr_word();
|
||||||
|
return word[state.curr_letter_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_curr_letter_index() {
|
||||||
|
return state.curr_letter_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_wins() {
|
||||||
|
return state.wins;
|
||||||
|
}
|
||||||
|
|
||||||
|
// goes to the next word in the word bank, wrapping when necessary
|
||||||
|
static void go_next_word() {
|
||||||
|
if (*(state.curr_el + 1) == NULL) {
|
||||||
|
state.curr_el = word_bank;
|
||||||
|
} else {
|
||||||
|
state.curr_el++;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.wins++;
|
||||||
|
state.curr_letter_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle either going to the next letter or next word if at the end
|
||||||
|
void next() {
|
||||||
|
size_t word_len = strlen(get_curr_word());
|
||||||
|
if (state.curr_letter_index >= word_len - 1) { // at last character
|
||||||
|
go_next_word();
|
||||||
|
} else {
|
||||||
|
state.curr_letter_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef GAMESTATE_H
|
||||||
|
#define GAMESTATE_H
|
||||||
|
|
||||||
|
void init_game_state();
|
||||||
|
|
||||||
|
// Gets the word at the current element. Will always return a valid non-null pointer to first char of the word
|
||||||
|
char *get_curr_word();
|
||||||
|
|
||||||
|
char get_curr_letter();
|
||||||
|
int get_curr_letter_index();
|
||||||
|
|
||||||
|
int get_wins();
|
||||||
|
|
||||||
|
// handle either going to the next letter or next word if at the end
|
||||||
|
void next();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,90 +1,80 @@
|
|||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
char *word_bank[] = {
|
#include "game_state.h"
|
||||||
"hypothesis",
|
|
||||||
"science",
|
|
||||||
"usurp",
|
|
||||||
"conditional",
|
|
||||||
"passionate",
|
|
||||||
"orion",
|
|
||||||
NULL // sentinel value marking end
|
|
||||||
};
|
|
||||||
|
|
||||||
#define WINDOW_HEIGHT 500
|
#define WINDOW_HEIGHT 500
|
||||||
#define WINDOW_WIDTH 700
|
#define WINDOW_WIDTH 700
|
||||||
#define CHAR_SPACING 40
|
#define CHAR_SPACING 40
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
void process_key_events() {
|
||||||
|
char buf[2] = {'c', '\0'};
|
||||||
|
int k;
|
||||||
|
const char *key_name;
|
||||||
|
|
||||||
|
while ((k = GetKeyPressed()) != 0) {
|
||||||
|
key_name = GetKeyName(k);
|
||||||
|
|
||||||
|
char c = get_curr_letter();
|
||||||
|
sprintf(buf, "%c\0", c);
|
||||||
|
|
||||||
|
if (key_name != NULL &&
|
||||||
|
strcmp(key_name, buf) == 0) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_game_state() {
|
||||||
|
char buf[2] = {'c', '\0'};
|
||||||
|
char *curr_word = get_curr_word();
|
||||||
|
int curr_letter_index = get_curr_letter_index();
|
||||||
|
size_t word_len = strlen(curr_word);
|
||||||
|
|
||||||
|
DrawText(curr_word, 10, 10, 20, BLACK);
|
||||||
|
|
||||||
|
int x = (WINDOW_WIDTH / 2) - (CHAR_SPACING * (word_len / 2));
|
||||||
|
int y = WINDOW_HEIGHT / 2;
|
||||||
|
|
||||||
|
for (int i = 0; i < word_len; i++) {
|
||||||
|
char c = curr_word[i];
|
||||||
|
|
||||||
|
sprintf(buf, "%c\0", c);
|
||||||
|
|
||||||
|
Color color;
|
||||||
|
if (i == curr_letter_index) {
|
||||||
|
color = GOLD;
|
||||||
|
} else if (i < curr_letter_index) {
|
||||||
|
color = DARKGRAY;
|
||||||
|
} else {
|
||||||
|
color = GRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawText(buf, x, y, 50, color);
|
||||||
|
x += CHAR_SPACING;
|
||||||
|
}
|
||||||
|
|
||||||
|
char wins_text[20];
|
||||||
|
snprintf(wins_text, 20, "%d wins", get_wins());
|
||||||
|
DrawText(wins_text, WINDOW_WIDTH - 100, WINDOW_HEIGHT - 20, 20, GRAY);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char **curr_word = word_bank;
|
|
||||||
unsigned short curr_letter_index = 0;
|
|
||||||
unsigned short wins = 0;
|
|
||||||
|
|
||||||
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Typing game");
|
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Typing game");
|
||||||
|
|
||||||
|
init_game_state();
|
||||||
|
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
char buf[2] = {'c', '\0'};
|
process_key_events();
|
||||||
size_t word_len = strlen(*curr_word);
|
|
||||||
|
|
||||||
int k = 0;
|
|
||||||
const char *key_name;
|
|
||||||
// process queued key events
|
|
||||||
while ((k = GetKeyPressed()) != 0) {
|
|
||||||
key_name = GetKeyName(k);
|
|
||||||
|
|
||||||
char c = (*curr_word)[curr_letter_index];
|
|
||||||
sprintf(buf, "%c\0", c);
|
|
||||||
|
|
||||||
if (key_name != NULL &&
|
|
||||||
strcmp(key_name, buf) == 0) {
|
|
||||||
if (curr_letter_index < word_len - 1) { // next letter
|
|
||||||
curr_letter_index++;
|
|
||||||
} else { // next word
|
|
||||||
if (*(curr_word + 1) == NULL) { // wrap around
|
|
||||||
curr_word = word_bank;
|
|
||||||
} else {
|
|
||||||
curr_word++;
|
|
||||||
wins++;
|
|
||||||
}
|
|
||||||
curr_letter_index = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// render
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(WHITE);
|
ClearBackground(WHITE);
|
||||||
DrawText(*curr_word, 10, 10, 20, BLACK);
|
|
||||||
|
render_game_state();
|
||||||
|
|
||||||
int x = (WINDOW_WIDTH / 2) - (CHAR_SPACING * (word_len / 2));
|
|
||||||
int y = WINDOW_HEIGHT / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < word_len; i++) {
|
|
||||||
char c = (*curr_word)[i];
|
|
||||||
|
|
||||||
sprintf(buf, "%c\0", c);
|
|
||||||
|
|
||||||
Color color;
|
|
||||||
if (i == curr_letter_index) {
|
|
||||||
color = GOLD;
|
|
||||||
} else if (i < curr_letter_index) {
|
|
||||||
color = GRAY;
|
|
||||||
} else {
|
|
||||||
color = DARKGRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawText(buf, x, y, 50, color);
|
|
||||||
x += CHAR_SPACING;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawFPS(WINDOW_WIDTH - 100, 10); // top right
|
DrawFPS(WINDOW_WIDTH - 100, 10); // top right
|
||||||
|
|
||||||
char wins_text[20];
|
|
||||||
snprintf(wins_text, 20, "%d wins", wins);
|
|
||||||
DrawText(wins_text, WINDOW_WIDTH - 100, WINDOW_HEIGHT - 20, 20, GRAY);
|
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user