C++ SDL рисовать динамический прямоугольник в зависимости от положения мыши

Многим это может показаться очевидным, но я застрял и не могу найти учебник, который бы мне помог, поэтому было бы здорово найти ответ здесь.

Я пытался сделать прямоугольник, как у вас в играх RTS, так сказать динамическое поле выбора, но он не работает правильно. Также было бы достаточно, если бы кто-то перечислял маркеры, которые каждый шаг для создания коробки, как это

(Не удивительно, что я действительно новичок в 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

Тогда в моем 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;
}

2 ответа

Решение

Я наконец узнал, что я делаю не так.

Я искал неправильные начальные точки для рисования прямоугольника. При срабатывании mousedown я должен был получить event.button.x вместо GetMouseState

Вот обновленный 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

Я нашел проблему здесь:

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

В этом фрагменте кода вы устанавливаете ширину и высоту прямоугольника равными 0 независимо от значения координат мыши. Поскольку вы рисуете ограничивающий прямоугольник, я предполагаю, что вы хотите сохранить два набора координат x, y: один для нажатия кнопки мыши, а второй - для отпускания.

Другие вопросы по тегам