The original selection box code had some problems and the issue dealt with the fact that your box is drawn as if the grid were a normal cartesian plane but the reality is that it is rotated 45 degrees clockwise. This creates oddity in the coordinates. For instance, which point is more to the "left"? You have to calculate based on "translated" coordinates to figure that out because just looking at only the x or only the y would give you inaccurate results. If you wanted the height of a box that is facing the user in the non-rotated view then you have to translate.
Here's a figure to show what I mean:
And now here is the updated code that draws the selection box properly to the correct size:
//get the bottom left corner and the top right corner based on the two locations std::pair<float,float> firstCorner = std::pair<float,float>(m_firstBoxCorner.first + m_firstBoxCorner.second, m_firstBoxCorner.second - m_firstBoxCorner.first); std::pair<float,float> secondCorner = std::pair<float,float>(m_mousePos.first + m_mousePos.second, m_mousePos.second - m_mousePos.first); float width = 0; float height = 0; if(firstCorner.first < secondCorner.first) { width = Ogre::Math::Abs((firstCorner.first - secondCorner.first) * Ogre::Math::Cos(Ogre::Degree(45))); } else { width = Ogre::Math::Abs(firstCorner.first - secondCorner.first) / 2; } if(firstCorner.second < secondCorner.second) { height = Ogre::Math::Abs((firstCorner.second - secondCorner.second) * Ogre::Math::Cos(Ogre::Degree(45))); } else { height = Ogre::Math::Abs(firstCorner.second - secondCorner.second) / 2; } float leftX = m_firstBoxCorner.first; float bottomY = m_firstBoxCorner.second; float rightX = m_mousePos.first; float topY = m_mousePos.second; //secondCorner is left of firstCorner if (secondCorner.first < firstCorner.first) { //move right rightX += width; topY += width; //move left leftX -= width; bottomY -= width; } //secondCorner is below firstCorner if (secondCorner.second < firstCorner.second) { //move up rightX -= height; topY += height; //move down leftX += height; bottomY -= height; } std::pair<float,float> lowerLeftCorner = std::pair<float,float>(leftX / UNIT_DISTANCE, bottomY / UNIT_DISTANCE); std::pair<float,float> topRightCorner = std::pair<float,float>(rightX / UNIT_DISTANCE, topY / UNIT_DISTANCE);
We can use the same logic to figure out the two corners and feed that into our unit selection code. But for unit selection itself there's an additional step which I will call "square picking". Based on the two corners (bottom left and top right) it needs to "pick" the squares that were selected. The issue arises when we get to really small selections, the square picking is much more apparent. Let's take a look at this example:
Maybe in the future I'll implement "fuzziness" to the edges of the selection. Players might not expect that the instant the box touches a square that it selects it. There may be some other "one off" box selection problems but for now I'll move onto context-sensitive right-click. Let's move some units around!
No comments:
Post a Comment