int updated = 0;
for (auto itr = _Btns.begin(); itr != _Btns.end(); ++itr) {
itr->update(sf::Mouse::getPosition(l_window).x / 2, sf::Mouse::getPosition(l_window).y / 2);
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
updated = itr->TestPress();
if (updated != 0) current = updated;
}
}
except that it only lets me render the last button added.
_Btns.back().render(l_window);
does not?
for (auto itr = _Btns.begin(); itr != _Btns.end(); ++itr) {
itr->render(l_window);
}
Now, seeing as i can iterate with the update function, and I can render calling only the "back()"
_Btns.front().render(l_window);
Add more precisions. What do you mean by "doesn't work" ?
You are using a std::vector and a button that hold a texture. Since using push_back from std::vector asume copying the object, do you handle it correctly ? How do you handle texture in general ?
Showing your implementation of the class Button can be usefull for us.
Unhandled exception at 0x00147BDE in Platformer.exe: 0xC0000005: Access violation reading location 0x00000259.
#include <SFML\Graphics.hpp>
#include <string>
#pragma once
using namespace std;
class ButtonTile
{
public:
ButtonTile();
void init(int x, int y, string Txt, int cmd, sf::Font font);
~ButtonTile();
void update(int x, int y);
int TestPress();
void render(sf::RenderWindow& l_window);
private:
int _x, _y, _xSize, _ySize, _btnCmd;
string _btnTxt;
sf::Color _col, _rCol;
sf::Text _Txt;
sf::Font _Font;
sf::RectangleShape _rect;
bool _hover;
};
#include "ButtonTile.h"
ButtonTile::ButtonTile()
{
}
ButtonTile::~ButtonTile()
{
}
void ButtonTile::init(int x, int y, string Txt, int cmd, sf::Font font)
{
_btnTxt = Txt;
_x = x;
_y = y;
_xSize = (_btnTxt.length() * 8 )+3;
_ySize = 23;
_btnCmd = cmd;
_col = sf::Color::Blue;
_rCol = _col;
_Font = font;
_rect.setPosition(sf::Vector2f(_x, _y));
_rect.setFillColor(_rCol);
_rect.setSize(sf::Vector2f(_xSize, _ySize));
_Txt.setFont(_Font);
_Txt.setColor(sf::Color::White);
_Txt.setPosition(sf::Vector2f(_x + 3, _y + 3));
_Txt.setCharacterSize(15);
_Txt.setString(sf::String(_btnTxt));
_hover = false;
}
void ButtonTile::update(int x, int y)
{
if (x > _x && x < _x + _xSize && y > _y && y < _y + _ySize) {
_rCol = sf::Color::Black;
_hover = true;
}
else {
_rCol = _col;
_hover = false;
}
}
int ButtonTile::TestPress()
{
if (_hover == true) {
_rCol = sf::Color::Red;
return _btnCmd;
}
else return 0;
}
void ButtonTile::render(sf::RenderWindow& l_window) {
_rect.setFillColor(_rCol);
l_window.draw(_rect);
l_window.draw(_Txt);
} /// <<<---- ACCESS VIALATION POINTS TO THIS END BARAK
#include "ButtonTile.h"
#include <vector>
#pragma once
using namespace std;
class MenuFile
{
public:
MenuFile();
~MenuFile();
//Update functions, one gets info, other makes it it self.
// int update(int x, int y, bool clicked, int current); //For later use
void init(sf::Font font, string l_title);
int update(int current, sf::RenderWindow& l_window);
void addButton(string Txt, int cmd);
void render(sf::RenderWindow& l_window);
private:
int _nBtns;
sf::RectangleShape _bg;
vector<ButtonTile> _Btns;
sf::Text _header;
sf::Font _font;
};
#include "MenuFile.h"
MenuFile::MenuFile()
{
}
MenuFile::~MenuFile()
{
}
void MenuFile::init(sf::Font font, string l_title) {
_font = font;
_header.setFont(_font);
_header.setString(l_title);
_header.setPosition(sf::Vector2f(130, 30));
_header.setColor(sf::Color::White);
_bg.setFillColor(sf::Color(100,100,130));
_bg.setSize(sf::Vector2f(350, 90));
_bg.setPosition(sf::Vector2f(25, 25));
}
int MenuFile::update(int current, sf::RenderWindow& l_window) {
int updated = 0;
///THIS WORKS FINE///
for (auto itr = _Btns.begin(); itr != _Btns.end(); ++itr) {
itr->update(sf::Mouse::getPosition(l_window).x / 2, sf::Mouse::getPosition(l_window).y / 2);
if (sf::Mouse::isButtonPressed(sf::Mouse::Left)) {
updated = itr->TestPress();
if (updated != 0) current = updated;
}
}
return current;
}
void MenuFile::addButton(string Txt, int cmd) {
_Btns.push_back(ButtonTile());
_Btns.back().init(100, 70 + (_nBtns * 25), Txt, cmd, _font);
_nBtns++;
_bg.setSize(sf::Vector2f(350, 90 + (_nBtns * 25)));
}
void MenuFile::render(sf::RenderWindow& l_window) {
l_window.draw(_bg);
l_window.draw(_header);
///THIS WORKS FINE///
_Btns.back().render(l_window);
///THIS DOES NOT WORK///
for (auto itr = _Btns.begin(); itr != _Btns.end(); ++itr) {
itr->render(l_window);
}
}
Nitpick: "_Btns" is, strictly speaking, not an allowed name. All names beginning with underscore and followed by a upper-case letter (as well as names containing double underscores "__" anywhere) arre reserved for the implementation. That is, only your compiler and standard library are allowed to use such names.
If that's where the program breaks, it looks like it's the drawing of the sf::Text. I noticed that the actual font resource is stored in the button class.Ifthe vector is re-arranged/re-located, the font is re-located and therefore the text points to the wrong location.
for (auto itr = _btns.begin(); itr != _btns.end(); ++itr) {
itr->render(l_window, _font);
}
void ButtonTile::render(sf::RenderWindow& l_window, sf::Font& font) {
_rect.setFillColor(_rCol);
_txt.setFont(font);
l_window.draw(_rect);
l_window.draw(_txt);
}