summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--common.h21
-rw-r--r--dat/arial.ttfbin0 -> 275572 bytes
-rw-r--r--functions.c599
-rw-r--r--functions.h19
-rw-r--r--main.c113
-rw-r--r--shape_maps.c219
-rw-r--r--tet_conf.h86
8 files changed, 1061 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..59de243
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+This is unfinished tetris project written in pure C with CSFML-2.3-2 library.
+
+To compile source code I use following command:
+gcc -g main.c functions.c shape_maps.c -o debug/main -lcsfml-graphics -lcsfml-window -lcsfml-system
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..84cbe2c
--- /dev/null
+++ b/common.h
@@ -0,0 +1,21 @@
+#include <SFML/Audio.h>
+#include <SFML/Graphics.h>
+#include <SFML/System.h>
+#include <SFML/Window/Keyboard.h>
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include "functions.h"
+#include "tet_conf.h"
+
+//#define EXIT_FAILURE -1
+//#define EXIT_SUCCESS 0
+
+struct tCell {
+ short a; // active/empty state of cell
+ sfColor fColor, oColor; // fill and outline color of cell
+};
+
+struct tCell activeShape[4][4], // 4x4 block of active crawling shape
+ field_rAttr[20][10];// field cells attributess
+
diff --git a/dat/arial.ttf b/dat/arial.ttf
new file mode 100644
index 0000000..7ff88f2
--- /dev/null
+++ b/dat/arial.ttf
Binary files differ
diff --git a/functions.c b/functions.c
new file mode 100644
index 0000000..5b48b08
--- /dev/null
+++ b/functions.c
@@ -0,0 +1,599 @@
+#include "functions.h"
+#include "common.h"
+
+/* Externs from main.c */
+int activeShape_s = 1; // Rotate state of activeShape
+int activeShape_t = 1; // Type of shape (look at shape_maps.c)
+extern sfVector2f textScore_pos;
+extern sfText* textScore;
+extern sfFont* font;
+extern int gameIsStarted;
+
+extern sfRectangleShape* field[20][10]; // Array of field rectangles
+extern sfVector2f field_rPos[20][10]; // Array of absolute coordinates of field rectangles
+
+extern int field_rOutThick; // Field rectangles outline thickness
+extern sfVector2f field_rSize; // Field rectangles size variable x/y
+
+extern sfVector2i offsetActiveShape; // Offset active shape relative to field
+
+extern sfVector2i fieldSize, fieldPos;
+extern sfVector2i offsetActiveShape; // Offset active shape relative to field
+extern short arrKeys; // arrow keys states byte container
+/* arrKeys = ...n|7|6|5|4|3|2|1|0| (just a little bit of such called "bit fucking")
+ * 0 - Right arrow pushed and held
+ * 1 - Down arrow pushed and held
+ * 2 - N/A
+ * 3 - Left arrow pushed and held
+ * 4 - Right arrow short repeat activated (after once long repeat)
+ * 5 - N/A
+ * 6 - N/A
+ * 7 - Right arrow short repeat activated (after once long repeat)
+ */
+
+sfClock* gameTick;
+sfClock* mTick;
+sfClock* repPushDown; // Clock for repeat latency when Down arrow long push
+sfClock* repPushLeft; // Clock for repeat latency when Left arrow long push
+sfClock* repPushRight; // Clock for repeat latency when Left arrow long push
+
+extern int lvlLatency;
+extern int scoreCurrent;
+extern char* scoreDisp;
+/* Shapes maps */
+extern short arrShapeL_a1[4][4];
+extern short arrShapeL_a2[4][4];
+extern short arrShapeL_a3[4][4];
+extern short arrShapeL_a4[4][4];
+
+extern short arrShapeRL_a1[4][4];
+extern short arrShapeRL_a2[4][4];
+extern short arrShapeRL_a3[4][4];
+extern short arrShapeRL_a4[4][4];
+
+extern short arrShapeZ_a1[4][4];
+extern short arrShapeZ_a2[4][4];
+extern short arrShapeZ_a3[4][4];
+extern short arrShapeZ_a4[4][4];
+
+extern short arrShapeS_a1[4][4];
+extern short arrShapeS_a2[4][4];
+extern short arrShapeS_a3[4][4];
+extern short arrShapeS_a4[4][4];
+
+extern short arrShapeB_a1[4][4];
+extern short arrShapeB_a2[4][4];
+extern short arrShapeB_a3[4][4];
+extern short arrShapeB_a4[4][4];
+
+extern short arrShapeI_a1[4][4];
+extern short arrShapeI_a2[4][4];
+extern short arrShapeI_a3[4][4];
+extern short arrShapeI_a4[4][4];
+
+extern short arrShapeT_a1[4][4];
+extern short arrShapeT_a2[4][4];
+extern short arrShapeT_a3[4][4];
+extern short arrShapeT_a4[4][4];
+
+
+/* Miscellaneous functions */
+void initAll() {
+
+ /* --- Initialization --- */
+
+ field_rSize.x = 23; // Dimensions of every field block
+ field_rSize.y = 23; // 19px - fill color 1px - for outline, 20 - at all
+
+ fieldPos.x = 10; // Field bottom left corner coordinates
+ fieldPos.y = 10+500-25;
+ fieldSize.x = 10; // Field size in blocks
+ fieldSize.y = 20;
+
+ srand( time(NULL) );
+ gameTick = sfClock_create();
+ mTick = sfClock_create();
+ resetActiveShape();
+
+ /* Create field */
+ for (int j=0;j<fieldSize.y;j++){
+ for(int i=0;i<fieldSize.x;i++){
+ field_rAttr[j][i].fColor = hudColor1_conf; // Fill empty color
+ field_rAttr[j][i].oColor = hudColor2_conf; // Outlie empty color
+ field_rAttr[j][i].a = 0; // Inactive = empty
+ field_rPos[j][i].x = fieldPos.x + (i * (field_rSize.x + 2 * field_rOutThick)); // Coordinates of every
+ field_rPos[j][i].y = fieldPos.y - (j * (field_rSize.y + 2 * field_rOutThick)); // rectangle
+ field[j][i] = sfRectangleShape_create(); // Creating
+ sfRectangleShape_setFillColor(field[j][i], field_rAttr[j][i].fColor); // FillColor
+ sfRectangleShape_setSize(field[j][i], field_rSize); // Size
+ sfRectangleShape_setPosition(field[j][i], field_rPos[j][i]); // Position
+ sfRectangleShape_setOutlineColor(field[j][i], field_rAttr[j][i].oColor); // Outline color
+ sfRectangleShape_setOutlineThickness(field[j][i], field_rOutThick); // Outline thickness
+ }
+ }
+ font = sfFont_createFromFile("dat/arial.ttf");
+ if (!font) {
+ //printf("dat/arial.ttf font load failed");
+ exit(-1);
+ }
+ textScore_pos.x = 250+10+10;
+ textScore_pos.y = 485;
+ textScore = sfText_create();
+ sfText_setFont(textScore, font);
+ sfText_setCharacterSize(textScore, 20);
+ sfText_setPosition(textScore, textScore_pos);
+}
+
+void scoreDisplay() {
+ char a[64];
+ char b[7];
+ sprintf(b, "Score: ");
+ sprintf(a, "%d", scoreCurrent);
+ for (int i=63;i>=7;i--) {
+ a[i] = a[i-7];
+ }
+ for (int i=0;i<7;i++) {
+ a[i] = b[i];
+ }
+ scoreDisp = &a;
+ sfText_setString(textScore, scoreDisp);
+}
+
+int linesRmScore() {
+ int k = 0; // "Filled line" indicator
+ int s = 0;
+ for (int j=0;j<20;j++) { // Passing all lines
+ for (int i=0;i<10;i++) { // Passing all elements of current line
+ if (field_rAttr[j][i].a == 1) k++; // Check all the elements of current line
+ }
+ if (k >= 10) { // If line is full
+ s++; // Take scores for line
+ for (int n=j;n<20;n++) { // Drop all lines down
+ if (n == 19) {
+ for (int m=0;m<10;m++) {
+ field_rAttr[n][m].a = 0; // Top line clear
+ field_rAttr[n][m].fColor = hudColor1_conf;
+ field_rAttr[n][m].oColor = hudColor2_conf;
+ }
+ } else {
+ for (int m=0;m<10;m++) {
+ field_rAttr[n][m].a = field_rAttr[n+1][m].a; //Drop every line down
+ field_rAttr[n][m].fColor = field_rAttr[n+1][m].fColor;
+ field_rAttr[n][m].oColor = field_rAttr[n+1][m].oColor;
+ }
+ }
+ }
+ j--; // Do not let loop to go to next line because next line go down itself =)
+ }
+ k = 0; // Clear line fill indicator
+ }
+ return s; // Return number of deleted lines
+}
+
+void putShape() {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ if (activeShape[j][i].a == 1) {
+ field_rAttr[j+offsetActiveShape.y][i+offsetActiveShape.x].a = activeShape[j][i].a;
+ if ((j+offsetActiveShape.y >= 0) && (i+offsetActiveShape.x >= 0)) {
+ field_rAttr[j+offsetActiveShape.y][i+offsetActiveShape.x].fColor = activeShape[j][i].fColor;
+ field_rAttr[j+offsetActiveShape.y][i+offsetActiveShape.x].oColor = activeShape[j][i].oColor;
+ }
+ }
+ }
+ }
+ resetActiveShape();
+ scoreCurrent += linesRmScore()*100; // Remove filled lines and get score;
+}
+
+void resetActiveShape() {
+ offsetActiveShape.x = 3;
+ offsetActiveShape.y = 16;
+ activeShape_s = 1;
+ activeShape_t = (rand()%7)+1; // Insert new random shape of 7 variants
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ switch (activeShape_t) {; // Copy cell active/inactive state
+ case 1 :
+ activeShape[j][i].a = arrShapeL_a1[j][i];
+ activeShape[j][i].fColor = tOrange;
+ break;
+ case 2 :
+ activeShape[j][i].a = arrShapeRL_a1[j][i];
+ activeShape[j][i].fColor = tBlue;
+ break;
+ case 3 :
+ activeShape[j][i].a = arrShapeZ_a1[j][i];
+ activeShape[j][i].fColor = tRed;
+ break;
+ case 4 :
+ activeShape[j][i].a = arrShapeS_a1[j][i];
+ activeShape[j][i].fColor = tGreen;
+ break;
+ case 5 :
+ activeShape[j][i].a = arrShapeB_a1[j][i];
+ activeShape[j][i].fColor = tYellow;
+ break;
+ case 6 :
+ activeShape[j][i].a = arrShapeI_a1[j][i];
+ activeShape[j][i].fColor = tCyan;
+ break;
+ case 7 :
+ activeShape[j][i].a = arrShapeT_a1[j][i];
+ activeShape[j][i].fColor = tMagneta;
+ break;
+ }
+ activeShape[j][i].oColor = sfBlack;
+ }
+ }
+}
+
+void tTick() {
+ if (sfClock_getElapsedTime(gameTick).microseconds >= lvlLatency){ // If tick exceeds current level tick latency
+ sfClock_restart(gameTick); // Restart gameTick
+ if ((wallCollisionCheck(0b0010) == 0) &&
+ (cellCollisionCheck(0b0010) == 0)) { // If bottom not reached
+ offsetActiveShape.y--; // Move
+ } else { // If bottom reached
+ putShape(); // Just put the shape
+ }
+ }
+}
+
+void rotateS1() {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ switch (activeShape_t) {
+ case 1 :
+ activeShape[j][i].a = arrShapeL_a1[j][i]; break; // Copy cell active/inactive state L type
+ case 2 :
+ activeShape[j][i].a = arrShapeRL_a1[j][i]; break; // Copy cell active/inactive state RL type
+ case 3 :
+ activeShape[j][i].a = arrShapeZ_a1[j][i]; break; // Copy cell active/inactive state Z type
+ case 4 :
+ activeShape[j][i].a = arrShapeS_a1[j][i]; break; // Copy cell active/inactive state S type
+ case 5 :
+ activeShape[j][i].a = arrShapeB_a1[j][i]; break; // Copy cell active/inactive state B type
+ case 6 :
+ activeShape[j][i].a = arrShapeI_a1[j][i]; break; // Copy cell active/inactive state I type
+ case 7 :
+ activeShape[j][i].a = arrShapeT_a1[j][i]; break; // Copy cell active/inactive state T type
+ default : //If type is invalid
+ activeShape_t = 1; //Set valid type
+ }
+ }
+ }
+}
+
+void rotateS2() {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ switch (activeShape_t) {
+ case 1 :
+ activeShape[j][i].a = arrShapeL_a2[j][i]; break; // Copy cell active/inactive state L type
+ case 2 :
+ activeShape[j][i].a = arrShapeRL_a2[j][i]; break; // Copy cell active/inactive state RL type
+ case 3 :
+ activeShape[j][i].a = arrShapeZ_a2[j][i]; break; // Copy cell active/inactive state Z type
+ case 4 :
+ activeShape[j][i].a = arrShapeS_a2[j][i]; break; // Copy cell active/inactive state S type
+ case 5 :
+ activeShape[j][i].a = arrShapeB_a2[j][i]; break; // Copy cell active/inactive state B type
+ case 6 :
+ activeShape[j][i].a = arrShapeI_a2[j][i]; break; // Copy cell active/inactive state I type
+ case 7 :
+ activeShape[j][i].a = arrShapeT_a2[j][i]; break; // Copy cell active/inactive state T type
+ default : //If type is invalid
+ activeShape_t = 1; //Set valid type
+ }
+ }
+ }
+}
+
+void rotateS3() {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ switch (activeShape_t) {
+ case 1 :
+ activeShape[j][i].a = arrShapeL_a3[j][i]; break; // Copy cell active/inactive state L type
+ case 2 :
+ activeShape[j][i].a = arrShapeRL_a3[j][i]; break; // Copy cell active/inactive state RL type
+ case 3 :
+ activeShape[j][i].a = arrShapeZ_a3[j][i]; break; // Copy cell active/inactive state Z type
+ case 4 :
+ activeShape[j][i].a = arrShapeS_a3[j][i]; break; // Copy cell active/inactive state S type
+ case 5 :
+ activeShape[j][i].a = arrShapeB_a3[j][i]; break; // Copy cell active/inactive state B type
+ case 6 :
+ activeShape[j][i].a = arrShapeI_a3[j][i]; break; // Copy cell active/inactive state I type
+ case 7 :
+ activeShape[j][i].a = arrShapeT_a3[j][i]; break; // Copy cell active/inactive state T type
+ default : //If type is invalid
+ activeShape_t = 1; //Set valid type
+ }
+ }
+ }
+}
+
+void rotateS4() {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ switch (activeShape_t) {
+ case 1 :
+ activeShape[j][i].a = arrShapeL_a4[j][i]; break; // Copy cell active/inactive state L type
+ case 2 :
+ activeShape[j][i].a = arrShapeRL_a4[j][i]; break; // Copy cell active/inactive state RL type
+ case 3 :
+ activeShape[j][i].a = arrShapeZ_a4[j][i]; break; // Copy cell active/inactive state Z type
+ case 4 :
+ activeShape[j][i].a = arrShapeS_a4[j][i]; break; // Copy cell active/inactive state S type
+ case 5 :
+ activeShape[j][i].a = arrShapeB_a4[j][i]; break; // Copy cell active/inactive state B type
+ case 6 :
+ activeShape[j][i].a = arrShapeI_a4[j][i]; break; // Copy cell active/inactive state I type
+ case 7 :
+ activeShape[j][i].a = arrShapeT_a4[j][i]; break; // Copy cell active/inactive state T type
+ default : //If type is invalid
+ activeShape_t = 1; //Set valid type
+ }
+ }
+ }
+}
+
+void rotateShape() {
+ switch (activeShape_s) {
+ case 1 :
+ rotateS2(); // Make rotate
+ if ((wallRotCollisionCheck() == 1) || // If collision happens
+ (cellRotCollisionCheck() == 1)) rotateS1(); // Just rotate back =)
+ else activeShape_s++; // Change state to next
+ break;
+ case 2 :
+ rotateS3(); // Make rotate
+ if ((wallRotCollisionCheck() == 1) || // If collision happens
+ (cellRotCollisionCheck() == 1)) rotateS2(); // Just rotate back =)
+ else activeShape_s++; // Change state to next
+ break;
+ case 3 :
+ rotateS4(); // Make rotate
+ if ((wallRotCollisionCheck() == 1) || // If collision happens
+ (cellRotCollisionCheck() == 1)) rotateS3(); // Just rotate back =)
+ else activeShape_s++; // Change state to next
+ break;
+ case 4 :
+ rotateS1(); // Make rotate
+ if ((wallRotCollisionCheck() == 1) || // If collision happens
+ (cellRotCollisionCheck() == 1)) rotateS4(); // Just rotate back =)
+ else activeShape_s = 1; // Change state to next
+ break;
+ default: // If rotate state is invalid
+ activeShape_s = 1; // Set valid state
+ rotateShape(); // And repeat rotate function
+ }
+}
+
+int cellRotCollisionCheck() {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ if ((activeShape[j][i].a == 1) && // If any active cell of shape meet any active cell
+ (field_rAttr[j+offsetActiveShape.y][i+offsetActiveShape.x].a == 1)) // of field
+ return 1; // Collision happens
+ }
+ }
+ return 0; // Else it do not
+}
+
+int wallRotCollisionCheck() {
+ if(offsetActiveShape.y < 0) { //If shape has crossed Bottom border
+ for(int i=0;i<4;i++) {
+ if (activeShape[-1-offsetActiveShape.y][i].a != 0){ // If active cell is out of field
+ return 1; // Collision happens
+ }
+ }
+ }
+ if(offsetActiveShape.x < 0) { //If shape has crossed Left border
+ for(int i=0;i<4;i++) {
+ if (activeShape[i][-1-offsetActiveShape.x].a != 0){ // If active cell is out of field
+ return 1; // Collision happens
+ }
+ }
+ }
+ if(offsetActiveShape.x > 6) { //If shape has crossed Right border
+ for(int i=0;i<4;i++) {
+ if (activeShape[i][3-(offsetActiveShape.x-7)].a != 0){ // If active cell is out of field
+ return 1; // Collision happens
+ }
+ }
+ }
+ return 0; // If no conditions are met collision is absent
+}
+
+int cellCollisionCheck(int dir) {
+ for (int j=0;j<4;j++) {
+ for (int i=0;i<4;i++) {
+ if((dir & 0b0001) != 0){ // Check Right
+ if ((j+offsetActiveShape.y >= 0) && (i+offsetActiveShape.x+1 >= 0)) { // Avoiding checking nonexisted field cells
+ if ((activeShape[j][i].a == 1) && // If any active cell of shape meet any active cell
+ (field_rAttr[j+offsetActiveShape.y][i+offsetActiveShape.x+1].a == 1)) // of field
+ return 1; // Collision happens
+ }
+ }
+ if((dir & 0b1000) != 0){ // Check Left
+ if ((j+offsetActiveShape.y >= 0) && (i+offsetActiveShape.x-1 >= 0)) { // Avoiding checking nonexisted field cells
+ if ((activeShape[j][i].a == 1) && // If any active cell of shape meet any active cell
+ (field_rAttr[j+offsetActiveShape.y][i+offsetActiveShape.x-1].a == 1)) // of field
+ return 1; // Collision happens
+ }
+ }
+ if((dir & 0b0010) != 0){ // Check Bottom
+ if ((j+offsetActiveShape.y-1 >= 0) && (i+offsetActiveShape.x >= 0)) { // Avoiding checking nonexisted field cells
+ if ((activeShape[j][i].a == 1) && // If any active cell of shape meet any active cell
+ (field_rAttr[j+offsetActiveShape.y-1][i+offsetActiveShape.x].a == 1)) // of field
+ return 1; // Collision happens
+ }
+ }
+ }
+ }
+ return 0; // Else it do not
+}
+
+int wallCollisionCheck(int dir) {
+ if((dir & 0b0001) != 0) { // Right collision request
+ if(offsetActiveShape.x >= 6) { // If shape has reached Right boreder
+ for(int i=0;i<4;i++) {
+ if(activeShape[i][3-(offsetActiveShape.x-6)].a != 0) {
+ return 1; // Collision happens
+ }
+ }
+ }
+ } else if((dir & 0b0010) != 0){ // Bottom collision request
+ if(offsetActiveShape.y <= 0) { //If shape has reached Bottom border
+ for(int i=0;i<4;i++) {
+ if (activeShape[-offsetActiveShape.y][i].a != 0){
+ return 1; // Collision happens
+ }
+ }
+ }
+ } else if((dir & 0b1000) != 0){ // Left collision request
+ if(offsetActiveShape.x <= 0) { // If shape has reached Left border
+ for(int i=0;i<4;i++) {
+ if(activeShape[i][-offsetActiveShape.x].a != 0) {
+ return 1; // Collision happens
+ }
+ }
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+
+/* Control keys handle */
+void tKeyCtrl() {
+
+ /* Up arrow key */
+ if (sfKeyboard_isKeyPressed(sfKeyUp) == 1){
+ if ((arrKeys & 0b0100) == 0){ // If "Up arrow button hold" bit is not enabled
+ arrKeys = arrKeys | 0b0100; // Enable the "Up arrow button hold" bit
+ rotateShape();
+ }
+ } else { // If Down arrow button not pressed
+ if ((arrKeys & 0b0100) != 0){ // and if "Up arrow button hold" bit is enabled
+ arrKeys = arrKeys & ~0b0100; // it means that button is already released
+ } // So it is time to clear "Up arrow button hold" bit
+ }
+
+ /* Down Arrow Key */
+ if (sfKeyboard_isKeyPressed(sfKeyDown) == 1){ // If Down arrow button is pressed
+ if ((arrKeys & 0b0010) == 0){ // If "pushed down" key of Down arrow button not enabled
+ arrKeys = arrKeys | 0b0010; // Enable "pushed down" key of down arrow button
+ if ((wallCollisionCheck(0b0010) == 0) && // If collision do not happen
+ (cellCollisionCheck(0b0010) == 0)) { // 0b0010 for "Down"
+ offsetActiveShape.y--; // then do move
+ sfClock_restart(gameTick); // Avoid excess move down by gameTick
+ scoreCurrent++;
+ }
+ repPushDown = sfClock_create(); // Create/restart clock
+ } else {
+ if (sfClock_getElapsedTime(repPushDown).microseconds >= moveRepeatLatency2) arrKeys = arrKeys & ~0b0010;
+ }
+ } else { // If Down arrow button not pressed
+ if ((arrKeys & 0b0010) != 0){ // and if "pushed down" key is enabled
+ arrKeys = arrKeys & ~0b0010; // it means that button is already released
+ arrKeys = arrKeys & ~0b100000;
+ } // So it is time to clear "down arrow pushed down" bit
+ }
+
+ /* Left Arrow Key */
+ if ((sfKeyboard_isKeyPressed(sfKeyLeft) == 1) && (sfKeyboard_isKeyPressed(sfKeyRight) == 0)){ // If left arrow button is pressed
+ if ((arrKeys & 0b1000) == 0){ // If "pushed down" key of left arrow button disabled
+ arrKeys = arrKeys | 0b1000; // Enable "pushed down" key of left arrow button
+ if ((wallCollisionCheck(0b1000) == 0) && // If collision do not happen
+ (cellCollisionCheck(0b1000) == 0)) // 0b1000 for "left"
+ offsetActiveShape.x--; // then do move
+ repPushLeft = sfClock_create(); // Create/restart clock
+ } else { // Push held action repeat handler
+ if ((arrKeys & 0b10000000) == 0) { // If "push Left repeat" bit is not set
+ if (sfClock_getElapsedTime(repPushLeft).microseconds >= moveRepeatLatency1) { // Wait long time
+ arrKeys = arrKeys | 0b10000000; // set "push Left repeat" bit
+ arrKeys = arrKeys & ~0b1000; // unset "pushed down" bit to repeat move
+ }
+ } else { // If "push Left repeat" bit is set
+ if (sfClock_getElapsedTime(repPushLeft).microseconds >= moveRepeatLatency2) // Wait short time
+ arrKeys = arrKeys & ~0b1000; // unset "pushed down" bit to repeat movse
+ }
+ }
+ } else if (sfKeyboard_isKeyPressed(sfKeyLeft) == 0) { // If left arrow button is released
+ if ((arrKeys & 0b1000) != 0){ // and if "pushed down" key is enabled
+ arrKeys = arrKeys & ~0b1000; // it means that button is already released
+ arrKeys = arrKeys & ~0b10000000;// So it is time to clear "right arrow pushed down" bit
+ } // And "push repeat" bit
+ }
+
+ /* Right Arrow Key */
+ if ((sfKeyboard_isKeyPressed(sfKeyRight) == 1) && (sfKeyboard_isKeyPressed(sfKeyLeft) == 0)) { // If right arrow button is pressed
+ if ((arrKeys & 0b0001) == 0){ // If "pushed down" key of right arrow button not enabled
+ arrKeys = arrKeys | 0b0001; // Enable "pushed down" key of right arrow button
+ if ((wallCollisionCheck(0b0001) == 0) && // If collision do not happen
+ (cellCollisionCheck(0b0001) == 0)) // 0b0001 for "right"
+ offsetActiveShape.x++; // then do move
+ repPushRight = sfClock_create();
+ } else { // Push held action repeat handler
+ if ((arrKeys & 0b10000) == 0) { // If "push Right repeat" bit is not set
+ if (sfClock_getElapsedTime(repPushRight).microseconds >= moveRepeatLatency1) { // Wait long time
+ arrKeys = arrKeys | 0b10000; // set "push Right repeat" bit
+ arrKeys = arrKeys & ~0b0001; // unset "pushed down" bit to repeat move
+ }
+ } else if (sfKeyboard_isKeyPressed(sfKeyLeft) == 0) { // If "push Right repeat" bit is set
+ if (sfClock_getElapsedTime(repPushRight).microseconds >= moveRepeatLatency2) // Wait short time
+ arrKeys = arrKeys & ~0b0001; // unset "pushed down" bit to repeat movse
+ }
+ }
+ } else { // If Right arrow button not pressed
+ if ((arrKeys & 0b0001) != 0){ // and if "pushed down" key is enabled
+ arrKeys = arrKeys & ~0b0001; // <---+ it means that button is already released
+ arrKeys = arrKeys & ~0b10000; // <-+ +--So it is time to clear "right arrow pushed down" bit
+ } // +-And "push repeat" bit
+ }
+}
+
+
+
+void menuTick() {
+ if(sfClock_getElapsedTime(mTick).microseconds >= lvlLatency){
+ sfClock_restart(mTick);
+ for (int j=0;j<fieldSize.y;j++){
+ for(int i=0;i<fieldSize.x;i++){
+ int a;
+ a = rand()%7+1;
+ switch (a) {;
+ case 1 :
+ field_rAttr[j][i].fColor = tOrange;
+ break;
+ case 2 :
+ field_rAttr[j][i].fColor = tBlue;
+ break;
+ case 3 :
+ field_rAttr[j][i].fColor = tRed;
+ break;
+ case 4 :
+ field_rAttr[j][i].fColor = tGreen;
+ break;
+ case 5 :
+ field_rAttr[j][i].fColor = tYellow;
+ break;
+ case 6 :
+ field_rAttr[j][i].fColor = tCyan;
+ break;
+ case 7 :
+ field_rAttr[j][i].fColor = tMagneta;
+ break;
+ }
+ field_rAttr[j][i].oColor = sfBlack;
+ sfRectangleShape_setFillColor(field[j][i], field_rAttr[j][i].fColor); // FillColor
+ sfRectangleShape_setOutlineColor(field[j][i], field_rAttr[j][i].oColor); // Outline color
+ }
+ }
+ }
+}
diff --git a/functions.h b/functions.h
new file mode 100644
index 0000000..1816399
--- /dev/null
+++ b/functions.h
@@ -0,0 +1,19 @@
+
+/* Prototypes of functions*/
+void tKeyCtrl();
+void initAll();
+void tTick();
+void resetActiveShape();
+void putShape();
+int cellCollisionCheck(int dir);
+int wallCollisionCheck();
+int cellRotCollisionCheck();
+int wallRotCollisionCheck();
+void rotateShape();
+void rotateS1();
+void rotateS2();
+void rotateS3();
+void rotateS4();
+int linesRmScore();
+void scoreDisplay();
+void menuTick(); \ No newline at end of file
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..fe61c38
--- /dev/null
+++ b/main.c
@@ -0,0 +1,113 @@
+#include "common.h"
+
+/* --- Variables --- */
+int gameIsStarted = 0;
+sfVideoMode mode = {450, 520, 32};
+sfRenderWindow* window;
+sfEvent event;
+sfText* textScore;
+sfFont* font;
+char *scoreDisp;
+
+sfRectangleShape* field[20][10]; // Array of field rectangles
+sfVector2f field_rPos[20][10]; // Array of absolute coordinates of field rectangles
+
+int field_rOutThick = 1; // Field rectangles outline thickness
+sfVector2f field_rSize; // Field rectangles size variable x/y
+sfVector2i offsetActiveShape; // Offset active shape relative to field
+sfVector2i fieldSize, fieldPos;
+sfVector2f textScore_pos;
+
+short arrKeys = 0b00000000; // Arrow keys states byte container
+
+int lvlLatency = 500000;
+int scoreCurrent = 0;
+/* --- Variables End --- */
+
+int main()
+{
+
+ initAll();
+
+ /* Create main window */
+ window = sfRenderWindow_create(mode, windowName_conf, sfResize | sfClose, NULL);
+ if (!window)
+ return EXIT_FAILURE;
+
+ /* Start the game loop */
+ while (sfRenderWindow_isOpen(window))
+ {
+ /* Process events */
+ while (sfRenderWindow_pollEvent(window, &event))
+ {
+ /* Close window : exit */
+ if (event.type == sfEvtClosed)
+ sfRenderWindow_close(window);
+ }
+ /* Clear the screen */
+ sfRenderWindow_clear(window, sfBlack);
+
+ if (gameIsStarted == 1) {
+ tTick();
+ tKeyCtrl();
+ scoreDisplay();
+
+ /* Colorize active cells of field */
+ for(int j=0;j<20;j++){
+ for(int i=0;i<10;i++){
+ sfRectangleShape_setFillColor(field[j][i], field_rAttr[j][i].fColor);
+ sfRectangleShape_setOutlineColor(field[j][i], field_rAttr[j][i].oColor);
+ }
+ }
+
+
+ /* Colorize active cells of active shape (overlay only active cells above background of field) */
+ for(int j=0;j<4;j++){
+ for(int i=0;i<4;i++){
+ if (activeShape[j][i].a != 0){
+ sfRectangleShape_setFillColor(field[j+offsetActiveShape.y][i+offsetActiveShape.x], activeShape[j][i].fColor);
+ sfRectangleShape_setOutlineColor(field[j+offsetActiveShape.y][i+offsetActiveShape.x], activeShape[j][i].oColor);
+ }
+ }
+ }
+
+ /* Draw all field cells */
+ for (int j=0;j<fieldSize.y;j++){
+ for(int i=0;i<fieldSize.x;i++){
+ sfRenderWindow_drawRectangleShape(window, field[j][i], NULL);
+ }
+ }
+ sfRenderWindow_drawText(window, textScore, NULL);
+ } else {
+ menuTick();
+ if (sfKeyboard_isKeyPressed(sfKeyReturn) == 1) {
+ gameIsStarted = 1;
+ initAll();
+ }
+ menuTick();
+
+ /* Draw all field cells */
+ for (int j=0;j<fieldSize.y;j++){
+ for(int i=0;i<fieldSize.x;i++){
+ sfRenderWindow_drawRectangleShape(window, field[j][i], NULL);
+ }
+ }
+ }
+ /* Update the window */
+ sfRenderWindow_display(window);
+ }
+
+ /* Just senseless printf */
+ printf("%d\n", scoreCurrent);
+
+ /* Cleanup resources */
+ for (int j=0;j<fieldSize.y;j++){
+ for(int i=0;i<fieldSize.x;i++){
+ sfRectangleShape_destroy(field[j][i]);
+ }
+ }
+
+ sfRenderWindow_destroy(window);
+
+ return EXIT_SUCCESS;
+} \ No newline at end of file
diff --git a/shape_maps.c b/shape_maps.c
new file mode 100644
index 0000000..e96ea8f
--- /dev/null
+++ b/shape_maps.c
@@ -0,0 +1,219 @@
+/* Shapes maps */
+
+/*
+ * L #1 tYellow
+ * ..#. .#.. .... ##..
+ * ###. .#.. ###. .#..
+ * .... .##. #... .#..
+ * .... .... .... ....
+ */
+short arrShapeL_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {1, 1, 1, 0},
+ {0, 0, 1, 0}};
+
+short arrShapeL_a2[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0}};
+
+short arrShapeL_a3[4][4] = {
+ {0, 0, 0, 0},
+ {1, 0, 0, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 0}};
+
+short arrShapeL_a4[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 0, 0}};
+
+/*
+ * RL #2 tBlue
+ * #... .##. .... .#..
+ * ###. .#.. ###. .#..
+ * .... .#.. ..#. ##..
+ * .... .... .... ....
+ */
+
+short arrShapeRL_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {1, 1, 1, 0},
+ {1, 0, 0, 0}};
+
+short arrShapeRL_a2[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 1, 0}};
+
+short arrShapeRL_a3[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 1, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 0}};
+
+short arrShapeRL_a4[4][4] = {
+ {0, 0, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0}};
+
+/*
+ * Z #3
+ * ##.. ..#. .... .#..
+ * .##. .##. ##.. ##..
+ * .... .#.. .##. #...
+ * .... .... .... ....
+ */
+short arrShapeZ_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {1, 1, 0, 0}};
+
+short arrShapeZ_a2[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 0, 1, 0}};
+
+short arrShapeZ_a3[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {1, 1, 0, 0},
+ {0, 0, 0, 0}};
+
+short arrShapeZ_a4[4][4] = {
+ {0, 0, 0, 0},
+ {1, 0, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 0, 0}};
+
+/*
+ * S #4
+ * .##. .#.. .... #...
+ * ##.. .##. .##. ##..
+ * .... ..#. ##.. .#..
+ * .... .... .... ....
+ */
+short arrShapeS_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 1, 0}};
+
+short arrShapeS_a2[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 1, 0},
+ {0, 1, 1, 0},
+ {0, 1, 0, 0}};
+
+short arrShapeS_a3[4][4] = {
+ {0, 0, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 0, 0, 0}};
+
+short arrShapeS_a4[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {1, 0, 0, 0}};
+
+/*
+ * B #5
+ * ##.. ##.. ##.. ##..
+ * ##.. ##.. ##.. ##..
+ * .... .... .... ....
+ * .... .... .... ....
+ */
+short arrShapeB_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0}};
+
+short arrShapeB_a2[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0}};
+
+short arrShapeB_a3[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0}};
+
+short arrShapeB_a4[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 1, 0}};
+
+/*
+ * I #6
+ * .#.. .... .#.. ....
+ * .#.. #### .#.. ####
+ * .#.. .... .#.. ....
+ * .#.. .... .#.. ....
+ */
+short arrShapeI_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {1, 1, 1, 1},
+ {0, 0, 0, 0}};
+
+short arrShapeI_a2[4][4] = {
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0}};
+
+short arrShapeI_a3[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {1, 1, 1, 1},
+ {0, 0, 0, 0}};
+
+short arrShapeI_a4[4][4] = {
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 0, 0}};
+
+/*
+ * T #7
+ * .#.. .#.. .... .#..
+ * ###. .##. ###. ##..
+ * .... .#.. .#.. .#..
+ * .... .... .... ....
+ */
+short arrShapeT_a1[4][4] = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {1, 1, 1, 0},
+ {0, 1, 0, 0}};
+
+short arrShapeT_a2[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {0, 1, 1, 0},
+ {0, 1, 0, 0}};
+
+short arrShapeT_a3[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 1, 0},
+ {0, 0, 0, 0}};
+
+short arrShapeT_a4[4][4] = {
+ {0, 0, 0, 0},
+ {0, 1, 0, 0},
+ {1, 1, 0, 0},
+ {0, 1, 0, 0}}; \ No newline at end of file
diff --git a/tet_conf.h b/tet_conf.h
new file mode 100644
index 0000000..0b37d65
--- /dev/null
+++ b/tet_conf.h
@@ -0,0 +1,86 @@
+#define windowName_conf "SFML" // Window name
+#define hudColor1_conf sfColor_fromRGB(0, 0, 0) // Field background
+#define hudColor2_conf sfColor_fromRGB(80, 80, 80) // Field cell outline
+#define tOrange sfColor_fromRGB(255, 130, 0) // Orange color of L shape
+#define tBlue sfColor_fromRGB(0, 0, 255)
+#define tGreen sfColor_fromRGB(0, 255, 0)
+#define tRed sfColor_fromRGB(255, 0, 0)
+#define tYellow sfColor_fromRGB(255, 255, 0)
+#define tCyan sfColor_fromRGB(0, 255, 255)
+#define tMagneta sfColor_fromRGB(192, 0, 255)
+#define moveRepeatLatency1 150000 //microseconds, only for left-right arrows, first repeat move when long push
+#define moveRepeatLatency2 30000 //microseconds, for Left, Right and Down arrows, the rest repeat move when long push
+
+
+/*
+ * 19..........
+ * 18..........
+ * 17..........
+ * 16..........
+ * 15..........
+ * 14..........
+ * 13..........
+ * 12..........
+ * 11..........
+ * 10..........
+ * 9..........
+ * 8..........
+ * 7..........
+ * 6..........
+ * 5.......#..
+ * 4......##..
+ * 3......#...
+ * 2.#.##.....
+ * 1.##.#..#..
+ * 0..#.#.###.
+ * 0123456789
+ *
+ * L
+ * ..#. .#.. .... ##..
+ * ###. .#.. ###. .#..
+ * .... .##. #... .#..
+ * .... .... .... ....
+ *
+ * RL
+ * #... .##. .... .#..
+ * ###. .#.. ###. .#..
+ * .... .#.. ..#. ##..
+ * .... .... .... ....
+ *
+ * Z
+ * ##.. ..#. .... .#..
+ * .##. .##. ##.. ##..
+ * .... .#.. .##. #...
+ * .... .... .... ....
+ *
+ * S
+ * .##. .#.. .... #...
+ * ##.. .##. .##. ##..
+ * .... ..#. ##.. .#..
+ * .... .... .... ....
+ *
+ * Brick
+ * ##.. ##.. ##.. ##..
+ * ##.. ##.. ##.. ##..
+ * .... .... .... ....
+ * .... .... .... ....
+ *
+ * I
+ * .#.. .... .#.. ....
+ * .#.. #### .#.. ####
+ * .#.. .... .#.. ....
+ * .#.. .... .#.. ....
+ *
+ * T
+ * .#.. .#.. .... .#..
+ * ###. .##. ###. ##..
+ * .... .#.. .#.. .#..
+ * .... .... .... ....
+ */
+
+
+
+
+char *aaa;
+char* aaa;
+