xhallix
xhallix

Reputation: 3011

c++ sdl draw dynamic rect based on mouse position

this might seem obvious to many, but I'm stuck and I cannot find any tutorial which helped me, so it would be great to find the answer here.

I tried to make a rectangle like you have in RTS games, so to speak a dynamic select box, but it does not work correctly. It would also be enough is someone lists up bullet points which each step for creating a box like this

(Don't wonder I'm really new to c++)

Mouse.h :

#ifndef MOUSE_H_
#define MOUSE_H_

class Mouse {

public:
    bool leftButtonDown = false;
    bool mouseMoves = false;

    struct MouseCoords {
        int x = -1;
        int y = -1;
    };

    MouseCoords start_coords;
    MouseCoords move_coords;
    Mouse(){}

    void setState(Uint32 eventType, SDL_Event event){

        if ( eventType == SDL_MOUSEBUTTONDOWN) {
            this->leftButtonDown = true;
            SDL_GetMouseState( &this->start_coords.x, &this->start_coords.y );
        }

        if ( eventType == SDL_MOUSEBUTTONUP ) {
            this->leftButtonDown = false;
        }

        if ( eventType == SDL_MOUSEMOTION ) {
            this->mouseMoves = true;
            this->move_coords.x = event.motion.x;
            this->move_coords.y = event.motion.y;
        } else {
            this->mouseMoves = false;
        }
    }

    /**
     * Provides coordinates when mousebutton down
     */
    MouseCoords getCoordinates(){
        return move_coords;
    }

    /**
     * Refresh the coordinates. MUST be called after Mouse::clearCoordinates();
     */
    void clearCoordinates(){
        this->move_coords.x = -1;
        this->move_coords.y = -1;

    }

    /**
     * Creates selector rect, call this in the render loop
     */
     void createSelectBox(SDL_Renderer *renderer){
         if(this->leftButtonDown) {
            Block rect(
                       this->start_coords.x, 
                       this->move_coords.y,
                       this->start_coords.y -this->move_coords.y ,
                       this->move_coords.x - this->start_coords.x
                       );
             rect.draw( renderer );
             this->clearCoordinates();
         }
     }
};

#endif

Block.h

#ifndef BLOCK_H_
#define BLOCK_H_
/**
 * Standard Class which can be used to build a player, enemy, or something similar
 */

class Block{
    SDL_Rect rect;
public:
    Block(int x=10, int y=10, int w=10, int h=10, int filled=true){
        rect.x = x;
        rect.y = y;
        rect.w = w;
        rect.h = h;
    }

    /**
     * draw with the given rendererer
     */
    void draw(SDL_Renderer *renderer){
        SDL_SetRenderDrawColor( renderer , 200 , 155 , 255 , 255);
        SDL_RenderDrawRect( renderer, &rect );
        SDL_RenderPresent( renderer );
    }

    bool framed(){
        return 0;
    }

};
#endif

Then in my main.cpp

SDL_Window *window;
SDL_Renderer *renderer;
Mouse mouse;
Block rect;


void renderWindow(){
    window = SDL_CreateWindow("commanding rects", 100, 100, 700, 600, 0);
    renderer = SDL_CreateRenderer(window, -1, 0);
}

void renderGame(Mouse mouse){
    SDL_RenderSetLogicalSize( renderer, 400, 300 );
    SDL_SetRenderDrawColor( renderer, 0, 0, 0, 0);
    SDL_RenderClear( renderer );
    SDL_RenderPresent( renderer );
    mouse.createSelectBox( renderer );

}


void gameLoop(){
    bool game_run = true;
    while (game_run) {
        SDL_Event event;
        while( SDL_PollEvent(&event)){
            if ( event.type == SDL_QUIT ) {
                game_run = false;
            }
            mouse.setState(event.type, event);
        }
        renderGame(mouse);
        SDL_Delay( 15 );
    }

}


int main(){
    renderWindow();
    gameLoop();
    return 0;
}

Upvotes: 1

Views: 2060

Answers (2)

xhallix
xhallix

Reputation: 3011

I finally found out what I was doing wrong.

I was retrieving the wrong start points for drawing the rectangle. When triggering the mousedown I had to get event.button.x instead of GetMouseState

Here is the updated Mouse.h

#ifndef MOUSE_H_
#define MOUSE_H_

class Mouse {

public:
    bool leftButtonDown = false;
    bool mouseMoves = false;

    struct MouseCoords {
        int x = -1;
        int y = -1;
    };

    MouseCoords start_coords;
    MouseCoords move_coords;
    Mouse(){}

    void setState(Uint32 eventType, SDL_Event event){

        if ( eventType == SDL_MOUSEBUTTONDOWN) {
            this->leftButtonDown = true;
            this->start_coords.x = event.button.x;
            this->start_coords.y = event.button.y;
        }

        if ( eventType == SDL_MOUSEBUTTONUP ) {
            this->leftButtonDown = false;
        }

        if ( eventType == SDL_MOUSEMOTION ) {
            this->move_coords.x = event.motion.x;
            this->move_coords.y = event.motion.y;
        }
    }

    /**
     * Provides coordinates when mousebutton down
     */
    MouseCoords getCoordinates(){
        return move_coords;
    }


    /**
     * Creates selector rect, call this in the render loop
     */
     void createSelectBox(SDL_Renderer *renderer){

        if(this->leftButtonDown) {

            float width = this->move_coords.x - this->start_coords.x;
            float height = this->start_coords.y - this->move_coords.y;
            float x = this->start_coords.x ;
            float y = this->move_coords.y;

            Block rect(x, y,width, height);
            rect.draw( renderer );



        }


     }
};

#endif

Upvotes: 0

JordanDee
JordanDee

Reputation: 68

I found a problem here:

void createSelectBox(SDL_Renderer *renderer){
    if(this->leftButtonDown) {
        Block rect(this->mousedown_coords.x,
                   this->mousemove_coords.y,
                   this->mousedown_coords.y - this->mousemove_coords.y,
                   this->mousemove_coords.x - this->mousedown_coords.x);

In this piece of code, you're setting the width and height of the rectangle to 0 no matter what the value of mouse coordinates are. Since you're drawing a bounding box, I imagine you want to store two sets of x,y coordinates, one for when the mouse button is pressed and one for when it is released.

Upvotes: 1

Related Questions