summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2018-07-03 15:11:54 +0300
committerOxore <oxore@protonmail.com>2018-07-03 15:11:54 +0300
commited8127a72e1a2d2703372d5b5dfa8d96703ec3bb (patch)
tree80f340c64861913f2dc648c2c7280c144b988881
parent21a0a44853451f3d791bafc80c01deab0ff4c79e (diff)
Refactor field, refactor next shape drawing
Refactor field functions names. Transfer next shape drawing to painter. Introduce idlist struct with foreach function. Refactor config. Introduce color map array instead of "switch case" statement bloating while coloring rectangles. Decouple field and shape structs from SFML sfVector2 structs by introducing own vector2i and vector2ui structs. Also remove sfRectangleShape members form field an shape structs.
-rw-r--r--include/common.h22
-rw-r--r--include/draw.h17
-rw-r--r--include/engine.h16
-rw-r--r--include/field.h66
-rw-r--r--include/idlist.h12
-rw-r--r--include/tet_conf.h73
-rw-r--r--src/draw.c202
-rw-r--r--src/engine.c86
-rw-r--r--src/field.c158
-rw-r--r--src/idlist.c55
-rw-r--r--src/main.c78
11 files changed, 392 insertions, 393 deletions
diff --git a/include/common.h b/include/common.h
index 7a85dbc..098ea9e 100644
--- a/include/common.h
+++ b/include/common.h
@@ -1,13 +1,13 @@
struct game {
- 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
+ unsigned int level;
+ int isStarted;
+ int scoreCurrent;
+ int moveLatency;
+ int lines;
+ sfClock *gameTick;
+ sfClock *putTick;
+ sfClock *mTick;
+ sfClock *repPushDown; // repeat latency when hold Down arrow
+ sfClock *repKeyLeft; // repeat latency when hold Left arrow
+ sfClock *repKeyRight; // repeat latency when hold Left arrow
};
diff --git a/include/draw.h b/include/draw.h
index 3408142..17bf176 100644
--- a/include/draw.h
+++ b/include/draw.h
@@ -4,20 +4,15 @@ struct window {
sfEvent event;
};
-//struct field_conf {
-// sfVector2i pos;
-// int cOutThick;
-// sfVector2f cSize;
-// sfVector2i size;
-//} field_conf;
-
void painter_init_window();
+void painter_destroy_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_destroy_field(unsigned long id);
+void painter_destroy_fields();
void painter_draw();
-void painter_destroy_window();
+
+void painter_destroy_drawables();
+void painter_destroy_all();
diff --git a/include/engine.h b/include/engine.h
index 2dd7e9f..bca16ed 100644
--- a/include/engine.h
+++ b/include/engine.h
@@ -1,15 +1,13 @@
-#define RIGHT 1
-#define DOWN 2
-#define UP 4
-#define LEFT 8
-#define RIGHTHOLD 16
-#define LEFTHOLD 128
+#define RIGHT (1 << 0)
+#define DOWN (1 << 1)
+#define UP (1 << 2)
+#define LEFT (1 << 3)
+#define RIGHTHOLD (1 << 4)
+#define LEFTHOLD (1 << 5)
void tKeyCtrl();
void tTick();
void checkLevelUp(struct game *game);
-int getMoveLatencyOfLevel(int level);
+int getMoveLatencyOfLevel(unsigned int level);
void valueAfterTextDisplay(int value, List *texts, char *type);
-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 f037d41..93f80f0 100644
--- a/include/field.h
+++ b/include/field.h
@@ -1,17 +1,18 @@
-#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}
+#define FLD_ATTR_INVISIBLE (1 << 0)
+#define FLD_ATTR_TRANSPARENT (1 << 1)
struct cell {
char a; // active/empty state of cell
- sfColor fColor; // fill color
unsigned int color;
};
+struct vector2i {
+ int x, y;
+};
+
+struct vector2ui {
+ unsigned int x, y;
+};
/*
* field + shape coord system
@@ -34,36 +35,31 @@ struct shape {
int x; // x coord of shape's left side
int y; // y coord of shape's bottom
int t; // shape type
- sfColor fColor; // shape color
+ unsigned int color; // shape color
char c[4][4]; // array of logic shape cells
- sfRectangleShape *p[4][4]; // array of physical shape cells
- int cOutThick; // shape rectangles outline thickness
- sfVector2f cSize; // shape rectangles size variable x/y
};
struct field {
- sfVector2i pos;
- struct cell c[FLD_BOUND_Y][FLD_SIZE_X]; // array of logic 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;
+ unsigned long id;
+ unsigned int attr;
+ struct vector2i pos;
+ struct vector2ui size;
+ struct vector2ui bound;
+ struct cell **c; // array of logic shape cells
+ unsigned int shape_cnt;
+ struct shape *shape;
};
-void init_field(struct field *fld);
-void colorize_field(struct field *fld);
-void colorize_field_random(struct field *fld);
-void colorize_active_shape(struct field *fld, struct shape *shape);
-void init_next_shape(struct shape *next);
-void putShape(struct field *fld, struct shape *active);
-int out_of_field(struct field *fld, struct shape *active);
-void load_shape(struct shape *shape);
-void rotate_shape(struct field *fld, struct shape *shape);
-int collide(struct field *fld, struct shape *active);
-void resetActiveShape(struct field *fld, struct shape *active);
-void gen_shape(struct shape *shape);
-int rm_lines(struct field *fld);
-void free_field(struct field *fld);
-void free_shape(struct shape *shape);
+void field_init(struct field *fld);
+void field_deinit(struct field *fld);
+void field_fill_random(struct field *fld);
+void field_clear(struct field *fld);
+void field_rotate_shape(struct field *fld, unsigned int index);
+void field_put_shape(struct field *fld, struct shape *shape);
+void field_reset_walking_shape(struct field *fld, unsigned int index);
+int field_rm_lines(struct field *fld);
+int field_shape_collision(struct field *fld, struct shape *shape);
+int field_shape_out_of_bounds(struct field *fld, struct shape *shape);
+
+void shape_load(struct shape *shape);
+void shape_gen_random(struct shape *shape);
diff --git a/include/idlist.h b/include/idlist.h
new file mode 100644
index 0000000..d1badc7
--- /dev/null
+++ b/include/idlist.h
@@ -0,0 +1,12 @@
+struct idlist {
+ unsigned long id;
+ void *obj;
+ struct idlist *next;
+ struct idlist *prev;
+};
+
+struct idlist *list_new();
+struct idlist *list_append(struct idlist *list);
+struct idlist *list_get(const struct idlist *list, unsigned long id);
+void list_rm_node(struct idlist *node);
+void list_foreach(struct idlist *list, void (*job)(void *));
diff --git a/include/tet_conf.h b/include/tet_conf.h
index 134e8a9..14a8c2a 100644
--- a/include/tet_conf.h
+++ b/include/tet_conf.h
@@ -1,42 +1,55 @@
-#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)
-#define SCOLOR sfColor_fromRGB(140, 148, 64)
-#define ZCOLOR sfColor_fromRGB(165, 66, 66)
-#define BCOLOR sfColor_fromRGB(197, 200, 198)
-#define ICOLOR sfColor_fromRGB(94, 141, 135)
-#define TCOLOR sfColor_fromRGB(133, 103, 143)
+#define windowName_conf "Tetris CSFML" // Window name
+#define OUT_THICK 1
+#define UITRANSPARENT {0, 0, 0, 0 } // Field background
+#define UIBGCOLOR {26, 26, 26, 255} // Field background
+#define UIFGINACTIVECOLOR {55, 59, 65, 255} // Field inactive cell outline
+#define UIFGACTIVECOLOR {40, 42, 46, 255} // Field active cell outline
+#define LCOLOR {222, 147, 95, 255} // Orange color of L shape
+#define RLCOLOR {95, 129, 157, 255}
+#define ZCOLOR {165, 66, 66, 255}
+#define SCOLOR {140, 148, 64, 255}
+#define BCOLOR {197, 200, 198, 255}
+#define ICOLOR {94, 141, 135, 255}
+#define TCOLOR {133, 103, 143, 255}
+
#define moveRepeatLatency1 150000 // microseconds, only for left-right arrows,
- // first repeat move when long push
+ // first repeat move when long push
#define moveRepeatLatency2 30000 // microseconds, for Left, Right and Down
- // arrows, the rest repeat move when long push
+ // arrows, the rest repeat move when long push
#define basicLatency 500000
-#define L00LATENCY 800000
-#define L01LATENCY 716667
-#define L02LATENCY 633334
-#define L03LATENCY 550000
-#define L04LATENCY 466667
-#define L05LATENCY 383334
-#define L06LATENCY 300000
-#define L07LATENCY 216667
-#define L08LATENCY 133334
-#define L09LATENCY 100000
-#define L10LATENCY 83334
-#define L13LATENCY 66667
-#define L16LATENCY 50000
-#define L19LATENCY 33334
-#define L29LATENCY 16667
-#define PUT_LATENCY 300000
+#define L00LATENCY 800000
+#define L01LATENCY 716667
+#define L02LATENCY 633334
+#define L03LATENCY 550000
+#define L04LATENCY 466667
+#define L05LATENCY 383334
+#define L06LATENCY 300000
+#define L07LATENCY 216667
+#define L08LATENCY 133334
+#define L09LATENCY 100000
+#define L10LATENCY 83334
+#define L13LATENCY 66667
+#define L16LATENCY 50000
+#define L19LATENCY 33334
+#define L29LATENCY 16667
+#define PUT_LATENCY 300000
#define RM_1LINES_SCORE 40
#define RM_2LINES_SCORE 100
#define RM_3LINES_SCORE 300
#define RM_4LINES_SCORE 1200
#define LEVELUP_LINES 10
+#define FLD_SIZE_Y 22
+#define FLD_SIZE_X 10
+#define FLD_BOUND_Y FLD_SIZE_Y + 4
+#define FLD_BOUND_X FLD_SIZE_X
+#define FLD_POS (struct vector2i){.x = 10, .y = 10+550-24}
+#define CELL_SIZE (sfVector2f){.x = 23, .y = 23}
+
+#define NXT_SIZE_Y 8
+#define NXT_SIZE_X 4
+#define NXT_POS (struct vector2i){.x = 250 + 10 + 30, .y = 300}
+#define NXT_SIZE (struct vector2ui){.x = NXT_SIZE_X, .y = NXT_SIZE_Y}
/*
* 22..........
diff --git a/src/draw.c b/src/draw.c
index a8c776f..dd888d0 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -6,53 +6,30 @@
#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;
+#include "idlist.h"
+
+static sfColor shape_color_map[] = {
+ UIBGCOLOR,
+ LCOLOR,
+ RLCOLOR,
+ ZCOLOR,
+ SCOLOR,
+ BCOLOR,
+ ICOLOR,
+ TCOLOR,
};
-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
+struct field_drawable {
+ sfRectangleShape ***p;
+ struct vector2ui size;
+ unsigned int attr;
+};
-/* Must be static in future */
+/*
+ * TODO: Must be static in future
+ *
+ * */
struct window w;
static struct idlist *fields_list = NULL;
@@ -64,29 +41,42 @@ void painter_init_window()
sfResize | sfClose, NULL);
if (!w.window)
exit(EXIT_FAILURE);
+ sfRenderWindow_setFramerateLimit(w.window, 60);
+}
+
+void painter_destroy_window()
+{
+ if (w.window) {
+ sfRenderWindow_destroy(w.window);
+ w.window = 0;
+ }
}
-unsigned long painter_register_field()
+unsigned long painter_register_field(struct field *fld)
{
struct idlist *last;
- if (!fields_list) {
+ if (!fields_list)
last = fields_list = list_new();
- } else
+ 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->size = fld->size;
+ f->p = calloc(f->size.y, sizeof(sfRectangleShape **));
+ for (unsigned int j = 0; j < f->size.y; j++) {
+ f->p[j] = calloc(f->size.x, sizeof(sfRectangleShape *));
+ for (unsigned int i = 0; i < f->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);
+ 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_setPosition(f->p[j][i], cell_pos);
- sfRectangleShape_setOutlineColor(f->p[j][i], UIFGACTIVECOLOR);
+ sfRectangleShape_setFillColor(f->p[j][i], (sfColor)UIBGCOLOR);
+ sfRectangleShape_setSize(f->p[j][i], CELL_SIZE);
+ sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UIFGACTIVECOLOR);
sfRectangleShape_setOutlineThickness(f->p[j][i], OUT_THICK);
}
+ }
last->obj = f;
return last->id;
@@ -98,56 +88,74 @@ void painter_update_field(unsigned long id, struct field *fld)
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;
+ f->attr = fld->attr;
+ for (unsigned int j = 0; j < fld->size.y; j++) {
+ for (unsigned int i = 0; i < fld->size.x; i++) {
+ 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_setPosition(f->p[j][i], cell_pos);
+ if (fld->c[j][i].a) {
+ sfRectangleShape_setFillColor(f->p[j][i], shape_color_map[fld->c[j][i].color]);
+ sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UIFGACTIVECOLOR);
+ } else if (f->attr & FLD_ATTR_TRANSPARENT) {
+ sfRectangleShape_setFillColor(f->p[j][i], (sfColor)UITRANSPARENT);
+ sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UITRANSPARENT);
+ } else {
+ sfRectangleShape_setFillColor(f->p[j][i], (sfColor)UIBGCOLOR);
+ sfRectangleShape_setOutlineColor(f->p[j][i], (sfColor)UIFGINACTIVECOLOR);
}
- sfRectangleShape_setOutlineColor(f->p[j][i], UIFGACTIVECOLOR);
}
}
+ for (unsigned int s = 0; s < fld->shape_cnt; ++s)
+ for (int j = 0; j < 4; j++)
+ for (int i = 0; i < 4; i++)
+ if (fld->shape[s].c[j][i] && j + fld->shape[s].y < (int)fld->size.y) {
+ sfRectangleShape_setFillColor(
+ f->p[j + fld->shape[s].y][i + fld->shape[s].x],
+ shape_color_map[fld->shape[s].color]);
+ sfRectangleShape_setOutlineColor(
+ f->p[j + fld->shape[s].y][i + fld->shape[s].x],
+ (sfColor)UIFGACTIVECOLOR);
+ }
}
-static void draw_field(struct field_drawable *f)
+static void draw_field(void *field)
{
- 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);
+ struct field_drawable *f = field;
+ 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()
{
- 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);
- }
+ list_foreach(fields_list, draw_field);
+}
+
+static void destroy_field(void *field)
+{
+ struct field_drawable *f = field;
+ 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]);
+ free(f->p[j]);
}
+ free(f->p);
+ free(f);
+}
+
+void painter_destroy_field(unsigned long id)
+{
+ struct idlist *node = list_get(fields_list, id);
+ destroy_field(node->obj);
+ list_rm_node(node);
+}
+
+void painter_destroy_fields()
+{
+ list_foreach(fields_list, destroy_field);
}
void painter_draw()
@@ -155,7 +163,13 @@ void painter_draw()
draw_fields();
}
-void painter_destroy_window()
+void painter_destroy_drawables()
+{
+ painter_destroy_fields();
+}
+
+void painter_destroy_all()
{
- sfRenderWindow_destroy(w.window);
+ painter_destroy_drawables();
+ painter_destroy_window();
}
diff --git a/src/engine.c b/src/engine.c
index 210257b..9840b34 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -2,32 +2,23 @@
#include <stdlib.h>
#include <string.h>
#include <SFML/System/Clock.h>
+#include <SFML/Window/Keyboard.h>
#include <SFML/Graphics/RenderWindow.h>
#include <SFML/Graphics/Text.h>
-#include <SFML/Graphics/RectangleShape.h>
#include "common.h"
#include "tet_conf.h"
#include "text.h"
#include "field.h"
+#include "draw.h"
#include "engine.h"
/* Externs from main.c */
extern struct game game;
-extern struct shape active, next;
-extern struct field fld;
-
-extern sfFont *fontScore;
+extern struct field fld, nxt;
extern char arrKeys; // Arrow keys states byte container
-extern sfClock *gameTick;
-extern sfClock *putTick;
-extern sfClock *mTick;
-extern sfClock *repPushDown; // Clock for repeat latency when Down key held
-extern sfClock *repKeyLeft; // Clock for repeat latency when Left key held
-extern sfClock *repKeyRight; // Clock for repeat latency when Left key held
-
void valueAfterTextDisplay(int value, List *texts, char *type)
{
List *l = texts;
@@ -59,7 +50,7 @@ void checkLevelUp(struct game *game)
}
}
-int getMoveLatencyOfLevel(int level)
+int getMoveLatencyOfLevel(unsigned int level)
{
if (level >= 29)
return L29LATENCY;
@@ -103,18 +94,22 @@ void tTick()
{ // If tick exceeds current level tick latency
if (sfClock_getElapsedTime(game.gameTick).microseconds >= game.moveLatency) {
sfClock_restart(game.gameTick);
- active.y--; // try
- if (collide(&fld, &active))
- active.y++; // fallback
+ 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 (out_of_field(&fld, &active)) {
+ 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 {
- putShape(&fld, &active);
- int removedLines = rm_lines(&fld);
+ field_put_shape(&fld, &fld.shape[0]);
+ int removedLines = field_rm_lines(&fld);
game.lines += removedLines;
switch (removedLines) {
case 1:
@@ -130,9 +125,13 @@ void tTick()
game.scoreCurrent += RM_4LINES_SCORE * game.level;
break;
}
- active.t = next.t;
- resetActiveShape(&fld, &active);
- gen_shape(&next);
+ 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);
@@ -150,7 +149,7 @@ void tKeyCtrl()
if (sfKeyboard_isKeyPressed(sfKeyUp)) {
if (!(arrKeys & UP)) {
arrKeys = arrKeys | UP;
- rotate_shape(&fld, &active);
+ field_rotate_shape(&fld, 0);
}
} else {
if ((arrKeys & UP)) {
@@ -162,9 +161,9 @@ void tKeyCtrl()
if (sfKeyboard_isKeyPressed(sfKeyDown)) {
if (!(arrKeys & DOWN)) {
arrKeys = arrKeys | DOWN;
- active.y--;
- if (collide(&fld, &active))
- active.y++;
+ 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);
@@ -188,9 +187,9 @@ void tKeyCtrl()
&& !sfKeyboard_isKeyPressed(sfKeyRight)) {
if (!(arrKeys & LEFT)) {
arrKeys = arrKeys | LEFT;
- active.x--;
- if (collide(&fld, &active))
- active.x++;
+ 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);
@@ -219,9 +218,9 @@ void tKeyCtrl()
&& !sfKeyboard_isKeyPressed(sfKeyLeft)) {
if (!(arrKeys & RIGHT)) {
arrKeys = arrKeys | RIGHT;
- active.x++;
- if (collide(&fld, &active))
- active.x--;
+ 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);
@@ -246,17 +245,6 @@ void tKeyCtrl()
}
}
-/*
- * Draw all fld cells
- *
- */
-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);
-}
-
void gameover(struct game *game)
{
game->isStarted = 0;
@@ -265,15 +253,3 @@ void gameover(struct game *game)
game->moveLatency = L00LATENCY;
game->lines = 0;
}
-
-void drawNextShape(sfRenderWindow *window)
-{
- for (int j = 0; j < 4; j++)
- for (int i = 0; i < 4; i++)
- if (next.c[j][i]) {
- sfRectangleShape_setFillColor(next.p[j][i], next.fColor);
- sfRectangleShape_setOutlineColor(next.p[j][i], UIFGACTIVECOLOR);
- sfRenderWindow_drawRectangleShape(window, next.p[j][i], NULL);
- }
-}
-
diff --git a/src/field.c b/src/field.c
index c0e3fe5..37680ae 100644
--- a/src/field.c
+++ b/src/field.c
@@ -5,7 +5,6 @@
#include "field.h"
#include "tet_conf.h"
-/* Shapes maps */
extern char arrShapeL[4][4];
extern char arrShapeRL[4][4];
extern char arrShapeZ[4][4];
@@ -18,161 +17,112 @@ static void rotate_shape_left(struct shape *shape);
static void rotate_shape_right(struct shape *shape);
static int out_of_bounds(struct field *fld, struct shape *active);
-void init_field(struct field *fld)
+void field_init(struct field *fld)
{
- sfVector2f fldCPos[22][10];
- for (int j = 0; j < fld->size.y; j++) {
- for (int i = 0; i < fld->size.x; i++) {
- fld->c[j][i].a = 0; // Inactive = empty
- fldCPos[j][i].x
- = fld->pos.x + (i * (fld->cSize.x + 2 * fld->cOutThick));
- fldCPos[j][i].y
- = fld->pos.y - (j * (fld->cSize.y + 2 * fld->cOutThick));
- fld->p[j][i] = sfRectangleShape_create();
- sfRectangleShape_setFillColor(fld->p[j][i], UIBGCOLOR);
- sfRectangleShape_setSize(fld->p[j][i], fld->cSize);
- sfRectangleShape_setPosition(fld->p[j][i], fldCPos[j][i]);
- sfRectangleShape_setOutlineColor(fld->p[j][i], UIFGACTIVECOLOR);
- sfRectangleShape_setOutlineThickness(fld->p[j][i], fld->cOutThick);
- }
+ fld->c = calloc(fld->bound.y, sizeof(struct cell *));
+ for (unsigned int j = 0; j < fld->bound.y; j++) {
+ fld->c[j] = calloc(fld->bound.x, sizeof(struct cell));
+ for (unsigned int i = 0; i < fld->size.x; i++)
+ fld->c[j][i].a = 0;
}
+ fld->shape = calloc(fld->shape_cnt, sizeof(struct shape));
}
-void colorize_field(struct field *fld)
+void field_clear(struct field *fld)
{
- for (int j = 0; j < fld->size.y; j++)
- for (int i = 0; i < fld->size.x; i++)
- if (fld->c[j][i].a) {
- sfRectangleShape_setFillColor(fld->p[j][i], fld->c[j][i].fColor);
- sfRectangleShape_setOutlineColor(fld->p[j][i], UIFGACTIVECOLOR);
- } else {
- sfRectangleShape_setFillColor(fld->p[j][i], UIBGCOLOR);
- sfRectangleShape_setOutlineColor(fld->p[j][i], UIFGINACTIVECOLOR);
- }
+ for (unsigned int j = 0; j < fld->bound.y; j++)
+ for (unsigned int i = 0; i < fld->bound.x; i++) {
+ fld->c[j][i].a = 0;
+ fld->c[j][i].color = 0;
+ }
}
-void colorize_field_random(struct field *fld)
+void field_fill_random(struct field *fld)
{
- for (int j = 0; j < fld->size.y; j++)
- for (int i = 0; i < fld->size.x; i++)
+ for (unsigned int j = 0; j < fld->size.y; j++)
+ for (unsigned int i = 0; i < fld->size.x; i++) {
+ fld->c[j][i].a = 1;
fld->c[j][i].color = rand() % 7 + 1;
-}
-
-void colorize_active_shape(struct field *fld, struct shape *shape)
-{
- for (int j = 0; j < 4; j++)
- for (int i = 0; i < 4; i++)
- if (shape->c[j][i] && j + shape->y < FLD_SIZE_Y) {
- sfRectangleShape_setFillColor(
- fld->p[j + shape->y][i + shape->x], shape->fColor);
- sfRectangleShape_setOutlineColor(
- fld->p[j + shape->y][i + shape->x], UIFGACTIVECOLOR);
- }
-}
-
-void init_next_shape(struct shape *next)
-{
- sfVector2f nsPos;
- for (int j = 0; j < 4; j++) {
- for (int i = 0; i < 4; i++) {
- nsPos.x = next->x + i *(next->cSize.x + 2 * next->cOutThick);
- nsPos.y = next->y - j *(next->cSize.y + 2 * next->cOutThick);
- next->p[j][i] = sfRectangleShape_create();
- sfRectangleShape_setSize(next->p[j][i], next->cSize);
- sfRectangleShape_setPosition(next->p[j][i], nsPos);
- sfRectangleShape_setOutlineThickness(next->p[j][i], next->cOutThick);
}
- }
}
-/*
- * Inserts shape into field, runs filled lines searching, puts new shape
- * into the game at the top.
- *
- */
-void putShape(struct field *fld, struct shape *active)
+void field_put_shape(struct field *fld, struct shape *active)
{
for (int j = 0; j < 4; j++)
for (int i = 0; i < 4; i++)
if (active->c[j][i]) {
fld->c[j+active->y][i+active->x].a = active->c[j][i];
- fld->c[j+active->y][i+active->x].fColor = active->fColor;
+ fld->c[j+active->y][i+active->x].color = active->color;
}
}
-int out_of_field(struct field *fld, struct shape *active)
+int field_shape_out_of_bounds(struct field *fld, struct shape *active)
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
- if (active->c[i][j] && active->y + i >= fld->size.y)
+ if (active->c[i][j] && active->y + i >= (int)fld->size.y)
return 1;
return 0;
}
-void load_shape(struct shape *shape)
+void shape_load(struct shape *shape)
{
+ shape->color = shape->t;
switch (shape->t) { // Copy cell active/inactive state
case 1 :
memcpy(&shape->c[0][0], &arrShapeL[0][0], sizeof(char)*4*4);
- shape->fColor = LCOLOR;
break;
case 2 :
memcpy(&shape->c[0][0], &arrShapeRL[0][0], sizeof(char)*4*4);
- shape->fColor = RLCOLOR;
break;
case 3 :
memcpy(&shape->c[0][0], &arrShapeZ[0][0], sizeof(char)*4*4);
- shape->fColor = ZCOLOR;
break;
case 4 :
memcpy(&shape->c[0][0], &arrShapeS[0][0], sizeof(char)*4*4);
- shape->fColor = SCOLOR;
break;
case 5 :
memcpy(&shape->c[0][0], &arrShapeB[0][0], sizeof(char)*4*4);
- shape->fColor = BCOLOR;
break;
case 6 :
memcpy(&shape->c[0][0], &arrShapeI[0][0], sizeof(char)*4*4);
- shape->fColor = ICOLOR;
break;
case 7 :
memcpy(&shape->c[0][0], &arrShapeT[0][0], sizeof(char)*4*4);
- shape->fColor = TCOLOR;
break;
}
}
-void resetActiveShape(struct field *fld, struct shape *active)
+void field_reset_walking_shape(struct field *fld, unsigned int index)
{
- load_shape(active);
+ struct shape *active = &fld->shape[index];
+ shape_load(active);
active->x = 3;
if (active->t == 6)
active->y = 19;
else
active->y = 18;
- while (collide(fld, active)) {
+ while (field_shape_collision(fld, active))
active->y++;
- }
}
-void gen_shape(struct shape *shape)
+void shape_gen_random(struct shape *shape)
{
shape->t = (rand() % 7) + 1; // Insert new random shape of 7 variants
- load_shape(shape);
+ shape_load(shape);
if (shape->t == 5)
for (int j = 0; j < 3; j++)
for (int i = 0; i < 4; i++)
shape->c[i][j] = shape->c[i][j+1];
}
-int collide(struct field *fld, struct shape *active)
+int field_shape_collision(struct field *fld, struct shape *shape)
{
- if (out_of_bounds(fld, active))
+ if (out_of_bounds(fld, shape))
return 1;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
- if (active->c[i][j] && fld->c[i + active->y][j + active->x].a)
+ if (shape->c[i][j] && fld->c[i + shape->y][j + shape->x].a)
return 1;
return 0;
}
@@ -182,8 +132,8 @@ static int out_of_bounds(struct field *fld, struct shape *active)
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (active->c[i][j])
- if (active->x + j >= fld->bound.x || active->x + j < 0
- || active->y + i >= fld->bound.y || active->y + i < 0)
+ if (active->x + j >= (int)fld->bound.x || active->x + j < 0
+ || active->y + i >= (int)fld->bound.y || active->y + i < 0)
return 1;
return 0;
}
@@ -222,27 +172,28 @@ static void rotate_shape_right(struct shape *shape)
shape->c[j][i] = arr[i+1][3-j];
}
-void rotate_shape(struct field *fld, struct shape *shape)
+void field_rotate_shape(struct field *fld, unsigned int index)
{
+ struct shape *shape = &fld->shape[index];
rotate_shape_right(shape);
- if (collide(fld, shape))
+ if (field_shape_collision(fld, shape))
rotate_shape_left(shape);
}
-int rm_lines(struct field *fld)
+int field_rm_lines(struct field *fld)
{
- int lines = 0;
- for (int j = 0; j < FLD_SIZE_Y; j++) {
- int cells = 0;
- for (int i = 0; i < FLD_SIZE_X; i++)
+ unsigned int lines = 0;
+ for (unsigned int j = 0; j < fld->bound.y; j++) {
+ unsigned int cells = 0;
+ for (unsigned int i = 0; i < fld->bound.x; i++)
if (fld->c[j][i].a)
++cells;
- if (cells == FLD_SIZE_X) {
+ if (cells == fld->bound.x) {
++lines;
- for (int n = j; n < FLD_SIZE_Y; n++)
- for (int m = 0; m < 10; m++) {
- fld->c[n][m].a = fld->c[n+1][m].a;
- fld->c[n][m].fColor = fld->c[n+1][m].fColor;
+ for (unsigned int n = j; n < fld->bound.y - 1; n++)
+ for (unsigned int m = 0; m < fld->bound.x; m++) {
+ fld->c[n][m].a = fld->c[n + 1][m].a;
+ fld->c[n][m].color = fld->c[n + 1][m].color;
}
--j;
}
@@ -250,14 +201,9 @@ int rm_lines(struct field *fld)
return lines;
}
-void free_field(struct field *fld) {
- for (int j = 0; j < fld->size.y; j++)
- for (int i = 0; i < fld->size.x; i++)
- sfRectangleShape_destroy(fld->p[j][i]);
-}
-
-void free_shape(struct shape *shape) {
- for (int j = 0; j < 4; j++)
- for (int i = 0; i < 4; i++)
- sfRectangleShape_destroy(shape->p[j][i]);
+void field_deinit(struct field *fld) {
+ for (int j = 0; j < (int)fld->bound.y; j++)
+ free(fld->c[j]);
+ free(fld->c);
+ free(fld->shape);
}
diff --git a/src/idlist.c b/src/idlist.c
new file mode 100644
index 0000000..5b4d99b
--- /dev/null
+++ b/src/idlist.c
@@ -0,0 +1,55 @@
+#include <stdlib.h>
+#include "idlist.h"
+
+struct idlist *list_new()
+{
+ struct idlist *list = calloc(1, sizeof(struct idlist));
+ list->id = 1;
+ return list;
+}
+
+struct idlist *list_append(struct idlist *list)
+{
+ if (!list)
+ return list;
+ struct idlist *last = list;
+ while (last->next)
+ last = last->next;
+ last->next = calloc(1, sizeof(struct idlist));
+ last->next->id = last->id + 1;
+ last->next->prev = last;
+ return last->next;
+}
+
+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 = sought->next))
+ if (sought->id == id)
+ return (struct idlist *)sought;
+ }
+ return NULL;
+}
+
+void list_rm_node(struct idlist *node)
+{
+ if (node) {
+ if (node->prev)
+ node->prev->next = node->next;
+ if (node->next)
+ node->next->prev = node->prev;
+ free(node);
+ }
+}
+
+void list_foreach(struct idlist *list, void (*job)(void *))
+{
+ if (list) {
+ job(list->obj);
+ while ((list = list->next))
+ job(list->obj);
+ }
+}
diff --git a/src/main.c b/src/main.c
index 4386205..aa27332 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,8 +18,7 @@ extern struct window w;
List *texts;
sfFont *fontScore;
-struct shape active, next;
-struct field fld;
+struct field fld, nxt;
struct game game = {
.isStarted = 0,
.scoreCurrent = 0,
@@ -31,31 +30,6 @@ struct game game = {
char arrKeys = 0; // Arrow keys states byte container
void prepare() {
- sfRenderWindow_setFramerateLimit(w.window, 60);
-
- /*
- * Dimensions of every fld's cell
- * 23px - fill color 1px - for outline, 25 - at all
- */
- fld.cSize = CELL_SIZE; //Fld's cell size in pixels
- fld.cOutThick = 1;
- 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
-
- next = (struct shape){
- .x = 250 + 10 + 20,
- .y = 200,
- .cOutThick = 1,
- .cSize = {.x = 23, .y = 23}
- };
-
- init_field(&fld);
- init_next_shape(&next);
- gen_shape(&next);
- active.t = next.t;
- resetActiveShape(&fld, &active);
- gen_shape(&next);
}
void handleWindowEvents() {
@@ -78,18 +52,17 @@ void gameLoop() {
tKeyCtrl();
valueAfterTextDisplay(game.scoreCurrent, texts, "score");
valueAfterTextDisplay(game.level, texts, "level");
- colorize_field(&fld);
- colorize_active_shape(&fld, &active);
- drawFld(w.window, &fld);
- drawNextShape(w.window);
+ painter_update_field(fld.id, &fld);
+ painter_update_field(nxt.id, &nxt);
drawTextsAtScene(texts, "game", w.window);
+ painter_draw();
}
void menuTick()
{
if (sfClock_getElapsedTime(game.mTick).microseconds >= basicLatency) {
sfClock_restart(game.mTick);
- colorize_field_random(&fld);
+ field_fill_random(&fld);
painter_update_field(fld.id, &fld);
}
}
@@ -99,10 +72,12 @@ void menuLoop() {
drawTextsAtScene(texts, "menu", w.window);
if (sfKeyboard_isKeyPressed(sfKeyS) == 1) {
game.isStarted = 1;
- free_field(&fld);
- free_shape(&next);
- init_field(&fld);
- init_next_shape(&next);
+ 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();
@@ -111,7 +86,7 @@ void menuLoop() {
void mainLoop() {
while (sfRenderWindow_isOpen(w.window)) {
handleWindowEvents();
- sfRenderWindow_clear(w.window, UIBGCOLOR);
+ sfRenderWindow_clear(w.window, (sfColor)UIBGCOLOR);
if (game.isStarted)
gameLoop();
else
@@ -139,13 +114,32 @@ int main()
texts = ListOfText_getFromListOfKeyMapOfString(tmp);
ListOfKeyMapOfString_free(&tmp);
- prepare();
- colorize_field_random(&fld);
- fld.id = painter_register_field();
+ fld.pos = FLD_POS;
+ fld.size = (struct vector2ui){.x = FLD_SIZE_X, .y = FLD_SIZE_Y};
+ fld.bound = (struct vector2ui){.x = FLD_BOUND_X, .y = FLD_BOUND_Y};
+ fld.shape_cnt = 1;
+ field_init(&fld);
+
+ nxt.pos = NXT_POS;
+ nxt.size = NXT_SIZE;
+ nxt.bound = NXT_SIZE;
+ nxt.shape_cnt = 3;
+ nxt.attr |= FLD_ATTR_TRANSPARENT | FLD_ATTR_INVISIBLE;
+ field_init(&nxt);
+ nxt.shape[0].y = 4;
+ nxt.shape[1].y = 1;
+ nxt.shape[2].y = -2;
+
+ fld.id = painter_register_field(&fld);
+ nxt.id = painter_register_field(&nxt);
+ field_fill_random(&fld);
painter_update_field(fld.id, &fld);
+ painter_update_field(nxt.id, &nxt);
+
mainLoop();
- free_field(&fld);
- free_shape(&next);
+ painter_destroy_drawables();
+ field_deinit(&fld);
+ field_deinit(&nxt);
painter_destroy_window();
sfFont_destroy(fontScore);