-1

I'm trying to make a click and drag selection system in c++ and SDL2 like the kind used in real time strategy games. You click with the mouse and drag it over what you want to select. How can I go about making it?

Edit: I know how to handle the mouse inputs. I have used a Rect structure to track the size of the selection zone. However while the zone draws correctly, the objects inside the zone don't react at all. However individually clicking on them works fine every time.

I guess my question is what is the best way to check for a group selection vs individual object selection?

AmeanGecko
  • 11
  • 1
  • Which part? Object representation? Interacting with the mouse in SDL2? Collision detection/selection? – genpfault Mar 07 '15 at 18:12
  • I got a Open Source RTS implemented in C++ with SDL2, if you want to take look at the source, this thing is already implemented to select multiple units. You can check my repo at : https://github.com/jordsti/LibreSTR and this is located in this file : https://github.com/jordsti/LibreSTR/blob/master/LibreSTR/GameState.cpp – jordsti Mar 09 '15 at 14:16
  • I wrote a tiny library just for this: https://github.com/jmmaunus/SDL2_extraevents In spirit of one-man open source projects written to scratch an itch, the documentation consists of a hastily written README and sparsely scattered comments in sources. Beware. – jaymmer - Reinstate Monica Mar 12 '15 at 12:59

2 Answers2

0

You have to check what's inside the rect you are gonna drag (the test depends on the shapes that are included) and the drag those shapes aswell

inusO
  • 1
  • 2
0

I can describe how i have implemented this.

In the event handling routine, do something like the code below. I think the method names explain quite well what's happening and how i'm thinking (this is copied from my hobby-hack-RTS-engine which is based on SDL2):

        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;
       }

My selectable objects are stored as std::list<MGMovingObject> in m_MO.

The idea is that i save tile coordinates of the start of the selection frame and the end of the selection frame. I then iterate over the selectable objects and detect the ones inside the selection frame. I select these (mark()) and when i iterate over the objsects at a later stage, say during rendering, i can read out if they are selected (isMarked()).

If you want to steal code or ideas, here is the actual source file i copied it from: https://github.com/qmargyl/mgframework/blob/master/src/mgframework/mgframework.cpp

Martin G
  • 17,357
  • 9
  • 82
  • 98