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 <stdbool.h>
|
||||
|
||||
#include "../main.h"
|
||||
#include "../window/renderer.h"
|
||||
#include "shapes.h"
|
||||
|
||||
|
||||
static void add_shape(const Shape shape, Uint16* row) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Uint8 rowData = (shape >> (4 * i)) & 0x0F;
|
||||
static void _add_shape(Row* row, const Shape shape, const uint8_t colour, const uint8_t pos_x) {
|
||||
for (uint8_t y = 0; y < SHAPE_HEIGHT; y++) {
|
||||
ShapeRow shape_row = shape_get_row(shape, y);
|
||||
|
||||
if (rowData != 0)
|
||||
row[4 - i] |= rowData;
|
||||
if (shape_row == 0)
|
||||
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
|
||||
void game_update(GameData* game_data, const Uint8* keys) {
|
||||
if (keys[SDL_SCANCODE_ESCAPE]) {
|
||||
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
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
typedef uint16_t Shape;
|
||||
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
|
||||
typedef uint32_t PackedRow;
|
||||
|
||||
// stores the data used in the game
|
||||
#define ROWS 32
|
||||
#define COLUMNS (sizeof(Row) * 8 / 3)
|
||||
#define COLUMNS ((uint8_t)(sizeof(PackedRow) * 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 {
|
||||
Row row[ROWS];
|
||||
} 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
SDL_Renderer* renderer = render_data->renderer;
|
||||
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
|
||||
|
||||
// clear render
|
||||
success |= SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0x50);
|
||||
success |= SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF);
|
||||
success |= SDL_RenderClear(renderer);
|
||||
|
||||
for (uint8_t y = 0; y < ROWS; y++) {
|
||||
Row row = data->row[y];
|
||||
|
||||
for (uint8_t x = 0; x < COLUMNS; x += 2) {
|
||||
uint8_t block = row >> (x * 3); // get the two blocks stored at this column
|
||||
|
||||
if ((block & 0x0F) != 0)
|
||||
success |= set_block(renderer, row, block, 0x0F, x + 1, y);
|
||||
|
||||
if ((block & 0xF0) != 0)
|
||||
success |= set_block(renderer, row, block, 0xF0, x, y);
|
||||
for (uint8_t x = 0; x < COLUMNS; x++) {
|
||||
if (row.columns[x].block != 0) {
|
||||
success |= SDL_SetRenderDrawColor(renderer,
|
||||
0xFF * !!(row.columns[x].block & RED),
|
||||
0xFF * !!(row.columns[x].block & GREEN),
|
||||
0xFF * !!(row.columns[x].block & BLUE),
|
||||
0xFF);
|
||||
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_HEIGHT (SCREEN_WIDTH * 2)
|
||||
#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
|
||||
// 4th bit is unused
|
||||
|
||||
Reference in New Issue
Block a user