summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2018-07-09 01:06:04 +0300
committerOxore <oxore@protonmail.com>2018-07-09 01:06:04 +0300
commit73ec96ee907f0a8ebdeec20f2058de705b00d65d (patch)
tree144d4558a6cf91948e2946194406c2268ae6bb7c /src
parent45ebf081cbf623bc258d20f38b68ed6c334316d3 (diff)
Finish painter, refactor game logic & keys handling
Add dependencies in Makefile: now it tracks headers too! Introduce texts in painter. Delegate all the window painting to the painter. Refactor texts from yaml parsing. Remove overcomplicated keymaps and lists of keymaps of... Whatever! Just let em go! Simple idlist with foreach is more than enough. Make displayable values be separate text objects which consists only of a number value that rendered every tick and then displayed. Refactor game logic: make state machine look much obvious with transition functions. Refactor long if-else and switch-case statement chains: replace them with arrays of values (it actually takes more lines of code :P) Refactor keys handling: shorten and separate shape moving code to functions.
Diffstat (limited to 'src')
-rw-r--r--src/engine.c493
-rw-r--r--src/field.c1
-rw-r--r--src/idlist.c11
-rw-r--r--src/main.c116
-rw-r--r--src/painter.c (renamed from src/draw.c)185
-rw-r--r--src/text.c287
6 files changed, 564 insertions, 529 deletions
diff --git a/src/engine.c b/src/engine.c
index 9840b34..c218105 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -7,41 +7,97 @@
#include <SFML/Graphics/Text.h>
#include "common.h"
+#include "idlist.h"
#include "tet_conf.h"
+#include "vector.h"
#include "text.h"
#include "field.h"
-#include "draw.h"
+#include "painter.h"
#include "engine.h"
+#define RIGHT (1 << 0)
+#define UP (1 << 1)
+#define DOWN (1 << 2)
+#define LEFT (1 << 3)
+#define RIGHTHOLD (1 << 4)
+#define LEFTHOLD (1 << 7)
+
+int level_move_latency[] = {
+ L00LATENCY,
+ L01LATENCY,
+ L02LATENCY,
+ L03LATENCY,
+ L04LATENCY,
+ L05LATENCY,
+ L06LATENCY,
+ L07LATENCY,
+ L08LATENCY,
+ L09LATENCY,
+ L10LATENCY,
+ L11LATENCY,
+ L12LATENCY,
+ L13LATENCY,
+ L14LATENCY,
+ L15LATENCY,
+ L16LATENCY,
+ L17LATENCY,
+ L18LATENCY,
+ L19LATENCY,
+ L20LATENCY,
+ L21LATENCY,
+ L22LATENCY,
+ L23LATENCY,
+ L24LATENCY,
+ L25LATENCY,
+ L26LATENCY,
+ L27LATENCY,
+ L28LATENCY,
+ L29LATENCY
+};
+
+int rmlines_score[] = {
+ 0,
+ RM_1LINES_SCORE,
+ RM_2LINES_SCORE,
+ RM_3LINES_SCORE,
+ RM_4LINES_SCORE
+};
+
/* Externs from main.c */
-extern struct game game;
-extern struct field fld, nxt;
-
-extern char arrKeys; // Arrow keys states byte container
-
-void valueAfterTextDisplay(int value, List *texts, char *type)
-{
- List *l = texts;
- while (l) {
- Text *text = (Text *)l->obj;
- if (text->type)
- if (!strcmp(text->type, type)) {
- char a[64];
- if (text->text) {
- if (strlen(text->text) > 52) {
- memset(text->text+52, '\0', 1);
- strcpy(a, text->text);
- }
- sprintf(a, "%s%d", text->text, value);
- sfText_setString(text->sfText, (char *)&a);
- break;
- }
- }
- l = l->next;
+extern struct game game;
+extern struct field fld, nxt;
+extern struct idlist *texts;
+extern char arrKeys;
+
+static void render_score_value(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->type, "score.value")) {
+ if (!text->text)
+ text->text = malloc(sizeof(char) * BUFSIZ);
+ sprintf(text->text, "%d", game.scoreCurrent);
}
}
-void checkLevelUp(struct game *game)
+static void render_level_value(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->type, "level.value")) {
+ if (!text->text)
+ text->text = malloc(sizeof(char) * BUFSIZ);
+ sprintf(text->text, "%d", game.level);
+ }
+}
+
+static int getMoveLatencyOfLevel(unsigned int level)
+{
+ if (level > 29)
+ return level_move_latency[29];
+ else
+ return level_move_latency[level];
+}
+
+static void level_up(struct game *game)
{
while (game->lines >= LEVELUP_LINES) {
game->level++;
@@ -50,206 +106,259 @@ void checkLevelUp(struct game *game)
}
}
-int getMoveLatencyOfLevel(unsigned int level)
-{
- if (level >= 29)
- return L29LATENCY;
- else if (level >= 19)
- return L19LATENCY;
- else if (level >= 16)
- return L16LATENCY;
- else if (level >= 13)
- return L13LATENCY;
- else if (level >= 10)
- return L10LATENCY;
- else if (level == 9)
- return L09LATENCY;
- else if (level == 8)
- return L08LATENCY;
- else if (level == 7)
- return L07LATENCY;
- else if (level == 6)
- return L06LATENCY;
- else if (level == 5)
- return L05LATENCY;
- else if (level == 4)
- return L04LATENCY;
- else if (level == 3)
- return L03LATENCY;
- else if (level == 2)
- return L02LATENCY;
- else if (level == 1)
- return L01LATENCY;
- else if (level == 0)
- return L00LATENCY;
- return L00LATENCY;
-}
-
-
-/*
- * Game tick
- *
- */
-void tTick()
-{ // If tick exceeds current level tick latency
- if (sfClock_getElapsedTime(game.gameTick).microseconds >= game.moveLatency) {
- sfClock_restart(game.gameTick);
- fld.shape[0].y--; // try
- if (field_shape_collision(&fld, &fld.shape[0]))
- fld.shape[0].y++; // fallback
+static void hide_menu_text(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->scene, "menu"))
+ text->attr |= TXT_ATTR_INVISIBLE;
+}
+
+static void show_menu_text(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->scene, "menu"))
+ text->attr &= ~TXT_ATTR_INVISIBLE;
+}
+
+static void hide_game_text(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->scene, "game"))
+ text->attr |= TXT_ATTR_INVISIBLE;
+}
+
+static void show_game_text(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->scene, "game"))
+ text->attr &= ~TXT_ATTR_INVISIBLE;
+}
+
+static void update_menu_text(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->scene, "menu"))
+ painter_update_text(text->id, text);
+}
+
+static void update_game_text(void *obj)
+{
+ struct text *text = obj;
+ if (!strcmp(text->scene, "game"))
+ painter_update_text(text->id, text);
+}
+
+static void transition_game_over()
+{
+ game.isStarted = 0;
+ game.scoreCurrent = 0;
+ game.level = 0;
+ game.moveLatency = L00LATENCY;
+ game.lines = 0;
+
+ nxt.attr |= FLD_ATTR_INVISIBLE;
+ painter_update_field(nxt.id, &nxt);
+
+ fld.shape[0].y = fld.size.y;
+ field_fill_random(&fld);
+ painter_update_field(fld.id, &fld);
+
+ list_foreach(texts, show_menu_text);
+ list_foreach(texts, hide_game_text);
+ list_foreach(texts, update_menu_text);
+ list_foreach(texts, update_game_text);
+}
+
+static void transition_put_shape()
+{
+ field_put_shape(&fld, &fld.shape[0]);
+ int removedLines = field_rm_lines(&fld);
+ game.lines += removedLines;
+ game.scoreCurrent += rmlines_score[removedLines] * game.level;
+ fld.shape[0].t = nxt.shape[0].t;
+ field_reset_walking_shape(&fld, 0);
+ for (unsigned int s = 0; s < nxt.shape_cnt - 1; ++s) {
+ nxt.shape[s] = nxt.shape[s + 1];
+ nxt.shape[s].y = 4 - s * 3;
+ }
+ shape_gen_random(&nxt.shape[nxt.shape_cnt - 1]);
+ level_up(&game);
+}
+
+static void game_tick()
+{
+ sfClock_restart(game.gameTick);
+ fld.shape[0].y--; // try
+ if (field_shape_collision(&fld, &fld.shape[0]))
+ fld.shape[0].y++; // fallback
+ else
+ sfClock_restart(game.putTick);
+ if (sfClock_getElapsedTime(game.putTick).microseconds >= PUT_LATENCY) {
+ if (field_shape_out_of_bounds(&fld, &fld.shape[0]))
+ transition_game_over();
else
- sfClock_restart(game.putTick);
- if (sfClock_getElapsedTime(game.putTick).microseconds >= PUT_LATENCY) {
- if (field_shape_out_of_bounds(&fld, &fld.shape[0])) {
- gameover(&game);
- fld.shape[0].y = fld.size.y;
- field_fill_random(&fld);
- nxt.attr |= FLD_ATTR_INVISIBLE;
- painter_update_field(nxt.id, &nxt);
- return;
- } else {
- field_put_shape(&fld, &fld.shape[0]);
- int removedLines = field_rm_lines(&fld);
- game.lines += removedLines;
- switch (removedLines) {
- case 1:
- game.scoreCurrent += RM_1LINES_SCORE * game.level;
- break;
- case 2:
- game.scoreCurrent += RM_2LINES_SCORE * game.level;
- break;
- case 3:
- game.scoreCurrent += RM_3LINES_SCORE * game.level;
- break;
- case 4:
- game.scoreCurrent += RM_4LINES_SCORE * game.level;
- break;
- }
- fld.shape[0].t = nxt.shape[0].t;
- field_reset_walking_shape(&fld, 0);
- for (unsigned int s = 0; s < nxt.shape_cnt - 1; ++s) {
- nxt.shape[s] = nxt.shape[s + 1];
- nxt.shape[s].y = 4 - s * 3;
- }
- shape_gen_random(&nxt.shape[nxt.shape_cnt - 1]);
- checkLevelUp(&game);
- }
- sfClock_restart(game.putTick);
- }
+ transition_put_shape();
+ sfClock_restart(game.putTick);
}
}
-/*
- * Keys hold handler
- *
- */
-void tKeyCtrl()
+static void signal_up()
+{
+ field_rotate_shape(&fld, 0);
+}
+
+static void signal_down()
{
- /* Up arrow key 'hold' handler */
+ fld.shape[0].y--;
+ if (field_shape_collision(&fld, &fld.shape[0])) {
+ fld.shape[0].y++;
+ } else {
+ sfClock_restart(game.gameTick);
+ game.scoreCurrent++;
+ }
+ sfClock_restart(game.repPushDown);
+}
+
+static void signal_left()
+{
+ fld.shape[0].x--;
+ if (field_shape_collision(&fld, &fld.shape[0]))
+ fld.shape[0].x++;
+ else
+ sfClock_restart(game.putTick);
+ sfClock_restart(game.repKeyLeft);
+}
+
+static void signal_right()
+{
+ fld.shape[0].x++;
+ if (field_shape_collision(&fld, &fld.shape[0]))
+ fld.shape[0].x--;
+ else
+ sfClock_restart(game.putTick);
+ sfClock_restart(game.repKeyRight);
+}
+
+static void game_keys()
+{
+ /* UP */
if (sfKeyboard_isKeyPressed(sfKeyUp)) {
if (!(arrKeys & UP)) {
arrKeys = arrKeys | UP;
- field_rotate_shape(&fld, 0);
+ signal_up();
}
} else {
- if ((arrKeys & UP)) {
- arrKeys = arrKeys & ~UP;
- }
+ arrKeys = arrKeys & ~UP;
}
- /* Down Arrow Key 'hold' handler */
+ /* DOWN */
if (sfKeyboard_isKeyPressed(sfKeyDown)) {
if (!(arrKeys & DOWN)) {
arrKeys = arrKeys | DOWN;
- fld.shape[0].y--;
- if (field_shape_collision(&fld, &fld.shape[0]))
- fld.shape[0].y++;
- else {
- // Avoid excess move down by gameTick
- sfClock_restart(game.putTick);
- sfClock_restart(game.gameTick);
- game.scoreCurrent++;
- }
- sfClock_restart(game.repPushDown);
+ signal_down();
} else {
- if (sfClock_getElapsedTime(game.repPushDown).microseconds
- >= moveRepeatLatency2)
+ if (sfClock_getElapsedTime(game.repPushDown).microseconds >= moveRepeatLatency2)
arrKeys = arrKeys & ~DOWN;
}
} else {
- if ((arrKeys & DOWN)) {
- arrKeys = arrKeys & ~DOWN;
- }
+ arrKeys = arrKeys & ~DOWN;
}
- /* Left Arrow Key 'hold' handler */
- if (sfKeyboard_isKeyPressed(sfKeyLeft)
- && !sfKeyboard_isKeyPressed(sfKeyRight)) {
+ /* LEFT */
+ if (sfKeyboard_isKeyPressed(sfKeyLeft) && !sfKeyboard_isKeyPressed(sfKeyRight)) {
if (!(arrKeys & LEFT)) {
arrKeys = arrKeys | LEFT;
- fld.shape[0].x--;
- if (field_shape_collision(&fld, &fld.shape[0]))
- fld.shape[0].x++;
- else
- sfClock_restart(game.putTick);
- sfClock_restart(game.repKeyLeft);
- } else {
- if (!(arrKeys & LEFTHOLD)) {
- if (sfClock_getElapsedTime(game.repKeyLeft).microseconds
- >= moveRepeatLatency1) {
- arrKeys = arrKeys | LEFTHOLD;
- arrKeys = arrKeys & ~LEFT;
- }
- } else {
- if (sfClock_getElapsedTime(game.repKeyLeft).microseconds
- >= moveRepeatLatency2)
- arrKeys = arrKeys & ~LEFT;
+ signal_left();
+ } else if (!(arrKeys & LEFTHOLD)) {
+ if (sfClock_getElapsedTime(game.repKeyLeft).microseconds >= moveRepeatLatency1) {
+ arrKeys = arrKeys | LEFTHOLD;
+ arrKeys = arrKeys & ~LEFT;
}
+ } else {
+ if (sfClock_getElapsedTime(game.repKeyLeft).microseconds >= moveRepeatLatency2)
+ arrKeys = arrKeys & ~LEFT;
}
- } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) {
- if ((arrKeys & LEFT)) {
- arrKeys = arrKeys & ~LEFT;
- arrKeys = arrKeys & ~LEFTHOLD;
- }
+ } else {
+ arrKeys = arrKeys & ~LEFT;
+ arrKeys = arrKeys & ~LEFTHOLD;
}
- /* Right Arrow Key 'hold' handler */
- if (sfKeyboard_isKeyPressed(sfKeyRight)
- && !sfKeyboard_isKeyPressed(sfKeyLeft)) {
+ /* RIGHT */
+ if (sfKeyboard_isKeyPressed(sfKeyRight) && !sfKeyboard_isKeyPressed(sfKeyLeft)) {
if (!(arrKeys & RIGHT)) {
arrKeys = arrKeys | RIGHT;
- fld.shape[0].x++;
- if (field_shape_collision(&fld, &fld.shape[0]))
- fld.shape[0].x--;
- else
- sfClock_restart(game.putTick);
- sfClock_restart(game.repKeyRight);
- } else {
- if (!(arrKeys & RIGHTHOLD)) {
- if (sfClock_getElapsedTime(game.repKeyRight).microseconds
- >= moveRepeatLatency1) {
- arrKeys = arrKeys | RIGHTHOLD;
- arrKeys = arrKeys & ~RIGHT;
- }
- } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) {
- if (sfClock_getElapsedTime(game.repKeyRight).microseconds
- >= moveRepeatLatency2) // Wait short time
- arrKeys = arrKeys & ~RIGHT;
+ signal_right();
+ } else if (!(arrKeys & RIGHTHOLD)) {
+ if (sfClock_getElapsedTime(game.repKeyRight).microseconds >= moveRepeatLatency1) {
+ arrKeys = arrKeys | RIGHTHOLD;
+ arrKeys = arrKeys & ~RIGHT;
}
+ } else {
+ if (sfClock_getElapsedTime(game.repKeyRight).microseconds >= moveRepeatLatency2)
+ arrKeys = arrKeys & ~RIGHT;
}
} else {
- if ((arrKeys & RIGHT)) {
- arrKeys = arrKeys & ~RIGHT;
- arrKeys = arrKeys & ~RIGHTHOLD;
- }
+ arrKeys = arrKeys & ~RIGHT;
+ arrKeys = arrKeys & ~RIGHTHOLD;
}
}
-void gameover(struct game *game)
+static void menuTick()
{
- game->isStarted = 0;
- game->scoreCurrent = 0;
- game->level = 0;
- game->moveLatency = L00LATENCY;
- game->lines = 0;
+ sfClock_restart(game.mTick);
+ field_fill_random(&fld);
+ painter_update_field(fld.id, &fld);
}
+
+void transition_init(void)
+{
+ list_foreach(texts, show_menu_text);
+ list_foreach(texts, hide_game_text);
+ list_foreach(texts, update_menu_text);
+ list_foreach(texts, update_game_text);
+}
+
+static void transition_game_start()
+{
+ game.isStarted = 1;
+ field_clear(&fld);
+ shape_gen_random(&fld.shape[0]);
+ field_reset_walking_shape(&fld, 0);
+ for (unsigned int i = 0; i < nxt.shape_cnt; ++i)
+ shape_gen_random(&nxt.shape[i]);
+ nxt.attr &= ~FLD_ATTR_INVISIBLE;
+ list_foreach(texts, hide_menu_text);
+ list_foreach(texts, show_game_text);
+ list_foreach(texts, update_menu_text);
+ list_foreach(texts, update_game_text);
+ sfClock_restart(game.gameTick);
+}
+
+static void menu_loop() {
+ if (sfClock_getElapsedTime(game.mTick).microseconds >= basicLatency)
+ menuTick();
+ if (sfKeyboard_isKeyPressed(sfKeyS) == 1)
+ transition_game_start();
+ painter_draw();
+}
+
+static void game_loop() {
+ game_keys();
+ if (sfClock_getElapsedTime(game.gameTick).microseconds >= game.moveLatency)
+ game_tick();
+ list_foreach(texts, render_score_value);
+ list_foreach(texts, render_level_value);
+ painter_update_field(fld.id, &fld);
+ painter_update_field(nxt.id, &nxt);
+ list_foreach(texts, update_game_text);
+ painter_draw();
+}
+
+void main_loop()
+{
+ if (game.isStarted)
+ game_loop();
+ else
+ menu_loop();
+}
+
diff --git a/src/field.c b/src/field.c
index 37680ae..18b4fed 100644
--- a/src/field.c
+++ b/src/field.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <SFML/Graphics/RectangleShape.h>
+#include "vector.h"
#include "field.h"
#include "tet_conf.h"
diff --git a/src/idlist.c b/src/idlist.c
index 5b4d99b..b9d551a 100644
--- a/src/idlist.c
+++ b/src/idlist.c
@@ -53,3 +53,14 @@ void list_foreach(struct idlist *list, void (*job)(void *))
job(list->obj);
}
}
+
+void list_destroy(struct idlist *list)
+{
+ if (list) {
+ while (list->next) {
+ list = list->next;
+ free(list->prev);
+ }
+ free(list);
+ }
+}
diff --git a/src/main.c b/src/main.c
index aa27332..6eafc6e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,15 +8,17 @@
#include <SFML/Graphics/Font.h>
#include "common.h"
+#include "idlist.h"
+#include "vector.h"
#include "text.h"
#include "field.h"
-#include "draw.h"
+#include "painter.h"
#include "engine.h"
#include "tet_conf.h"
-extern struct window w;
+sfRenderWindow *window;
+struct idlist *texts;
-List *texts;
sfFont *fontScore;
struct field fld, nxt;
struct game game = {
@@ -27,72 +29,19 @@ struct game game = {
.lines = 0
};
-char arrKeys = 0; // Arrow keys states byte container
+char arrKeys = 0;
-void prepare() {
+static void handleWindowEvents() {
+ sfEvent event;
+ while (sfRenderWindow_pollEvent(window, &event))
+ if (event.type == sfEvtClosed)
+ sfRenderWindow_close(window);
}
-void handleWindowEvents() {
- while (sfRenderWindow_pollEvent(w.window, &w.event))
- if (w.event.type == sfEvtClosed)
- sfRenderWindow_close(w.window);
-}
-
-void drawTextsAtScene(List *texts, char *scene, sfRenderWindow *window) {
- List *t = texts;
- while (t) {
- if (!strcmp(((Text *)t->obj)->scene, scene))
- sfRenderWindow_drawText(window, ((Text *)t->obj)->sfText, NULL);
- t = t->next;
- }
-}
-
-void gameLoop() {
- tTick();
- tKeyCtrl();
- valueAfterTextDisplay(game.scoreCurrent, texts, "score");
- valueAfterTextDisplay(game.level, texts, "level");
- painter_update_field(fld.id, &fld);
- painter_update_field(nxt.id, &nxt);
- drawTextsAtScene(texts, "game", w.window);
- painter_draw();
-}
-
-void menuTick()
+static void register_text(void *obj)
{
- if (sfClock_getElapsedTime(game.mTick).microseconds >= basicLatency) {
- sfClock_restart(game.mTick);
- field_fill_random(&fld);
- painter_update_field(fld.id, &fld);
- }
-}
-
-void menuLoop() {
- menuTick();
- drawTextsAtScene(texts, "menu", w.window);
- if (sfKeyboard_isKeyPressed(sfKeyS) == 1) {
- game.isStarted = 1;
- field_clear(&fld);
- shape_gen_random(&fld.shape[0]);
- field_reset_walking_shape(&fld, 0);
- for (unsigned int i = 0; i < nxt.shape_cnt; ++i)
- shape_gen_random(&nxt.shape[i]);
- nxt.attr &= ~FLD_ATTR_INVISIBLE;
- sfClock_restart(game.gameTick);
- }
- painter_draw();
-}
-
-void mainLoop() {
- while (sfRenderWindow_isOpen(w.window)) {
- handleWindowEvents();
- sfRenderWindow_clear(w.window, (sfColor)UIBGCOLOR);
- if (game.isStarted)
- gameLoop();
- else
- menuLoop();
- sfRenderWindow_display(w.window);
- }
+ struct text *text = obj;
+ text->id = painter_register_text(text);
}
int main()
@@ -104,15 +53,19 @@ int main()
game.repPushDown = sfClock_create();
game.repKeyLeft = sfClock_create();
game.repKeyRight = sfClock_create();
+ painter_load_font("dat/arial.ttf");
fontScore = sfFont_createFromFile("dat/arial.ttf");
if (!fontScore) {
- printf("dat/arial.ttf font load failed");
- exit(-1);
+ printf("%s font load failed", "dat/arial.ttf");
+ exit(EXIT_FAILURE);
}
- painter_init_window();
- List *tmp = ListOfKeyMapOfString_getFromYaml("dat/texts.yaml");
- texts = ListOfText_getFromListOfKeyMapOfString(tmp);
- ListOfKeyMapOfString_free(&tmp);
+
+ sfVideoMode mode = (sfVideoMode){450, 570, 32};
+ window = sfRenderWindow_create(mode, windowName_conf, sfResize | sfClose, NULL);
+ if (!window)
+ exit(EXIT_FAILURE);
+ sfRenderWindow_setFramerateLimit(window, 60);
+ painter_set_window(window);
fld.pos = FLD_POS;
fld.size = (struct vector2ui){.x = FLD_SIZE_X, .y = FLD_SIZE_Y};
@@ -136,19 +89,34 @@ int main()
painter_update_field(fld.id, &fld);
painter_update_field(nxt.id, &nxt);
- mainLoop();
+ texts = load_texts("dat/texts.yaml");
+
+ list_foreach(texts, register_text);
+
+ transition_init();
+ while (sfRenderWindow_isOpen(window)) {
+ handleWindowEvents();
+ main_loop();
+ }
+
+ list_foreach(texts, text_destroy);
+ list_destroy(texts);
+
painter_destroy_drawables();
field_deinit(&fld);
field_deinit(&nxt);
- painter_destroy_window();
+ if (window) {
+ sfRenderWindow_destroy(window);
+ window = 0;
+ }
sfFont_destroy(fontScore);
+ painter_destroy_font();
sfClock_destroy(game.gameTick);
sfClock_destroy(game.putTick);
sfClock_destroy(game.mTick);
sfClock_destroy(game.repPushDown);
sfClock_destroy(game.repKeyLeft);
sfClock_destroy(game.repKeyRight);
- ListOfText_free(&texts);
return EXIT_SUCCESS;
}
diff --git a/src/draw.c b/src/painter.c
index dd888d0..9f6b911 100644
--- a/src/draw.c
+++ b/src/painter.c
@@ -1,10 +1,15 @@
#include <SFML/Graphics/RenderWindow.h>
#include <SFML/Graphics/RectangleShape.h>
+#include <SFML/Graphics/Font.h>
+#include <SFML/Graphics/Text.h>
#include <stdlib.h>
+#include <stdio.h>
#include "tet_conf.h"
+#include "vector.h"
+#include "text.h"
#include "field.h"
-#include "draw.h"
+#include "painter.h"
#include "idlist.h"
@@ -19,48 +24,65 @@ static sfColor shape_color_map[] = {
TCOLOR,
};
+enum t {
+ TYPE_U,
+ TYPE_FIELD,
+ TYPE_TEXT
+};
+
+struct drawable {
+ enum t t;
+};
struct field_drawable {
+ struct drawable;
+
sfRectangleShape ***p;
- struct vector2ui size;
- unsigned int attr;
+ struct vector2ui size;
+ unsigned int attr;
};
-/*
- * TODO: Must be static in future
- *
- * */
-struct window w;
+struct text_drawable {
+ struct drawable;
+
+ sfText *text;
+ unsigned long attr;
+};
-static struct idlist *fields_list = NULL;
+static sfRenderWindow *window;
+static sfFont *font;
-void painter_init_window()
+static struct idlist *drawables = NULL;
+
+void painter_set_window(sfRenderWindow *w)
{
- w = (struct window){.mode = {450, 570, 32}};
- w.window = sfRenderWindow_create(w.mode, windowName_conf,
- sfResize | sfClose, NULL);
- if (!w.window)
- exit(EXIT_FAILURE);
- sfRenderWindow_setFramerateLimit(w.window, 60);
+ window = w;
}
-void painter_destroy_window()
+void painter_load_font(char *filename)
{
- if (w.window) {
- sfRenderWindow_destroy(w.window);
- w.window = 0;
+ font = sfFont_createFromFile(filename);
+ if (!font) {
+ printf("%s font load failed", filename);
+ exit(EXIT_FAILURE);
}
}
+void painter_destroy_font()
+{
+ sfFont_destroy(font);
+}
+
unsigned long painter_register_field(struct field *fld)
{
struct idlist *last;
- if (!fields_list)
- last = fields_list = list_new();
+ if (!drawables)
+ last = drawables = list_new();
else
- last = list_append(fields_list);
+ last = list_append(drawables);
struct field_drawable *f = calloc(1, sizeof(struct field_drawable));
+ f->t = TYPE_FIELD;
f->size = fld->size;
f->p = calloc(f->size.y, sizeof(sfRectangleShape **));
for (unsigned int j = 0; j < f->size.y; j++) {
@@ -84,7 +106,7 @@ unsigned long painter_register_field(struct field *fld)
void painter_update_field(unsigned long id, struct field *fld)
{
- struct idlist *node = list_get(fields_list, id);
+ struct idlist *node = list_get(drawables, id);
if (!node)
return;
struct field_drawable *f = node->obj;
@@ -120,23 +142,18 @@ void painter_update_field(unsigned long id, struct field *fld)
}
}
-static void draw_field(void *field)
+static void draw_field_drawable(struct drawable *d)
{
- struct field_drawable *f = field;
+ struct field_drawable *f = (void *)d;
if (!(f->attr & FLD_ATTR_INVISIBLE))
for (unsigned int j = 0; j < f->size.y; j++)
for (unsigned int i = 0; i < f->size.x; i++)
- sfRenderWindow_drawRectangleShape(w.window, f->p[j][i], NULL);
-}
-
-static void draw_fields()
-{
- list_foreach(fields_list, draw_field);
+ sfRenderWindow_drawRectangleShape(window, f->p[j][i], NULL);
}
-static void destroy_field(void *field)
+static void destroy_field_drawable(struct drawable *d)
{
- struct field_drawable *f = field;
+ struct field_drawable *f = (void *)d;
for (unsigned int j = 0; j < f->size.y; j++) {
for (unsigned int i = 0; i < f->size.x; i++)
sfRectangleShape_destroy(f->p[j][i]);
@@ -146,30 +163,112 @@ static void destroy_field(void *field)
free(f);
}
-void painter_destroy_field(unsigned long id)
+unsigned long painter_register_text(struct text *txt)
{
- struct idlist *node = list_get(fields_list, id);
- destroy_field(node->obj);
- list_rm_node(node);
+ struct idlist *last;
+ if (!drawables)
+ last = drawables = list_new();
+ else
+ last = list_append(drawables);
+
+ struct text_drawable *t = calloc(1, sizeof(struct text_drawable));
+ t->t = TYPE_TEXT;
+ t->text = sfText_create();
+ sfText_setFont(t->text, font);
+ sfText_setCharacterSize(t->text, txt->size);
+ sfVector2f pos = (sfVector2f){.x = txt->pos.x, .y = txt->pos.y};
+ sfText_setPosition(t->text, pos);
+ sfText_setString(t->text, txt->text);
+
+ last->obj = t;
+ return last->id;
}
-void painter_destroy_fields()
+void painter_update_text(unsigned long id, struct text *txt)
{
- list_foreach(fields_list, destroy_field);
+ struct idlist *node = list_get(drawables, id);
+ if (!node)
+ return;
+ struct text_drawable *t = node->obj;
+ t->attr = txt->attr;
+ sfText_setCharacterSize(t->text, txt->size);
+ sfVector2f pos = (sfVector2f){.x = txt->pos.x, .y = txt->pos.y};
+ sfText_setPosition(t->text, pos);
+ sfText_setString(t->text, txt->text);
+}
+
+static void draw_text_drawable(struct drawable *d)
+{
+ struct text_drawable *t = (struct text_drawable *)d;
+ if (!(t->attr & TXT_ATTR_INVISIBLE))
+ sfRenderWindow_drawText(window, t->text, NULL);
+}
+
+static void destroy_text_drawable(struct drawable *d)
+{
+ struct text_drawable *t = (struct text_drawable *)d;
+ sfText_destroy(t->text);
+ free(t);
+}
+
+static void draw_drawable(void *obj)
+{
+ struct drawable *d = obj;
+ switch (d->t) {
+ case TYPE_FIELD:
+ draw_field_drawable(d);
+ break;
+ case TYPE_TEXT:
+ draw_text_drawable(d);
+ break;
+ case TYPE_U:
+ fprintf(stderr, "ERROR: Unknown type of drawable\n");
+ exit(EXIT_FAILURE);
+ break;
+ }
}
void painter_draw()
{
- draw_fields();
+ sfRenderWindow_clear(window, (sfColor)UIBGCOLOR);
+ list_foreach(drawables, draw_drawable);
+ sfRenderWindow_display(window);
+}
+
+static void destroy_drawable(void *obj)
+{
+ struct drawable *d = obj;
+ switch (d->t) {
+ case TYPE_FIELD:
+ destroy_field_drawable(d);
+ break;
+ case TYPE_TEXT:
+ destroy_text_drawable(d);
+ break;
+ case TYPE_U:
+ fprintf(stderr, "ERROR: Unknown type of drawable\n");
+ exit(EXIT_FAILURE);
+ break;
+ }
+}
+
+void painter_destroy_drawable(unsigned long id)
+{
+ struct idlist *node = list_get(drawables, id);
+ destroy_drawable(node->obj);
+ list_rm_node(node);
}
void painter_destroy_drawables()
{
- painter_destroy_fields();
+ list_foreach(drawables, destroy_drawable);
+ list_destroy(drawables);
+ drawables = 0;
}
void painter_destroy_all()
{
painter_destroy_drawables();
- painter_destroy_window();
+ painter_destroy_font();
+ window = 0;
}
diff --git a/src/text.c b/src/text.c
index e1e1e6e..a61d28a 100644
--- a/src/text.c
+++ b/src/text.c
@@ -7,255 +7,102 @@
#include <yaml.h>
#include "common.h"
+#include "idlist.h"
+#include "vector.h"
#include "text.h"
-extern sfFont *fontScore;
-
-FILE *openFile(char *filename)
+static FILE *openFile(char *filename)
{
FILE *file;
if (!(file = fopen(filename, "rb"))){
- printf("ERROR\n");
+ printf("ERROR: fild \"%s\"cannot be opened\n", filename);
exit(EXIT_FAILURE);
}
return file;
}
-void checkArgs(int argc, char **argv)
-{
- if (argc < 2) {
- printf("Usage: %s file1.yaml ...\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-}
-
-KeyMap *KeyMap_getLast(KeyMap **keyMap)
-{
- KeyMap *keyMapLocal = *keyMap;
- if (keyMapLocal)
- while (keyMapLocal->next)
- keyMapLocal = keyMapLocal->next;
- return keyMapLocal;
-}
-
-KeyMap *KeyMap_new(KeyMap **keyMap)
-{
- KeyMap *keyMapLocal = KeyMap_getLast(keyMap);
- if (keyMapLocal) {
- keyMapLocal->next = malloc(sizeof(KeyMap));
- ((KeyMap *)keyMapLocal->next)->prev = keyMapLocal;
- keyMapLocal = keyMapLocal->next;
- } else {
- *keyMap = malloc(sizeof(KeyMap));
- keyMapLocal = *keyMap;
- keyMapLocal->prev = 0;
- }
- keyMapLocal->pair = malloc(sizeof(Pair));
- keyMapLocal->next = 0;
- return keyMapLocal;
-}
-
-KeyMap *KeyMap_get(KeyMap **keyMap, const void *key)
-{
- KeyMap *keyMapLocal = *keyMap;
- while (keyMapLocal)
- if (keyMapLocal->pair)
- if (keyMapLocal->pair->k)
- if (!strcmp(keyMapLocal->pair->k, key))
- return keyMapLocal;
- else
- keyMapLocal = keyMapLocal->next;
- else
- keyMapLocal = keyMapLocal->next;
- else
- keyMapLocal = keyMapLocal->next;
- return 0;
-}
-
-KeyMap *KeyMap_put(KeyMap **keyMap, const void *key, const void *value)
+struct idlist *load_texts(char *filename)
{
- KeyMap *keyMapLocal = KeyMap_get(keyMap, key);
- if (!keyMapLocal) {
- keyMapLocal = KeyMap_new(keyMap);
- keyMapLocal->pair->k = malloc(strlen(key)+1);
- strcpy(keyMapLocal->pair->k, key);
- }
- keyMapLocal->pair->v = malloc(strlen(value)+1);
- strcpy(keyMapLocal->pair->v, value);
- return keyMapLocal;
-}
-
-List *List_getLast(List **list)
-{
- List *listLocal = *list;
- if (listLocal)
- while (listLocal->next)
- listLocal = listLocal->next;
- return listLocal;
-}
-
-List *List_new(List **list)
-{
- List *listLocal = List_getLast(list);
- if (listLocal) {
- (listLocal)->next = malloc(sizeof(List));
- ((List *)listLocal->next)->prev = listLocal;
- listLocal = listLocal->next;
- } else {
- *list = malloc(sizeof(List));
- (*list)->prev = 0;
- listLocal = *list;
- }
- listLocal->obj = 0;
- listLocal->next = 0;
- return listLocal;
-}
-
-List *ListOfKeyMapOfString_getFromYaml(char *filename)
-{
- List *list = 0;
FILE *file = openFile(filename);
yaml_parser_t parser;
yaml_event_t event;
yaml_parser_initialize(&parser);
yaml_parser_set_input_file(&parser, file);
+
+ struct idlist *texts = NULL;
+ struct idlist *texts_node = texts;
do {
if (!yaml_parser_parse(&parser, &event)) {
- printf("Parser error %d\n", parser.error);
+ fprintf(stderr, "Parser error %d\n", parser.error);
exit(EXIT_FAILURE);
}
- switch(event.type)
+
+ switch (event.type)
{
- case YAML_MAPPING_START_EVENT:
- List_new(&list);
- break;
- case YAML_SCALAR_EVENT:
- ;yaml_event_t ev;
- yaml_parser_parse(&parser, &ev);
- while (ev.type != YAML_SCALAR_EVENT) {
- yaml_event_delete(&ev);
- if (!yaml_parser_parse(&parser, &ev)) {
- printf("Parser error %d\n", parser.error);
- exit(EXIT_FAILURE);
- }
- }
- KeyMap **keyMap = (KeyMap **)&((List *)List_getLast(&list))->obj;
- KeyMap_put(keyMap, event.data.scalar.value, ev.data.scalar.value);
+ case YAML_MAPPING_START_EVENT:
+ if (!texts) {
+ texts = list_new();
+ texts_node = texts;
+ } else
+ texts_node = list_append(texts);
+ texts_node->obj = calloc(1, sizeof(struct text));
+ break;
+ case YAML_SCALAR_EVENT:
+ ;yaml_event_t ev;
+ yaml_parser_parse(&parser, &ev);
+ while (ev.type != YAML_SCALAR_EVENT) {
yaml_event_delete(&ev);
- break;
- default: break;
+ if (!yaml_parser_parse(&parser, &ev)) {
+ fprintf(stderr, "Parser error %d\n", parser.error);
+ exit(EXIT_FAILURE);
+ }
+ }
+ struct text *text = texts_node->obj;
+ if (!strcmp((char *)event.data.scalar.value, "type")) {
+ text->type = malloc(sizeof(char) * (strlen((char *)ev.data.scalar.value) + 1));
+ strcpy(text->type, (char *)ev.data.scalar.value);
+ } else if (!strcmp((char *)event.data.scalar.value, "scene")) {
+ text->scene = malloc(sizeof(char) * (strlen((char *)ev.data.scalar.value) + 1));
+ strcpy(text->scene, (char *)ev.data.scalar.value);
+ } else if (!strcmp((char *)event.data.scalar.value, "text")) {
+ text->text = malloc(sizeof(char) * (strlen((char *)ev.data.scalar.value) + 1));
+ strcpy(text->text, (char *)ev.data.scalar.value);
+ } else if (!strcmp((char *)event.data.scalar.value, "font")) {
+ text->font = malloc(sizeof(char) * (strlen((char *)ev.data.scalar.value) + 1));
+ strcpy(text->font, (char *)ev.data.scalar.value);
+ } else if (!strcmp((char *)event.data.scalar.value, "size")) {
+ text->size = atoi((char *)ev.data.scalar.value);
+ } else if (!strcmp((char *)event.data.scalar.value, "x")) {
+ text->pos.x = atoi((char *)ev.data.scalar.value);
+ } else if (!strcmp((char *)event.data.scalar.value, "y")) {
+ text->pos.y = atoi((char *)ev.data.scalar.value);
+ }
+ yaml_event_delete(&ev);
+ break;
+ default:
+ break;
}
- if(event.type != YAML_STREAM_END_EVENT)
+
+ if (event.type != YAML_STREAM_END_EVENT)
yaml_event_delete(&event);
- } while(event.type != YAML_STREAM_END_EVENT);
+ } while (event.type != YAML_STREAM_END_EVENT);
+
yaml_event_delete(&event);
yaml_parser_delete(&parser);
fclose(file);
- return list;
-}
-
-void KeyMapOfString_free(KeyMap *keyMap)
-{
- KeyMap *keyMapLocal = KeyMap_getLast(&keyMap);
- while (keyMapLocal) {
- free(keyMapLocal->pair->k);
- free(keyMapLocal->pair->v);
- free(keyMapLocal->pair);
- KeyMap *prev = keyMapLocal->prev;
- free(keyMapLocal);
- keyMapLocal = prev;
- }
-}
-
-void ListOfKeyMapOfString_free(List **list)
-{
- List *listLocal = List_getLast(list);
- while (listLocal) {
- KeyMapOfString_free(listLocal->obj);
- List *prev = listLocal->prev;
- free(listLocal);
- listLocal = prev;
- }
- *list = 0;
-}
-
-static int _loadText_getInt(void *obj, char *key)
-{
- int v = 0;
- KeyMap *keyMap = KeyMap_get((KeyMap **)&obj, key);
- if (keyMap)
- if (keyMap->pair)
- if (keyMap->pair->v)
- v = atoi(keyMap->pair->v);
- return v;
+ return texts;
}
-static char *_loadText_getString(void *obj, char *key)
+void text_destroy(void *obj)
{
- char *v = 0;
- KeyMap *keyMap = KeyMap_get((KeyMap **)&obj, key);
- if (keyMap)
- if (keyMap->pair)
- if (keyMap->pair->v) {
- v = malloc(strlen(keyMap->pair->v)+1);
- strcpy(v, keyMap->pair->v);
- }
- return v;
-}
-
-static void _loadText_initSfText(Text *objo, void *obji)
-{
- sfVector2f pos = {
- .x = _loadText_getInt(obji, "x"),
- .y = _loadText_getInt(obji, "y")
- };
- int size = _loadText_getInt(obji, "size");
- char *text = _loadText_getString(obji, "text");
- objo->sfText = sfText_create();
- sfText_setFont(objo->sfText, fontScore);
- sfText_setCharacterSize(objo->sfText, size);
- sfText_setPosition(objo->sfText, pos);
- sfText_setString(objo->sfText, text);
+ struct text *text = obj;
+ if (text->type)
+ free(text->type);
+ if (text->scene)
+ free(text->scene);
+ if (text->text)
+ free(text->text);
+ if (text->font)
+ free(text->font);
free(text);
}
-
-List *ListOfText_getFromListOfKeyMapOfString(List *list)
-{
- List *li = list;
- List *lo = 0;
- List *l = 0;
- while (li) {
- List_new(&lo);
- l = List_getLast(&lo);
- l->obj = malloc(sizeof(Text));
- ((Text *)l->obj)->type = _loadText_getString(li->obj, "type");
- ((Text *)l->obj)->font = _loadText_getString(li->obj, "font");
- ((Text *)l->obj)->scene = _loadText_getString(li->obj, "scene");
- ((Text *)l->obj)->text = _loadText_getString(li->obj, "text");
- _loadText_initSfText(l->obj, li->obj);
- li = li->next;
- }
- return lo;
-}
-
-void Text_free(Text *obj)
-{
- free(obj->type);
- free(obj->scene);
- free(obj->text);
- free(obj->font);
- sfText_destroy(obj->sfText);
- free(obj);
-}
-
-void ListOfText_free(List **list)
-{
- List *listLocal = List_getLast(list);
- while (listLocal) {
- Text_free(listLocal->obj);
- List *prev = listLocal->prev;
- free(listLocal);
- listLocal = prev;
- }
- *list = 0;
-}