|
|
@ -19,86 +19,11 @@
|
|
|
|
#include <packed/textures/blocks_texture_data.hpp>
|
|
|
|
#include <packed/textures/blocks_texture_data.hpp>
|
|
|
|
#include <packed/textures/numerals_texture_data.hpp>
|
|
|
|
#include <packed/textures/numerals_texture_data.hpp>
|
|
|
|
|
|
|
|
|
|
|
|
#define TILE_SIZE 20
|
|
|
|
#include <Config.hpp>
|
|
|
|
|
|
|
|
#include <NumberRenderer.hpp>
|
|
|
|
#define GRID_WIDTH 14
|
|
|
|
#include <TileType.hpp>
|
|
|
|
#define GRID_HEIGHT 20
|
|
|
|
#include <BlockType.hpp>
|
|
|
|
|
|
|
|
#include <Block.hpp>
|
|
|
|
#define WINDOW_WIDTH 500
|
|
|
|
|
|
|
|
#define WINDOW_HEIGHT 440
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define PLAYFIELD_X 20
|
|
|
|
|
|
|
|
#define PLAYFIELD_Y 20
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define LINES_PER_LEVEL 5
|
|
|
|
|
|
|
|
#define POINTS_1_LINE 40
|
|
|
|
|
|
|
|
#define POINTS_2_LINES 100
|
|
|
|
|
|
|
|
#define POINTS_3_LINES 300
|
|
|
|
|
|
|
|
#define POINTS_4_LINES 1200
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class NumberRenderer {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
sf::Texture texture;
|
|
|
|
|
|
|
|
sf::IntRect comma_rect;
|
|
|
|
|
|
|
|
sf::IntRect numeral_rects[10];
|
|
|
|
|
|
|
|
NumberRenderer(
|
|
|
|
|
|
|
|
sf::Texture _texture,
|
|
|
|
|
|
|
|
sf::IntRect _comma_rect,
|
|
|
|
|
|
|
|
std::initializer_list<sf::IntRect> _numeral_rects
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
texture = _texture;
|
|
|
|
|
|
|
|
comma_rect = _comma_rect;
|
|
|
|
|
|
|
|
sprite = sf::Sprite(texture);
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
for (auto numeral_rect = _numeral_rects.begin(); numeral_rect != _numeral_rects.end(); ++numeral_rect) {
|
|
|
|
|
|
|
|
numeral_rects[i] = *numeral_rect;
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void render(sf::RenderWindow* window, uint number, int x, int y) {
|
|
|
|
|
|
|
|
auto number_string = std::to_string(number);
|
|
|
|
|
|
|
|
std::string numeral_string;
|
|
|
|
|
|
|
|
numeral_string.push_back(number_string.back());
|
|
|
|
|
|
|
|
auto numeral_rect = numeral_rects[std::stoi(numeral_string)];
|
|
|
|
|
|
|
|
int x_offset = -numeral_rect.width;
|
|
|
|
|
|
|
|
uint digits = number_string.length();
|
|
|
|
|
|
|
|
for (int i = digits - 1; i >= 0; i--) {
|
|
|
|
|
|
|
|
char numeral_string[] = {number_string[i]};
|
|
|
|
|
|
|
|
auto numeral_rect = numeral_rects[std::stoi(numeral_string)];
|
|
|
|
|
|
|
|
if ((digits - i) % 3 == 1 && i != digits - 1) {
|
|
|
|
|
|
|
|
sprite.setTextureRect(comma_rect);
|
|
|
|
|
|
|
|
sprite.setPosition(x + x_offset, y);
|
|
|
|
|
|
|
|
window->draw(sprite);
|
|
|
|
|
|
|
|
x_offset -= numeral_rect.width;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
sprite.setTextureRect(numeral_rect);
|
|
|
|
|
|
|
|
sprite.setPosition(x + x_offset, y);
|
|
|
|
|
|
|
|
window->draw(sprite);
|
|
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((digits - i) % 3 == 0) {
|
|
|
|
|
|
|
|
x_offset -= comma_rect.width;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
numeral_string[0] = number_string[i - 1];
|
|
|
|
|
|
|
|
numeral_rect = numeral_rects[std::stoi(numeral_string)];
|
|
|
|
|
|
|
|
x_offset -= numeral_rect.width;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
sf::Sprite sprite;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TileType {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
sf::IntRect texture_rect;
|
|
|
|
|
|
|
|
sf::IntRect ghost_texture_rect;
|
|
|
|
|
|
|
|
TileType(sf::IntRect _texture_rect, sf::IntRect _ghost_texture_rect) {
|
|
|
|
|
|
|
|
texture_rect = _texture_rect;
|
|
|
|
|
|
|
|
ghost_texture_rect = _ghost_texture_rect;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TileType tile_type_0(
|
|
|
|
TileType tile_type_0(
|
|
|
|
sf::IntRect(0, 0, TILE_SIZE, TILE_SIZE),
|
|
|
|
sf::IntRect(0, 0, TILE_SIZE, TILE_SIZE),
|
|
|
@ -129,42 +54,6 @@ TileType tile_type_6(
|
|
|
|
sf::IntRect(TILE_SIZE * 6, TILE_SIZE, TILE_SIZE, TILE_SIZE)
|
|
|
|
sf::IntRect(TILE_SIZE * 6, TILE_SIZE, TILE_SIZE, TILE_SIZE)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
class BlockType {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
static BlockType i, j, l, o, s, t, z;
|
|
|
|
|
|
|
|
static BlockType* list[];
|
|
|
|
|
|
|
|
static BlockType* random() {
|
|
|
|
|
|
|
|
return list[rand() % 7];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
TileType* tile_type;
|
|
|
|
|
|
|
|
std::vector<std::vector<bool>> grid;
|
|
|
|
|
|
|
|
uint width, height, starting_line;
|
|
|
|
|
|
|
|
bool rotate;
|
|
|
|
|
|
|
|
BlockType(TileType* _tile_type, const std::vector<std::vector<bool>> _grid, bool _rotate = true) {
|
|
|
|
|
|
|
|
tile_type = _tile_type;
|
|
|
|
|
|
|
|
grid = _grid;
|
|
|
|
|
|
|
|
rotate = _rotate;
|
|
|
|
|
|
|
|
// Used for alignment in "next block" area
|
|
|
|
|
|
|
|
width = 0;
|
|
|
|
|
|
|
|
starting_line = 0;
|
|
|
|
|
|
|
|
for (uint y = 0; y < grid.size(); y++) {
|
|
|
|
|
|
|
|
bool has_content = false;
|
|
|
|
|
|
|
|
for (uint x = 0; x < grid[y].size(); x++) {
|
|
|
|
|
|
|
|
if (grid[y][x]) {
|
|
|
|
|
|
|
|
width = std::max({width, x + 1});
|
|
|
|
|
|
|
|
has_content = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (has_content) {
|
|
|
|
|
|
|
|
if (height == 0) {
|
|
|
|
|
|
|
|
starting_line = y;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
height = y + 1 - starting_line;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://gamedev.stackexchange.com/a/17978
|
|
|
|
// https://gamedev.stackexchange.com/a/17978
|
|
|
|
BlockType BlockType::i(&tile_type_0, {
|
|
|
|
BlockType BlockType::i(&tile_type_0, {
|
|
|
|
{0, 0, 0, 0},
|
|
|
|
{0, 0, 0, 0},
|
|
|
@ -203,60 +92,6 @@ BlockType BlockType::z(&tile_type_6, {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
BlockType* BlockType::list[] = {&i, &j, &l, &o, &s, &t, &z};
|
|
|
|
BlockType* BlockType::list[] = {&i, &j, &l, &o, &s, &t, &z};
|
|
|
|
|
|
|
|
|
|
|
|
class Block {
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
BlockType* type;
|
|
|
|
|
|
|
|
sf::Vector2i position;
|
|
|
|
|
|
|
|
int rotation_state;
|
|
|
|
|
|
|
|
Block() {
|
|
|
|
|
|
|
|
type = BlockType::random();
|
|
|
|
|
|
|
|
position = sf::Vector2i(GRID_WIDTH / 2 - type->grid[0].size() / 2, 0);
|
|
|
|
|
|
|
|
rotation_state = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<sf::Vector2i> get_tiles() {
|
|
|
|
|
|
|
|
std::vector<sf::Vector2i>tiles = {};
|
|
|
|
|
|
|
|
for (int y = 0; y < type->grid.size(); y++) {
|
|
|
|
|
|
|
|
for (int x = 0; x < type->grid[y].size(); x++) {
|
|
|
|
|
|
|
|
if (!type->grid[y][x]) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int rotated_x = x;
|
|
|
|
|
|
|
|
int rotated_y = y;
|
|
|
|
|
|
|
|
if (type->rotate) {
|
|
|
|
|
|
|
|
int center_x = type->grid[0].size() / 2;
|
|
|
|
|
|
|
|
int center_y = type->grid.size() / 2;
|
|
|
|
|
|
|
|
int offset_x = x - center_x;
|
|
|
|
|
|
|
|
int offset_y = y - center_y;
|
|
|
|
|
|
|
|
switch (rotation_state) {
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
|
|
|
|
rotated_x = x;
|
|
|
|
|
|
|
|
rotated_y = y;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
|
|
rotated_x = center_x + offset_y;
|
|
|
|
|
|
|
|
rotated_y = center_y - offset_x;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
|
|
rotated_x = center_x - offset_x;
|
|
|
|
|
|
|
|
rotated_y = center_y - offset_y;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
|
|
|
|
rotated_x = center_x - offset_y;
|
|
|
|
|
|
|
|
rotated_y = center_y + offset_x;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
rotation_state %= 4;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int global_x = rotated_x + position.x;
|
|
|
|
|
|
|
|
int global_y = rotated_y + position.y;
|
|
|
|
|
|
|
|
tiles.push_back(sf::Vector2i(global_x, global_y));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return tiles;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint get_level(int lines) {
|
|
|
|
uint get_level(int lines) {
|
|
|
|
return std::min(lines / LINES_PER_LEVEL, 15);
|
|
|
|
return std::min(lines / LINES_PER_LEVEL, 15);
|
|
|
|
}
|
|
|
|
}
|
|
|
|