Moving image based on mouse click/drag...

IfYouSaySo

Well-known member
Joined
Jan 4, 2006
Messages
102
Location
Hermosa Beach, CA
Programming Experience
3-5
Ok, still working on my chessboard control, and another issue comes up. When the user clicks on a chesspiece and drags it to a new square, I want to animate that. So what I did is, I made a handler for mouse-down, mouse-up, and mouse-move. On mouse down, I populate what I call a drag-image and put what it's coordinates are at. On mouse-move, I update the drag-image's coordinates and call Invalidate() against the control. And in mouse down I set the image into whatever the destination square I am sitting over and clear out the drag-image. The Paint code just paints the drag-image at whatever location it is currently at. This works...SORT OF. The problem is if I simply call Me.Invalidate() in mouse-move handler, the drawing seems pretty slow. Like if I move a piece very quickly, there is a noticable delay before the piece catches up with the mouse. If I call Me.Invalidate(rect) where rect is the space occupied by the image, it is somewhat better in terms of responsiveness, but now if I move the mouse quickly, the clip rectangle doesn't catch everything to redraw...so you see parts of the image left behind where it was moved over. And yes, I'm using double buffer....

Hope that makes sense. Does anyone have any ideas?
 
I think it would be better if you used only one picturebox control displaying the board, and its Paint event to draw the pieces at their current location. I have posted a project that show this basic interactive graphics concept here. In your case you don't have 3 circles but instead 16 images each player to manage. The hittest and dragging of these graphical object is the same as the circles. You also have to define the board squares and hittest against this matrix for allowed moves and more accurate dropping of the pieces if needed.
 
John,

Thanks for the reply. I'll check out your sample, but I think I'm already doing what you suggest. I have a UserControl and the entire board is custom drawn in the Paint handler with the Graphics object and double-buffering. There two square images, one for light square, and one for dark square. There is one image for each of Knight, Rook, Bishop, Pawn, King, Queen. I have the board drawing OK with pieces on it. No flicker or anything. The pieces move with animation, again no flicker.

The problem is that it seems somewhat slow in drawing when I move the piece from square to square. I have seen other chessboard controls, and the drawing when I move a piece is lightening-fast on those controls. So I wonder what I am doing wrong.

I am wondering about the technique of handling MouseDown/MouseUp/MouseMove events and Invalidating the control in each handler to update the display. Is this the wrong way? Is there a better way? Why is the drawing so slow?

I guess I could use DirectInput and DirectDraw, but I have a hard time believing that GDI+ is insufficient for something as normal as what I'm trying to do.
 
I think drawing the board to an image and display it as background will not make as much drawing flicker.

Mousemove code is executed every little pixel movement, in a split second you may move the mouse pointer just a small amount of 100 pixels and that would cause the code to run 100 times. You could here calculate how much movement there is before calling for refresh, also including the timespan in the algoritm, stuff that save CPU time without loosing too much detail.

What you also can do instead of mousemove is to start a timer when mousedown on object and stop timer on mouseup. With timer event you can Invalidate/Refresh. This means the 'problem' cases of much movement or large movement is reduced to same amount of processing.
 
Well...the problem is not so much flicker (actually no flicker at all) as it is slowness to move the image that I am dragging. For example, I will mouse click down, and move quickly across the screen, and the mouse will be over the destination square that I want to drop into, and the image is still in it's original location. Then, once, the events start firing, the image zooms and catches up with the cursor very quickly. So not sure what that is. FWIW, I tried reducing the number of mouse-move events that actually do a draw, and I really didn't see any difference, except that when the image did move, it was jumping around more.
 
I'd still suggest the same thing. It's slow because it has to redraw the whole board the way you have it now. If you set the board as form background, it should make it faster.

It seems to me that painting on a timer would only make the form repaint less fluid and smooth.
 
Thanks guys...that worked. So what I was doing to reiterate, is I had an array of 64 squares, and in the draw function I was doing

VB.NET:
For Each square in Squares
    square.Draw(g)
Next

Which eventually resolves to g.DrawImage(theSquare). So I was calling DrawImage 64 times to draw the board. And as recommended I do that drawing once onto a single bitmap and then I only call DrawImage once to draw the board.

Moving the pieces around the board is very snappy now. Thanks again!
 
Back
Top