I have a game with a menu made up of 9 'tiles'. I want the tiles to turn white when the cursor hovers over them (and play a sound), and go back to default when the mouse moves off. My code works when the cursor is moved slowly, but when it is moved quickly the tiles don't turn back to the default colour when the mouse is moved off, resulting in multiple tiles staying white. I'm not sure if the problem is with my code or with SDL event polling. Below are the relevant code snippets, the full source can be found here
void MenuState::handleEvents(SDL_Event& e) {
//(...)
if (e.type == SDL_MOUSEMOTION) {
int x; int y;
SDL_GetMouseState(&x, &y);
mousePos = getActiveTile(x, y);
if (mousePos >= 0 && tiles[mousePos].tileType() != Tile::type::buttonpressed) {
tiles[mousePos].setTileType(Tile::type::rollover);
}
else if (prevMousePos >= 0 && tiles[prevMousePos].tileType() != Tile::type::buttonpressed) {
// if mouse is *no longer* inside button
tiles[prevMousePos].setTileType(Tile::type::button);
prevMousePos = -1;
}
}
//(...)
}
int MenuState::getActiveTile(const int &x, const int &y) {
int tilenum = -1;
for (int i = 0; i < tiles.size(); ++i) {
if ( !(x < tiles[i].position().x || x > tiles[i].position().x + tiles[i].position().w ||
y < tiles[i].position().y || y > tiles[i].position().y + tiles[i].position().h) )
tilenum = i ;
}
return tilenum;
}
void MenuState::update() {
if (mousePos >= 0 && prevMousePos == -1) { // only play when mouse first touches button
Mix_PlayChannel(-1, rollOver, 0);
prevMousePos = mousePos;
}
//(...)
}
the render function (the 'buttons' are held in a vector of 'Tile's)
void Graphics::drawBoard(const std::vector<Tile>& t, const bool& drawnumber) {
for (int i = 0; i < t.size(); ++i) {
SDL_Rect temp = t[i].position();
if (t[i].tileType() == Tile::type::invisible)
SDL_SetRenderDrawColor(renderer, 163, 118, 172, 1); // bg colour
else if (t[i].tileType() == Tile::type::rollover || t[i].tileType() == Tile::type::buttonpressed)
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 1); // highlight colour
else if (t[i].tileType() == Tile::type::shadow)
SDL_SetRenderDrawColor(renderer, 100, 65, 107, 1); // shadow colour
else
SDL_SetRenderDrawColor(renderer, 237, 229, 239, 1); // default colour
SDL_RenderFillRect(renderer, &temp);
if (drawnumber){
if (t[i].tileType() != Tile::type::invisible) {
std::string num = std::to_string(t[i].number());
tilenumber = renderText(num, "assets/Calibrib.ttf", fontcolour, 25);
SDL_QueryTexture(tilenumber, NULL, NULL, &temp.w, &temp.h);
renderTexture(tilenumber, temp.x+(TILE_SIZE/2 - temp.w/2), temp.y+(TILE_SIZE/2 - temp.h/2), nullptr);
}
}
}
}
rollover
, and reset the other 8 tobutton
. Don't bother remembering the previous mouse position and trying to reset just one (unless you have hundreds of tiles, and even then I would recommend this approach until you empirically find it to be too slow). \$\endgroup\$ – Dan Oct 28 '16 at 12:46prevMousePos
. Without the full context, I can't say exactly. You'd have to write some debug output whenever you set or use that variable, reproduce the problem, then examine the output. \$\endgroup\$ – Dan Oct 28 '16 at 13:35