implement setting coloured shapes

This commit is contained in:
2025-01-20 00:27:01 +01:00
parent 2933f5bdd8
commit 34fd24b01f
5 changed files with 86 additions and 51 deletions

View File

@@ -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);
}

View File

@@ -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
View 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;
}

View File

@@ -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});
}
}
}

View File

@@ -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