mirror of
https://github.com/thepigeongenerator/tetris_clone.git
synced 2025-12-17 14:05:45 +01:00
implement setting coloured shapes
This commit is contained in:
@@ -1,22 +1,43 @@
|
|||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
|
#include "../window/renderer.h"
|
||||||
|
#include "shapes.h"
|
||||||
|
|
||||||
|
|
||||||
static void add_shape(const Shape shape, Uint16* row) {
|
static void _add_shape(Row* row, const Shape shape, const uint8_t colour, const uint8_t pos_x) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (uint8_t y = 0; y < SHAPE_HEIGHT; y++) {
|
||||||
Uint8 rowData = (shape >> (4 * i)) & 0x0F;
|
ShapeRow shape_row = shape_get_row(shape, y);
|
||||||
|
|
||||||
if (rowData != 0)
|
if (shape_row == 0)
|
||||||
row[4 - i] |= rowData;
|
continue;
|
||||||
|
|
||||||
|
for (uint8_t x = 0; x < SHAPE_WIDTH; x++)
|
||||||
|
if (is_set(shape_row, x))
|
||||||
|
row[y].columns[x + pos_x].block = colour;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void add_shape(Row* row, const Shape shape, const uint8_t colour, const uint8_t pos_x, const uint8_t pos_y) {
|
||||||
|
_add_shape(&row[pos_y], shape, colour, pos_x);
|
||||||
|
}
|
||||||
|
|
||||||
// called every time the game's state is updated
|
// called every time the game's state is updated
|
||||||
void game_update(GameData* game_data, const Uint8* keys) {
|
void game_update(GameData* game_data, const Uint8* keys) {
|
||||||
if (keys[SDL_SCANCODE_ESCAPE]) {
|
if (keys[SDL_SCANCODE_ESCAPE]) {
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
add_shape(TETROMINO_I, &game_data->row[4]);
|
add_shape(game_data->row, TETROMINO_I, CYAN, 1, 0);
|
||||||
|
add_shape(game_data->row, TETROMINO_O, YELLOW, 5, 4);
|
||||||
|
|
||||||
|
add_shape(game_data->row, TETROMINO_Z, GREEN, 1, 8);
|
||||||
|
add_shape(game_data->row, TETROMINO_S, RED, 5, 8);
|
||||||
|
|
||||||
|
add_shape(game_data->row, TETROMINO_J, BLUE, 1, 12);
|
||||||
|
add_shape(game_data->row, TETROMINO_L, YELLOW | RED, 5, 12);
|
||||||
|
|
||||||
|
add_shape(game_data->row, TETROMINO_T, MAGENTA, 5, 16);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +1,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
typedef uint16_t Shape;
|
typedef uint32_t PackedRow;
|
||||||
typedef uint16_t Row;
|
|
||||||
|
|
||||||
// 0 1 2 3
|
|
||||||
#define TETROMINO_I ((Shape)0b1000100010001000) // 1000 1000 1000 1000 the I tetromino with no rotation
|
|
||||||
#define TETROMINO_I_90 ((Shape)0b0000000000001111) // 0000 0000 0000 1111 the I tetromino with a no rotation
|
|
||||||
#define TETROMINO_O ((Shape)0b1100110000000000) // 1100 1100 0000 0000 the O tetromino with no rotation
|
|
||||||
#define TETROMINO_T ((Shape)0b1110010000000000) // 1110 0100 0000 0000 the T tetromino with no rotation
|
|
||||||
#define TETROMINO_T_90 ((Shape)0b1100110010000000) // 1100 1100 1000 0000 the T tetromino with a no rotation
|
|
||||||
#define TETROMINO_T_180 ((Shape)0b0100111000000000) // 0100 1110 0000 0000 the T tetromino with a 180° rotation
|
|
||||||
#define TETROMINO_T_270 ((Shape)0b0010011000100000) // 0010 0110 0010 0000 the T tetromino with a 270° rotation
|
|
||||||
#define TETROMINO_L ((Shape)0b1000100011000000) // 1000 1000 1100 0000 the L tetromino with no rotation
|
|
||||||
#define TETROMINO_L_90 ((Shape)0b1110100000000000) // 1110 1000 0000 0000 the L tetromino with a no rotation
|
|
||||||
#define TETROMINO_L_180 ((Shape)0b1100010001000000) // 1100 0100 0100 0000 the L tetromino with a 180° rotation
|
|
||||||
#define TETROMINO_L_270 ((Shape)0b0000001011100000) // 0000 0010 1110 0000 the L tetromino with a 270° rotation
|
|
||||||
#define TETROMINO_J ((Shape)0b0100010011000000) // 0100 0100 1100 0000 the J tetromino with no rotation
|
|
||||||
#define TETROMINO_J_90 ((Shape)0b1000111000000000) // 1000 1110 0000 0000 the J tetromino with a no rotation
|
|
||||||
#define TETROMINO_J_180 ((Shape)0b1100100010000000) // 1100 1000 1000 0000 the J tetromino with a 180° rotation
|
|
||||||
#define TETROMINO_J_270 ((Shape)0b1110001000000000) // 1110 0010 0000 0000 the J tetromino with a 270° rotation
|
|
||||||
#define TETROMINO_S ((Shape)0b0110110000000000) // 0110 1100 0000 0000 the S tetromino with no rotation
|
|
||||||
#define TETROMINO_S_90 ((Shape)0b1000110001000000) // 1000 1100 0100 0000 the S tetromino with a no rotation
|
|
||||||
#define TETROMINO_Z ((Shape)0b1100011000000000) // 1100 0110 0000 0000 the Z tetromino with no rotation
|
|
||||||
#define TETROMINO_Z_90 ((Shape)0b0100110010000000) // 0100 1100 1000 0000 the Z tetromino with a no rotation
|
|
||||||
|
|
||||||
// stores the data used in the game
|
// stores the data used in the game
|
||||||
#define ROWS 32
|
#define COLUMNS ((uint8_t)(sizeof(PackedRow) * 8 / 3))
|
||||||
#define COLUMNS (sizeof(Row) * 8 / 3)
|
#define ROWS ((uint8_t)(COLUMNS * 2))
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
// NOTE: this has packing issues
|
||||||
|
struct {
|
||||||
|
uint8_t block : 3;
|
||||||
|
} columns[COLUMNS];
|
||||||
|
PackedRow val;
|
||||||
|
} Row;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Row row[ROWS];
|
Row row[ROWS];
|
||||||
} GameData;
|
} GameData;
|
||||||
|
|||||||
36
src/game/shapes.h
Normal file
36
src/game/shapes.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#define SHAPE_WIDTH 4
|
||||||
|
#define SHAPE_HEIGHT 4
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint16_t Shape;
|
||||||
|
typedef uint8_t ShapeRow;
|
||||||
|
|
||||||
|
// 0 1 2 3
|
||||||
|
#define TETROMINO_I ((Shape)0b1000100010001000) // 1000 1000 1000 1000 the I tetromino with no rotation
|
||||||
|
#define TETROMINO_I_90 ((Shape)0b0000000000001111) // 0000 0000 0000 1111 the I tetromino with a no rotation
|
||||||
|
#define TETROMINO_O ((Shape)0b1100110000000000) // 1100 1100 0000 0000 the O tetromino with no rotation
|
||||||
|
#define TETROMINO_T ((Shape)0b1110010000000000) // 1110 0100 0000 0000 the T tetromino with no rotation
|
||||||
|
#define TETROMINO_T_90 ((Shape)0b1100110010000000) // 1100 1100 1000 0000 the T tetromino with a no rotation
|
||||||
|
#define TETROMINO_T_180 ((Shape)0b0100111000000000) // 0100 1110 0000 0000 the T tetromino with a 180° rotation
|
||||||
|
#define TETROMINO_T_270 ((Shape)0b0010011000100000) // 0010 0110 0010 0000 the T tetromino with a 270° rotation
|
||||||
|
#define TETROMINO_L ((Shape)0b1000100011000000) // 1000 1000 1100 0000 the L tetromino with no rotation
|
||||||
|
#define TETROMINO_L_90 ((Shape)0b1110100000000000) // 1110 1000 0000 0000 the L tetromino with a no rotation
|
||||||
|
#define TETROMINO_L_180 ((Shape)0b1100010001000000) // 1100 0100 0100 0000 the L tetromino with a 180° rotation
|
||||||
|
#define TETROMINO_L_270 ((Shape)0b0000001011100000) // 0000 0010 1110 0000 the L tetromino with a 270° rotation
|
||||||
|
#define TETROMINO_J ((Shape)0b0100010011000000) // 0100 0100 1100 0000 the J tetromino with no rotation
|
||||||
|
#define TETROMINO_J_90 ((Shape)0b1000111000000000) // 1000 1110 0000 0000 the J tetromino with a no rotation
|
||||||
|
#define TETROMINO_J_180 ((Shape)0b1100100010000000) // 1100 1000 1000 0000 the J tetromino with a 180° rotation
|
||||||
|
#define TETROMINO_J_270 ((Shape)0b1110001000000000) // 1110 0010 0000 0000 the J tetromino with a 270° rotation
|
||||||
|
#define TETROMINO_S ((Shape)0b0110110000000000) // 0110 1100 0000 0000 the S tetromino with no rotation
|
||||||
|
#define TETROMINO_S_90 ((Shape)0b1000110001000000) // 1000 1100 0100 0000 the S tetromino with a no rotation
|
||||||
|
#define TETROMINO_Z ((Shape)0b1100011000000000) // 1100 0110 0000 0000 the Z tetromino with no rotation
|
||||||
|
#define TETROMINO_Z_90 ((Shape)0b0100110010000000) // 0100 1100 1000 0000 the Z tetromino with a no rotation
|
||||||
|
|
||||||
|
static inline ShapeRow shape_get_row(Shape shape, uint8_t index) {
|
||||||
|
return shape >> (((SHAPE_HEIGHT - 1) - index) * 4) & 0b1111;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline _Bool is_set(ShapeRow row, uint8_t index) {
|
||||||
|
return (row >> ((SHAPE_WIDTH - 1) - index) & 1) != 0;
|
||||||
|
}
|
||||||
@@ -26,16 +26,6 @@ int renderer_init(SDL_Window** window, SDL_Renderer** renderer) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int set_block(SDL_Renderer* renderer, const Row row, const uint8_t block, const uint8_t filter, const uint8_t x, const uint8_t y) {
|
|
||||||
uint8_t colour = block & filter;
|
|
||||||
return SDL_SetRenderDrawColor(renderer,
|
|
||||||
0xFF * (0 != (colour & (RED | RED << 3))),
|
|
||||||
0xFF * (0 != (colour & (GREEN | GREEN << 3))),
|
|
||||||
0xFF * (0 != (colour & (BLUE | BLUE << 3))),
|
|
||||||
0xFF) |
|
|
||||||
SDL_RenderFillRect(renderer, &(SDL_Rect){x * BLOCK_WIDTH + 1, y * BLOCK_HEIGHT + 1, BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderer_update(const RenderData* render_data) {
|
void renderer_update(const RenderData* render_data) {
|
||||||
SDL_Renderer* renderer = render_data->renderer;
|
SDL_Renderer* renderer = render_data->renderer;
|
||||||
GameData* data = render_data->game_data;
|
GameData* data = render_data->game_data;
|
||||||
@@ -43,20 +33,21 @@ void renderer_update(const RenderData* render_data) {
|
|||||||
int success = 0; // if an error occurs, this value is <0
|
int success = 0; // if an error occurs, this value is <0
|
||||||
|
|
||||||
// clear render
|
// clear render
|
||||||
success |= SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x50);
|
success |= SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
|
||||||
success |= SDL_RenderClear(renderer);
|
success |= SDL_RenderClear(renderer);
|
||||||
|
|
||||||
for (uint8_t y = 0; y < ROWS; y++) {
|
for (uint8_t y = 0; y < ROWS; y++) {
|
||||||
Row row = data->row[y];
|
Row row = data->row[y];
|
||||||
|
|
||||||
for (uint8_t x = 0; x < COLUMNS; x += 2) {
|
for (uint8_t x = 0; x < COLUMNS; x++) {
|
||||||
uint8_t block = row >> (x * 3); // get the two blocks stored at this column
|
if (row.columns[x].block != 0) {
|
||||||
|
success |= SDL_SetRenderDrawColor(renderer,
|
||||||
if ((block & 0x0F) != 0)
|
0xFF * !!(row.columns[x].block & RED),
|
||||||
success |= set_block(renderer, row, block, 0x0F, x + 1, y);
|
0xFF * !!(row.columns[x].block & GREEN),
|
||||||
|
0xFF * !!(row.columns[x].block & BLUE),
|
||||||
if ((block & 0xF0) != 0)
|
0xFF);
|
||||||
success |= set_block(renderer, row, block, 0xF0, x, y);
|
success |= SDL_RenderFillRect(renderer, &(SDL_Rect){x * BLOCK_WIDTH + 1, y * BLOCK_HEIGHT + 1, BLOCK_WIDTH - 1, BLOCK_HEIGHT - 1});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#define SCREEN_WIDTH 256
|
#define SCREEN_WIDTH 256
|
||||||
#define SCREEN_HEIGHT (SCREEN_WIDTH * 2)
|
#define SCREEN_HEIGHT (SCREEN_WIDTH * 2)
|
||||||
#define BLOCK_WIDTH (SCREEN_WIDTH / COLUMNS)
|
#define BLOCK_WIDTH (SCREEN_WIDTH / COLUMNS)
|
||||||
#define BLOCK_HEIGHT (SCREEN_HEIGHT / (BLOCK_WIDTH * 2))
|
#define BLOCK_HEIGHT (SCREEN_HEIGHT / ROWS)
|
||||||
|
|
||||||
// fits colours in a 3 bit length
|
// fits colours in a 3 bit length
|
||||||
// 4th bit is unused
|
// 4th bit is unused
|
||||||
|
|||||||
Reference in New Issue
Block a user