From bf0e5690a31d4c3cecd2ba512729a0b73989bbda Mon Sep 17 00:00:00 2001 From: Oxore Date: Mon, 25 Jun 2018 15:50:58 +0300 Subject: Major refactoring Fix memleak in KeyMap, fix memleak caused by loading a yaml file in main.c. Change Copyright information. Rename functions.c and .h to engine.c and .h. Take field and shape related functions to separate file (still not all of them) and refactor them a lot. Refactor collision detection. Add more warnings. Add sanitizer option commented out. --- .clang | 0 LICENSE.md | 2 +- Makefile | 8 + README.md | 4 +- include/common.h | 77 +----- include/engine.h | 19 ++ include/field.h | 58 +++++ include/functions.h | 34 --- include/text.h | 48 +++- src/engine.c | 367 ++++++++++++++++++++++++++++ src/field.c | 235 ++++++++++++++++++ src/functions.c | 678 ---------------------------------------------------- src/main.c | 61 +++-- src/text.c | 9 +- 14 files changed, 771 insertions(+), 829 deletions(-) delete mode 100644 .clang create mode 100644 include/engine.h create mode 100644 include/field.h delete mode 100644 include/functions.h create mode 100644 src/engine.c create mode 100644 src/field.c delete mode 100644 src/functions.c diff --git a/.clang b/.clang deleted file mode 100644 index e69de29..0000000 diff --git a/LICENSE.md b/LICENSE.md index a27360c..ba2432b 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,7 +2,7 @@ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE Version 2, December 2004 - Copyright (C) 2004 Sam Hocevar + Copyright (C) 2018 Vladimir Novikov Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long diff --git a/Makefile b/Makefile index 1f7ddfd..133184a 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,20 @@ OBJECTS:=$(patsubst $(SRC)/%.c,$(BUILD)/%.c.o,$(SOURCES)) INCLUDE+=include INCLUDE:=$(patsubst %,-I%,$(INCLUDE)) +#COMMON+=-fsanitize=leak + +CFLAGS+=$(COMMON) CFLAGS+=$(INCLUDE) CFLAGS+=-Wall +CFLAGS+=-Wextra +CFLAGS+=-Wpedantic +CFLAGS+=-Wduplicated-branches +CFLAGS+=-Wduplicated-cond CFLAGS+=-std=c11 CFLAGS+=-g3 CFLAGS+=-O0 +LDFLAGS+=$(COMMON) LDFLAGS+=-lcsfml-graphics LDFLAGS+=-lcsfml-window LDFLAGS+=-lcsfml-system diff --git a/README.md b/README.md index 414f850..6ace971 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,9 @@ make clean __Windows__ -Hey look at the [repo releases](https://github.com/Oxore/tetris-csfml/releases)! Now I have some windows binaries there! +Look at the [repo releases](https://github.com/Oxore/tetris-csfml/releases)! Now I have some windows binaries there! -__TODO:__ +### TODO: - Add screenshots and gameplay gif - [x] Levels speed and scores calibration diff --git a/include/common.h b/include/common.h index 773cb3f..275547a 100644 --- a/include/common.h +++ b/include/common.h @@ -1,82 +1,13 @@ -/* - * Types - * - * */ - -typedef struct Cell { - char a; // active/empty state of cell - sfColor fColor; // fill color -} Cell; - - -/* - * shape coords - * y - * ^. . . . - * |. . . . - * |. . . . - * |. . . . - * 0------->x - * - */ - -typedef 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 - char c[4][4]; // array of logic shape cells - sfRectangleShape *p[4][4]; // array of physical shape cells - sfVector2f cSize; // shape rectangles size variable x/y -} Shape; - -typedef struct Field { - sfVector2i pos; - sfColor fColor; // shape color - Cell c[25][10]; // array of logic shape cells - sfRectangleShape *p[25][10]; // array of physical shape cells - int cOutThick; // Field rectangles outline thickness - sfVector2f cSize; // shape rectangles size variable x/y - sfVector2i size; -} Field; - -typedef struct Window { +struct window { sfVideoMode mode; sfRenderWindow *window; sfEvent event; -} Window; +}; -typedef struct Game { +struct game { int isStarted; int scoreCurrent; int level; int moveLatency; int lines; -} Game; - -/* ======== text.[c|h] types =========== */ - -typedef struct List { - void *obj; - void *next; - void *prev; -} List; - -typedef struct Pair { - void *k; - void *v; -} Pair; - -typedef struct KeyMap { - Pair *pair; - void *next; - void *prev; -} KeyMap; - -typedef struct Text { - char *font; - char *type; - char *scene; - char *text; - void *sfText; -} Text; +}; diff --git a/include/engine.h b/include/engine.h new file mode 100644 index 0000000..655eb01 --- /dev/null +++ b/include/engine.h @@ -0,0 +1,19 @@ +#define RIGHT 1 +#define DOWN 2 +#define UP 4 +#define LEFT 8 +#define RIGHTHOLD 16 +#define LEFTHOLD 128 + +void tKeyCtrl(); +void tTick(); +void checkLevelUp(struct game *game); +int getMoveLatencyOfLevel(int level); +int rmLines(); +void valueAfterTextDisplay(int value, List *texts, char *type); +void colorizeActive(); +void drawFld(sfRenderWindow *window); +void gameover(struct game *game); +void genNextShape(); +void drawNextShape(); +void freeFld(); diff --git a/include/field.h b/include/field.h new file mode 100644 index 0000000..410e609 --- /dev/null +++ b/include/field.h @@ -0,0 +1,58 @@ +#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 +/* + * Types + * + * */ + +struct cell { + char a; // active/empty state of cell + sfColor fColor; // fill color +}; + + +/* + * shape coords + * y + * ^. . . . + * |. . . . + * |. . . . + * |. . . . + * 0------->x + * + */ + +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 + 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; + sfColor fColor; // shape color + struct cell c[FLD_BOUND_Y][FLD_SIZE_X]; // array of logic shape cells + sfRectangleShape *p[FLD_BOUND_Y][FLD_SIZE_X]; // array of physical shape cells + int cOutThick; // Field rectangles outline thickness + sfVector2f cSize; // shape rectangles size variable x/y + sfVector2i size; + sfVector2i bound; +}; + +void init_field(struct field *fld); +void colorize_field(struct field *fld); +void colorize_field_random(struct field *fld); +void init_next_shape_field(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); diff --git a/include/functions.h b/include/functions.h deleted file mode 100644 index f47f816..0000000 --- a/include/functions.h +++ /dev/null @@ -1,34 +0,0 @@ -#define RIGHT 0b0001 -#define DOWN 0b0010 -#define UP 0b0100 -#define LEFT 0b1000 -#define RIGHTHOLD 0b10000 -#define LEFTHOLD 0b10000000 - -void tKeyCtrl(); -void initFld(); -void tTick(); -void resetActiveShape(Shape *active); -void putShape(); -int outOfFieldCheck(Field *fld, Shape *active); -void checkLevelUp(Game *game); -int getMoveLatencyOfLevel(int level); -int cellCollisionCheckHere(Field *fld, Shape *active); -int cellCollisionCheck(int dir); -int wallCollisionCheck(); -int cellRotCollisionCheck(); -int wallRotCollisionCheck(); -void rotateLeft(); -void rotateRight(); -void rotateShape(); -int rmLines(); -void valueAfterTextDisplay(int value, List *texts, char *type); -void colorizeFld(); -void colorizeActive(); -void drawFld(sfRenderWindow *window); -void colorizeRandom(Field *fld); -void gameover(Game *game); -void genNextShape(); -void copyShape(Shape *localSh); -void drawNextShape(); -void freeFld(); diff --git a/include/text.h b/include/text.h index 1171a51..73285bf 100644 --- a/include/text.h +++ b/include/text.h @@ -1,17 +1,39 @@ -FILE *openFile(char *filename); -void checkArgs(int argc, char **argv); +typedef struct List { + void *obj; + void *next; + void *prev; +} List; + +typedef struct Pair { + void *k; + void *v; +} Pair; + +typedef struct KeyMap { + Pair *pair; + void *next; + void *prev; +} KeyMap; + +typedef struct Text { + char *font; + char *type; + char *scene; + char *text; + void *sfText; +} Text; + +FILE *openFile(char *filename); +void checkArgs(int argc, char **argv); KeyMap *KeyMap_getLast(KeyMap **keyMap); KeyMap *KeyMap_new(KeyMap **keyMap); KeyMap *KeyMap_get(KeyMap **keyMap, const void *key); KeyMap *KeyMap_put(KeyMap **keyMap, const void *key, const void *value); -List *List_getLast(List **list); -List *List_new(List **list); -List *ListOfKeyMapOfString_getFromYaml(char *filename); -void KeyMapOfString_free(KeyMap *keyMap); -void ListOfKeyMapOfString_free(List **list); -int _loadText_getInt(void *obj, char *key); -char *_loadText_getString(void *obj, char *key); -void _loadText_initSfText(Text *objo, void *obji); -List *ListOfText_getFromListOfKeyMapOfString(List *list); -void Text_free(Text *obj); -void ListOfText_free(List **list); +List *List_getLast(List **list); +List *List_new(List **list); +List *ListOfKeyMapOfString_getFromYaml(char *filename); +void KeyMapOfString_free(KeyMap *keyMap); +void ListOfKeyMapOfString_free(List **list); +List *ListOfText_getFromListOfKeyMapOfString(List *list); +void Text_free(Text *obj); +void ListOfText_free(List **list); diff --git a/src/engine.c b/src/engine.c new file mode 100644 index 0000000..6df3c79 --- /dev/null +++ b/src/engine.c @@ -0,0 +1,367 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "tet_conf.h" +#include "text.h" +#include "field.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 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; + while (l) { + Text *text = (Text *)l->obj; + if (text->type) + if (!strcmp(text->type, type)) { + char a[64]; + if (text->text) { + if (strlen(text->text) > 52) { + memset(text->text+52, '\0', 1); + strcpy(a, text->text); + } + sprintf(a, "%s%d", text->text, value); + sfText_setString(text->sfText, (char *)&a); + break; + } + } + l = l->next; + } +} + +/* + * Removes line when cells all are in row in it + * + */ +int rmLines() +{ + int k = 0; // "Filled line" indicator + int s = 0; + for (int j = 0; j < 22; j++) { + for (int i = 0; i < 10; i++) + if (fld.c[j][i].a != 0) + k++; + if (k >= 10) { // If line is full + s++; // Give scores for line + for (int n = j; n < 22; n++) { // Drop all lines down + if (n == 21) { + for (int m = 0; m < 10; m++) { + fld.c[n][m].a = 0; + fld.c[n][m].fColor = UIBGCOLOR; + } + break; + } + 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; + } + } + j--; // Do not let loop to go to next line because + // next line go down by itself =) + } + k = 0; // Clear line fill indicator + } + return s; // Return number of deleted lines +} + +void checkLevelUp(struct game *game) +{ + while (game->lines >= LEVELUP_LINES) { + game->level++; + game->lines -= LEVELUP_LINES; + game->moveLatency = getMoveLatencyOfLevel(game->level); + } +} + +int getMoveLatencyOfLevel(int level) +{ + if (level >= 29) + return L29LATENCY; + else if (level >= 19) + return L19LATENCY; + else if (level >= 16) + return L16LATENCY; + else if (level >= 13) + return L13LATENCY; + else if (level >= 10) + return L10LATENCY; + else if (level == 9) + return L09LATENCY; + else if (level == 8) + return L08LATENCY; + else if (level == 7) + return L07LATENCY; + else if (level == 6) + return L06LATENCY; + else if (level == 5) + return L05LATENCY; + else if (level == 4) + return L04LATENCY; + else if (level == 3) + return L03LATENCY; + else if (level == 2) + return L02LATENCY; + else if (level == 1) + return L01LATENCY; + else if (level == 0) + return L00LATENCY; + return L00LATENCY; +} + + +/* + * Game tick + * + */ +void tTick() +{ // If tick exceeds current level tick latency + if (sfClock_getElapsedTime(gameTick).microseconds >= game.moveLatency) { + sfClock_restart(gameTick); + active.y--; // try + if (collide(&fld, &active)) + active.y++; // fallback + else + sfClock_restart(putTick); + if (sfClock_getElapsedTime(putTick).microseconds >= PUT_LATENCY) { + if (out_of_field(&fld, &active)) { + gameover(&game); + return; + } else { + putShape(&fld, &active); + int removedLines = rmLines(); + game.lines += removedLines; + switch (removedLines) { + case 1: + game.scoreCurrent += RM_1LINES_SCORE * game.level; + break; + case 2: + game.scoreCurrent += RM_2LINES_SCORE * game.level; + break; + case 3: + game.scoreCurrent += RM_3LINES_SCORE * game.level; + break; + case 4: + game.scoreCurrent += RM_4LINES_SCORE * game.level; + break; + } + active.t = next.t; + resetActiveShape(&fld, &active); + genNextShape(); + checkLevelUp(&game); + } + sfClock_restart(putTick); + } + } +} + + + + + + +/* + * Keys hold handler + * + */ +void tKeyCtrl() +{ + /* Up arrow key 'hold' handler */ + if (sfKeyboard_isKeyPressed(sfKeyUp)) { + if (!(arrKeys & UP)) { + arrKeys = arrKeys | UP; + rotate_shape(&fld, &active); + } + } else { + if ((arrKeys & UP)) { + arrKeys = arrKeys & ~UP; + } + } + + /* Down Arrow Key 'hold' handler */ + if (sfKeyboard_isKeyPressed(sfKeyDown)) { + if (!(arrKeys & DOWN)) { + arrKeys = arrKeys | DOWN; + active.y--; + if (collide(&fld, &active)) + active.y++; + else { + // Avoid excess move down by gameTick + sfClock_restart(putTick); + sfClock_restart(gameTick); + game.scoreCurrent++; + } + sfClock_restart(repPushDown); + } else { + if (sfClock_getElapsedTime(repPushDown).microseconds + >= moveRepeatLatency2) + arrKeys = arrKeys & ~DOWN; + } + } else { + if ((arrKeys & DOWN)) { + arrKeys = arrKeys & ~DOWN; + } + } + + /* Left Arrow Key 'hold' handler */ + if (sfKeyboard_isKeyPressed(sfKeyLeft) + && !sfKeyboard_isKeyPressed(sfKeyRight)) { + if (!(arrKeys & LEFT)) { + arrKeys = arrKeys | LEFT; + active.x--; + if (collide(&fld, &active)) + active.x++; + else + sfClock_restart(putTick); + sfClock_restart(repKeyLeft); + } else { + if (!(arrKeys & LEFTHOLD)) { + if (sfClock_getElapsedTime(repKeyLeft).microseconds + >= moveRepeatLatency1) { + arrKeys = arrKeys | LEFTHOLD; + arrKeys = arrKeys & ~LEFT; + } + } else { + if (sfClock_getElapsedTime(repKeyLeft).microseconds + >= moveRepeatLatency2) + arrKeys = arrKeys & ~LEFT; + } + } + } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) { + if ((arrKeys & LEFT)) { + arrKeys = arrKeys & ~LEFT; + arrKeys = arrKeys & ~LEFTHOLD; + } + } + + /* Right Arrow Key 'hold' handler */ + if (sfKeyboard_isKeyPressed(sfKeyRight) + && !sfKeyboard_isKeyPressed(sfKeyLeft)) { + if (!(arrKeys & RIGHT)) { + arrKeys = arrKeys | RIGHT; + active.x++; + if (collide(&fld, &active)) + active.x--; + else + sfClock_restart(putTick); + sfClock_restart(repKeyRight); + } else { + if (!(arrKeys & RIGHTHOLD)) { + if (sfClock_getElapsedTime(repKeyRight).microseconds + >= moveRepeatLatency1) { + arrKeys = arrKeys | RIGHTHOLD; + arrKeys = arrKeys & ~RIGHT; + } + } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) { + if (sfClock_getElapsedTime(repKeyRight).microseconds + >= moveRepeatLatency2) // Wait short time + arrKeys = arrKeys & ~RIGHT; + } + } + } else { + if ((arrKeys & RIGHT)) { + arrKeys = arrKeys & ~RIGHT; + arrKeys = arrKeys & ~RIGHTHOLD; + } + } +} + + +/* + * Colorize active cells of active shape (overlay only + * active cells above background of fld) + * + */ +void colorizeActive() +{ + for (int j = 0; j < 4; j++) + for (int i = 0; i < 4; i++) + if (active.c[j][i] && j+active.y < 22) { + sfRectangleShape_setFillColor(fld.p[j + active.y][i + active.x], + active.fColor); + sfRectangleShape_setOutlineColor( + fld.p[j + active.y][i + active.x], UIFGACTIVECOLOR); + } +} + + +/* + * Draw all fld cells + * + */ +void drawFld(sfRenderWindow *window) +{ + 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; + game->scoreCurrent = 0; + game->level = 0; + game->moveLatency = L00LATENCY; + game->lines = 0; +} + + +void genNextShape() +{ + next.t = (rand() % 7) + 1; // Insert new random shape of 7 variants + load_shape(&next); + if (next.t == 5) + for (int j = 0; j < 3; j++) + for (int i = 0; i < 4; i++) + next.c[i][j] = next.c[i][j+1]; +} + + + + +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); + } +} + +void freeFld() { + for (int j = 0; j < fld.size.y; j++) + for (int i = 0; i < fld.size.x; i++) + sfRectangleShape_destroy(fld.p[j][i]); + for (int j = 0; j < 4; j++) + for (int i = 0; i < 4; i++) + sfRectangleShape_destroy(next.p[j][i]); +} diff --git a/src/field.c b/src/field.c new file mode 100644 index 0000000..dcb332d --- /dev/null +++ b/src/field.c @@ -0,0 +1,235 @@ +#include +#include +#include + +#include "field.h" +#include "tet_conf.h" + +/* Shapes maps */ +extern char arrShapeL[4][4]; +extern char arrShapeRL[4][4]; +extern char arrShapeZ[4][4]; +extern char arrShapeS[4][4]; +extern char arrShapeB[4][4]; +extern char arrShapeI[4][4]; +extern char arrShapeT[4][4]; + +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) +{ + 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); + } + } +} + +void colorize_field(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); + } +} + +void colorize_field_random(struct field *fld) +{ + int a; + for (int j = 0; j < fld->size.y; j++) { + for (int i = 0; i < fld->size.x; i++) { + a = rand() % 7 + 1; + switch (a) { + case 1 : + sfRectangleShape_setFillColor(fld->p[j][i], LCOLOR); + break; + case 2 : + sfRectangleShape_setFillColor(fld->p[j][i], RLCOLOR); + break; + case 3 : + sfRectangleShape_setFillColor(fld->p[j][i], ZCOLOR); + break; + case 4 : + sfRectangleShape_setFillColor(fld->p[j][i], SCOLOR); + break; + case 5 : + sfRectangleShape_setFillColor(fld->p[j][i], BCOLOR); + break; + case 6 : + sfRectangleShape_setFillColor(fld->p[j][i], ICOLOR); + break; + case 7 : + sfRectangleShape_setFillColor(fld->p[j][i], TCOLOR); + break; + } + sfRectangleShape_setOutlineColor(fld->p[j][i], UIFGACTIVECOLOR); + } + } +} + +void init_next_shape_field(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) +{ + 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; + } +} + +int out_of_field(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) + return 1; + return 0; +} + +void load_shape(struct shape *shape) +{ + 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) +{ + load_shape(active); + active->x = 3; + if (active->t == 6) + active->y = 19; + else + active->y = 18; + while (collide(fld, active)) { + active->y++; + } +} + +int collide(struct field *fld, struct shape *active) +{ + if (out_of_bounds(fld, active)) + 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) + return 1; + return 0; +} + +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) + return 1; + return 0; +} + +static void rotate_shape_left(struct shape *shape) +{ + char arr[4][4]; + memcpy(&arr[0][0], &shape->c[0][0], sizeof(char)*4*4); + if (shape->t == 5) + return; + if (shape->t == 6) { + for (int j = 3; j >= 0; j--) + for (int i = 0; i < 4; i++) + shape->c[j][i] = arr[3-i][3-j]; + return; + } + for (int j = 3; j > 0; j--) + for (int i = 0; i < 3; i++) + shape->c[j][i] = arr[3-i][j-1]; +} + +static void rotate_shape_right(struct shape *shape) +{ + char arr[4][4]; + memcpy(&arr[0][0], &shape->c[0][0], sizeof(char)*4*4); + if (shape->t == 5) + return; + if (shape->t == 6) { + for (int j = 3; j >= 0; j--) + for (int i = 0; i < 4; i++) + shape->c[j][i] = arr[3-i][3-j]; + return; + } + for (int j = 3; j > 0; j--) + for (int i = 0; i < 3; i++) + shape->c[j][i] = arr[i+1][3-j]; +} + +void rotate_shape(struct field *fld, struct shape *shape) +{ + rotate_shape_right(shape); + if (collide(fld, shape)) + rotate_shape_left(shape); +} diff --git a/src/functions.c b/src/functions.c deleted file mode 100644 index eebbf67..0000000 --- a/src/functions.c +++ /dev/null @@ -1,678 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "tet_conf.h" -#include "functions.h" - -/* Externs from main.c */ -extern Game game; -extern Shape active, next; -extern Field fld; - -extern sfFont *fontScore; - -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 - -/* Shapes maps */ -extern char arrShapeL[4][4]; -extern char arrShapeRL[4][4]; -extern char arrShapeZ[4][4]; -extern char arrShapeS[4][4]; -extern char arrShapeB[4][4]; -extern char arrShapeI[4][4]; -extern char arrShapeT[4][4]; - - -/* Field init routine */ -void initFld() -{ - sfVector2f fldCPos[22][10]; - /* Create field */ - 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); - } - } - /* Create next shape field */ - 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*fld.cOutThick); - nsPos.y = next.y-j*(next.cSize.y+2*fld.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], fld.cOutThick); - } - } - genNextShape(); - resetActiveShape(&active); -} - - -void valueAfterTextDisplay(int value, List *texts, char *type) -{ - List *l = texts; - while (l) { - Text *text = (Text *)l->obj; - if (text->type) - if (!strcmp(text->type, type)) { - char a[64]; - if (text->text) { - if (strlen(text->text) > 52) { - memset(text->text+52, '\0', 1); - strcpy(a, text->text); - } - sprintf(a, "%s%d", text->text, value); - sfText_setString(text->sfText, (char *)&a); - break; - } - } - l = l->next; - } -} - -/* - * Removes line when cells all are in row in it - * - */ -int rmLines() -{ - int k = 0; // "Filled line" indicator - int s = 0; - for (int j = 0; j < 22; j++) { - for (int i = 0; i < 10; i++) - if (fld.c[j][i].a != 0) - k++; - if (k >= 10) { // If line is full - s++; // Give scores for line - for (int n = j; n < 22; n++) { // Drop all lines down - if (n == 21) { - for (int m = 0; m < 10; m++) { - fld.c[n][m].a = 0; - fld.c[n][m].fColor = UIBGCOLOR; - } - break; - } - 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; - } - } - j--; // Do not let loop to go to next line because - // next line go down by itself =) - } - k = 0; // Clear line fill indicator - } - return s; // Return number of deleted lines -} - -/* - * Inserts shape into field, runs filled lines searching, puts new shape - * into the game at the top. - * - */ -void putShape() -{ - if (outOfFieldCheck(&fld, &active)) { - gameover(&game); - return; - } - 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]; - if ((j+active.y >= 0) && (i+active.x >= 0)) - fld.c[j+active.y][i+active.x].fColor = active.fColor; - } - int removedLines = rmLines(); - game.lines += removedLines; - switch (removedLines) { - case 1: - game.scoreCurrent += RM_1LINES_SCORE * game.level; - break; - case 2: - game.scoreCurrent += RM_2LINES_SCORE * game.level; - break; - case 3: - game.scoreCurrent += RM_3LINES_SCORE * game.level; - break; - case 4: - game.scoreCurrent += RM_4LINES_SCORE * game.level; - break; - } - resetActiveShape(&active); - checkLevelUp(&game); -} - -int outOfFieldCheck(Field *fld, 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) { - gameover(&game); - return 1; - } - } - } - return 0; -} - -void checkLevelUp(Game *game) -{ - while (game->lines >= LEVELUP_LINES) { - game->level++; - game->lines -= LEVELUP_LINES; - game->moveLatency = getMoveLatencyOfLevel(game->level); - } -} - -int getMoveLatencyOfLevel(int level) -{ - if (level >= 29) - return L29LATENCY; - else if (level >= 19) - return L19LATENCY; - else if (level >= 16) - return L16LATENCY; - else if (level >= 13) - return L13LATENCY; - else if (level >= 10) - return L10LATENCY; - else if (level == 9) - return L09LATENCY; - else if (level == 8) - return L08LATENCY; - else if (level == 7) - return L07LATENCY; - else if (level == 6) - return L06LATENCY; - else if (level == 5) - return L05LATENCY; - else if (level == 4) - return L04LATENCY; - else if (level == 3) - return L03LATENCY; - else if (level == 2) - return L02LATENCY; - else if (level == 1) - return L01LATENCY; - else if (level == 0) - return L00LATENCY; - return L00LATENCY; -} - -void resetActiveShape(Shape *active) -{ - genNextShape(); - copyShape(active); - active->x = 3; - if (active->t == 6) - active->y = 19; - else - active->y = 18; - for (;;) { - if (cellCollisionCheckHere(&fld, active)) - active->y++; - else - break; - } -} - -/* - * Game tick - * - */ -void tTick() -{ // If tick exceeds current level tick latency - if (sfClock_getElapsedTime(gameTick).microseconds - >= game.moveLatency) { - sfClock_restart(gameTick); - /* if bottom not reached */ - if ((wallCollisionCheck(DOWN) == 0) - && (cellCollisionCheck(DOWN) == 0)) { - active.y--; // Move - sfClock_restart(putTick); - } else { - if (sfClock_getElapsedTime(putTick).microseconds >= PUT_LATENCY) { - putShape(); // Just put the shape - sfClock_restart(putTick); - } - } - } -} - - -/* - * Rotate matrix left routine - * - */ -void rotateLeft() -{ - char arr[4][4]; - memcpy(&arr[0][0], &active.c[0][0], sizeof(char)*4*4); - if (active.t == 5) - return; - if (active.t == 6) { - for (int j = 3; j >= 0; j--) - for (int i = 0; i < 4; i++) - active.c[j][i] = arr[3-i][3-j]; - return; - } - for (int j = 3; j > 0; j--) - for (int i = 0; i < 3; i++) - active.c[j][i] = arr[3-i][j-1]; -} - - -/* - * Rotate matrix right routine - * - */ -void rotateRight() -{ - char arr[4][4]; - memcpy(&arr[0][0], &active.c[0][0], sizeof(char)*4*4); - if (active.t == 5) - return; - if (active.t == 6) { - for (int j = 3; j >= 0; j--) - for (int i = 0; i < 4; i++) - active.c[j][i] = arr[3-i][3-j]; - return; - } - for (int j = 3; j > 0; j--) - for (int i = 0; i < 3; i++) - active.c[j][i] = arr[i+1][3-j]; -} - - -/* - * Rotates active shape with callling collision checkers - * - */ -void rotateShape() -{ - rotateRight(); // Try rotate - if ((wallRotCollisionCheck()) - || (cellRotCollisionCheck())) - rotateLeft(); -} - -int cellRotCollisionCheck() -{ - 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) - return 1; // Collision happens - return 0; // Else it do not -} - - -int wallRotCollisionCheck() -{ - if (active.y < 0) //If shape has crossed Bottom border - for (int i = 0; i < 4; i++) - if (active.c[-1-active.y][i]) - return 1; // Collision happens - if (active.x < 0) //If shape has crossed Left border - for (int i = 0; i < 4; i++) - if (active.c[i][-1-active.x]) - return 1; // Collision happens - if (active.x > 6) //If shape has crossed Right border - for (int i = 0; i < 4; i++) - if (active.c[i][3-(active.x-7)]) - return 1; // Collision happens - return 0; // If no conditions are met collision is absent -} - -int cellCollisionCheckHere(Field *fld, Shape *active) -{ - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - if (active->y + i < fld->size.y) - if (active->c[i][j] && fld->c[i+active->y][j+active->x].a) - return 1; - return 0; -} - -int cellCollisionCheck(int dir) -{ - for (int j = 0; j < 4; j++) { - for (int i = 0; i < 4; i++) { - if ((dir & RIGHT) // Check Right - && (j+active.y >= 0) // Avoiding nonexisting fld cells - && (i+active.x+1 >= 0) // --- - && active.c[j][i] // Check activity - && fld.c[j+active.y][i+active.x+1].a) - return 1; // Collision happens - if ((dir & LEFT) // Check Left - && (j+active.y >= 0) // Avoiding nonexisting fld cells - && (i+active.x-1 >= 0) // --- - && active.c[j][i] // Check activity - && fld.c[j+active.y][i+active.x-1].a) - return 1; // Collision happens - if ((dir & DOWN) // Check Bottom - && (j+active.y-1 >= 0) // Avoiding nonexisting fld cells - && (i+active.x >= 0) // --- - && active.c[j][i] // Check activity - && fld.c[j+active.y-1][i+active.x].a) - return 1; // Collision happens - } - } - return 0; // Else it do not -} - -int wallCollisionCheck(int dir) -{ - if (dir & RIGHT) { // Right collision request - if (active.x >= 6) // If shape has reached Right boreder - for (int i = 0 ; i < 4; i++) - if (active.c[i][3-(active.x-6)]) - return 1; // Collision happens - } else if (dir & DOWN) { // Bottom collision request - if (active.y <= 0) //If shape has reached Bottom border - for (int i = 0; i < 4; i++) - if (active.c[-active.y][i]) - return 1; // Collision happens - } else if (dir & LEFT) // Left collision request - if (active.x <= 0) // If shape has reached Left border - for (int i = 0; i < 4; i++) - if (active.c[i][-active.x]) - return 1; // Collision happens - return 0; -} - - -/* - * Keys hold handler - * - */ -void tKeyCtrl() -{ - /* Up arrow key 'hold' handler */ - if (sfKeyboard_isKeyPressed(sfKeyUp)) { - if (!(arrKeys & UP)) { - arrKeys = arrKeys | UP; - rotateShape(); - } - } else { - if ((arrKeys & UP)) { - arrKeys = arrKeys & ~UP; - } - } - - /* Down Arrow Key 'hold' handler */ - if (sfKeyboard_isKeyPressed(sfKeyDown)) { - if (!(arrKeys & DOWN)) { - arrKeys = arrKeys | DOWN; - if (!wallCollisionCheck(DOWN) - && !cellCollisionCheck(DOWN)) { - active.y--; - // Avoid excess move down by gameTick - sfClock_restart(putTick); - sfClock_restart(gameTick); - game.scoreCurrent++; - } - repPushDown = sfClock_create(); - } else { - if (sfClock_getElapsedTime(repPushDown).microseconds - >= moveRepeatLatency2) - arrKeys = arrKeys & ~DOWN; - } - } else { - if ((arrKeys & DOWN)) { - arrKeys = arrKeys & ~DOWN; - } - } - - /* Left Arrow Key 'hold' handler */ - if (sfKeyboard_isKeyPressed(sfKeyLeft) - && !sfKeyboard_isKeyPressed(sfKeyRight)) { - if (!(arrKeys & LEFT)) { - arrKeys = arrKeys | LEFT; - if (!wallCollisionCheck(LEFT) - && !cellCollisionCheck(LEFT)) { - active.x--; - sfClock_restart(putTick); - } - repKeyLeft = sfClock_create(); - } else { - if (!(arrKeys & LEFTHOLD)) { - if (sfClock_getElapsedTime(repKeyLeft) - .microseconds - >= moveRepeatLatency1) { - arrKeys = arrKeys | LEFTHOLD; - arrKeys = arrKeys & ~LEFT; - } - } else { - if (sfClock_getElapsedTime(repKeyLeft) - .microseconds - >= moveRepeatLatency2) - arrKeys = arrKeys & ~LEFT; - } - } - } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) { - if ((arrKeys & LEFT)) { - arrKeys = arrKeys & ~LEFT; - arrKeys = arrKeys & ~LEFTHOLD; - } - } - - /* Right Arrow Key 'hold' handler */ - if (sfKeyboard_isKeyPressed(sfKeyRight) - && !sfKeyboard_isKeyPressed(sfKeyLeft)) { - if (!(arrKeys & RIGHT)) { - arrKeys = arrKeys | RIGHT; - if (!wallCollisionCheck(RIGHT) - && !cellCollisionCheck(RIGHT)) { - active.x++; - sfClock_restart(putTick); - } - repKeyRight = sfClock_create(); - } else { - if (!(arrKeys & RIGHTHOLD)) { - if (sfClock_getElapsedTime(repKeyRight).microseconds - >= moveRepeatLatency1) { - arrKeys = arrKeys | RIGHTHOLD; - arrKeys = arrKeys & ~RIGHT; - } - } else if (!sfKeyboard_isKeyPressed(sfKeyLeft)) { - if (sfClock_getElapsedTime(repKeyRight).microseconds - >= moveRepeatLatency2) // Wait short time - arrKeys = arrKeys & ~RIGHT; - } - } - } else { - if ((arrKeys & RIGHT)) { - arrKeys = arrKeys & ~RIGHT; - arrKeys = arrKeys & ~RIGHTHOLD; - } - } -} - - -/* - * Colorize active cells of field - * - */ -void colorizeFld() -{ - 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); - } -} - -/* - * Colorize active cells of active shape (overlay only - * active cells above background of fld) - * - */ -void colorizeActive() -{ - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - if (active.c[j][i] && j+active.y < 22) { - sfRectangleShape_setFillColor( - fld.p[j+active.y][i+active.x], - active.fColor); - sfRectangleShape_setOutlineColor( - fld.p[j+active.y][i+active.x], - UIFGACTIVECOLOR); - } -} - - -/* - * Draw all fld cells - * - */ -void drawFld(sfRenderWindow *window) -{ - 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 colorizeRandom(Field *fld) -{ - int a; - for (int j = 0; j < fld->size.y; j++) { - for (int i = 0; i < fld->size.x; i++) { - a = rand()%7+1; - switch (a) { - case 1 : - sfRectangleShape_setFillColor(fld->p[j][i], LCOLOR); - break; - case 2 : - sfRectangleShape_setFillColor(fld->p[j][i], RLCOLOR); - break; - case 3 : - sfRectangleShape_setFillColor(fld->p[j][i], ZCOLOR); - break; - case 4 : - sfRectangleShape_setFillColor(fld->p[j][i], SCOLOR); - break; - case 5 : - sfRectangleShape_setFillColor(fld->p[j][i], BCOLOR); - break; - case 6 : - sfRectangleShape_setFillColor(fld->p[j][i], ICOLOR); - break; - case 7 : - sfRectangleShape_setFillColor(fld->p[j][i], TCOLOR); - break; - } - sfRectangleShape_setOutlineColor(fld->p[j][i], UIFGACTIVECOLOR); - } - } -} - - -void gameover(Game *game) -{ - game->isStarted = 0; - game->scoreCurrent = 0; - game->level = 0; - game->moveLatency = L00LATENCY; - game->lines = 0; -} - - -void genNextShape() -{ - active.t = next.t; - next.t = (rand()%7)+1; // Insert new random shape of 7 variants - copyShape(&next); - if (next.t == 5) - for (int j = 0; j < 3; j++) - for (int i = 0; i < 4; i++) - next.c[i][j] = next.c[i][j+1]; -} - - -void copyShape(Shape *localSh) -{ - switch (localSh->t) { // Copy cell active/inactive state - case 1 : - memcpy(&localSh->c[0][0], &arrShapeL[0][0], sizeof(char)*4*4); - localSh->fColor = LCOLOR; - break; - case 2 : - memcpy(&localSh->c[0][0], &arrShapeRL[0][0], sizeof(char)*4*4); - localSh->fColor = RLCOLOR; - break; - case 3 : - memcpy(&localSh->c[0][0], &arrShapeZ[0][0], sizeof(char)*4*4); - localSh->fColor = ZCOLOR; - break; - case 4 : - memcpy(&localSh->c[0][0], &arrShapeS[0][0], sizeof(char)*4*4); - localSh->fColor = SCOLOR; - break; - case 5 : - memcpy(&localSh->c[0][0], &arrShapeB[0][0], sizeof(char)*4*4); - localSh->fColor = BCOLOR; - break; - case 6 : - memcpy(&localSh->c[0][0], &arrShapeI[0][0], sizeof(char)*4*4); - localSh->fColor = ICOLOR; - break; - case 7 : - memcpy(&localSh->c[0][0], &arrShapeT[0][0], sizeof(char)*4*4); - localSh->fColor = TCOLOR; - break; - } -} - - -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); - } -} - -void freeFld() { - for (int j = 0; j < fld.size.y; j++) - for (int i = 0; i < fld.size.x; i++) - sfRectangleShape_destroy(fld.p[j][i]); - for (int j = 0; j < 4; j++) - for (int i = 0; i < 4; i++) - sfRectangleShape_destroy(next.p[j][i]); -} diff --git a/src/main.c b/src/main.c index 521d1c5..853e974 100644 --- a/src/main.c +++ b/src/main.c @@ -8,24 +8,25 @@ #include #include "common.h" -#include "functions.h" #include "text.h" +#include "field.h" +#include "engine.h" #include "tet_conf.h" -Window w = {.mode = {450, 570, 32}}; -Game game = { +List *texts; +sfFont *fontScore; +struct shape active, next; +struct field fld; +struct window w = {.mode = {450, 570, 32}}; +struct game game = { .isStarted = 0, .scoreCurrent = 0, .level = 0, .moveLatency = L00LATENCY, .lines = 0 }; -List *texts; -sfFont *fontScore; -Shape active, next; -Field fld; -char arrKeys = 0b00000000; // Arrow keys states byte container +char arrKeys = 0; // Arrow keys states byte container sfClock *gameTick; sfClock *putTick; @@ -35,10 +36,13 @@ sfClock *repKeyLeft; // Clock for repeat latency when Left arrow long push sfClock *repKeyRight; // Clock for repeat latency when Left arrow long push void prepare() { - srand( time(NULL) ); + srand(time(NULL)); gameTick = sfClock_create(); putTick = sfClock_create(); mTick = sfClock_create(); + repPushDown = sfClock_create(); + repKeyLeft = sfClock_create(); + repKeyRight = sfClock_create(); fontScore = sfFont_createFromFile("dat/arial.ttf"); if (!fontScore) { printf("dat/arial.ttf font load failed"); @@ -52,17 +56,27 @@ void prepare() { fld.cSize = (sfVector2f){.x = 23, .y = 23}; //Fld's cell size in pixels fld.cOutThick = 1; fld.pos = (sfVector2i){.x = 10, .y = 10+550-24}; // Fld bot left corner - fld.size = (sfVector2i){.x = 10, .y = 22}; // Field's size in blocks + 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 = (Shape){.x = 250+10+20, .y = 200, - .cSize = {.x = 23, .y = 23}}; + next = (struct shape){ + .x = 250 + 10 + 20, + .y = 200, + .cOutThick = 1, + .cSize = {.x = 23, .y = 23} + }; - initFld(); - texts = ListOfText_getFromListOfKeyMapOfString(ListOfKeyMapOfString_getFromYaml("dat/texts.yaml")); - w.window = sfRenderWindow_create(w.mode, - windowName_conf, - sfResize | sfClose, - NULL); + init_field(&fld); + init_next_shape_field(&next); + genNextShape(); + active.t = next.t; + resetActiveShape(&fld, &active); + genNextShape(); + List *tmp = ListOfKeyMapOfString_getFromYaml("dat/texts.yaml"); + texts = ListOfText_getFromListOfKeyMapOfString(tmp); + ListOfKeyMapOfString_free(&tmp); + w.window = sfRenderWindow_create(w.mode, windowName_conf, + sfResize | sfClose, NULL); if (!w.window) exit(EXIT_FAILURE); sfRenderWindow_setFramerateLimit(w.window, 60); @@ -88,7 +102,7 @@ void gameLoop() { tKeyCtrl(); valueAfterTextDisplay(game.scoreCurrent, texts, "score"); valueAfterTextDisplay(game.level, texts, "level"); - colorizeFld(); + colorize_field(&fld); colorizeActive(); drawFld(w.window); drawNextShape(w.window); @@ -97,9 +111,9 @@ void gameLoop() { void menuTick() { - if(sfClock_getElapsedTime(mTick).microseconds >= basicLatency) { + if (sfClock_getElapsedTime(mTick).microseconds >= basicLatency) { sfClock_restart(mTick); - colorizeRandom(&fld); + colorize_field_random(&fld); } } @@ -110,7 +124,8 @@ void menuLoop() { if (sfKeyboard_isKeyPressed(sfKeyS) == 1) { game.isStarted = 1; freeFld(); - initFld(); + init_field(&fld); + init_next_shape_field(&next); sfClock_restart(gameTick); } } @@ -130,7 +145,7 @@ void mainLoop() { int main() { prepare(); - colorizeRandom(&fld); + colorize_field_random(&fld); mainLoop(); freeFld(); sfRenderWindow_destroy(w.window); diff --git a/src/text.c b/src/text.c index 20b9797..e1e1e6e 100644 --- a/src/text.c +++ b/src/text.c @@ -77,7 +77,6 @@ KeyMap *KeyMap_put(KeyMap **keyMap, const void *key, const void *value) KeyMap *keyMapLocal = KeyMap_get(keyMap, key); if (!keyMapLocal) { keyMapLocal = KeyMap_new(keyMap); - keyMapLocal->pair = malloc(sizeof(Pair)); keyMapLocal->pair->k = malloc(strlen(key)+1); strcpy(keyMapLocal->pair->k, key); } @@ -180,7 +179,7 @@ void ListOfKeyMapOfString_free(List **list) *list = 0; } -int _loadText_getInt(void *obj, char *key) +static int _loadText_getInt(void *obj, char *key) { int v = 0; KeyMap *keyMap = KeyMap_get((KeyMap **)&obj, key); @@ -191,7 +190,7 @@ int _loadText_getInt(void *obj, char *key) return v; } -char *_loadText_getString(void *obj, char *key) +static char *_loadText_getString(void *obj, char *key) { char *v = 0; KeyMap *keyMap = KeyMap_get((KeyMap **)&obj, key); @@ -204,10 +203,10 @@ char *_loadText_getString(void *obj, char *key) return v; } -void _loadText_initSfText(Text *objo, void *obji) +static void _loadText_initSfText(Text *objo, void *obji) { sfVector2f pos = { - .x = _loadText_getInt(obji, "x"), + .x = _loadText_getInt(obji, "x"), .y = _loadText_getInt(obji, "y") }; int size = _loadText_getInt(obji, "size"); -- cgit v1.2.3