diff options
-rw-r--r-- | include/common.h | 22 | ||||
-rw-r--r-- | include/draw.h | 17 | ||||
-rw-r--r-- | include/engine.h | 16 | ||||
-rw-r--r-- | include/field.h | 66 | ||||
-rw-r--r-- | include/idlist.h | 12 | ||||
-rw-r--r-- | include/tet_conf.h | 73 | ||||
-rw-r--r-- | src/draw.c | 202 | ||||
-rw-r--r-- | src/engine.c | 86 | ||||
-rw-r--r-- | src/field.c | 158 | ||||
-rw-r--r-- | src/idlist.c | 55 | ||||
-rw-r--r-- | src/main.c | 78 |
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.......... @@ -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); + } +} @@ -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); |