C++ SDL:如何基于鼠标事件渲染多个不同的纹理

C++ SDL:如何基于鼠标事件渲染多个不同的纹理,c++,sdl,C++,Sdl,我正在尝试制作一个包含3个不同选项的简单菜单。播放,选择,退出 我想让他们改变颜色时,你悬停在他们和当你鼠标在他们身上。我尝试使用lazy foo的鼠标事件参考,但我不知道如何使用不同的“按钮”。如果他们说的都是一样的话,那是一回事 这是我的密码: #include "Menu.h" #include <iostream> std::string tmpCap; SDL_Color tmpColor; SDL_Color colorW = { 255, 255

我正在尝试制作一个包含3个不同选项的简单菜单。播放,选择,退出

我想让他们改变颜色时,你悬停在他们和当你鼠标在他们身上。我尝试使用lazy foo的鼠标事件参考,但我不知道如何使用不同的“按钮”。如果他们说的都是一样的话,那是一回事

这是我的密码:

#include "Menu.h"
#include <iostream>

std::string tmpCap;

SDL_Color tmpColor;
SDL_Color colorW = { 255, 255, 255, 255 };
SDL_Color colorG1 = { 65, 65, 65, 255 };
SDL_Color colorG2 = { 85, 85, 85, 255 };
SDL_Color colorG3 = { 125, 125, 125, 255 };

SDL_Texture* currentPlaySet[3];
SDL_Texture* currentOptionsSet[3];
SDL_Texture* currentExitSet[3];


SDL_Texture* currentPlay;
SDL_Texture* currentOptions;
SDL_Texture* currentExit;
SDL_Texture* currentTexboo[3];

enum mMenuNum
{
    PLAY_MOUT = 0,
    PLAY_MON = 1,
    PLAY_MUP = 2,
    OPTIONS_MOUT = 3,
    OPTIONS_MON = 4,
    OPTIONS_MUP = 5,
    EXIT_MOUT = 6,
    EXIT_MON = 7,
    EXIT_MUP = 8,
    MENUNUM_TOTAL = 9
};

enum mCheckButton
{
    B_OUT = 0,
    B_ON = 1,
    B_UP = 2,
    B_TOTAL = 3
};

int xCenter = 1024 / 2;
int yCenter = 768 / 2;

SDL_Rect rtmp[3];


SDL_Texture* btmp[9];


class Button
{
    public:
        //Initializes internal variables
        Button();

        //Sets top left position
        void setPosition( int x, int y );

        void setSize(int x, int y, int w, int h);

        //Handles mouse event
        void handleEvent(SDL_Event* e);

        //Shows button sprite
        void renderButtons();

    private:
        //Top left position
        SDL_Point mPosition;

        SDL_Rect mSize;

        //Currently used global sprite
        mCheckButton mCurrentSprite;

};

