302 lines
9.7 KiB
C++
302 lines
9.7 KiB
C++
#ifndef TETRIS_CUSTOM_CLASSES_H
|
|
#define TETRIS_CUSTOM_CLASSES_H
|
|
|
|
#include "../sdlpp/sdlpp.hpp"
|
|
#include "config.hpp"
|
|
|
|
class TetrisBlock : public SDLPP::RectangleRender {
|
|
public:
|
|
TetrisBlock() = delete;
|
|
TetrisBlock( double x, double y, double w, double h,
|
|
const std::shared_ptr< SDLPP::Renderer > &r,
|
|
const std::string &img_or_color, bool is_polygon, int index,
|
|
std::shared_ptr< SDLPP::Scene > scene,
|
|
std::vector< int > &bag )
|
|
: RectangleRender( x, y, w, h, r, img_or_color, is_polygon ),
|
|
pieces_bag( bag ) {
|
|
_index = index;
|
|
pieces_bag[_index]--;
|
|
_scene = scene;
|
|
setColors();
|
|
if ( g_show_3d )
|
|
setTexture( "block.png" );
|
|
}
|
|
TetrisBlock( const TetrisBlock &other )
|
|
: TetrisBlock( other.getDoubleRect().first.first,
|
|
other.getDoubleRect().first.second,
|
|
other.getDoubleRect().second.first,
|
|
other.getDoubleRect().second.second,
|
|
other.getRenderer(), other.getColor(), true,
|
|
other._index, other._scene, other.pieces_bag ) {}
|
|
~TetrisBlock() {
|
|
if ( _index != PIECE_SHADOW )
|
|
pieces_bag[_index]++;
|
|
}
|
|
virtual std::shared_ptr< RenderObject > copySelf() override {
|
|
auto ret = std::make_shared< TetrisBlock >( *this );
|
|
copyTo(ret);
|
|
return ret;
|
|
}
|
|
virtual void copyTo(std::shared_ptr<RenderObject> other) override {
|
|
RectangleRender::copyTo(other);
|
|
}
|
|
std::shared_ptr< TetrisBlock > copyInScene() {
|
|
auto ret = std::shared_ptr< TetrisBlock >( new TetrisBlock( *this ) );
|
|
_scene->addObject( ret );
|
|
return ret;
|
|
}
|
|
bool isSamePos( const SDLPP::RenderObject &other ) const {
|
|
auto mypos = getPos();
|
|
auto otherpos = other.getPos();
|
|
auto diff1 = mypos.first - otherpos.first;
|
|
diff1 = ( diff1 < 0 ) * ( -1 ) * diff1 + ( diff1 > 0 ) * diff1;
|
|
auto diff2 = mypos.second - otherpos.second;
|
|
diff2 = ( diff2 < 0 ) * ( -1 ) * diff2 + ( diff2 > 0 ) * diff2;
|
|
return diff1 < 0.0001 && diff2 < 0.0001;
|
|
}
|
|
virtual void specialAction( int code ) override {
|
|
switch ( code ) {
|
|
case PIECE_ACTION_UPDATE_COLOR: {
|
|
setColors();
|
|
if ( g_show_3d )
|
|
setTexture( "block.png" );
|
|
else
|
|
unsetTexture();
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
void turnIntoShadow() {
|
|
setId( SHADOW_ID );
|
|
// shadows don't consume pieces from bag
|
|
pieces_bag[_index]++;
|
|
_index = PIECE_SHADOW;
|
|
setColors();
|
|
}
|
|
|
|
private:
|
|
std::string getPieceName() {
|
|
switch ( _index ) {
|
|
case PIECE_BRICK:
|
|
return "piece_brick";
|
|
case PIECE_T:
|
|
return "piece_T";
|
|
case PIECE_L_RIGHT:
|
|
return "piece_L_right";
|
|
case PIECE_Z_RIGHT:
|
|
return "piece_Z_right";
|
|
case PIECE_LINE:
|
|
return "piece_line";
|
|
case PIECE_L_LEFT:
|
|
return "piece_L_left";
|
|
case PIECE_Z_LEFT:
|
|
return "piece_Z_left";
|
|
case PIECE_SHADOW:
|
|
return "shadow";
|
|
default:
|
|
break;
|
|
}
|
|
return "";
|
|
}
|
|
void setColors() {
|
|
auto piece_name = getPieceName();
|
|
setColor( colors[piece_name] );
|
|
setOutlineColor( colors[piece_name + "_out"] );
|
|
}
|
|
int _index = 0;
|
|
std::shared_ptr< SDLPP::Scene > _scene;
|
|
std::vector< int > &pieces_bag;
|
|
};
|
|
|
|
class TetrisPiece {
|
|
public:
|
|
TetrisPiece() {
|
|
original_pos.reserve( 4 );
|
|
}
|
|
void addPiece( std::shared_ptr< TetrisBlock > piece, int x, int y ) {
|
|
pieces.push_back( piece );
|
|
pieces_rel_position.push_back( { 0, 0, 0, 0 } );
|
|
// done this way for SPEEEEEEED
|
|
// left
|
|
pieces_rel_position.back()[0] = ( x < 0 ) * ( -1 ) * x;
|
|
// right
|
|
pieces_rel_position.back()[1] = ( x > 0 ) * x;
|
|
// top
|
|
pieces_rel_position.back()[2] = ( y < 0 ) * ( -1 ) * y;
|
|
// bottom
|
|
pieces_rel_position.back()[3] = ( y > 0 ) * y;
|
|
}
|
|
void rotate() {
|
|
if ( !rotate_allowed )
|
|
return;
|
|
for ( unsigned long i = 0; i < pieces.size(); i++ ) {
|
|
auto &piece = pieces[i];
|
|
auto &positions = pieces_rel_position[i];
|
|
auto position = piece->getPos();
|
|
original_pos[i] = position;
|
|
position.first += positions[0] * BLOCK_SIZE;
|
|
position.first -= positions[1] * BLOCK_SIZE;
|
|
position.second += positions[2] * BLOCK_SIZE;
|
|
position.second -= positions[3] * BLOCK_SIZE;
|
|
auto bottom = positions[3];
|
|
auto top = positions[2];
|
|
positions[3] = positions[1];
|
|
positions[2] = positions[0];
|
|
positions[1] = top;
|
|
positions[0] = bottom;
|
|
position.first -= positions[0] * BLOCK_SIZE;
|
|
position.first += positions[1] * BLOCK_SIZE;
|
|
position.second -= positions[2] * BLOCK_SIZE;
|
|
position.second += positions[3] * BLOCK_SIZE;
|
|
piece->setPos( position.first, position.second );
|
|
}
|
|
}
|
|
void revert() {
|
|
for ( unsigned long i = 0; i < pieces.size(); i++ ) {
|
|
auto &piece = pieces[i];
|
|
auto &positions = pieces_rel_position[i];
|
|
piece->setPos( original_pos[i].first, original_pos[i].second );
|
|
auto top = positions[1];
|
|
auto bottom = positions[0];
|
|
positions[1] = positions[3];
|
|
positions[0] = positions[2];
|
|
positions[2] = top;
|
|
positions[3] = bottom;
|
|
}
|
|
}
|
|
std::vector< std::shared_ptr< TetrisBlock > > &getObjects() {
|
|
return pieces;
|
|
}
|
|
void setPos( double x, double y ) {
|
|
for ( unsigned long i = 0; i < pieces.size(); i++ ) {
|
|
auto &piece = pieces[i];
|
|
auto &positions = pieces_rel_position[i];
|
|
std::pair< double, double > pos = { x, y };
|
|
pos.first -= positions[0] * BLOCK_SIZE;
|
|
pos.first += positions[1] * BLOCK_SIZE;
|
|
pos.second -= positions[2] * BLOCK_SIZE;
|
|
pos.second += positions[3] * BLOCK_SIZE;
|
|
piece->setPos( pos.first, pos.second );
|
|
}
|
|
}
|
|
void setPos( const std::pair< double, double > &pos ) {
|
|
setPos( pos.first, pos.second );
|
|
}
|
|
std::pair< double, double > getPos() {
|
|
auto &piece = pieces[0];
|
|
auto &relpositions = pieces_rel_position[0];
|
|
auto pos = piece->getPos();
|
|
pos.first += relpositions[0] * BLOCK_SIZE;
|
|
pos.first -= relpositions[1] * BLOCK_SIZE;
|
|
pos.second += relpositions[2] * BLOCK_SIZE;
|
|
pos.second -= relpositions[3] * BLOCK_SIZE;
|
|
return pos;
|
|
}
|
|
void clear() {
|
|
pieces.clear();
|
|
pieces_rel_position.clear();
|
|
}
|
|
void startDescend() {
|
|
descend = true;
|
|
}
|
|
void stopDescend() {
|
|
descend = false;
|
|
}
|
|
void startMovement() {
|
|
userMovement += 1;
|
|
}
|
|
void stopMovement() {
|
|
userMovement -= 1;
|
|
}
|
|
bool isDescending() {
|
|
return descend;
|
|
}
|
|
bool isMoving() {
|
|
return userMovement > 0;
|
|
}
|
|
bool isLeft( const SDLPP::RenderObject &block ) const {
|
|
return isPosition( block, 0 );
|
|
}
|
|
bool isRight( const SDLPP::RenderObject &block ) const {
|
|
return isPosition( block, 1 );
|
|
}
|
|
void movePiece( double x, double y ) {
|
|
for ( auto &block : getObjects() ) {
|
|
auto pos = block->getPos();
|
|
block->setPos( pos.first + x, pos.second + y );
|
|
}
|
|
}
|
|
void disableRotation() {
|
|
rotate_allowed = false;
|
|
}
|
|
|
|
void turnIntoShadow() {
|
|
for ( auto &block : getObjects() )
|
|
block->turnIntoShadow();
|
|
setHidden( !g_show_shadow );
|
|
}
|
|
std::shared_ptr< TetrisPiece > copySelf() {
|
|
auto ret = std::make_shared< TetrisPiece >();
|
|
for ( int i = 0; i < 4; i++ ) {
|
|
auto block = pieces[i]->copyInScene();
|
|
block->centerX();
|
|
ret->addBlockInPos( block, pieces_rel_position[i] );
|
|
}
|
|
if ( !rotate_allowed )
|
|
ret->disableRotation();
|
|
ret->setHidden( _hidden );
|
|
return ret;
|
|
}
|
|
void destroy() {
|
|
for ( auto &x : getObjects() ) {
|
|
x->destroy();
|
|
}
|
|
}
|
|
void addMovement( int x, int y ) {
|
|
movement.first += x;
|
|
movement.second += y;
|
|
}
|
|
std::pair< int, int > getMovement() const {
|
|
return movement;
|
|
}
|
|
void setHidden( bool hidden ) {
|
|
_hidden = hidden;
|
|
for ( auto &x : getObjects() ) {
|
|
x->setHidden( hidden );
|
|
}
|
|
}
|
|
bool getHidden() {
|
|
return _hidden;
|
|
}
|
|
|
|
private:
|
|
bool isPosition( const SDLPP::RenderObject &block, int pos ) const {
|
|
for ( int i = 0; i < 4; i++ ) {
|
|
if ( pieces[i]->isSamePos( block ) ) {
|
|
return pieces_rel_position[i][pos] != 0;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
void resetBlock( int index, std::shared_ptr< TetrisBlock > piece ) {
|
|
piece->setPos( pieces[index]->getPos() );
|
|
pieces[index] = piece;
|
|
}
|
|
void addBlockInPos( std::shared_ptr< TetrisBlock > piece,
|
|
const std::vector< int > &relpos ) {
|
|
pieces.push_back( piece );
|
|
pieces_rel_position.push_back( relpos );
|
|
}
|
|
std::vector< std::vector< int > > pieces_rel_position;
|
|
std::vector< std::shared_ptr< TetrisBlock > > pieces;
|
|
std::vector< std::pair< double, double > > original_pos;
|
|
bool descend = false;
|
|
int userMovement = 0;
|
|
bool rotate_allowed = true;
|
|
std::pair< int, int > movement = { 0, 0 };
|
|
bool _hidden = false;
|
|
};
|
|
|
|
#endif
|