RTS风格的拖动和选择系统

时间:2015-03-07 16:51:04

标签: c++ sdl drag-to-select

我正在尝试使用c ++和SDL2中的点击和拖动选择系统,就像实时策略游戏中使用的类型一样。单击鼠标并将其拖动到要选择的内容上。我该怎么做呢?

编辑:我知道如何处理鼠标输入。我使用Rect结构来跟踪选择区域的大小。但是,当区域正确绘制时,区域内的对象根本不会做出反应。但是,每次点击它们都可以正常工作。

我想我的问题是检查组选择与单个对象选择的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

您必须检查要拖动的矩形内部的内容(测试取决于所包含的形状)以及拖动这些形状以及

答案 1 :(得分:0)

我可以描述我是如何实现这一点的。

在事件处理例程中,执行类似下面的代码。我认为方法名称可以很好地解释发生了什么以及我是如何思考的(这是从我的基于SDL2的hobby-hack-RTS引擎中复制而来的):

        case SDL_MOUSEBUTTONDOWN:
        {
            // Calculate index, x and y for the tile that was clicked in the map.
            int iClick = m_Map.getTileIndex(event.button.x, event.button.y);
            if(iClick >= 0)
            {
                int xClick = m_Map.getTileX(iClick);
                int yClick = m_Map.getTileY(iClick);

                if((int)event.button.button == 1)
                {

                    // Unmark all MO..
                    for(std::list<MGMovingObject>::iterator it = m_MO.begin(); it != m_MO.end(); it++)
                    {
                        it->unMark();
                    }

                    activateFraming(event.button.x, event.button.y);
               }
               else
               {
                    ...
               }
           }
           break;
       }



        case SDL_MOUSEBUTTONUP:
        {
            if((int)event.button.button == 1)
            {
                int endClickX = m_Map.getTileX(m_Map.getTileIndex(getFrameEndX(), getFrameEndY()));
                int endClickY = m_Map.getTileY(m_Map.getTileIndex(getFrameEndX(), getFrameEndY()));
                int startClickX = m_Map.getTileX(m_Map.getTileIndex(getFrameStartX(), getFrameStartY()));
                int startClickY = m_Map.getTileY(m_Map.getTileIndex(getFrameStartX(), getFrameStartY()));
                if(endClickX > 0 && endClickY > 0 && startClickX > 0 && startClickY > 0)
                {
                    for(int x = std::min(startClickX, endClickX); x <= std::max(startClickX, endClickX); x++)
                    {
                        for(int y = std::min(startClickY, endClickY); y <= std::max(startClickY, endClickY); y++)
                        {
                            for(std::list<MGMovingObject>::iterator it = m_MO.begin(); it != m_MO.end(); it++)
                            {
                                if(it->getTileX() == x && it->getTileY() == y)
                                {
                                    it->mark();
                                }
                            }
                        }
                    }
                }
                deactivateFraming();
            }
            else
            {
                 ...
            }
            break;
       }

我的可选对象在std::list<MGMovingObject>中存储为m_MO

我的想法是保存选择框开始和选择框结束的图块坐标。然后我遍历可选对象并检测选择框内的对象。我选择这些(mark()),当我在稍后阶段迭代objsects时,比如在渲染期间,我可以读出它们是否被选中(isMarked())。

如果你想窃取代码或想法,这里是我复制的实际源文件:https://github.com/qmargyl/mgframework/blob/master/src/mgframework/mgframework.cpp