huge portion of rewrite done, basic movement updates to UI
This commit is contained in:
@@ -2,22 +2,22 @@
|
|||||||
#define BLOCK_H_
|
#define BLOCK_H_
|
||||||
#include "point.h"
|
#include "point.h"
|
||||||
|
|
||||||
/* still unsure how i want to name structs and enums */
|
/* Not sure where this should belong tbh */
|
||||||
|
#define BLOCKS_WITHIN_A_TETROMINO 4
|
||||||
|
|
||||||
typedef enum btype_t
|
typedef enum btype_t {
|
||||||
{
|
bt_Empty,
|
||||||
bt_I,
|
bt_I,
|
||||||
bt_J,
|
bt_J,
|
||||||
bt_L,
|
bt_L,
|
||||||
bt_O,
|
bt_O,
|
||||||
bt_S,
|
bt_S,
|
||||||
bt_T,
|
bt_T,
|
||||||
bt_Z,
|
bt_Z
|
||||||
bt_Empty
|
|
||||||
} btype_t;
|
} btype_t;
|
||||||
|
|
||||||
typedef struct block_t
|
typedef struct block_t {
|
||||||
{
|
int id;
|
||||||
point_t point;
|
point_t point;
|
||||||
btype_t type;
|
btype_t type;
|
||||||
} block_t;
|
} block_t;
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#include "m_block.h"
|
#include "m_block.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define BLOCK_ARRAY_COLUMNS 10
|
#define BLOCK_ARRAY_COLUMNS 10
|
||||||
#define BLOCK_ARRAY_ROWS 20
|
#define BLOCK_ARRAY_ROWS 20
|
||||||
@@ -7,14 +10,22 @@
|
|||||||
|
|
||||||
block_t *_blocks[BLOCK_ARRAY_LENGTH];
|
block_t *_blocks[BLOCK_ARRAY_LENGTH];
|
||||||
block_t *_updated_blocks[BLOCK_ARRAY_LENGTH];
|
block_t *_updated_blocks[BLOCK_ARRAY_LENGTH];
|
||||||
int updated_blocks_current_length = 0;
|
block_t *_recently_spawned_blocks[BLOCKS_WITHIN_A_TETROMINO];
|
||||||
|
int _updated_blocks_current_length = 0;
|
||||||
|
int _spawn_tetromino_flag = 1;
|
||||||
|
int _can_spawn_tetromino_flag = 1;
|
||||||
|
btype_t _next_block_type = bt_Empty;
|
||||||
|
const int _spawn_x = BLOCK_ARRAY_COLUMNS / 2 - 1;
|
||||||
|
const point_offset_t _shift_down_offset = {0, 1};
|
||||||
|
const point_offset_t _shift_left_offset = {-1, 0};
|
||||||
|
const point_offset_t _shift_right_offset = {1, 0};
|
||||||
|
void (*on_block_spawn)(block_t *blocks[BLOCKS_WITHIN_A_TETROMINO]);
|
||||||
|
|
||||||
void M_Create_Blocks(void)
|
void M_B_Create_Blocks(void) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < BLOCK_ARRAY_LENGTH; i++)
|
for (i = 0; i < BLOCK_ARRAY_LENGTH; i++) {
|
||||||
{
|
|
||||||
block_t *block = malloc(sizeof(block_t));
|
block_t *block = malloc(sizeof(block_t));
|
||||||
|
block->id = -1;
|
||||||
block->point.x = i % BLOCK_ARRAY_COLUMNS;
|
block->point.x = i % BLOCK_ARRAY_COLUMNS;
|
||||||
block->point.y = i / BLOCK_ARRAY_COLUMNS;
|
block->point.y = i / BLOCK_ARRAY_COLUMNS;
|
||||||
block->type = bt_Empty;
|
block->type = bt_Empty;
|
||||||
@@ -23,28 +34,333 @@ void M_Create_Blocks(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_Update_Blocks(void)
|
void M_B_Update_Blocks(void) {
|
||||||
{
|
M_B_Reset_Blocks_Updated();
|
||||||
/* implement */
|
if (_spawn_tetromino_flag) {
|
||||||
|
M_B_Spawn_Blocks();
|
||||||
|
M_B_Set_Next_Block_Type();
|
||||||
|
_spawn_tetromino_flag = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block_t **M_Get_Blocks(int *length)
|
block_t **M_B_Get_Blocks(int *length) {
|
||||||
{
|
|
||||||
*length = BLOCK_ARRAY_LENGTH;
|
*length = BLOCK_ARRAY_LENGTH;
|
||||||
return _blocks;
|
return _blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
block_t **M_Get_Updated_Blocks(int *length)
|
block_t **M_B_Get_Updated_Blocks(int *length) {
|
||||||
{
|
*length = _updated_blocks_current_length;
|
||||||
*length = updated_blocks_current_length;
|
|
||||||
return _updated_blocks;
|
return _updated_blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_Destroy_Blocks(void)
|
void M_B_Destroy_Blocks(void) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < BLOCK_ARRAY_LENGTH; i++)
|
for (i = 0; i < BLOCK_ARRAY_LENGTH; i++) {
|
||||||
{
|
|
||||||
free(_blocks[i]);
|
free(_blocks[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void M_B_Reset_Blocks_Updated(void) { _updated_blocks_current_length = 0; }
|
||||||
|
|
||||||
|
void M_B_On_Block_Spawn(void (*callback)(block_t **blocks)) {
|
||||||
|
on_block_spawn = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_B_Spawn_Blocks(void) {
|
||||||
|
struct point_offset_t offsets[BLOCKS_WITHIN_A_TETROMINO];
|
||||||
|
|
||||||
|
if (_next_block_type == bt_Empty) {
|
||||||
|
M_B_Set_Next_Block_Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_next_block_type) {
|
||||||
|
case bt_I:
|
||||||
|
offsets[0].x_offset = 0;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 0;
|
||||||
|
offsets[1].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 0;
|
||||||
|
offsets[2].y_offset = 2;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 0;
|
||||||
|
offsets[3].y_offset = 3;
|
||||||
|
break;
|
||||||
|
case bt_J:
|
||||||
|
offsets[0].x_offset = 2;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 0;
|
||||||
|
offsets[1].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 1;
|
||||||
|
offsets[2].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 2;
|
||||||
|
offsets[3].y_offset = 1;
|
||||||
|
break;
|
||||||
|
case bt_L:
|
||||||
|
offsets[0].x_offset = 0;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 0;
|
||||||
|
offsets[1].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 1;
|
||||||
|
offsets[2].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 2;
|
||||||
|
offsets[3].y_offset = 1;
|
||||||
|
break;
|
||||||
|
case bt_O:
|
||||||
|
offsets[0].x_offset = 0;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 1;
|
||||||
|
offsets[1].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 0;
|
||||||
|
offsets[2].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 1;
|
||||||
|
offsets[3].y_offset = 1;
|
||||||
|
break;
|
||||||
|
case bt_S:
|
||||||
|
offsets[0].x_offset = 1;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 2;
|
||||||
|
offsets[1].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 0;
|
||||||
|
offsets[2].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 1;
|
||||||
|
offsets[3].y_offset = 1;
|
||||||
|
break;
|
||||||
|
case bt_T:
|
||||||
|
offsets[0].x_offset = 1;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 0;
|
||||||
|
offsets[1].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 1;
|
||||||
|
offsets[2].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 2;
|
||||||
|
offsets[3].y_offset = 1;
|
||||||
|
break;
|
||||||
|
case bt_Z:
|
||||||
|
offsets[0].x_offset = 0;
|
||||||
|
offsets[0].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[1].x_offset = 1;
|
||||||
|
offsets[1].y_offset = 0;
|
||||||
|
|
||||||
|
offsets[2].x_offset = 1;
|
||||||
|
offsets[2].y_offset = 1;
|
||||||
|
|
||||||
|
offsets[3].x_offset = 2;
|
||||||
|
offsets[3].y_offset = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (M_B_Try_Spawn_Blocks_With_Offset(offsets)) {
|
||||||
|
on_block_spawn(_recently_spawned_blocks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_B_Set_Next_Block_Type(void) {
|
||||||
|
_next_block_type = M_B_Get_Random_Block_Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
btype_t M_B_Get_Random_Block_Type(void) {
|
||||||
|
srand(time(NULL));
|
||||||
|
return (btype_t)(rand() % 7) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Try_Spawn_Blocks_With_Offset(point_offset_t *offsets) {
|
||||||
|
int i = 0, kinda_unique_id = M_B_Generate_Block_Id();
|
||||||
|
point_t spawn_point;
|
||||||
|
block_t *spawn_block;
|
||||||
|
while (i < BLOCKS_WITHIN_A_TETROMINO) {
|
||||||
|
spawn_point.x = _spawn_x + offsets->x_offset;
|
||||||
|
spawn_point.y = offsets->y_offset;
|
||||||
|
|
||||||
|
spawn_block = M_B_Get_Block_At_Point(spawn_point);
|
||||||
|
if (spawn_block->type != bt_Empty) {
|
||||||
|
_can_spawn_tetromino_flag = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
spawn_block->id = kinda_unique_id;
|
||||||
|
M_B_Set_Block_Type(spawn_block, _next_block_type);
|
||||||
|
|
||||||
|
_recently_spawned_blocks[i] = spawn_block;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
offsets++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_t *M_B_Get_Block_At_Point(point_t point) {
|
||||||
|
return _blocks[(point.x % BLOCK_ARRAY_COLUMNS) +
|
||||||
|
(point.y * BLOCK_ARRAY_COLUMNS)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_B_Set_Block_Type(block_t *block, btype_t type) {
|
||||||
|
block->type = type;
|
||||||
|
M_B_Register_Updated_block(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_B_Register_Updated_block(block_t *block) {
|
||||||
|
if (_updated_blocks_current_length < BLOCK_ARRAY_LENGTH) {
|
||||||
|
_updated_blocks[_updated_blocks_current_length] = block;
|
||||||
|
_updated_blocks_current_length++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Can_Move_Blocks_Left(block_t **blocks) {
|
||||||
|
int i = 0, result = 1;
|
||||||
|
for (; i < BLOCKS_WITHIN_A_TETROMINO; i++) {
|
||||||
|
if (!M_B_Can_Move_Block_Left(*(blocks[i]))) {
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Can_Move_Block_Left(block_t block) {
|
||||||
|
point_t left_adj_block_point;
|
||||||
|
left_adj_block_point.x = block.point.x - 1;
|
||||||
|
left_adj_block_point.y = block.point.y;
|
||||||
|
if (left_adj_block_point.x < 0) {
|
||||||
|
return 0;
|
||||||
|
} else if (M_B_Point_Intersects_Static_Block(left_adj_block_point,
|
||||||
|
block.id)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block_t *M_B_Move_Block_Left(block_t *block) {
|
||||||
|
/* Kinda dupe from right and down, might consolidate */
|
||||||
|
block_t *updated_block = M_B_Get_Block_At_Offset(block, _shift_left_offset);
|
||||||
|
updated_block->id = block->id;
|
||||||
|
M_B_Set_Block_Type(updated_block, block->type);
|
||||||
|
block->id = -1;
|
||||||
|
M_B_Set_Block_Type(block, bt_Empty);
|
||||||
|
|
||||||
|
return updated_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Can_Move_Blocks_Right(block_t **blocks) {
|
||||||
|
int i = 0, result = 1;
|
||||||
|
for (; i < BLOCKS_WITHIN_A_TETROMINO; i++) {
|
||||||
|
if (!M_B_Can_Move_Block_Right(*(blocks[i]))) {
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Can_Move_Block_Right(block_t block) {
|
||||||
|
point_t right_adj_block_point;
|
||||||
|
right_adj_block_point.x = block.point.x + 1;
|
||||||
|
right_adj_block_point.y = block.point.y;
|
||||||
|
if (right_adj_block_point.x >= BLOCK_ARRAY_COLUMNS) {
|
||||||
|
return 0;
|
||||||
|
} else if (M_B_Point_Intersects_Static_Block(right_adj_block_point,
|
||||||
|
block.id)) {
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block_t *M_B_Move_Block_Right(block_t *block) {
|
||||||
|
block_t *updated_block = M_B_Get_Block_At_Offset(block, _shift_right_offset);
|
||||||
|
updated_block->id = block->id;
|
||||||
|
M_B_Set_Block_Type(updated_block, block->type);
|
||||||
|
block->id = -1;
|
||||||
|
M_B_Set_Block_Type(block, bt_Empty);
|
||||||
|
|
||||||
|
return updated_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Can_Move_Blocks_Down(block_t **blocks) {
|
||||||
|
int i = 0, result = 1;
|
||||||
|
for (; i < BLOCKS_WITHIN_A_TETROMINO; i++) {
|
||||||
|
if (!M_B_Can_Move_Block_Down(*(blocks[i]))) {
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
_spawn_tetromino_flag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Can_Move_Block_Down(block_t block) {
|
||||||
|
point_t bottom_adj_block_point;
|
||||||
|
bottom_adj_block_point.x = block.point.x;
|
||||||
|
bottom_adj_block_point.y = block.point.y + 1;
|
||||||
|
if (bottom_adj_block_point.y >= BLOCK_ARRAY_ROWS) {
|
||||||
|
return 0;
|
||||||
|
} else if (M_B_Point_Intersects_Static_Block(bottom_adj_block_point,
|
||||||
|
block.id)) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block_t *M_B_Move_Block_Down(block_t *block) {
|
||||||
|
block_t *updated_block = M_B_Get_Block_At_Offset(block, _shift_down_offset);
|
||||||
|
updated_block->id = block->id;
|
||||||
|
M_B_Set_Block_Type(updated_block, block->type);
|
||||||
|
block->id = -1;
|
||||||
|
M_B_Set_Block_Type(block, bt_Empty);
|
||||||
|
|
||||||
|
return updated_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
block_t *M_B_Get_Block_At_Offset(block_t *block, point_offset_t offset) {
|
||||||
|
point_t updated_point;
|
||||||
|
updated_point.x = block->point.x + offset.x_offset;
|
||||||
|
updated_point.y = block->point.y + offset.y_offset;
|
||||||
|
|
||||||
|
return M_B_Get_Block_At_Point(updated_point);
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Point_Intersects_Static_Block(point_t point, int id) {
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
block_t *block_at_point = M_B_Get_Block_At_Point(point);
|
||||||
|
|
||||||
|
if (block_at_point->type != bt_Empty && block_at_point->id != id) {
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_B_Generate_Block_Id(void) {
|
||||||
|
/* The odds of this not being unique are high enough, surely
|
||||||
|
SURELY
|
||||||
|
*/
|
||||||
|
srand(time(NULL));
|
||||||
|
return rand();
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,31 @@
|
|||||||
#define M_BLOCK_H_
|
#define M_BLOCK_H_
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
|
||||||
void M_Create_Blocks(void);
|
void M_B_Create_Blocks(void);
|
||||||
void M_Update_Blocks(void);
|
void M_B_Update_Blocks(void);
|
||||||
block_t **M_Get_Blocks(int *length);
|
block_t **M_B_Get_Blocks(int *length);
|
||||||
block_t **M_Get_Updated_Blocks(int *length);
|
block_t **M_B_Get_Updated_Blocks(int *length);
|
||||||
void M_Destroy_Blocks(void);
|
void M_B_Destroy_Blocks(void);
|
||||||
|
void M_B_Reset_Blocks_Updated(void);
|
||||||
|
void M_B_Spawn_Blocks(void);
|
||||||
|
void M_B_Set_Next_Block_Type(void);
|
||||||
|
btype_t M_B_Get_Random_Block_Type(void);
|
||||||
|
int M_B_Try_Spawn_Blocks_With_Offset(point_offset_t *offsets);
|
||||||
|
block_t *M_B_Get_Block_At_Point(point_t point);
|
||||||
|
void M_B_Set_Block_Type(block_t *block, btype_t type);
|
||||||
|
void M_B_Register_Updated_block(block_t *block);
|
||||||
|
int M_B_Can_Move_Blocks_Left(block_t **blocks);
|
||||||
|
int M_B_Can_Move_Block_Left(block_t block);
|
||||||
|
block_t *M_B_Move_Block_Left(block_t *block);
|
||||||
|
int M_B_Can_Move_Blocks_Right(block_t **blocks);
|
||||||
|
int M_B_Can_Move_Block_Right(block_t block);
|
||||||
|
block_t *M_B_Move_Block_Right(block_t *block);
|
||||||
|
int M_B_Can_Move_Blocks_Down(block_t **blocks);
|
||||||
|
int M_B_Can_Move_Block_Down(block_t block);
|
||||||
|
block_t *M_B_Move_Block_Down(block_t *block);
|
||||||
|
block_t *M_B_Get_Block_At_Offset(block_t *block, point_offset_t offset);
|
||||||
|
void M_B_On_Block_Spawn(void (*callback)(block_t **blocks));
|
||||||
|
int M_B_Point_Intersects_Static_Block(point_t point, int id);
|
||||||
|
int M_B_Generate_Block_Id(void);
|
||||||
|
|
||||||
#endif /* M_BLOCK_H_ */
|
#endif /* M_BLOCK_H_ */
|
||||||
|
|||||||
@@ -1,6 +1,45 @@
|
|||||||
#include "m_tetromino.h"
|
#include "m_tetromino.h"
|
||||||
|
#include "m_block.h"
|
||||||
|
|
||||||
void M_Update_Tetromino(void)
|
/* Blocks are gauranteed to be in order top left to bottom right */
|
||||||
{
|
block_t *_tetromino_blocks[BLOCKS_WITHIN_A_TETROMINO];
|
||||||
/* implement */
|
int registered_flag = 0;
|
||||||
|
|
||||||
|
void M_T_Update_Tetromino(void) { M_T_Tetromino_Fall(); }
|
||||||
|
|
||||||
|
void M_T_Tetromino_Fall(void) {
|
||||||
|
int i;
|
||||||
|
if (registered_flag && M_B_Can_Move_Blocks_Down(_tetromino_blocks)) {
|
||||||
|
for (i = BLOCKS_WITHIN_A_TETROMINO - 1; i >= 0; i--) {
|
||||||
|
_tetromino_blocks[i] = M_B_Move_Block_Down(_tetromino_blocks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_T_Register_Falling_Blocks(block_t *blocks[BLOCKS_WITHIN_A_TETROMINO]) {
|
||||||
|
int i;
|
||||||
|
if (!registered_flag) {
|
||||||
|
registered_flag = 1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < BLOCKS_WITHIN_A_TETROMINO; i++) {
|
||||||
|
_tetromino_blocks[i] = blocks[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_T_Move_Tetromino_Left(void) {
|
||||||
|
int i;
|
||||||
|
if (registered_flag && M_B_Can_Move_Blocks_Left(_tetromino_blocks)) {
|
||||||
|
for (i = 0; i < BLOCKS_WITHIN_A_TETROMINO; i++) {
|
||||||
|
_tetromino_blocks[i] = M_B_Move_Block_Left(_tetromino_blocks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void M_T_Move_Tetromino_Right(void) {
|
||||||
|
int i;
|
||||||
|
if (registered_flag && M_B_Can_Move_Blocks_Right(_tetromino_blocks)) {
|
||||||
|
for (i = BLOCKS_WITHIN_A_TETROMINO - 1; i >= 0; i--) {
|
||||||
|
_tetromino_blocks[i] = M_B_Move_Block_Right(_tetromino_blocks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
#define M_TETROMINO_H_
|
#define M_TETROMINO_H_
|
||||||
#include "block.h"
|
#include "block.h"
|
||||||
|
|
||||||
void M_Update_Tetromino(void);
|
void M_T_Update_Tetromino(void);
|
||||||
|
void M_T_Apply_To_Tetromino_Blocks(block_t *(*callback)(block_t *block));
|
||||||
|
void M_T_Tetromino_Fall(void);
|
||||||
|
void M_T_Register_Falling_Blocks(block_t **blocks);
|
||||||
|
void M_T_Move_Tetromino_Left(void);
|
||||||
|
void M_T_Move_Tetromino_Right(void);
|
||||||
|
|
||||||
#endif /* M_TETROMINO_H_ */
|
#endif /* M_TETROMINO_H_ */
|
||||||
|
|||||||
@@ -2,16 +2,14 @@
|
|||||||
#define POINT_H_
|
#define POINT_H_
|
||||||
#include "point.h"
|
#include "point.h"
|
||||||
|
|
||||||
typedef struct point_t
|
typedef struct point_t {
|
||||||
{
|
int x;
|
||||||
unsigned int x;
|
int y;
|
||||||
unsigned int y;
|
|
||||||
} point_t;
|
} point_t;
|
||||||
|
|
||||||
typedef struct point_offset_t
|
typedef struct point_offset_t {
|
||||||
{
|
int x_offset;
|
||||||
int xOffset;
|
int y_offset;
|
||||||
int yOffset;
|
|
||||||
} point_offset_t;
|
} point_offset_t;
|
||||||
|
|
||||||
#endif /* POINT_H_ */
|
#endif /* POINT_H_ */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "r_block.h"
|
#include "r_block.h"
|
||||||
|
|
||||||
#include "sc_def.h"
|
#include "sc_def.h"
|
||||||
|
|
||||||
#define RES_PNG_FILE(name) "resources/" #name ".png"
|
|
||||||
#define TEXTURE_SIZE 32
|
#define TEXTURE_SIZE 32
|
||||||
|
|
||||||
Texture2D yellow_texture;
|
Texture2D yellow_texture;
|
||||||
@@ -13,23 +13,20 @@ Texture2D green_texture;
|
|||||||
Texture2D orange_texture;
|
Texture2D orange_texture;
|
||||||
Texture2D empty_texture;
|
Texture2D empty_texture;
|
||||||
|
|
||||||
void R_Load_Textures(void)
|
void R_Load_Textures(void) {
|
||||||
{
|
yellow_texture = LoadTexture("resources/yellow.png");
|
||||||
yellow_texture = LoadTexture(RES_PNG_FILE(yellow));
|
blue_texture = LoadTexture("resources/blue.png");
|
||||||
blue_texture = LoadTexture(RES_PNG_FILE(blue));
|
light_blue_texture = LoadTexture("resources/light-blue.png");
|
||||||
light_blue_texture = LoadTexture(RES_PNG_FILE(light - blue));
|
red_texture = LoadTexture("resources/red.png");
|
||||||
red_texture = LoadTexture(RES_PNG_FILE(red));
|
purple_texture = LoadTexture("resources/purple.png");
|
||||||
purple_texture = LoadTexture(RES_PNG_FILE(purple));
|
green_texture = LoadTexture("resources/green.png");
|
||||||
green_texture = LoadTexture(RES_PNG_FILE(green));
|
orange_texture = LoadTexture("resources/orange.png");
|
||||||
orange_texture = LoadTexture(RES_PNG_FILE(orange));
|
empty_texture = LoadTexture("resources/black.png");
|
||||||
empty_texture = LoadTexture(RES_PNG_FILE(black));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_Draw_Blocks(block_t **blocks, int block_count)
|
void R_Draw_Blocks(block_t **blocks, int block_count) {
|
||||||
{
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
while (block_count--)
|
while (block_count--) {
|
||||||
{
|
|
||||||
R_Draw_Block(*(*blocks));
|
R_Draw_Block(*(*blocks));
|
||||||
blocks++;
|
blocks++;
|
||||||
}
|
}
|
||||||
@@ -37,16 +34,14 @@ void R_Draw_Blocks(block_t **blocks, int block_count)
|
|||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_Draw_Block(block_t block)
|
void R_Draw_Block(block_t block) {
|
||||||
{
|
|
||||||
Texture2D *texture = __R_Get_Texture_By_Block_Type(block.type);
|
Texture2D *texture = __R_Get_Texture_By_Block_Type(block.type);
|
||||||
DrawTexture(*texture, block.point.x * TEXTURE_SIZE, block.point.y * TEXTURE_SIZE, SC_White);
|
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)
|
Texture2D *__R_Get_Texture_By_Block_Type(btype_t block_type) {
|
||||||
{
|
switch (block_type) {
|
||||||
switch (block_type)
|
|
||||||
{
|
|
||||||
case bt_O:
|
case bt_O:
|
||||||
return &yellow_texture;
|
return &yellow_texture;
|
||||||
case bt_I:
|
case bt_I:
|
||||||
|
|||||||
@@ -2,20 +2,27 @@
|
|||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "sc_def.h"
|
#include "sc_def.h"
|
||||||
|
|
||||||
void R_Draw_Ui(void)
|
#define UI_PADDING 16
|
||||||
{
|
|
||||||
|
void R_Draw_Ui(void) {
|
||||||
|
int up_next_box_size;
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
DrawRectangle(SC_GAME_WIDTH, 0, SC_UI_WIDTH, SC_HEIGHT, SC_Gray);
|
DrawRectangle(SC_GAME_WIDTH, 0, SC_UI_WIDTH, SC_HEIGHT, SC_Gray);
|
||||||
|
up_next_box_size = SC_UI_WIDTH - UI_PADDING * 3;
|
||||||
|
DrawRectangle(SC_GAME_WIDTH + UI_PADDING, 0 + UI_PADDING, up_next_box_size,
|
||||||
|
up_next_box_size, SC_Black);
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
void R_Draw_Game_Over(int score)
|
void R_Draw_Game_Over(int score) {
|
||||||
{
|
|
||||||
const char *score_message = TextFormat("Score: %d", score);
|
const char *score_message = TextFormat("Score: %d", score);
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
DrawRectangle(0, 0, SC_GAME_WIDTH, SC_HEIGHT, SC_Black);
|
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("Game Over", SC_GAME_WIDTH / 2 - MeasureText("Game Over", 24) / 2,
|
||||||
DrawText(score_message, SC_GAME_WIDTH / 2 - MeasureText(score_message, 18) / 2, 232, 18, SC_Red);
|
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 */
|
/* Draw a play again button */
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 881 B After Width: | Height: | Size: 4.7 KiB |
@@ -1,7 +1,23 @@
|
|||||||
#include "tc_input.h"
|
#include "tc_input.h"
|
||||||
|
|
||||||
|
#include "m_tetromino.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
void TC_Process_Input(void)
|
void TC_Process_Input(void) {
|
||||||
{
|
/* Was having issues with raylib input, wasn't having these
|
||||||
/* implement */
|
issues before but I figured out that I can just cast to
|
||||||
|
a char to get the result I want :)
|
||||||
|
|
||||||
|
THIS IS NOT HOW RAYLIB IS INTENDED TO BE USED
|
||||||
|
|
||||||
|
should look into what's going on
|
||||||
|
*/
|
||||||
|
if ((char)IsKeyPressed(KEY_SPACE)) {
|
||||||
|
/* Implement after rotation */
|
||||||
|
}
|
||||||
|
if ((char)IsKeyDown(KEY_A)) {
|
||||||
|
M_T_Move_Tetromino_Left();
|
||||||
|
} else if ((char)IsKeyDown(KEY_D)) {
|
||||||
|
M_T_Move_Tetromino_Right();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "m_block.h"
|
#include "m_block.h"
|
||||||
#include "m_tetromino.h"
|
#include "m_tetromino.h"
|
||||||
#include "r_block.h"
|
#include "r_block.h"
|
||||||
@@ -5,23 +8,17 @@
|
|||||||
#include "tc_input.h"
|
#include "tc_input.h"
|
||||||
#include "tc_settings.h"
|
#include "tc_settings.h"
|
||||||
#include "tc_window.h"
|
#include "tc_window.h"
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void TC_Start(void);
|
void TC_Start(void);
|
||||||
void TC_Initialize(void);
|
void TC_Initialize(void);
|
||||||
void TC_Game_Loop(void);
|
void TC_Game_Loop(void);
|
||||||
void TC_Stop(void);
|
void TC_Stop(void);
|
||||||
|
|
||||||
int main(int c, char *v[])
|
int main(int c, char *v[]) {
|
||||||
{
|
|
||||||
/* Move somwhere else to parse options */
|
/* Move somwhere else to parse options */
|
||||||
/* =================================== */
|
/* =================================== */
|
||||||
if (c > 1)
|
if (c > 1) {
|
||||||
{
|
if (strcmp(v[1], "--speed") == 0) {
|
||||||
if (strcmp(v[1], "--speed") == 0)
|
|
||||||
{
|
|
||||||
TC_Set_Game_Speed(atoi(v[2]));
|
TC_Set_Game_Speed(atoi(v[2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,50 +28,42 @@ int main(int c, char *v[])
|
|||||||
TC_Stop();
|
TC_Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TC_Start(void)
|
void TC_Start(void) {
|
||||||
{
|
|
||||||
TC_Initialize();
|
TC_Initialize();
|
||||||
TC_Game_Loop();
|
TC_Game_Loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TC_Initialize(void)
|
void TC_Initialize(void) {
|
||||||
{
|
|
||||||
int n_blocks_created = 0;
|
int n_blocks_created = 0;
|
||||||
block_t **blocks_created = NULL;
|
block_t **blocks_created = NULL;
|
||||||
TC_Create_Window();
|
TC_Create_Window();
|
||||||
M_Create_Blocks();
|
M_B_Create_Blocks();
|
||||||
|
M_B_On_Block_Spawn(&M_T_Register_Falling_Blocks);
|
||||||
R_Load_Textures();
|
R_Load_Textures();
|
||||||
blocks_created = M_Get_Blocks(&n_blocks_created);
|
blocks_created = M_B_Get_Blocks(&n_blocks_created);
|
||||||
R_Draw_Blocks(blocks_created, n_blocks_created);
|
R_Draw_Blocks(blocks_created, n_blocks_created);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TC_Game_Loop(void)
|
void TC_Game_Loop(void) {
|
||||||
{
|
int tick_rate = 0, n_updated_blocks = 0;
|
||||||
int tick_rate, n_updated_blocks = 0;
|
|
||||||
block_t **updated_blocks = NULL;
|
block_t **updated_blocks = NULL;
|
||||||
while (!TC_Close_Window())
|
while (!TC_Close_Window()) {
|
||||||
{
|
|
||||||
R_Draw_Ui();
|
R_Draw_Ui();
|
||||||
if (tick_rate == 0)
|
if (tick_rate == 0) {
|
||||||
{
|
|
||||||
TC_Process_Input();
|
TC_Process_Input();
|
||||||
M_Update_Tetromino();
|
M_T_Update_Tetromino();
|
||||||
M_Update_Blocks();
|
M_B_Update_Blocks();
|
||||||
M_Get_Updated_Blocks(&n_updated_blocks);
|
updated_blocks = M_B_Get_Blocks(&n_updated_blocks);
|
||||||
R_Draw_Blocks(updated_blocks, n_updated_blocks);
|
R_Draw_Blocks(updated_blocks, n_updated_blocks);
|
||||||
tick_rate = game_speed_setting;
|
tick_rate = game_speed_setting;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
tick_rate--;
|
tick_rate--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
R_Draw_Game_Over(0);
|
R_Draw_Game_Over(0);
|
||||||
getchar(); /* putting this here just to stop prog from ending atm */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TC_Stop(void)
|
void TC_Stop(void) {
|
||||||
{
|
M_B_Destroy_Blocks();
|
||||||
M_Destroy_Blocks();
|
|
||||||
TC_Close_Window();
|
TC_Close_Window();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ int target_fps_setting = 60;
|
|||||||
|
|
||||||
struct TC_Setting *tc_settings;
|
struct TC_Setting *tc_settings;
|
||||||
|
|
||||||
void TC_Set_Game_Speed(int speed)
|
void TC_Set_Game_Speed(int speed) { game_speed_setting = speed; }
|
||||||
{
|
|
||||||
game_speed_setting = speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TC_Set_Target_Fps(int fps)
|
void TC_Set_Target_Fps(int fps) { target_fps_setting = fps; }
|
||||||
{
|
|
||||||
target_fps_setting = fps;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#ifndef TC_SETTINGS_H_
|
#ifndef TC_SETTINGS_H_
|
||||||
#define TC_SETTINGS_H_
|
#define TC_SETTINGS_H_
|
||||||
|
|
||||||
/* these settings could probably be more robust, probably doesn't matter until i need more*/
|
/* these settings could probably be more robust, probably doesn't matter until i
|
||||||
|
* need more*/
|
||||||
/* Maybe have a load defaults, then optionally update? */
|
/* Maybe have a load defaults, then optionally update? */
|
||||||
|
|
||||||
void TC_Set_Game_Speed(int speed);
|
void TC_Set_Game_Speed(int speed);
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
#include "tc_window.h"
|
#include "tc_window.h"
|
||||||
|
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "sc_def.h"
|
#include "sc_def.h"
|
||||||
#include "tc_settings.h"
|
#include "tc_settings.h"
|
||||||
|
|
||||||
void TC_Create_Window(void)
|
void TC_Create_Window(void) {
|
||||||
{
|
|
||||||
InitWindow(SC_WIDTH, SC_HEIGHT, "Tetris Clone");
|
InitWindow(SC_WIDTH, SC_HEIGHT, "Tetris Clone");
|
||||||
SetTargetFPS(target_fps_setting);
|
SetTargetFPS(target_fps_setting);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TC_Close_Window(void)
|
int TC_Close_Window(void) { return WindowShouldClose(); }
|
||||||
{
|
|
||||||
return WindowShouldClose();
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user