C++ SDL:如何基于鼠标事件渲染多个不同的纹理
我正在尝试制作一个包含3个不同选项的简单菜单。播放,选择,退出 我想让他们改变颜色时,你悬停在他们和当你鼠标在他们身上。我尝试使用lazy foo的鼠标事件参考,但我不知道如何使用不同的“按钮”。如果他们说的都是一样的话,那是一回事 这是我的密码: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
#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]);
}