void Menu::init()
{
    const char* buttonCaptions[3] = {
        "  Play  ", "  Options  ", "  Exit  "
    };

    for (int i = 0; i < 9; i++)
    {
        if(i < 3)
        {
            tmpCap = buttonCaptions[0];
        }
        if(i < 6 && i > 2)
        {
            tmpCap = buttonCaptions[1];
        }
        if(i < 9 && i > 5)
        {
            tmpCap = buttonCaptions[2];
        }
        if(i == 0 || i == 3 || i == 6)
        {
            tmpColor = colorG1;
        }
        if(i == 1 || i == 4 || i == 7)
        {
            tmpColor = colorG2;
        }
        if(i == 2 || i == 5 || i == 8)
        {
            tmpColor = colorG3;
        }

        btmp[i] = TextureManager::TextTexture("../src/assets/Arial Black.ttf", tmpCap, 40, tmpColor);
        //std::cout << tmpCap << " " << i << std::endl;

    }

    currentPlaySet[0] = btmp[0];
    currentOptionsSet[0] = btmp[3];
    currentExitSet[0] = btmp[6];


    currentPlaySet[1] = btmp[1];
    currentOptionsSet[1] = btmp[4];
    currentExitSet[1] = btmp[7];


    currentPlaySet[2] = btmp[2];
    currentOptionsSet[2] = btmp[5];
    currentExitSet[2] = btmp[8];
    Menu::getSize();

}
Button::Button()
{
    currentPlay = btmp[0];
    currentOptions = btmp[3];
    currentExit = btmp[6];


    mCurrentSprite = B_OUT;
}
Button f[9];
void Button::setPosition(int x, int y)
{
    mPosition.x = x;
    mPosition.y = y;
}
void Button::setSize(int x, int y, int w, int h)
{
    mSize.x = x;
    mSize.y = y;
    mSize.w = w;
    mSize.h = h;
}
void Menu::getSize()
{
    SDL_QueryTexture(btmp[0], NULL, NULL, &rtmp[0].w, &rtmp[0].h);


    int aX = xCenter - (rtmp[0].w / 2);
    int aY = (yCenter - (rtmp[0].h / 2)) - 100;
    int aW = rtmp[0].w;
    int aH = rtmp[0].h;
    f[0].setPosition(aX, aY);
    f[0].setSize(aX, aY, aW, aH);


    SDL_QueryTexture(btmp[3], NULL, NULL, &rtmp[1].w, &rtmp[1].h);
    int bX = xCenter - (rtmp[1].w / 2);
    int bY = (yCenter - (rtmp[1].h / 2));
    int bW = rtmp[1].w;
    int bH = rtmp[1].h;
    f[1].setPosition(bX, bY);
    f[1].setSize(bX, bY, bW, bH);

    SDL_QueryTexture(btmp[6], NULL, NULL, &rtmp[2].w, &rtmp[2].h);
    int cX = xCenter - (rtmp[2].w / 2);
    int cY = (yCenter - (rtmp[2].h / 2)) + 100;
    int cW = rtmp[2].w;
    int cH = rtmp[2].h;
    f[2].setPosition(cX, cY);
    f[2].setSize(cX, cY, cW, cH);

}
void Button::handleEvent(SDL_Event* e)
{
    if( e->type == SDL_MOUSEMOTION || e->type == SDL_MOUSEBUTTONDOWN || e->type == SDL_MOUSEBUTTONUP )
    {
        int x, y;
        SDL_GetMouseState(&x, &y);

        //Check if mouse is in button
        bool inside = true;

        //Mouse is left of the button
        if( x < mPosition.x )
        {
            inside = false;
        }
        //Mouse is right of the button
        else if( x > mPosition.x + mSize.w )
        {
            inside = false;
        }
        //Mouse above the button
        else if( y < mPosition.y )
        {
            inside = false;
        }
        //Mouse below the button
        else if( y > mPosition.y + mSize.h )
        {
            inside = false;
        }

        //Mouse is outside button
        if( !inside )
        {
            std::cout << "Outside " << " " << mCurrentSprite << std::endl;
            //currentPlay = currentPlaySet[mCurrentSprite];
            //currentOptions = currentOptionsSet[mCurrentSprite];
            //currentExit = currentExitSet[mCurrentSprite];
            mCurrentSprite = B_OUT;
        }
        //Mouse is inside button
        else
        {
            switch( Game::event.type )
            {
                case SDL_MOUSEMOTION:
                mCurrentSprite = B_ON;
                //currentPlay = btmp[(mCurrentSprite/3)+1];
                //currentOptions = btmp[(mCurrentSprite/3)+1];
                //currentExit = btmp[(mCurrentSprite/3)+1];
                //currentPlay = currentPlaySet[mCurrentSprite];
                //currentOptions = currentOptionsSet[mCurrentSprite];
                //currentExit = currentExitSet[mCurrentSprite];

                std::cout << "In " << mCurrentSprite << std::endl;
                break;

                case SDL_MOUSEBUTTONDOWN:
                //currentPlay = currentPlaySet[mCurrentSprite];
                //currentOptions = currentOptionsSet[mCurrentSprite];
                //currentExit = currentExitSet[mCurrentSprite];
                //mCurrentSprite = B_DOWN;
                //currentTex = mTex3;
                break;

                case SDL_MOUSEBUTTONUP:
                //currentPlay = currentPlaySet[mCurrentSprite];
                //currentOptions = currentOptionsSet[mCurrentSprite];
                //currentExit = currentExitSet[mCurrentSprite];
                mCurrentSprite = B_UP;
                //currentTex = mTex4;
                break;
            }

        }
    }
}
void Button::renderButtons()
{

    while( SDL_PollEvent( &Game::event ) != 0 )
    {
        for( int i = 0; i < 3; ++i )
        {
            f[i].handleEvent(&Game::event);
        //isMouseOverText();
        }
    }

        SDL_RenderCopy(Game::mRenderer, btmp[mCurrentSprite], nullptr, &mSize);
        //SDL_RenderCopy(Game::mRenderer, currentOptionsSet[mCurrentSprite], nullptr, &mSize);
        //SDL_RenderCopy(Game::mRenderer, currentExitSet[mCurrentSprite], nullptr, &mSize);

}
void Menu::render()
{
    for( int i = 0; i < 3; ++i )
    {
        f[i].renderButtons();
    }
}
#包括“Menu.h”
#包括
std::字符串tmpCap;
SDL_彩色TMP彩色;
SDL_颜色W={255,255,255};
SDL_颜色G1={65,65,65,255};
SDL_颜色G2={85,85,85,255};
SDL_颜色3={125、125、125、255};
SDL_纹理*当前播放集[3];
SDL_纹理*当前选项集[3];
SDL_纹理*currentExitSet[3];
SDL_纹理*当前播放;
SDL_纹理*当前选项;
SDL_纹理*当前退出;
SDL_纹理*currentTexboo[3];
枚举数
{
PLAY_MOUT=0,
PLAY_MON=1,
播放MUP=2,
选项\u MOUT=3,
选项_MON=4,
选项μMUP=5,
出口=6,
退出\u MON=7,
退出_MUP=8,
MENUNUM_总计=9
};
枚举mCheckButton
{
B_OUT=0,
B_ON=1,
B_UP=2,
B_总计=3
};
int xCenter=1024/2;
国际中心=768/2;
SDL_Rect rtmp[3];
SDL_纹理*btmp[9];
类按钮
{
公众:
//初始化内部变量
按钮();
//设置左上角位置
无效设置位置(整数x,整数y);
无效设置大小(整数x、整数y、整数w、整数h);
//处理鼠标事件
无效handleEvent(SDL_事件*e);
//显示按钮精灵
无效渲染按钮();
私人:
//左上角位置
SDL_点组合;
SDL_-Rect mSize;
//当前使用的全局sprite
mCheckButton mCurrentSprite;
};
void菜单::init()
{
常量字符*按钮选项[3]={
“播放”、“选项”、“退出”
};
对于(int i=0;i<9;i++)
{
如果(i<3)
{
tmpCap=按钮选项[0];
}
如果(i<6&&i>2)
{
tmpCap=按钮选项[1];
}
如果(i<9&&i>5)
{
tmpCap=按钮选项[2];
}
如果(i==0 | | i==3 | | i==6)
{
tmpColor=colorG1;
}
如果(i==1 | | i==4 | | i==7)
{
tmpColor=colorG2;
}
如果(i==2 | | i==5 | | i==8)
{
tmpColor=colorG3;
}
btmp[i]=TextureManager::TextTextTextTexture(../src/assets/Arial Black.ttf),tmpCap,40,tmpColor;
//标准::cout composition.x+mSize.w)
{
内=假;
}
//鼠标放在按钮上方
else if(ymPosition.y+mSize.h)
{
内=假;
}
//鼠标在按钮外
如果(!内部)
{

std::cout我能够使用来自的旧SDL教程代码来理解它

在interact上删除和创建这些纹理是否可行

我已经更新了我的代码,以避免每次在底部删除纹理。有没有更好的方法来做到这一点?我觉得它看起来很干净,但我担心资源的使用

任何见解都值得赞赏

我的代码:

const int NUMMENU = 2;
const char* labels[NUMMENU] = {"Continue","Exit"};
SDL_Texture* menus[NUMMENU];
bool selected[NUMMENU] = {0,0};
SDL_Color color[2] = {{0,0,0,255},{255,0,0,255}};
SDL_Rect pos[NUMMENU];
int x,y;
const char* font = "../assets/Arial Black.ttf";


void MainMenu::init()
{
    menus[0] = TextureManager::CreateFontTexture(font, labels[0], 40, color[0]);
    menus[1] = TextureManager::CreateFontTexture(font, labels[1], 40, color[0]);

    SDL_QueryTexture(menus[0], NULL, NULL, &pos[0].w, &pos[0].h);
    SDL_QueryTexture(menus[1], NULL, NULL, &pos[1].w, &pos[1].h);

    pos[0].x = (1024/2) - (pos[0].w / 2);
    pos[0].y = (768/2) - (pos[0].h / 2) - 100;
    pos[1].x = (1024/2) - (pos[1].w / 2);
    pos[1].y = (768/2) - (pos[1].h / 2);
}

void MainMenu::render()
{
    SDL_RenderCopy(App::appRenderer, menus[0], NULL, &pos[0]);
    SDL_RenderCopy(App::appRenderer, menus[1], NULL, &pos[1]);

    if( App::event.type == SDL_MOUSEMOTION || App::event.type == SDL_MOUSEBUTTONDOWN || App::event.type == SDL_MOUSEBUTTONUP )
        {
                switch(App::event.type)
                {
                    case SDL_MOUSEMOTION:
                        x = App::event.motion.x;
                        y = App::event.motion.y;
                        for(int i = 0; i < NUMMENU; i += 1) {
                            if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h)
                            {
                                if(!selected[i])
                                {
                                    selected[i] = 1;
                                    SDL_DestroyTexture(menus[i]);
                                    menus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[1]);
                                }
                            }
                            else
                            {
                                if(selected[i])
                                {
                                    selected[i] = 0;
                                    SDL_DestroyTexture(menus[i]);
                                    menus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[0]);
                                }
                            }
                        }
                        break;
                    case SDL_MOUSEBUTTONDOWN:
                        x = App::event.button.x;
                        y = App::event.button.y;
                        for(int i = 0; i < NUMMENU; i += 1) {
                            if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h)
                            {
                                SDL_DestroyTexture(menus[0]);
                                SDL_DestroyTexture(menus[1]);
                            }
                        }
                        break;
                }
            }

}
const int NUMMENU=2;
常量字符*标签[NUMMENU]={“继续”,“退出”};
SDL_纹理*菜单[NUMMENU];
bool selected[NUMMENU]={0,0};
SDL_颜色[2]={0,0,0255},{255,0,0255};
SDL_Rect pos[NUMMENU];
int x,y;
const char*font=“../assets/Arial Black.ttf”;
void主菜单::init()
{
菜单[0]=TextureManager::CreateFontTexture(字体,标签[0],40,颜色[0]);
菜单[1]=TextureManager::CreateFontTexture(字体,标签[1],40,颜色[0]);
SDL_QueryTexture(菜单[0],NULL,NULL,&pos[0].w,&pos[0].h);
SDL_QueryTexture(菜单[1],NULL,NULL,&pos[1].w,&pos[1].h);
位置[0].x=(1024/2)-(位置[0].w/2);
位置[0].y=(768/2)-(位置[0].h/2)-100;
位置[1].x=(1024/2)-(位置[1].w/2);
位置[1].y=(768/2)-(位置[1].h/2);
}
void主菜单::render()
{
SDL_RenderCopy(App::appender,菜单[0]、NULL和pos[0]);
SDL_RenderCopy(App::appender,菜单[1],NULL和pos[1]);
如果(App::event.type==SDL_MOUSEMOTION | | App::event.type==SDL_MOUSEBUTTONDOWN | | App::event.type==SDL_MOUSEBUTTONUP)
{
开关(App::event.type)
{
案例SDL_:
x=App::event.motion.x;
y=App::event.motion.y;
对于(int i=0;i=pos[i].x&&x=pos[i].y&&y=pos[i].x&&x=pos[i].y&&y
const int NUMMENU = 3;
const char* labels[NUMMENU] = {"New Game", "Options","Exit"};

SDL_Texture* menus[NUMMENU];
SDL_Texture* selectedMenus[NUMMENU];
SDL_Texture* toRender[NUMMENU];

bool selected[NUMMENU] = {0,0};

SDL_Color color[2] = {{0,0,0,255},{125,125,125,255}};
SDL_Rect pos[NUMMENU];
int x,y;
const char* font = "../assets/Arial Black.ttf";
int aOne = 0;

void MainMenu::init()
{
    for(int i = 0; i < NUMMENU; i++)
    {
        menus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[0]);
        toRender[i] = menus[i];
        selectedMenus[i] = TextureManager::CreateFontTexture(font, labels[i], 40, color[1]);
        SDL_QueryTexture(menus[i], NULL, NULL, &pos[i].w, &pos[i].h);
    }

    pos[0].x = (1024/2) - (pos[0].w / 2);
    pos[0].y = (768/2) - (pos[0].h / 2) - 100;
    pos[1].x = (1024/2) - (pos[1].w / 2);
    pos[1].y = (768/2) - (pos[1].h / 2);
    pos[2].x = (1024/2) - (pos[2].w / 2);
    pos[2].y = (768/2) - (pos[2].h / 2) + 100;

}

void MainMenu::inputD()
{
    aOne++;
    std::cout << aOne << std::endl;
    switch(App::event.type)
    {
        case SDL_MOUSEMOTION:
            x = App::event.motion.x;
            y = App::event.motion.y;
            for(int i = 0; i < NUMMENU; i += 1)
            {
                if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h)
                {
                    if(!selected[i])
                    {
                        selected[i] = 1;
                        toRender[i] = selectedMenus[i];
                    }
                }
                else
                {
                    if(selected[i])
                    {
                        selected[i] = 0;
                        toRender[i] = menus[i];
                    }
                }
            }
            break;
        case SDL_MOUSEBUTTONDOWN:
            x = App::event.button.x;
            y = App::event.button.y;
            for(int i = 0; i < NUMMENU; i += 1)
            {
                if(x>=pos[i].x && x<=pos[i].x+pos[i].w && y>=pos[i].y && y<=pos[i].y+pos[i].h)
                {
                    std::cout << labels[i] << " button clicked" << std::endl;
                }
            }
            break;
    }
}

void MainMenu::render()
{
    for(int i = 0; i < NUMMENU; i++)
        SDL_RenderCopy(App::appRenderer, toRender[i], NULL, &pos[i]);
}