summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);