Improve piece animation code

This commit is contained in:
Loic Guegan 2022-12-29 13:00:23 +01:00
parent aa94a41353
commit fdab451352
2 changed files with 52 additions and 47 deletions

View file

@ -4,20 +4,21 @@ wxDEFINE_EVENT(PLAY_MOVE_EVENT, wxCommandEvent);
BoardCanvas::BoardCanvas(wxFrame *parent) BoardCanvas::BoardCanvas(wxFrame *parent)
: wxPanel(parent), black_side(false), is_black_turn(true), frozen(false), : wxPanel(parent), black_side(false), is_black_turn(true), frozen(false),
lock_square_size(false), t(new Theme()), t_captures(new Theme()), buffer(nullptr) { lock_square_size(false), t(new Theme()), t_captures(new Theme()) {
board = "rnbqkbnrpppppppp PPPPPPPPRNBQKBNR"; board = "rnbqkbnrpppppppp PPPPPPPPRNBQKBNR";
is_dragging = false; is_dragging = false;
valid_drag = false; valid_drag = false;
reuseBuffer=false; adata.reuseBuffer=false;
adata.buffer=nullptr;
t_captures->ResizePieces(t->GetPiecesSizes() * CAPTURE_FACTOR); t_captures->ResizePieces(t->GetPiecesSizes() * CAPTURE_FACTOR);
SetClockTime(-1, -1, -1, false); SetClockTime(-1, -1, -1, false);
SetClockTime(-1, -1, -1, true); SetClockTime(-1, -1, -1, true);
ApplyPreferences(); ApplyPreferences();
// The following should be called when using an EVT_PAINT handler // The following should be called when using an EVT_PAINT handler
SetBackgroundStyle(wxBG_STYLE_PAINT); SetBackgroundStyle(wxBG_STYLE_PAINT);
duration=200; adata.duration=200;
duration_fast=80; adata.duration_fast=80;
fps=30; adata.fps=30;
Bind(wxEVT_KEY_DOWN, [p=this](wxKeyEvent &e){e.ResumePropagation(1);e.Skip();}); Bind(wxEVT_KEY_DOWN, [p=this](wxKeyEvent &e){e.ResumePropagation(1);e.Skip();});
Bind(wxEVT_KEY_UP, [p=this](wxKeyEvent &e){e.ResumePropagation(1);e.Skip();}); Bind(wxEVT_KEY_UP, [p=this](wxKeyEvent &e){e.ResumePropagation(1);e.Skip();});
@ -42,7 +43,7 @@ void BoardCanvas::OnPaint(wxPaintEvent &event) {
dc.SetBackground(*wxWHITE_BRUSH); dc.SetBackground(*wxWHITE_BRUSH);
dc.Clear(); dc.Clear();
if(!reuseBuffer){ if(!adata.reuseBuffer){
// Setting up required attributes // Setting up required attributes
REFRESH_MOUSE_LOCATION(); REFRESH_MOUSE_LOCATION();
square_width = t->GetSquaresSizes(); square_width = t->GetSquaresSizes();
@ -55,27 +56,27 @@ void BoardCanvas::OnPaint(wxPaintEvent &event) {
boardY = 0; boardY = 0;
// Setup buffer (later use for animations) // Setup buffer (later use for animations)
if(buffer!=nullptr) if(adata.buffer!=nullptr)
free(buffer); free(adata.buffer);
buffer=new wxBitmap(canvas_size.x,canvas_size.y,32); adata.buffer=new wxBitmap(canvas_size.x,canvas_size.y,32);
wxMemoryDC memDC(*buffer); wxMemoryDC memDC(*adata.buffer);
DrawBoard(memDC); DrawBoard(memDC);
dc.Blit(0,0,canvas_size.x,canvas_size.y,(wxDC*)&memDC,0,0); dc.Blit(0,0,canvas_size.x,canvas_size.y,(wxDC*)&memDC,0,0);
} }
else { else {
// Otherwise reuse buffer and animate. TEST CODE FOR NOW: // Otherwise reuse buffer and animate. TEST CODE FOR NOW:
dc.DrawBitmap(*buffer, 0, 0, true); dc.DrawBitmap(*adata.buffer, 0, 0, true);
double frames=duration/(1000/fps); double frames=adata.duration/(1000/adata.fps);
double percent=frame/frames; double percent=adata.frame/frames;
// Draw moving piece // Draw moving piece
dc.DrawBitmap(*t->Get(piece_moved), dc.DrawBitmap(*t->Get(adata.piece_moved),
src.x + frame*(transVect.x/frames), adata.src.x + adata.frame*(adata.transVect.x/frames),
src.y + frame*(transVect.y/frames), false); adata.src.y + adata.frame*(adata.transVect.y/frames), false);
// end drawing // end drawing
frame++; adata.frame++;
if(frame>=frames){ if(adata.frame>=frames){
reuseBuffer=false; adata.reuseBuffer=false;
SetupBoard(final_board, final_is_black_turn, final_captures); SetupBoard(adata.final_board, adata.final_is_black_turn, adata.final_captures);
} }
} }
} }
@ -111,17 +112,17 @@ void BoardCanvas::SetupBoard(std::string board, bool is_black_turn,
} }
void BoardCanvas::Animate(std::string board, bool is_black_turn, std::map<char, std::uint8_t> captures, std::string src, std::string dst,bool faster){ void BoardCanvas::Animate(std::string board, bool is_black_turn, std::map<char, std::uint8_t> captures, std::string src, std::string dst,bool faster){
this->final_board=board; adata.final_board=board;
this->final_is_black_turn=is_black_turn; adata.final_is_black_turn=is_black_turn;
this->final_captures=captures; adata.final_captures=captures;
std::uint8_t pfile = src[0]-'a'; std::uint8_t pfile = src[0]-'a';
std::uint8_t prank = src[1]-'1'; std::uint8_t prank = src[1]-'1';
this->piece_moved = this->board[pfile + 8 * (7-prank)]; // Piece to move adata.piece_moved = this->board[pfile + 8 * (7-prank)]; // Piece to move
// Now remove the piece that will be moved // Now remove the piece that will be moved
this->board[pfile + 8 * (7-prank)]=' '; this->board[pfile + 8 * (7-prank)]=' ';
wxMemoryDC memDC(*buffer); wxMemoryDC memDC(*adata.buffer);
DrawBoard(memDC); DrawBoard(memDC);
// Now compute piece start position and translation vector (Copy paste from DrawBoard()) // Now compute piece start position and translation vector (Copy paste from DrawBoard())
@ -133,8 +134,8 @@ void BoardCanvas::Animate(std::string board, bool is_black_turn, std::map<char,
} }
std::uint32_t x = boardX + (7 - pfile) * square_width; std::uint32_t x = boardX + (7 - pfile) * square_width;
std::uint32_t y = boardY + prank * square_width; std::uint32_t y = boardY + prank * square_width;
this->src.x = x + centrer_offset; adata.src.x = x + centrer_offset;
this->src.y = y + centrer_offset; adata.src.y = y + centrer_offset;
// Now dst: // Now dst:
pfile = dst[0]-'a'; pfile = dst[0]-'a';
prank = dst[1]-'1'; prank = dst[1]-'1';
@ -144,16 +145,16 @@ void BoardCanvas::Animate(std::string board, bool is_black_turn, std::map<char,
} }
x = boardX + (7 - pfile) * square_width; x = boardX + (7 - pfile) * square_width;
y = boardY + prank * square_width; y = boardY + prank * square_width;
transVect.x=x-this->src.x+centrer_offset; adata.transVect.x=x-adata.src.x+centrer_offset;
transVect.y=y-this->src.y+centrer_offset; adata.transVect.y=y-adata.src.y+centrer_offset;
// Start animation: // Start animation:
reuseBuffer=true; adata.reuseBuffer=true;
int duration_backup=duration; int duration_backup=adata.duration;
duration=faster ? duration_fast : duration; adata.duration=faster ? adata.duration_fast : adata.duration;
frame=0; adata.frame=0;
int frames=duration/(1000/fps); // total number of frames int frames=adata.duration/(1000/adata.fps); // total number of frames
int time_per_frame=duration/frames; int time_per_frame=adata.duration/frames;
wxStopWatch sw; wxStopWatch sw;
for(int i=frames;i>0;i--){ for(int i=frames;i>0;i--){
Refresh(); Refresh();
@ -164,8 +165,8 @@ void BoardCanvas::Animate(std::string board, bool is_black_turn, std::map<char,
} }
sw.Start(0); sw.Start(0);
} }
duration=faster ? duration_backup : duration_backup; adata.duration=faster ? duration_backup : duration_backup;
reuseBuffer=false; adata.reuseBuffer=false;
} }
void BoardCanvas::DrawBoard(wxDC &dc) { void BoardCanvas::DrawBoard(wxDC &dc) {

View file

@ -40,6 +40,19 @@ wxDECLARE_EVENT(NEXT_MOVE_EVENT, wxCommandEvent);
typedef std::tuple<short, short, short> ClockTime; typedef std::tuple<short, short, short> ClockTime;
// Drawing buffer (ANIMATIONS)
typedef struct AnimState {
wxBitmap *buffer;
bool reuseBuffer;
int frame,duration,fps,duration_fast;
std::string final_board;
bool final_is_black_turn;
std::map<char, std::uint8_t> final_captures;
char piece_moved;
wxPoint src;
wxPoint transVect;
} AnimState;
class BoardCanvas : public wxPanel { class BoardCanvas : public wxPanel {
// *t is theme for board+pieces and // *t is theme for board+pieces and
// *t_captures is theme for captured pieces (scale down version of t) // *t_captures is theme for captured pieces (scale down version of t)
@ -57,16 +70,7 @@ class BoardCanvas : public wxPanel {
ClockTime black_time, white_time; ClockTime black_time, white_time;
bool frozen,lock_square_size; bool frozen,lock_square_size;
// Drawing buffer (ANIMATIONS) AnimState adata;
wxBitmap *buffer;
bool reuseBuffer;
int frame,duration,fps,duration_fast;
std::string final_board;
bool final_is_black_turn;
std::map<char, std::uint8_t> final_captures;
char piece_moved;
wxPoint src;
wxPoint transVect;
public: public:
BoardCanvas(wxFrame *parent); BoardCanvas(wxFrame *parent);