diff --git a/.gitignore b/.gitignore index d28e0a3..8cfcd25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .vscode/ tetris-clone +*.o \ No newline at end of file diff --git a/README.md b/README.md index 68269b3..99dc2a7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,11 @@ Here are some early screenshots of my progress: ![gameplay](screenshots/game_screenshot.png "Gameplay") ![gameover](screenshots/game_over_screenshot.png "Game Over") -Features left to implement: +I am currently in the progress of re-writing the entire codebase. I am a relatively new C programmer, and when I first started +this project I hadn't nailed down a C style that I like. So I have been working on updating the overall style of the code; plus +I have been challenging myself to use a ANSI-C standard. + +There are also quite a few features left to implement: - Update codebase to use cohesive style (still haven't landed on exactly what I like) - Re-Implement rotation algorithm; my original algorithm was extremely buggy - Empty rows that are full should "break" @@ -20,7 +24,7 @@ Features left to implement: - display upcoming block - introduce levels and increasing speed/score multiplier -I hope you enjoy! +I will be able to focus on those again once I finish the re-write. ## Getting Started diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 2106f58..0000000 --- a/src/main.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "app.h" -#include -#include -#include - -int main(int argc, char **argv) { - // Not great code if I were to need multiple options, but I just need to be - // able to debug - if (argc > 1) { - if (strcmp(argv[1], "--speed") == 0) { - a_run(atoi(argv[2])); - } - } else { - a_run(50); - } - - return 0; -} diff --git a/src/Makefile b/src/old/Makefile similarity index 78% rename from src/Makefile rename to src/old/Makefile index 8d1f2bc..49af283 100644 --- a/src/Makefile +++ b/src/old/Makefile @@ -1,5 +1,5 @@ CC=clang -CFLAGS=-Wall -Wextra -include raylib.h +CFLAGS=-Wall -Wextra -std=c89 -pedantic -include raylib.h LIBS=-lraylib -lGL -lm -lpthread -ldl -lrt -lX11 tetris-clone: main.c manager.c renderer.c app.c diff --git a/src/app.c b/src/old/app.c similarity index 100% rename from src/app.c rename to src/old/app.c diff --git a/src/app.h b/src/old/app.h similarity index 100% rename from src/app.h rename to src/old/app.h diff --git a/src/old/main.c b/src/old/main.c new file mode 100644 index 0000000..ca165d6 --- /dev/null +++ b/src/old/main.c @@ -0,0 +1,24 @@ +#include +#include +#include + +#include "app.h" + +int main(int argc, char **argv) +{ + // Not great code if I were to need multiple options, but I just need to be + // able to debug + if (argc > 1) + { + if (strcmp(argv[1], "--speed") == 0) + { + a_run(atoi(argv[2])); + } + } + else + { + a_run(50); + } + + return 0; +} diff --git a/src/manager.c b/src/old/manager.c similarity index 100% rename from src/manager.c rename to src/old/manager.c diff --git a/src/manager.h b/src/old/manager.h similarity index 86% rename from src/manager.h rename to src/old/manager.h index afa1df7..069594b 100644 --- a/src/manager.h +++ b/src/old/manager.h @@ -4,7 +4,6 @@ #include #include "tetromino.h" -// TODO - I'm not sure whether the internal functions should actually be here... void m_initialize(void); void m_update(void); void m_blocks_set_empty(void); diff --git a/src/renderer.c b/src/old/renderer.c similarity index 100% rename from src/renderer.c rename to src/old/renderer.c diff --git a/src/renderer.h b/src/old/renderer.h similarity index 100% rename from src/renderer.h rename to src/old/renderer.h diff --git a/src/resources/black.png b/src/old/resources/black.png similarity index 100% rename from src/resources/black.png rename to src/old/resources/black.png diff --git a/src/resources/blue.png b/src/old/resources/blue.png similarity index 100% rename from src/resources/blue.png rename to src/old/resources/blue.png diff --git a/src/resources/green.png b/src/old/resources/green.png similarity index 100% rename from src/resources/green.png rename to src/old/resources/green.png diff --git a/src/resources/light-blue.png b/src/old/resources/light-blue.png similarity index 100% rename from src/resources/light-blue.png rename to src/old/resources/light-blue.png diff --git a/src/resources/orange.png b/src/old/resources/orange.png similarity index 100% rename from src/resources/orange.png rename to src/old/resources/orange.png diff --git a/src/resources/purple.png b/src/old/resources/purple.png similarity index 100% rename from src/resources/purple.png rename to src/old/resources/purple.png diff --git a/src/resources/red.png b/src/old/resources/red.png similarity index 100% rename from src/resources/red.png rename to src/old/resources/red.png diff --git a/src/resources/yellow.png b/src/old/resources/yellow.png similarity index 100% rename from src/resources/yellow.png rename to src/old/resources/yellow.png diff --git a/src/tetromino.h b/src/old/tetromino.h similarity index 100% rename from src/tetromino.h rename to src/old/tetromino.h diff --git a/src/rewrite/Makefile b/src/rewrite/Makefile new file mode 100644 index 0000000..c5f3a0f --- /dev/null +++ b/src/rewrite/Makefile @@ -0,0 +1,22 @@ +CC=clang +CFLAGS=-Wall -Wextra -ansi -pedantic -include raylib.h +LIBS=-lraylib -lGL -lm -lpthread -ldl -lrt -lX11 + +default: tetris-clone + +OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c)) +HEADERS = $(wildcard *.h) + +%.o: %.c $(HEADERS) + $(CC) -c $< -o $@ $(CFLAGS) + +.PRECIOUS: $(TARGET) $(OBJECTS) + +tetris-clone: $(OBJECTS) + $(CC) -o $@ $(OBJECTS) $(CFLAGS) $(LIBS) + +.PHONY: clean + +clean: + rm -f *.o + rm -f tetris-clone \ No newline at end of file diff --git a/src/rewrite/block.h b/src/rewrite/block.h new file mode 100644 index 0000000..a8b9369 --- /dev/null +++ b/src/rewrite/block.h @@ -0,0 +1,25 @@ +#ifndef BLOCK_H_ +#define BLOCK_H_ +#include "point.h" + +/* still unsure how i want to name structs and enums */ + +typedef enum btype_t +{ + bt_I, + bt_J, + bt_L, + bt_O, + bt_S, + bt_T, + bt_Z, + bt_Empty +} btype_t; + +typedef struct block_t +{ + point_t point; + btype_t type; +} block_t; + +#endif /* BLOCK_H_ */ diff --git a/src/rewrite/m_block.c b/src/rewrite/m_block.c new file mode 100644 index 0000000..127e489 --- /dev/null +++ b/src/rewrite/m_block.c @@ -0,0 +1,50 @@ +#include "m_block.h" +#include + +#define BLOCK_ARRAY_COLUMNS 10 +#define BLOCK_ARRAY_ROWS 20 +#define BLOCK_ARRAY_LENGTH 200 + +block_t *_blocks[BLOCK_ARRAY_LENGTH]; +block_t *_updated_blocks[BLOCK_ARRAY_LENGTH]; +int updated_blocks_current_length = 0; + +void M_Create_Blocks(void) +{ + int i; + for (i = 0; i < BLOCK_ARRAY_LENGTH; i++) + { + block_t *block = malloc(sizeof(block_t)); + block->point.x = i % BLOCK_ARRAY_COLUMNS; + block->point.y = i / BLOCK_ARRAY_COLUMNS; + block->type = bt_Empty; + + _blocks[i] = block; + } +} + +void M_Update_Blocks(void) +{ + /* implement */ +} + +block_t **M_Get_Blocks(int *length) +{ + *length = BLOCK_ARRAY_LENGTH; + return _blocks; +} + +block_t **M_Get_Updated_Blocks(int *length) +{ + *length = updated_blocks_current_length; + return _updated_blocks; +} + +void M_Destroy_Blocks(void) +{ + int i; + for (i = 0; i < BLOCK_ARRAY_LENGTH; i++) + { + free(_blocks[i]); + } +} diff --git a/src/rewrite/m_block.h b/src/rewrite/m_block.h new file mode 100644 index 0000000..ed54519 --- /dev/null +++ b/src/rewrite/m_block.h @@ -0,0 +1,11 @@ +#ifndef M_BLOCK_H_ +#define M_BLOCK_H_ +#include "block.h" + +void M_Create_Blocks(void); +void M_Update_Blocks(void); +block_t **M_Get_Blocks(int *length); +block_t **M_Get_Updated_Blocks(int *length); +void M_Destroy_Blocks(void); + +#endif /* M_BLOCK_H_ */ diff --git a/src/rewrite/m_tetromino.c b/src/rewrite/m_tetromino.c new file mode 100644 index 0000000..21c8e4d --- /dev/null +++ b/src/rewrite/m_tetromino.c @@ -0,0 +1,6 @@ +#include "m_tetromino.h" + +void M_Update_Tetromino(void) +{ + /* implement */ +} diff --git a/src/rewrite/m_tetromino.h b/src/rewrite/m_tetromino.h new file mode 100644 index 0000000..1f57c65 --- /dev/null +++ b/src/rewrite/m_tetromino.h @@ -0,0 +1,7 @@ +#ifndef M_TETROMINO_H_ +#define M_TETROMINO_H_ +#include "block.h" + +void M_Update_Tetromino(void); + +#endif /* M_TETROMINO_H_ */ diff --git a/src/rewrite/point.h b/src/rewrite/point.h new file mode 100644 index 0000000..a6ae79e --- /dev/null +++ b/src/rewrite/point.h @@ -0,0 +1,17 @@ +#ifndef POINT_H_ +#define POINT_H_ +#include "point.h" + +typedef struct point_t +{ + unsigned int x; + unsigned int y; +} point_t; + +typedef struct point_offset_t +{ + int xOffset; + int yOffset; +} point_offset_t; + +#endif /* POINT_H_ */ diff --git a/src/rewrite/r_block.c b/src/rewrite/r_block.c new file mode 100644 index 0000000..40e65fa --- /dev/null +++ b/src/rewrite/r_block.c @@ -0,0 +1,67 @@ +#include "r_block.h" +#include "sc_def.h" + +#define RES_PNG_FILE(name) "resources/" #name ".png" +#define TEXTURE_SIZE 32 + +Texture2D yellow_texture; +Texture2D blue_texture; +Texture2D light_blue_texture; +Texture2D red_texture; +Texture2D purple_texture; +Texture2D green_texture; +Texture2D orange_texture; +Texture2D empty_texture; + +void R_Load_Textures(void) +{ + yellow_texture = LoadTexture(RES_PNG_FILE(yellow)); + blue_texture = LoadTexture(RES_PNG_FILE(blue)); + light_blue_texture = LoadTexture(RES_PNG_FILE(light - blue)); + red_texture = LoadTexture(RES_PNG_FILE(red)); + purple_texture = LoadTexture(RES_PNG_FILE(purple)); + green_texture = LoadTexture(RES_PNG_FILE(green)); + orange_texture = LoadTexture(RES_PNG_FILE(orange)); + empty_texture = LoadTexture(RES_PNG_FILE(black)); +} + +void R_Draw_Blocks(block_t **blocks, int block_count) +{ + BeginDrawing(); + while (block_count--) + { + R_Draw_Block(*(*blocks)); + blocks++; + } + /* implement */ + EndDrawing(); +} + +void R_Draw_Block(block_t block) +{ + Texture2D *texture = __R_Get_Texture_By_Block_Type(block.type); + DrawTexture(*texture, block.point.x * TEXTURE_SIZE, block.point.y * TEXTURE_SIZE, SC_White); +} + +Texture2D *__R_Get_Texture_By_Block_Type(btype_t block_type) +{ + switch (block_type) + { + case bt_O: + return &yellow_texture; + case bt_I: + return &light_blue_texture; + case bt_T: + return &purple_texture; + case bt_J: + return &blue_texture; + case bt_L: + return &orange_texture; + case bt_S: + return &green_texture; + case bt_Z: + return &red_texture; + default: + return &empty_texture; + } +} diff --git a/src/rewrite/r_block.h b/src/rewrite/r_block.h new file mode 100644 index 0000000..26310c1 --- /dev/null +++ b/src/rewrite/r_block.h @@ -0,0 +1,11 @@ +#ifndef R_BLOCK_H_ +#define R_BLOCK_H_ +#include "block.h" +#include "raylib.h" + +void R_Load_Textures(void); +void R_Draw_Blocks(block_t **blocks, int block_count); +void R_Draw_Block(block_t block); +Texture2D *__R_Get_Texture_By_Block_Type(btype_t block_type); + +#endif /* R_BLOCK_H_ */ diff --git a/src/rewrite/r_def.h b/src/rewrite/r_def.h new file mode 100644 index 0000000..e69de29 diff --git a/src/rewrite/r_ui.c b/src/rewrite/r_ui.c new file mode 100644 index 0000000..acb7121 --- /dev/null +++ b/src/rewrite/r_ui.c @@ -0,0 +1,21 @@ +#include "r_ui.h" +#include "raylib.h" +#include "sc_def.h" + +void R_Draw_Ui(void) +{ + BeginDrawing(); + DrawRectangle(SC_GAME_WIDTH, 0, SC_UI_WIDTH, SC_HEIGHT, SC_Gray); + EndDrawing(); +} + +void R_Draw_Game_Over(int score) +{ + const char *score_message = TextFormat("Score: %d", score); + BeginDrawing(); + DrawRectangle(0, 0, SC_GAME_WIDTH, SC_HEIGHT, SC_Black); + DrawText("Game Over", SC_GAME_WIDTH / 2 - MeasureText("Game Over", 24) / 2, 200, 24, SC_Red); + DrawText(score_message, SC_GAME_WIDTH / 2 - MeasureText(score_message, 18) / 2, 232, 18, SC_Red); + /* Draw a play again button */ + EndDrawing(); +} diff --git a/src/rewrite/r_ui.h b/src/rewrite/r_ui.h new file mode 100644 index 0000000..ec6b1a8 --- /dev/null +++ b/src/rewrite/r_ui.h @@ -0,0 +1,7 @@ +#ifndef R_UI_H_ +#define R_UI_H_ + +void R_Draw_Ui(void); +void R_Draw_Game_Over(int score); + +#endif diff --git a/src/rewrite/resources/black.png b/src/rewrite/resources/black.png new file mode 100644 index 0000000..d0f2187 Binary files /dev/null and b/src/rewrite/resources/black.png differ diff --git a/src/rewrite/resources/blue.png b/src/rewrite/resources/blue.png new file mode 100644 index 0000000..de06341 Binary files /dev/null and b/src/rewrite/resources/blue.png differ diff --git a/src/rewrite/resources/green.png b/src/rewrite/resources/green.png new file mode 100644 index 0000000..1263e59 Binary files /dev/null and b/src/rewrite/resources/green.png differ diff --git a/src/rewrite/resources/light-blue.png b/src/rewrite/resources/light-blue.png new file mode 100644 index 0000000..23c3f39 Binary files /dev/null and b/src/rewrite/resources/light-blue.png differ diff --git a/src/rewrite/resources/orange.png b/src/rewrite/resources/orange.png new file mode 100644 index 0000000..f23b6d6 Binary files /dev/null and b/src/rewrite/resources/orange.png differ diff --git a/src/rewrite/resources/purple.png b/src/rewrite/resources/purple.png new file mode 100644 index 0000000..19f10b4 Binary files /dev/null and b/src/rewrite/resources/purple.png differ diff --git a/src/rewrite/resources/red.png b/src/rewrite/resources/red.png new file mode 100644 index 0000000..958e9a5 Binary files /dev/null and b/src/rewrite/resources/red.png differ diff --git a/src/rewrite/resources/yellow.png b/src/rewrite/resources/yellow.png new file mode 100644 index 0000000..661058a Binary files /dev/null and b/src/rewrite/resources/yellow.png differ diff --git a/src/rewrite/sc_def.h b/src/rewrite/sc_def.h new file mode 100644 index 0000000..74b9519 --- /dev/null +++ b/src/rewrite/sc_def.h @@ -0,0 +1,15 @@ +#ifndef SC_DEF_H_ +#define SC_DEF_H_ + +#define SC_HEIGHT 640 +#define SC_WIDTH 440 +#define SC_GAME_WIDTH 320 +#define SC_UI_WIDTH 140 + +/* These may fit better in a tc_raylib.h file or something of that nature */ +static const Color SC_Black = {0, 0, 0, 255}; +static const Color SC_Red = {230, 41, 55, 255}; +static const Color SC_White = {255, 255, 255, 255}; +static const Color SC_Gray = {130, 130, 130, 255}; + +#endif /* SC_DEF_H_ */ diff --git a/src/rewrite/tc_input.c b/src/rewrite/tc_input.c new file mode 100644 index 0000000..817d0f9 --- /dev/null +++ b/src/rewrite/tc_input.c @@ -0,0 +1,7 @@ +#include "tc_input.h" +#include "raylib.h" + +void TC_Process_Input(void) +{ + /* implement */ +} diff --git a/src/rewrite/tc_input.h b/src/rewrite/tc_input.h new file mode 100644 index 0000000..c899047 --- /dev/null +++ b/src/rewrite/tc_input.h @@ -0,0 +1,6 @@ +#ifndef TC_INPUT_H_ +#define TC_INPUT_H_ + +void TC_Process_Input(void); + +#endif /* TC_INPUT_H_ */ diff --git a/src/rewrite/tc_main.c b/src/rewrite/tc_main.c new file mode 100644 index 0000000..4bf495d --- /dev/null +++ b/src/rewrite/tc_main.c @@ -0,0 +1,80 @@ +#include "m_block.h" +#include "m_tetromino.h" +#include "r_block.h" +#include "r_ui.h" +#include "tc_input.h" +#include "tc_settings.h" +#include "tc_window.h" +#include +#include +#include + +void TC_Start(void); +void TC_Initialize(void); +void TC_Game_Loop(void); +void TC_Stop(void); + +int main(int c, char *v[]) +{ + /* Move somwhere else to parse options */ + /* =================================== */ + if (c > 1) + { + if (strcmp(v[1], "--speed") == 0) + { + TC_Set_Game_Speed(atoi(v[2])); + } + } + /* =================================== */ + + TC_Start(); + TC_Stop(); +} + +void TC_Start(void) +{ + TC_Initialize(); + TC_Game_Loop(); +} + +void TC_Initialize(void) +{ + int n_blocks_created = 0; + block_t **blocks_created = NULL; + TC_Create_Window(); + M_Create_Blocks(); + R_Load_Textures(); + blocks_created = M_Get_Blocks(&n_blocks_created); + R_Draw_Blocks(blocks_created, n_blocks_created); +} + +void TC_Game_Loop(void) +{ + int tick_rate, n_updated_blocks = 0; + block_t **updated_blocks = NULL; + while (!TC_Close_Window()) + { + R_Draw_Ui(); + if (tick_rate == 0) + { + TC_Process_Input(); + M_Update_Tetromino(); + M_Update_Blocks(); + M_Get_Updated_Blocks(&n_updated_blocks); + R_Draw_Blocks(updated_blocks, n_updated_blocks); + tick_rate = game_speed_setting; + } + else + { + tick_rate--; + } + } + R_Draw_Game_Over(0); + getchar(); /* putting this here just to stop prog from ending atm */ +} + +void TC_Stop(void) +{ + M_Destroy_Blocks(); + TC_Close_Window(); +} diff --git a/src/rewrite/tc_settings.c b/src/rewrite/tc_settings.c new file mode 100644 index 0000000..6c50576 --- /dev/null +++ b/src/rewrite/tc_settings.c @@ -0,0 +1,16 @@ +#include "tc_settings.h" + +int game_speed_setting = 50; +int target_fps_setting = 60; + +struct TC_Setting *tc_settings; + +void TC_Set_Game_Speed(int speed) +{ + game_speed_setting = speed; +} + +void TC_Set_Target_Fps(int fps) +{ + target_fps_setting = fps; +} diff --git a/src/rewrite/tc_settings.h b/src/rewrite/tc_settings.h new file mode 100644 index 0000000..d522dab --- /dev/null +++ b/src/rewrite/tc_settings.h @@ -0,0 +1,13 @@ +#ifndef TC_SETTINGS_H_ +#define TC_SETTINGS_H_ + +/* these settings could probably be more robust, probably doesn't matter until i need more*/ +/* Maybe have a load defaults, then optionally update? */ + +void TC_Set_Game_Speed(int speed); +void TC_Set_Target_Fps(int fps); + +extern int game_speed_setting; +extern int target_fps_setting; + +#endif /* TC_SETTINGS_H_ */ diff --git a/src/rewrite/tc_window.c b/src/rewrite/tc_window.c new file mode 100644 index 0000000..b4f4b58 --- /dev/null +++ b/src/rewrite/tc_window.c @@ -0,0 +1,15 @@ +#include "tc_window.h" +#include "raylib.h" +#include "sc_def.h" +#include "tc_settings.h" + +void TC_Create_Window(void) +{ + InitWindow(SC_WIDTH, SC_HEIGHT, "Tetris Clone"); + SetTargetFPS(target_fps_setting); +} + +int TC_Close_Window(void) +{ + return WindowShouldClose(); +} diff --git a/src/rewrite/tc_window.h b/src/rewrite/tc_window.h new file mode 100644 index 0000000..4f0f961 --- /dev/null +++ b/src/rewrite/tc_window.h @@ -0,0 +1,7 @@ +#ifndef TC_WINDOW_H_ +#define TC_WINDOW_H_ + +void TC_Create_Window(void); +int TC_Close_Window(void); + +#endif /* TC_WINDOW_H_ */ diff --git a/src/rewrite/tetromino.h b/src/rewrite/tetromino.h new file mode 100644 index 0000000..e69de29