summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2018-07-02 23:11:26 +0300
committerOxore <oxore@protonmail.com>2018-07-02 23:11:26 +0300
commit21a0a44853451f3d791bafc80c01deab0ff4c79e (patch)
tree7636e99380c570d903db114ad2834f8bbd93fd7b
parentbb9d1873ad414b09efdd7c8bf6798b431adb3cb2 (diff)
Introduce draw manager, refactor main
Move timers to struct game. Partially move field painting to draw manager.
-rw-r--r--Makefile2
-rw-r--r--include/common.h22
-rw-r--r--include/draw.h23
-rw-r--r--include/engine.h2
-rw-r--r--include/field.h12
-rw-r--r--include/tet_conf.h4
-rw-r--r--src/draw.c161
-rw-r--r--src/engine.c42
-rw-r--r--src/field.c33
-rw-r--r--src/main.c76
10 files changed, 273 insertions, 104 deletions
diff --git a/Makefile b/Makefile
index 133184a..bbe323d 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@ OBJECTS:=$(patsubst $(SRC)/%.c,$(BUILD)/%.c.o,$(SOURCES))
INCLUDE+=include
INCLUDE:=$(patsubst %,-I%,$(INCLUDE))
-#COMMON+=-fsanitize=leak
+#COMMON+=-fsanitize=address
CFLAGS+=$(COMMON)
CFLAGS+=$(INCLUDE)
diff --git a/include/common.h b/include/common.h
index 275547a..7a85dbc 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1,13 +1,13 @@
-struct window {
- sfVideoMode mode;
- sfRenderWindow *window;
- sfEvent event;
-};
-
struct game {
- int isStarted;
- int scoreCurrent;
- int level;
- int moveLatency;
- int lines;
+ int isStarted;
+ int scoreCurrent;
+ int level;
+ int moveLatency;
+ int lines;
+ sfClock *gameTick;
+ sfClock *putTick;
+ sfClock *mTick;
+ sfClock *repPushDown; // Clock for repeat latency when Down arrow long push
+ sfClock *repKeyLeft; // Clock for repeat latency when Left arrow long push
+ sfClock *repKeyRight; // Clock for repeat latency when Left arrow long push
};
diff --git a/include/draw.h b/include/draw.h
new file mode 100644
index 0000000..3408142
--- /dev/null
+++ b/include/draw.h
@@ -0,0 +1,23 @@
+struct window {
+ sfVideoMode mode;
+ sfRenderWindow *window;
+ sfEvent event;
+};
+
+//struct field_conf {
+// sfVector2i pos;
+// int cOutThick;
+// sfVector2f cSize;
+// sfVector2i size;
+//} field_conf;
+
+void painter_init_window();
+
+unsigned long painter_register_field();
+void painter_update_field(unsigned long id, struct field *fld);
+
+unsigned long painter_register_shape();
+void painter_update_shape(unsigned long id, struct shape *shape);
+
+void painter_draw();
+void painter_destroy_window();
diff --git a/include/engine.h b/include/engine.h
index 7a4ce32..2dd7e9f 100644
--- a/include/engine.h
+++ b/include/engine.h
@@ -10,6 +10,6 @@ void tTick();
void checkLevelUp(struct game *game);
int getMoveLatencyOfLevel(int level);
void valueAfterTextDisplay(int value, List *texts, char *type);
-void drawFld(sfRenderWindow *window);
+void drawFld(sfRenderWindow *window, struct field *fld);
void gameover(struct game *game);
void drawNextShape(sfRenderWindow *window);
diff --git a/include/field.h b/include/field.h
index 6e1c928..f037d41 100644
--- a/include/field.h
+++ b/include/field.h
@@ -1,11 +1,15 @@
-#define FLD_SIZE_Y 22
-#define FLD_SIZE_X 10
+#define FLD_SIZE_Y 22
+#define FLD_SIZE_X 10
#define FLD_BOUND_Y FLD_SIZE_Y + 3
#define FLD_BOUND_X FLD_SIZE_X
+#define FLD_POS (sfVector2i){.x = 10, .y = 10+550-24}
+#define FLD_SIZE (sfVector2f){.x = FLD_SIZE_X, .y = FLD_SIZE_Y}
+#define CELL_SIZE (sfVector2f){.x = 23, .y = 23}
struct cell {
char a; // active/empty state of cell
sfColor fColor; // fill color
+ unsigned int color;
};
@@ -39,13 +43,13 @@ struct shape {
struct field {
sfVector2i pos;
- sfColor fColor; // shape color
struct cell c[FLD_BOUND_Y][FLD_SIZE_X]; // array of logic shape cells
- sfRectangleShape *p[FLD_BOUND_Y][FLD_SIZE_X]; // array of physical shape cells
+ sfRectangleShape *p[FLD_SIZE_Y][FLD_SIZE_X]; // array of physical shape cells
int cOutThick; // Field rectangles outline thickness
sfVector2f cSize; // shape rectangles size variable x/y
sfVector2i size;
sfVector2i bound;
+ unsigned int id;
};
void init_field(struct field *fld);
diff --git a/include/tet_conf.h b/include/tet_conf.h
index 44da289..134e8a9 100644
--- a/include/tet_conf.h
+++ b/include/tet_conf.h
@@ -1,6 +1,7 @@
#define windowName_conf "Tetris CSFML" // Window name
#define UIBGCOLOR sfColor_fromRGB(26, 26, 26) // Field background
#define UIFGINACTIVECOLOR sfColor_fromRGB(55, 59, 65) // Field inactive cell outline
+#define OUT_THICK 1
#define UIFGACTIVECOLOR sfColor_fromRGB(40, 42, 46) // Field active cell outline
#define LCOLOR sfColor_fromRGB(222, 147, 95) // Orange color of L shape
#define RLCOLOR sfColor_fromRGB(95, 129, 157)
@@ -38,6 +39,9 @@
/*
+ * 22..........
+ * 21..........
+ * 20..........
* 19..........
* 18..........
* 17..........
diff --git a/src/draw.c b/src/draw.c
new file mode 100644
index 0000000..a8c776f
--- /dev/null
+++ b/src/draw.c
@@ -0,0 +1,161 @@
+#include <SFML/Graphics/RenderWindow.h>
+#include <SFML/Graphics/RectangleShape.h>
+#include <stdlib.h>
+
+#include "tet_conf.h"
+#include "field.h"
+#include "draw.h"
+
+struct field_drawable {
+ sfRectangleShape *p[FLD_BOUND_Y][FLD_SIZE_X];
+};
+
+struct idlist {
+ unsigned long id;
+ void *obj;
+ struct idlist *next;
+};
+
+static struct idlist *list_new()
+{
+ struct idlist *list = calloc(1, sizeof(struct idlist));
+ list->id = 1;
+ return list;
+}
+
+static struct idlist *list_append(struct idlist *list)
+{
+ unsigned long id = list->id + 1;
+ struct idlist *last = list;
+ while (last->next)
+ last = last->next;
+ last->next = calloc(1, sizeof(struct idlist));
+ last = last->next;
+ last->id = id;
+ return last;
+}
+
+static struct idlist *list_get(const struct idlist *list, unsigned long id)
+{
+ const struct idlist *sought = list;
+ if (sought) {
+ if (sought->id == id)
+ return (struct idlist *)sought;
+ while (sought->next) {
+ sought = sought->next;
+ if (sought->id == id)
+ return (struct idlist *)sought;
+ }
+ }
+ return NULL;
+}
+
+#define BUFSIZE 100
+
+/* Must be static in future */
+struct window w;
+
+static struct idlist *fields_list = NULL;
+
+void painter_init_window()
+{
+ w = (struct window){.mode = {450, 570, 32}};
+ w.window = sfRenderWindow_create(w.mode, windowName_conf,
+ sfResize | sfClose, NULL);
+ if (!w.window)
+ exit(EXIT_FAILURE);
+}
+
+unsigned long painter_register_field()
+{
+ struct idlist *last;
+ if (!fields_list) {
+ last = fields_list = list_new();
+ } else
+ last = list_append(fields_list);
+
+ struct field_drawable *f = calloc(1, sizeof(struct field_drawable));
+ for (int j = 0; j < FLD_SIZE_Y; j++)
+ for (int i = 0; i < FLD_SIZE_X; i++) {
+ f->p[j][i] = sfRectangleShape_create();
+ sfVector2f cell_pos;
+ cell_pos.x = FLD_POS.x + (i * (CELL_SIZE.x + 2 * OUT_THICK));
+ cell_pos.y = FLD_POS.y - (j * (CELL_SIZE.y + 2 * OUT_THICK));
+ sfRectangleShape_setFillColor(f->p[j][i], UIBGCOLOR);
+ sfRectangleShape_setSize(f->p[j][i], CELL_SIZE);
+ sfRectangleShape_setPosition(f->p[j][i], cell_pos);
+ sfRectangleShape_setOutlineColor(f->p[j][i], UIFGACTIVECOLOR);
+ sfRectangleShape_setOutlineThickness(f->p[j][i], OUT_THICK);
+ }
+
+ last->obj = f;
+ return last->id;
+}
+
+void painter_update_field(unsigned long id, struct field *fld)
+{
+ struct idlist *node = list_get(fields_list, id);
+ if (!node)
+ return;
+ struct field_drawable *f = node->obj;
+ for (int j = 0; j < fld->size.y; j++) {
+ for (int i = 0; i < fld->size.x; i++) {
+ switch (fld->c[j][i].color) {
+ case 1 :
+ sfRectangleShape_setFillColor(f->p[j][i], LCOLOR);
+ break;
+ case 2 :
+ sfRectangleShape_setFillColor(f->p[j][i], RLCOLOR);
+ break;
+ case 3 :
+ sfRectangleShape_setFillColor(f->p[j][i], ZCOLOR);
+ break;
+ case 4 :
+ sfRectangleShape_setFillColor(f->p[j][i], SCOLOR);
+ break;
+ case 5 :
+ sfRectangleShape_setFillColor(f->p[j][i], BCOLOR);
+ break;
+ case 6 :
+ sfRectangleShape_setFillColor(f->p[j][i], ICOLOR);
+ break;
+ case 7 :
+ sfRectangleShape_setFillColor(f->p[j][i], TCOLOR);
+ break;
+ }
+ sfRectangleShape_setOutlineColor(f->p[j][i], UIFGACTIVECOLOR);
+ }
+ }
+}
+
+static void draw_field(struct field_drawable *f)
+{
+ for (unsigned int j = 0; j < FLD_SIZE_Y; j++)
+ for (unsigned int i = 0; i < FLD_SIZE_X; i++)
+ sfRenderWindow_drawRectangleShape(w.window, f->p[j][i], NULL);
+}
+
+static void draw_fields()
+{
+ struct idlist *node = fields_list;
+ if (node) {
+ if (node->obj)
+ draw_field(node->obj);
+ while (node->next) {
+ node = node->next;
+ if (node)
+ if (node->obj)
+ draw_field(node->obj);
+ }
+ }
+}
+
+void painter_draw()
+{
+ draw_fields();
+}
+
+void painter_destroy_window()
+{
+ sfRenderWindow_destroy(w.window);
+}
diff --git a/src/engine.c b/src/engine.c
index b5e1bac..210257b 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -101,14 +101,14 @@ int getMoveLatencyOfLevel(int level)
*/
void tTick()
{ // If tick exceeds current level tick latency
- if (sfClock_getElapsedTime(gameTick).microseconds >= game.moveLatency) {
- sfClock_restart(gameTick);
+ if (sfClock_getElapsedTime(game.gameTick).microseconds >= game.moveLatency) {
+ sfClock_restart(game.gameTick);
active.y--; // try
if (collide(&fld, &active))
active.y++; // fallback
else
- sfClock_restart(putTick);
- if (sfClock_getElapsedTime(putTick).microseconds >= PUT_LATENCY) {
+ sfClock_restart(game.putTick);
+ if (sfClock_getElapsedTime(game.putTick).microseconds >= PUT_LATENCY) {
if (out_of_field(&fld, &active)) {
gameover(&game);
return;
@@ -135,7 +135,7 @@ void tTick()
gen_shape(&next);
checkLevelUp(&game);
}
- sfClock_restart(putTick);
+ sfClock_restart(game.putTick);
}
}
}
@@ -167,13 +167,13 @@ void tKeyCtrl()
active.y++;
else {
// Avoid excess move down by gameTick
- sfClock_restart(putTick);
- sfClock_restart(gameTick);
+ sfClock_restart(game.putTick);
+ sfClock_restart(game.gameTick);
game.scoreCurrent++;
}
- sfClock_restart(repPushDown);
+ sfClock_restart(game.repPushDown);
} else {
- if (sfClock_getElapsedTime(repPushDown).microseconds
+ if (sfClock_getElapsedTime(game.repPushDown).microseconds
>= moveRepeatLatency2)
arrKeys = arrKeys & ~DOWN;
}
@@ -192,17 +192,17 @@ void tKeyCtrl()
if (collide(&fld, &active))
active.x++;
else
- sfClock_restart(putTick);
- sfClock_restart(repKeyLeft);
+ sfClock_restart(game.putTick);
+ sfClock_restart(game.repKeyLeft);
} else {
if (!(arrKeys & LEFTHOLD)) {
- if (sfClock_getElapsedTime(repKeyLeft).microseconds
+ if (sfClock_getElapsedTime(game.repKeyLeft).microseconds
>= moveRepeatLatency1) {
arrKeys = arrKeys | LEFTHOLD;
arrKeys = arrKeys & ~LEFT;
}
} else {
- if (sfClock_getElapsedTime(repKeyLeft).microseconds
+ if (sfClock_getElapsedTime(game.repKeyLeft).microseconds
>= moveRepeatLatency2)
arrKeys = arrKeys & ~LEFT;
}
@@ -223,17 +223,17 @@ void tKeyCtrl()
if (collide(&fld, &active))
active.x--;
else
- sfClock_restart(putTick);
- sfClock_restart(repKeyRight);
+ sfClock_restart(game.putTick);
+ sfClock_restart(game.repKeyRight);
} else {
if (!(arrKeys & RIGHTHOLD)) {
- if (sfClock_getElapsedTime(repKeyRight).microseconds
+ if (sfClock_getElapsedTime(game.repKeyRight).microseconds
>= moveRepeatLatency1) {
arrKeys = arrKeys | RIGHTHOLD;
arrKeys = arrKeys & ~RIGHT;
}
} else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) {
- if (sfClock_getElapsedTime(repKeyRight).microseconds
+ if (sfClock_getElapsedTime(game.repKeyRight).microseconds
>= moveRepeatLatency2) // Wait short time
arrKeys = arrKeys & ~RIGHT;
}
@@ -250,11 +250,11 @@ void tKeyCtrl()
* Draw all fld cells
*
*/
-void drawFld(sfRenderWindow *window)
+void drawFld(sfRenderWindow *window, struct field *fld)
{
- for (int j = 0; j < fld.size.y; j++)
- for (int i = 0; i < fld.size.x; i++)
- sfRenderWindow_drawRectangleShape(window, fld.p[j][i], NULL);
+ for (int j = 0; j < fld->size.y; j++)
+ for (int i = 0; i < fld->size.x; i++)
+ sfRenderWindow_drawRectangleShape(window, fld->p[j][i], NULL);
}
void gameover(struct game *game)
diff --git a/src/field.c b/src/field.c
index 89abd02..c0e3fe5 100644
--- a/src/field.c
+++ b/src/field.c
@@ -53,36 +53,9 @@ void colorize_field(struct field *fld)
void colorize_field_random(struct field *fld)
{
- int a;
- for (int j = 0; j < fld->size.y; j++) {
- for (int i = 0; i < fld->size.x; i++) {
- a = rand() % 7 + 1;
- switch (a) {
- case 1 :
- sfRectangleShape_setFillColor(fld->p[j][i], LCOLOR);
- break;
- case 2 :
- sfRectangleShape_setFillColor(fld->p[j][i], RLCOLOR);
- break;
- case 3 :
- sfRectangleShape_setFillColor(fld->p[j][i], ZCOLOR);
- break;
- case 4 :
- sfRectangleShape_setFillColor(fld->p[j][i], SCOLOR);
- break;
- case 5 :
- sfRectangleShape_setFillColor(fld->p[j][i], BCOLOR);
- break;
- case 6 :
- sfRectangleShape_setFillColor(fld->p[j][i], ICOLOR);
- break;
- case 7 :
- sfRectangleShape_setFillColor(fld->p[j][i], TCOLOR);
- break;
- }
- sfRectangleShape_setOutlineColor(fld->p[j][i], UIFGACTIVECOLOR);
- }
- }
+ for (int j = 0; j < fld->size.y; j++)
+ for (int i = 0; i < fld->size.x; i++)
+ fld->c[j][i].color = rand() % 7 + 1;
}
void colorize_active_shape(struct field *fld, struct shape *shape)
diff --git a/src/main.c b/src/main.c
index 9bbf3bf..4386205 100644
--- a/src/main.c
+++ b/src/main.c
@@ -10,14 +10,16 @@
#include "common.h"
#include "text.h"
#include "field.h"
+#include "draw.h"
#include "engine.h"
#include "tet_conf.h"
+extern struct window w;
+
List *texts;
sfFont *fontScore;
struct shape active, next;
struct field fld;
-struct window w = {.mode = {450, 570, 32}};
struct game game = {
.isStarted = 0,
.scoreCurrent = 0,
@@ -28,34 +30,16 @@ struct game game = {
char arrKeys = 0; // Arrow keys states byte container
-sfClock *gameTick;
-sfClock *putTick;
-sfClock *mTick;
-sfClock *repPushDown; // Clock for repeat latency when Down arrow long push
-sfClock *repKeyLeft; // Clock for repeat latency when Left arrow long push
-sfClock *repKeyRight; // Clock for repeat latency when Left arrow long push
-
void prepare() {
- srand(time(NULL));
- gameTick = sfClock_create();
- putTick = sfClock_create();
- mTick = sfClock_create();
- repPushDown = sfClock_create();
- repKeyLeft = sfClock_create();
- repKeyRight = sfClock_create();
- fontScore = sfFont_createFromFile("dat/arial.ttf");
- if (!fontScore) {
- printf("dat/arial.ttf font load failed");
- exit(-1);
- }
+ sfRenderWindow_setFramerateLimit(w.window, 60);
/*
* Dimensions of every fld's cell
* 23px - fill color 1px - for outline, 25 - at all
*/
- fld.cSize = (sfVector2f){.x = 23, .y = 23}; //Fld's cell size in pixels
+ fld.cSize = CELL_SIZE; //Fld's cell size in pixels
fld.cOutThick = 1;
- fld.pos = (sfVector2i){.x = 10, .y = 10+550-24}; // Fld bot left corner
+ fld.pos = FLD_POS; // Fld bot left corner
fld.size = (sfVector2i){.x = FLD_SIZE_X, .y = FLD_SIZE_Y}; // Field's size in blocks
fld.bound = (sfVector2i){.x = FLD_BOUND_X, .y = FLD_BOUND_Y}; // Field's bound in blocks
@@ -72,14 +56,6 @@ void prepare() {
active.t = next.t;
resetActiveShape(&fld, &active);
gen_shape(&next);
- List *tmp = ListOfKeyMapOfString_getFromYaml("dat/texts.yaml");
- texts = ListOfText_getFromListOfKeyMapOfString(tmp);
- ListOfKeyMapOfString_free(&tmp);
- w.window = sfRenderWindow_create(w.mode, windowName_conf,
- sfResize | sfClose, NULL);
- if (!w.window)
- exit(EXIT_FAILURE);
- sfRenderWindow_setFramerateLimit(w.window, 60);
}
void handleWindowEvents() {
@@ -104,22 +80,22 @@ void gameLoop() {
valueAfterTextDisplay(game.level, texts, "level");
colorize_field(&fld);
colorize_active_shape(&fld, &active);
- drawFld(w.window);
+ drawFld(w.window, &fld);
drawNextShape(w.window);
drawTextsAtScene(texts, "game", w.window);
}
void menuTick()
{
- if (sfClock_getElapsedTime(mTick).microseconds >= basicLatency) {
- sfClock_restart(mTick);
+ if (sfClock_getElapsedTime(game.mTick).microseconds >= basicLatency) {
+ sfClock_restart(game.mTick);
colorize_field_random(&fld);
+ painter_update_field(fld.id, &fld);
}
}
void menuLoop() {
menuTick();
- drawFld(w.window);
drawTextsAtScene(texts, "menu", w.window);
if (sfKeyboard_isKeyPressed(sfKeyS) == 1) {
game.isStarted = 1;
@@ -127,8 +103,9 @@ void menuLoop() {
free_shape(&next);
init_field(&fld);
init_next_shape(&next);
- sfClock_restart(gameTick);
+ sfClock_restart(game.gameTick);
}
+ painter_draw();
}
void mainLoop() {
@@ -145,12 +122,39 @@ void mainLoop() {
int main()
{
+ srand(time(NULL));
+ game.gameTick = sfClock_create();
+ game.putTick = sfClock_create();
+ game.mTick = sfClock_create();
+ game.repPushDown = sfClock_create();
+ game.repKeyLeft = sfClock_create();
+ game.repKeyRight = sfClock_create();
+ fontScore = sfFont_createFromFile("dat/arial.ttf");
+ if (!fontScore) {
+ printf("dat/arial.ttf font load failed");
+ exit(-1);
+ }
+ painter_init_window();
+ List *tmp = ListOfKeyMapOfString_getFromYaml("dat/texts.yaml");
+ texts = ListOfText_getFromListOfKeyMapOfString(tmp);
+ ListOfKeyMapOfString_free(&tmp);
+
prepare();
colorize_field_random(&fld);
+ fld.id = painter_register_field();
+ painter_update_field(fld.id, &fld);
mainLoop();
free_field(&fld);
free_shape(&next);
- sfRenderWindow_destroy(w.window);
+
+ painter_destroy_window();
+ sfFont_destroy(fontScore);
+ 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;
}