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 Smile.

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:

calculation

… 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: , ,

8 Responses to “Simple drag and drop with snap-to-tiles in XNA”

  1. Dnec Says:

    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?

  2. admin Says:

    Yup - sure, mail me and I'll take a look :)

    /Jake

  3. Tiwi Says:

    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 :)

  4. admin Says:

    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

  5. Tiwi Says:

    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... 😀

  6. admin Says:

    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

  7. repstyle Says:

    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 ?

  8. admin Says:

    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

Leave a Reply