summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang0
-rw-r--r--LICENSE.md2
-rw-r--r--Makefile8
-rw-r--r--README.md4
-rw-r--r--include/common.h77
-rw-r--r--include/engine.h19
-rw-r--r--include/field.h58
-rw-r--r--include/functions.h34
-rw-r--r--include/text.h48
-rw-r--r--src/engine.c367
-rw-r--r--src/field.c235
-rw-r--r--src/functions.c678
-rw-r--r--src/main.c61
-rw-r--r--src/text.c9
14 files changed, 771 insertions, 829 deletions
diff --git a/.clang b/.clang
deleted file mode 100644
index e69de29..0000000
--- a/.clang
+++ /dev/null
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 <sam@hocevar.net>
+ Copyright (C) 2018 Vladimir Novikov <oxore@protonmail.com>
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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <SFML/System/Clock.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 "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 <stdlib.h>
+#include <string.h>
+#include <SFML/Graphics/RectangleShape.h>
+
+#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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <SFML/System/Clock.h>
-#include <SFML/Graphics/RenderWindow.h>
-#include <SFML/Graphics/Text.h>
-#include <SFML/Graphics/RectangleShape.h>
-
-#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 <SFML/Graphics/Font.h>
#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");