# Implementing grid based selection box

What is a good way of implementing a RTS selection box for tiles on a grid? I'm making a game with some similarities to Evil Genius, the building in particular. In that game you click one place, drag the cursor somewhere else and something similar to the GIF below shows.

To do so a grid and a way of translating mousePosition to the correct cell is needed. Then a set of for loops (one for x and one for y) for executing the necessary action on each cell. My main problem is accounting for the direction of dragging, and in particular when shrinking. My current solution (hastebin here) is rather crude, and I would like a more elegant solution for a more civilized age. Hopefully someone else can think of a easier way of accounting for drag direction, I surely can't.

Any help appreciated.

• Because your selection volume isn't one prefab, but several, I think the way you're doing it is going to be pretty darn close to the best you're going to get: creating a list of the current prefabs and calculating the difference between the need and have, and spawning new ones or destroying old ones as needed. You should be able to do it just based off the mouse coords, rather than having to predict the drag direction. – Draco18s no longer trusts SE Dec 11 '15 at 15:02
• I don't see how I can do this just based on mouse coordinates. – larsekje Dec 11 '15 at 15:41
• Well, if you save where the mouse started and compare to where the mouse is, that gives you a rectangular area, doesn't it? – Draco18s no longer trusts SE Dec 11 '15 at 15:58
• Yes, but I don't see how I can use the rectangular area to access each cell within said area. – larsekje Dec 11 '15 at 16:05
• Your starting coordinates are just offsets to variables used in a standard for loop. – Draco18s no longer trusts SE Dec 11 '15 at 16:10

The approach I would take is to track the selected squares and only add/remove squares as necessary when the drag-to location changes.

On option to making that efficient is a data structure which has good insertion and deletion times such as a R-B tree.

Another option is to maintain the selection in duplicate storage, one in row vector form and one in column vector form. This might be better because as you move you will always be losing or adding a row or column segment, assuming you can transform one to the other efficiently.

Another option is to use an interval tree to track the selected zones.

For anyone interested, here is the solution I (with great help from Draco18s) came up with:

void SelectionBox() {

//Get end position
Vector3 endCoordinate = FindCoordinate(FindHitPoint(), CellSize());
int xEnd = (int)endCoordinate.x;
int zEnd = (int)endCoordinate.z;

//Return if no change in mouse position
if (previousX == xEnd && previousZ == zEnd) return;

temporarySelectedCells.Clear();

//Get corners of selection rectangle
int left, right, bottom, top;

if (xStart > xEnd) {
left = xEnd;
right = xStart;
} else if (xStart < xEnd) {
left = xStart;
right = xEnd;
} else {
left = xEnd;
right = left;
}

if(zStart > zEnd) {
bottom = zEnd;
top = zStart;
} else if(zStart < zEnd) {
bottom = zStart;
top = zEnd;
} else {
bottom = zEnd;
top = bottom;
}

// Loop through selected cells and mark as selected
for(int x = left; x <= right; x++) {
for (int z = bottom; z <= top; z++) {
Cell cell = FindCell(x, z);

}
}

// Check if selected cells are still needed (inside selection rectangle)
for (int i = currentCells.Count - 1; i >= 0; i--) {
Cell cell = currentCells.ElementAt(i);
if (!temporarySelectedCells.Contains(cell)  && !selectedCells.Contains(cell)) {
RemoveFromSelection(cell);
}
}

//Set current position as previous for next frame
previousX = xEnd;
previousZ = zEnd;

}