Simple drag and drop with snap-to-tiles in XNA
If you need to create a tile-based editor, or for some other reason need to show selected tiles based on the mouseposition – here’s some code to help you do that .
The most basic part of the code is figuring out what tile you are over by doing an integer division using the tile size. Let’s say your mouse is at (x=432,y=197) and each tile is 64x64 pixels. Which square is the mouse over?
well 432 / 64 = 6.75, but if this is done using two integers (int in C#), the decimal part is removed and we’re left with 6. The same with the y-part 197 / 64 = 3.078125 which is 3 without the decimal part.
Often however, you don’t want the map to start in the upper lefthand corner of the screen, so we need to subtract the position of the map from the coordinates.
This gives us something like this:
… where you subtract the top and left from the mouse’s coordinates before doing the integer division to find the square’s coordinates.
Here's the code above as a method which given the coordinates of the mouse, returns the row and column in the map:
//get the column/row on the board for a given coordinate Vector2 GetSquareFromPosition(Vector2 position) { //adjust for the boards offset (_boardPosition) and do an integerdivision return new Vector2( (int)(_mousePosition.X - _boardPosition.X) / _tileSize, (int)(_mousePosition.Y - _boardPosition.Y) / _tileSize); }
Another noteworthy codesample
Making a “chessboard” out of the same Texture2D by alternating based on whether the column + row of a square is even or odd (by using the modulus “%” operator).
The modulus operator gives what is left after an integer division, so if you take an even number modulo 2 the remainder is zero, the remainder of an odd number modulo 2 is one.
float opacity = 1f; //if we add the x and y value of the tile //and it is even, we make it one third opaque if ((x + y) % 2 == 0) { opacity = .33f; } else { //otherwise it is one tenth opaque opacity = .1f; } //draw the white square at the given position, //offset by the x- and y-offset, in the opacity desired spriteBatch.Draw(_whiteSquare, squareToDrawPosition, Color.White * opacity);
You can find the code here
Tags: drag and drop, snap, tiles
December 26th, 2012 at 15:26
Good tutorial Kr@rup.dk. I have some doubts about the code.
As much as we have strictly followed your tutorial I cant run correctly the program.
I can drag the tiles, but I can not make it stay in the square. The red color does simple not appear. I can send my source, for you take a look?
December 27th, 2012 at 22:08
Yup - sure, mail me and I'll take a look
/Jake
June 24th, 2013 at 09:02
hi..i am a new learner of xna game studio and i've learn to drag and drop a multiple images..
how can i make a code to drag and drop some images in this source code?
or in this code just can to drag and drop only one images?
thanks for your help
June 24th, 2013 at 09:23
Hi Tiwi
How would you like to select those multiple images?
Clicking on each of them to add them to the selected images, or drag a selection rectangle around them?
Write a bit more and I'll see if I can come up with some help for you
Kind regards - Jakob
June 25th, 2013 at 03:09
i want to clicking on each of them to add them to the selected images...
it's like a mini market game, there are some goods... i choose the goods and put it in the basket...
how can i make the code like that?
thanks before... 😀
June 25th, 2013 at 06:46
Hi Tiwi
You could solve it this way:
- have a list of all selectable items in the market (you probably already have this)
- when the user clicks the mouse, run through the list of items till you find the item hit (or none, in which case you do nothing :))
- if the user clicked an item:
- toggle the item's "Selected" property (something you need to code yourself)
- maybe alter the drawing of the items when they are selected. Put a border on them, or something like that?
- have a list of selected items which you add the selected items to when you select them, and remove the items from when you deselect them
- if the user starts dragging (moving the mouse while the mousebutton is down on top of an item), in every Update() move all the items in the "selected list" the same amount as the mouse has moved since last Update (store the old mouse position at the end of every Update(), so you can calculate the change in movement).
- when the user releases the mousebutton, check to see where that is, and if it is in an "action area" (e.g. Shopping basket, sell area, etc.) then perform the needed action. If releasing the items in an invalid location should result in the items returning to their original position, then you will need to store their original position somewhere as well
Note: if your items can overlap you will need to search down through them for mouseclicks from the opposite end of the list as the direction you are drawing them in. So the last drawn (the ones visually on top) will be the first to be hit with the mouse.
Hope this helps!
Kind regards - Jakob
February 10th, 2015 at 20:23
Hello, thnaks for this tutorial but i don't understand how you create and use the grid shown in the video. Can you explain it ?
March 12th, 2015 at 08:22
Hi Ludo
If you read the article to its end, you'll see that the code to make the chess board is under the heading: "Another noteworthy codesample".
If that doesn't make sense, just ask again :).
Kind regards - Jakob