diff --git a/src/game_tab/left_panel/board/BoardCanvas.cpp b/src/game_tab/left_panel/board/BoardCanvas.cpp index 119c270..eabc615 100644 --- a/src/game_tab/left_panel/board/BoardCanvas.cpp +++ b/src/game_tab/left_panel/board/BoardCanvas.cpp @@ -3,8 +3,10 @@ #define TRANS(PT) { \ wxPoint2DDouble tmp((PT).x,(PT).y); \ tmp=rot_m.TransformPoint(tmp); \ -tmp=trans_m.TransformPoint(tmp); \ -(PT).x=tmp.m_x;(PT).y=tmp.m_y;} +(PT).x=tmp.m_x+xsrc;(PT).y=tmp.m_y+ysrc;} + +#define TRANS2(PT) { \ +(PT).x+=xsrc;(PT).y+=ysrc;} wxDEFINE_EVENT(PLAY_MOVE_EVENT, wxCommandEvent); @@ -140,6 +142,7 @@ void BoardCanvas::SetupBoard(const GameState &new_gs) { gs.black_time=new_gs.black_time; gs.white_time=new_gs.white_time; gs.squares_hl=new_gs.squares_hl; + gs.arrows=new_gs.arrows; Refresh(); } @@ -155,7 +158,7 @@ void BoardCanvas::Animate(const GameState &new_gs, const std::string &src, const // Now compute piece start position and translation vector std::uint32_t centrer_offset = (square_width - piece_width) / 2; - if (!black_side) { + if (!black_side) { prank = 7 - prank; pfile = 7 - pfile; } @@ -393,6 +396,35 @@ void BoardCanvas::DrawBoard(wxDC &dc) { dc.DrawText(time, wxPoint(boardX + square_width * 8 - width, boardY + square_width * 8 + numbers_size.y*2)); } + // Draw arrows + for(const std::string arrow: gs.arrows){ + std::uint8_t sfile = arrow[0]-'a'; + std::uint8_t srank = arrow[1]-'1'; + std::uint8_t dfile = arrow[2]-'a'; + std::uint8_t drank = arrow[3]-'1'; + if (!black_side) { + srank = 7 - srank; + sfile = 7 - sfile; + drank = 7 - drank; + dfile = 7 - dfile; + } + std::uint32_t sx = boardX + (7 - sfile) * square_width + square_width/2; + std::uint32_t sy = boardY + srank * square_width + square_width/2; + std::uint32_t dx = boardX + (7 - dfile) * square_width + square_width/2; + std::uint32_t dy = boardY + drank * square_width + square_width/2; + + if(((abs(drank-srank) == 2) && (abs(dfile-sfile) == 1))|| + ((abs(drank-srank) == 1) && (abs(dfile-sfile) == 2))){ + if(abs(drank-srank) == 1){ + DrawLArrow(dc,sx,sy,dx,dy); + } + else { + DrawLArrow(dc,sx,sy,dx,dy,true); + } + } else { + DrawArrow(dc,sx,sy,dx,dy); + } + } } void BoardCanvas::MouseEvent(wxMouseEvent &event) { @@ -472,7 +504,7 @@ void BoardCanvas::SetClockTime(short hours, short min, short sec, void BoardCanvas::DrawArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst){ // Compute arrow length and angle wxPoint vect(xdst-xsrc,ydst-ysrc); - double length=sqrt(pow(vect.x,2)+pow(vect.y,2)); + double length=ceil(sqrt(pow(vect.x,2)+pow(vect.y,2))); double angle=acos(vect.x/length); // Compute metrics @@ -481,9 +513,8 @@ void BoardCanvas::DrawArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst){ std::uint32_t tail_length=length-tip_height; // Setup transform matrix - wxAffineMatrix2D rot_m,trans_m; - rot_m.Rotate(angle); - trans_m.Translate(xsrc,ysrc); + wxAffineMatrix2D rot_m; + rot_m.Rotate(-angle); // Init polygons wxPoint tip[]={wxPoint(tail_length,-thickness/2),wxPoint(tail_length,thickness/2),wxPoint(tail_length+tip_height,0)}; @@ -499,3 +530,58 @@ void BoardCanvas::DrawArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst){ dc.DrawPolygon(3,tip); dc.DrawPolygon(4,tail); } + +void BoardCanvas::DrawLArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst, bool flip){ + double X=xdst-xsrc; + double Y=ydst-ysrc; + + // Check if L arrows are required + if(X==0 || Y==0){ + DrawArrow(dc, xsrc, ysrc, xdst, ydst); + return; + } + + if(flip){ + // Compute metrics + std::uint8_t thickness=50; + double tip_height=sqrt(3)/2*thickness; + double yoffset=Y<0 ? -thickness/4 : thickness/4; // Y tail should be longer to form a right angle (corner of tail joins) + if(X<0){tip_height=-tip_height;} + wxPoint tip[]={wxPoint(X-tip_height,-thickness/2+Y),wxPoint(X,Y),wxPoint(X-tip_height,thickness/2+Y)}; + wxPoint tail1[]={wxPoint(-thickness/4,0),wxPoint(thickness/4,0),wxPoint(thickness/4,Y+yoffset),wxPoint(-thickness/4,Y+yoffset)}; + wxPoint tail2[]={wxPoint(0,Y-thickness/4),wxPoint(X-tip_height,Y-thickness/4),wxPoint(X-tip_height,Y+thickness/4),wxPoint(0,Y+thickness/4)}; + + // Apply transforms + TRANS2(tip[0]);TRANS2(tip[1]);TRANS2(tip[2]); + TRANS2(tail1[0]);TRANS2(tail1[1]);TRANS2(tail1[2]);TRANS2(tail1[3]); + TRANS2(tail2[0]);TRANS2(tail2[1]);TRANS2(tail2[2]);TRANS2(tail2[3]); + + // Draw + dc.SetPen(wxNullPen); + dc.SetBrush(wxColour(255,0,0)); + dc.DrawPolygon(4,tail1); + dc.DrawPolygon(4,tail2); + dc.DrawPolygon(3,tip); + } else { + // Compute metrics + std::uint8_t thickness=50; + double tip_height=sqrt(3)/2*thickness; + double xoffset=X<0 ? -thickness/4 : thickness/4; // Y tail should be longer to form a right angle (corner of tail joins) + if(Y<0){tip_height=-tip_height;} + wxPoint tip[]={wxPoint(-thickness/2 + X,Y-tip_height),wxPoint(thickness/2 + X ,Y-tip_height),wxPoint(X,Y)}; + wxPoint tail1[]={wxPoint(0,-thickness/4),wxPoint(X+xoffset,-thickness/4),wxPoint(X+xoffset,thickness/4),wxPoint(0,thickness/4)}; + wxPoint tail2[]={wxPoint(X-thickness/4,0),wxPoint(X+thickness/4,0),wxPoint(X+thickness/4,Y-tip_height),wxPoint(X-thickness/4,Y-tip_height)}; + + // Apply transforms + TRANS2(tip[0]);TRANS2(tip[1]);TRANS2(tip[2]); + TRANS2(tail1[0]);TRANS2(tail1[1]);TRANS2(tail1[2]);TRANS2(tail1[3]); + TRANS2(tail2[0]);TRANS2(tail2[1]);TRANS2(tail2[2]);TRANS2(tail2[3]); + + // Draw + dc.SetPen(wxNullPen); + dc.SetBrush(wxColour(255,0,0)); + dc.DrawPolygon(4,tail1); + dc.DrawPolygon(4,tail2); + dc.DrawPolygon(3,tip); + } +} diff --git a/src/game_tab/left_panel/board/BoardCanvas.hpp b/src/game_tab/left_panel/board/BoardCanvas.hpp index ddab72b..946711f 100644 --- a/src/game_tab/left_panel/board/BoardCanvas.hpp +++ b/src/game_tab/left_panel/board/BoardCanvas.hpp @@ -64,6 +64,7 @@ typedef struct GameState { std::string board; std::map captures; std::vector squares_hl; + std::vector arrows; bool is_black_turn; bool mat_black; bool mat_white; @@ -93,6 +94,8 @@ class BoardCanvas : public wxPanel { /// @brief Draw an arrow from a source point to a destination point on DC void DrawArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst); + /// @brief Draw an arrow with a L shape (such as knight moves) + void DrawLArrow(wxDC &dc, int xsrc, int ysrc, int xdst, int ydst, bool flip=false); public: BoardCanvas(wxFrame *parent);