GameTestLib/Tetris/Figuras/Base.mqh
2025-11-14 17:18:48 -05:00

273 lines
8.3 KiB
MQL5

//+------------------------------------------------------------------+
//| Base.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com/es/users/nique_372/news |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Niquel Mendoza."
#property link "https://www.mql5.com/es/users/nique_372/news"
#property strict
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "..\\..\\..\\GrapichsByLeo\\General\\Canvas.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum ENUM_TETRIS_FIGURA_TYPE
{
TETRIS_FIGURA_CUADRADO,
TETRIS_FIGURA_L,
TETRIS_FIGURA_BARRA,
TETRIS_FIGURA_ESCALERA,
};
enum ENUM_TETRIS_FIGURA_POSITION
{
TETRIS_FIG_POS_INICIAL = 0,
TETRIS_FIG_POS_90 = 90,
TETRIS_FIG_POS_180 = 180,
TETRIS_FIG_POS_270 = 270
};
enum ENUM_TETRIS_DIR
{
TETRIS_DIR_ARRIBA = 0,
TETRIS_DIR_ABAJO = 1,
TETRIS_DIR_DERECHA = 2,
TETRIS_DIR_IZQUIERDA = 3
};
enum EMUM_TETRIS_DIR_SENT_Y
{
TETRIS_DIR_Y_ARRIBA = 0,
TETRIS_DIR_Y_ABAJO = 1,
};
enum EMUM_TETRIS_DIR_SENT_X
{
TETRIS_DIR_X_IZQUIERDA = 0,
TETRIS_DIR_X_DERECHA = 1,
};
#define TETRIS_FLAG_COLISION_END 1
#define TETRIS_FLAG_COLISION_INIT 2
/*
x1 x2
y1 y1
y2 y2
x1 x2
*/
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CTetrisFigura
{
protected:
bool m_init;
CCanvasCustom* m_canvas;
int m_width;
uint m_clr_clean;
uint m_color;
ENUM_TETRIS_FIGURA_POSITION m_position;
int m_x1;
int m_y1;
int m_x2;
int m_y2;
uint8_t m_flags_seccion;
//---
virtual void Draw() = 0;
public:
CTetrisFigura(void);
// ~CTetrisFigura(void);
//---
void Init(int x1, int y1, int x2, int y2, CCanvasCustom* c, uint clr_clean, uint clr);
//--- General
virtual void CleanPixles() = 0;
//--- Cordenadas
void Move(int x1, int y1, int x2, int y2);
void ChangeY2(int new_y2);
void ChangeY(int new_y1);
void ChangeX(int new_x1);
inline int X1() const { return m_x1; }
inline int Y1() const { return m_y1; }
inline int X2() const { return m_x2; }
inline int Y2() const { return m_y2; }
//--- aqui a tener en cuneta que seria -1, osea no el alto como tal... no el espacio en peixles si no la distanica
__forceinline int DistY() const { return fabs(m_y2 - m_y1); }
__forceinline int DistX() const { return fabs(m_x2 - m_x1); }
//--- Color
__forceinline uint Color() const { return m_color; }
void Color(uint new_clr);
//--- Tipo
virtual inline ENUM_TETRIS_FIGURA_TYPE Type() const = 0;
//--- Rotacion
// Rota a la siguiente posicion
ENUM_TETRIS_FIGURA_POSITION NextRotate();
// Rotacion custom
virtual void Rotate(ENUM_TETRIS_FIGURA_POSITION pos) = 0;
//--- Colision
bool Colisiona(int x, int y);
virtual bool Colisiona(ENUM_TETRIS_DIR direcicon_preferida, int x, int y) = 0;
//--- Pixeles ocupaods
virtual void GetOcupatePixels(int& pixels_pos[]) = 0;
virtual void GetOcupatePixels(ENUM_TETRIS_DIR direcicon, int& pixels_pos[]) = 0;
virtual void GetOcupatePixels(int y1, EMUM_TETRIS_DIR_SENT_Y y_direccion, int& pixels_pos[]) = 0;
virtual void GetOcupatePixels(int x1, EMUM_TETRIS_DIR_SENT_X x_direccion, int& pixels_pos[]) = 0;
//---
virtual int CalculateMinPixelsInYAbajo(int y, int& out_x) const = 0;
virtual int CalculateMinPixelsInYAbajo(int& out_x) const = 0;
//--- Colision ext
void FlagColisionEndAdd() { m_flags_seccion |= TETRIS_FLAG_COLISION_END; }
void FlagColisionEndRemove() { m_flags_seccion &= ~TETRIS_FLAG_COLISION_END; }
bool IsActiveColisionEnd() const { return (m_flags_seccion & TETRIS_FLAG_COLISION_END) != 0; }
void FlagColisionInitAdd() { m_flags_seccion |= TETRIS_FLAG_COLISION_INIT; }
void FlagColisionInitRemove() { m_flags_seccion &= ~TETRIS_FLAG_COLISION_INIT; }
bool IsActiveColisionInit() const { return (m_flags_seccion & TETRIS_FLAG_COLISION_INIT) != 0; }
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CTetrisFigura::CTetrisFigura(void)
: m_canvas(NULL), m_init(false), m_flags_seccion(0)
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTetrisFigura::Init(int x1, int y1, int x2, int y2, CCanvasCustom *c, uint clr_clean, uint clr)
{
if(m_init)
return;
m_x1 = x1;
m_x2 = x2;
m_y1 = y1;
m_y2 = y2;
m_canvas = c;
m_width = c.Width();
m_clr_clean = clr_clean;
m_color = clr;
m_init = true;
//---
Draw();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTetrisFigura::Move(int x1, int y1, int x2, int y2)
{
CleanPixles();
m_x1 = x1;
m_x2 = x2;
m_y1 = y1;
m_y2 = y2;
Draw();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTetrisFigura::ChangeY2(int new_y2)
{
CleanPixles();
m_y2 = new_y2;
Draw();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTetrisFigura::ChangeY(int new_y1)
{
CleanPixles();
const int y_size = fabs(m_y2 - m_y1);
m_y1 = new_y1;
m_y2 = m_y1 + y_size;
Draw();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTetrisFigura::ChangeX(int new_x1)
{
CleanPixles();
const int x_size = fabs(m_x2 - m_x1);
m_x1 = new_x1;
m_x2 = m_x1 + x_size;
Draw();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CTetrisFigura::Color(uint new_clr)
{
CleanPixles();
m_color = new_clr;
Draw();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ENUM_TETRIS_FIGURA_POSITION CTetrisFigura::NextRotate(void)
{
const int new_pos = m_position + 90; // Siguyiente posicion
m_position = ENUM_TETRIS_FIGURA_POSITION(new_pos % 360); // Modulo de 360, 0-90-180-270
Rotate(m_position);
return m_position;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CTetrisFigura::Colisiona(int x, int y)
{
for(int i = 0; i < 4; i++)
if(Colisiona(ENUM_TETRIS_DIR(i), x, y))
return true;
return false;
}
//+------------------------------------------------------------------+