Click here to Skip to main content
15,896,730 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm currently making a 2D video game using the SFML library on Visual Studio 2019 community with the help of a Youtube tutorial series by Suraj Sharma:

https://www.youtube.com/watch?v=IdKZpv6xqdw&list=PL6xSOsbVA1ebkU66okpi-KViAO8_9DJKg&index=1

Recently i'm making a drop list of buttons to be implemented in the game menu's settings(Video 44 to 48)

For example,when i click on the menu's 'Settings' button the menu will switch into a 'Settings' state that comprises a drop list of resolution options for me to choose from.

Here's the code:

Gui.h

C++
<pre>#pragma once
#ifndef GUI_H
#define GUI_H

#include "pch.h"

enum BStates { IDLE = 0,HOVER,ACTIVE };

namespace gui {
	class Button
	{
	private:
		short unsigned bStates;
		short unsigned Id;

		sf::RectangleShape Shape;
		sf::Font* Font;
		sf::Text Text;

		sf::Color TextIdl;
		sf::Color TextHover;
		sf::Color TextActive;

		sf::Color Idle;
		sf::Color Hover;
		sf::Color Active;

		sf::Color OutlIdle;
		sf::Color OutlHover;
		sf::Color OutlActive;
	public:
		Button(float x, float y, float w, float h,
			sf::Font* Font, std::string Text,
			unsigned CharSize, sf::Color TextIdl, sf::Color TextHover, sf::Color TextActive,
			sf::Color Idle, sf::Color Hover, sf::Color Active
			,sf::Color OutlIdle, //= sf::Color::Transparent
		        ,sf::Color OutlHover = sf::Color::Transparent, 
			sf::Color OutlActive = sf::Color::Transparent,
			short unsigned Id = 0);
		~Button();

		//Access
		const bool Pressed()const;
		const std::string GetText()const;
		const short unsigned& GetId()const;
		//Modifier
		void SetText(const std::string Text);
		void SetId(const short unsigned Id);
		//Function
		void Update(const sf::Vector2f& MousePos);
		void Render(sf::RenderTarget& target);
	};
	class DrpList {
	private:
		float Keytime;
		float KeytimeMax;
		sf::Font& Fnt;
		gui::Button* ActivElmnt;
		std::vector<gui::Button*> List;
		bool ShowList;
	public:
		DrpList(float x, float y, float w, float h, sf::Font& Fnt, std::string List[], unsigned NumElemnt, unsigned DefIndex = 0);
		~DrpList();

		//Funcs
		const bool GetKeytime();
		void UpdateKeytime(const float& dt);
		void Update(const sf::Vector2f& MousePos, const float& dt);
		void Render(sf::RenderTarget& target);
	};
}
#endif // !BUTTON_H


Gui.cpp

#include "Gui.h"

using namespace gui;

Button::Button(float x, float y, float w, float h,
	sf::Font* Font, std::string Text, unsigned CharSize,
	sf::Color TextIdl, sf::Color TextHover, sf::Color TextActive,
	sf::Color Idle, sf::Color Hover, sf::Color Active
   ,sf::Color OutlIdle, sf::Color OutlHover, sf::Color OutlActive, short unsigned Id)
{
	this->bStates = IDLE;
	this->Id = Id;

	this->Shape.setPosition(sf::Vector2f(x, y));
	this->Shape.setSize(sf::Vector2f(w, h));
	this->Shape.setFillColor(Idle);
	this->Shape.setOutlineThickness(1.f);
	this->Shape.setOutlineColor(OutlIdle);

	this->Font = Font;

	this->Text.setFont(*this->Font);
	this->Text.setString(Text);
	this->Text.setFillColor(TextIdl);
	this->Text.setCharacterSize(CharSize);
	this->Text.setPosition(this->Shape.getPosition().x + (this->Shape.getGlobalBounds().width / 2.f) - this->Text.getGlobalBounds().width / 2.f,
						   this->Shape.getPosition().y + (this->Shape.getGlobalBounds().height / 2.f) - this->Text.getGlobalBounds().height / 2.f);
	this->TextIdl = TextIdl;
	this->TextHover = TextHover;
	this->TextActive = TextActive;

	this->Idle = Idle;
	this->Hover = Hover;
	this->Active = Active;

	this->OutlIdle = OutlIdle;
	/*this->OutlHover = OutlHover;
	this->OutlActive = OutlActive;*/
}

Button::~Button()
{
}
//Access
const bool Button::Pressed() const
{
	if (this->bStates == ACTIVE)
		return true;
	return false;
}

const std::string gui::Button::GetText() const
{
	return this->Text.getString();
}
const short unsigned& gui::Button::GetId() const
{
	return this->Id;
}
//Modifier
void gui::Button::SetText(const std::string Text)
{
	this->Text.setString(Text);
}

void gui::Button::SetId(const short unsigned Id)
{
	this->Id = Id;
}

//Functions

void Button::Update(const sf::Vector2f& MousePos)
{
	this->bStates = IDLE;

	if (this->Shape.getGlobalBounds().contains(MousePos)) {
		this->bStates = HOVER;
		if (sf::Mouse::isButtonPressed(sf::Mouse::Left)){
			this->bStates = ACTIVE;
		}
	}
	switch (this->bStates)
	{
	case IDLE:
		this->Shape.setFillColor(this->Idle);
		this->Text.setFillColor(this->TextIdl);
		this->Shape.setOutlineColor(this->OutlIdle);
		break;
	case HOVER:
		this->Shape.setFillColor(this->Hover);
		this->Text.setFillColor(this->TextHover);
		this->Shape.setOutlineColor(this->OutlHover);
		break;
	case ACTIVE:
		this->Shape.setFillColor(this->Active);
		this->Text.setFillColor(this->TextActive);
		this->Shape.setOutlineColor(this->OutlActive);
		break;
	default:
		this->Shape.setFillColor(sf::Color::White);
		this->Text.setFillColor(sf::Color::Blue);
		this->Shape.setOutlineColor(sf::Color::Green);
		break;
	}
}

void Button::Render(sf::RenderTarget& target)
{
	target.draw(this->Shape);
	target.draw(this->Text);
}

//-------------DrpList---------------
gui::DrpList::DrpList(float x, float y, float w, float h, sf::Font& Fnt, std::string List[], unsigned NumElemnt, unsigned DefIndex)
	:Fnt(Fnt), ShowList(false), KeytimeMax(10.f), Keytime(0.f)
{
	//unsigned NumElemnt = sizeof(List) / sizeof(std::string);
	this->ActivElmnt = new gui::Button(
		x, y, w, h,
		&this->Fnt, List[DefIndex], 12,
		sf::Color(255, 255, 255, 150),
		sf::Color(255, 255, 255, 200),
		sf::Color(20, 20, 20, 50),
		sf::Color(70, 70, 70, 200),
		sf::Color(150, 150, 150, 200),
		sf::Color(20, 20, 20, 200),
		sf::Color(255, 255, 255, 200)
		sf::Color(255, 255, 255, 255),
		sf::Color(20, 20, 20, 200));

	for (size_t i = 0; i < NumElemnt; i++) {
		this->List.push_back(new gui::Button(
			x, y + ((i + 1) * h), w, h,
			&this->Fnt, List[i], 12,
			sf::Color(255, 255, 255, 150),
			sf::Color(255, 255, 255, 255),
			sf::Color(20, 20, 20, 50),
			sf::Color(70, 70, 70, 200),
			sf::Color(150, 150, 150, 200),
			sf::Color(20, 20, 20, 200),
			sf::Color(255, 255, 255, 0)
			sf::Color(255, 255, 255, 0),
			sf::Color(20, 20, 20, 0),i));
	}
}
	

gui::DrpList::~DrpList()
{
	delete this->ActivElmnt;
	for (size_t i = 0; i < this->List.size(); i++) {
		delete this->List[i];
	}
}

const bool gui::DrpList::GetKeytime()
{
	if (this->Keytime >= this->KeytimeMax) {
		this->Keytime = 0.f;
		return true;
	}
	return false;
}

void gui::DrpList::UpdateKeytime(const float& dt)
{
	if (this->Keytime < this->KeytimeMax)
		this->Keytime += 10.f * dt;
}

//DrpList
void gui::DrpList::Update(const sf::Vector2f& MousePos , const float& dt)
{
	this->UpdateKeytime(dt);
	this->ActivElmnt->Update(MousePos);
	//Show - hide list
	if (this->ActivElmnt->Pressed() && this->GetKeytime()) {
		if (this->ShowList)
			this->ShowList = false;
		else this->ShowList = true;
	}

	if (this->ShowList) {
		for (auto& i : this->List) {
			i->Update(MousePos);

			if (i->Pressed() && this->GetKeytime()) {
				this->ShowList = false;
				this->ActivElmnt->SetText(i->GetText());
				this->ActivElmnt->SetId(i->GetId());
			}
		}
	}
}

void gui::DrpList::Render(sf::RenderTarget& target)
{
	this->ActivElmnt->Render(target);
	if (this->ShowList) {
		for (auto& i : this->List) {
			i->Render(target);
		}
	}
}


Settings.h

#pragma once
#ifndef SETTINGS_H
#define SETTINGS_H

#include "State.h"
#include "Gui.h"

class Settings :
	public State
{
private:
	//Vars
	sf::Font Fnt;
	sf::Texture BgTex;
	sf::RectangleShape BackGrnd;

	std::map<std::string, gui::Button*> buttons;
	std::map<std::string, gui::DrpList*> drplist;
	gui::DrpList* Dl;

	//Functions
	void InitVars();
	void InitBackGrnd();
	void InitFonts();
	void InitKeybinds();
	void InitGui();

public:
	Settings(sf::RenderWindow* window, std::map<std::string, int>* SupportedKeys, std::stack<State*>* states);
	virtual~Settings();
	//Access
	//Funcs
	void UpdateInput(const float& dt);
	void Update(const float& dt);
	void UpdateGui(const float& dt);

	void RenderGui(sf::RenderTarget& target);
	void Render(sf::RenderTarget* target = nullptr);
};
#endif // !SETTINGS_H


Settings.cpp

#include "Settings.h"

//Init Funcs
void Settings::InitVars()
{

}

void Settings::InitBackGrnd()
{
	this->BackGrnd.setSize(
		sf::Vector2f(
			static_cast<float>(this->window->getSize().x),
			static_cast<float>(this->window->getSize().y)));

	if (!this->BgTex.loadFromFile("Resources/Images/BackGrounds/Menu/M2.png")) {
		throw "Error:Main_Menu:Failed to load background texture";
	}
	this->BackGrnd.setTexture(&this->BgTex);
}

void Settings::InitFonts()
{
	if (!this->Fnt.loadFromFile("Fonts/SPACEMAN.ttf")) {
		throw("Error:Main Menu St::Couldn't load font");
	}
}

void Settings::InitKeybinds()
{
	std::ifstream ifs("Config/MMKeys.ini");

	if (ifs.is_open()) {
		std::string key = "";
		std::string key2 = "";
		int keyval = 0;
		while (ifs >> key >> key2)
		{
			this->Keybinds[key] = this->SupportedKeys->at(key2);
		}
	}
	ifs.close();

	this->Keybinds["CLOSE"] = this->SupportedKeys->at("ESC");
	this->Keybinds["Left"] = this->SupportedKeys->at("A");
	this->Keybinds["Right"] = this->SupportedKeys->at("D");
	this->Keybinds["Up"] = this->SupportedKeys->at("W");
	this->Keybinds["Down"] = this->SupportedKeys->at("S");
}

void Settings::InitGui()//Lnk2019
{
	this->buttons["Exit"] = new gui::Button(
		900.f, 880.f, 250.f, 50.f,
		&this->Fnt, "Back", 50,
		sf::Color(70, 70, 70, 200),
		sf::Color(150, 150, 150, 250),
		sf::Color(20, 20, 20, 50),
		sf::Color(70, 70, 70, 0),
		sf::Color(150, 150, 150, 0),
		sf::Color(20, 20, 20, 0), sf::Color(70, 70, 70, 0));
	std::string Li[] = {"1920x1080","800x600","640x480"};
	this->drplist["Resolution"] = new gui::DrpList(800, 450, 200, 50, Fnt, Li, 3);
}

Settings::Settings(sf::RenderWindow* window, std::map<std::string, int>* SupportedKeys, std::stack<State*>* states)
	:State(window,SupportedKeys,states)
{
	this->InitVars();
	this->InitBackGrnd();
	this->InitFonts();
	this->InitKeybinds();
	this->InitGui();
}

Settings::~Settings()
{
	auto it = this->buttons.begin();
	for (it = this->buttons.begin(); it != this->buttons.end(); ++it) {
		delete it->second;
	}
	auto it2 = this->drplist.begin();
	for (it2 = this->drplist.begin(); it2 != this->drplist.end(); ++it2) {
		delete it2->second;
	}
}


//Access
//Funcs 
void Settings::UpdateInput(const float& dt)
{
}

void Settings::Update(const float& dt)
{
	this->UpdateMousePos();
	this->UpdateInput(dt);

	this->UpdateGui(dt);

	std::cout << this->MousePosView.x << " " << this->MousePosView.y << "\r";
}

void Settings::UpdateGui(const float& dt)
{	//Update guis and handle their functions
	for (auto& it : this->buttons) {
		it.second->Update(this->MousePosView);
	}
	//Quit
	if (this->buttons["Exit"]->Pressed()) {
		this->Endstate();
	}

	//Drop List
	for (auto& it : this->drplist) {
		it.second->Update(this->MousePosView, dt);
	}
	
}

void Settings::RenderGui(sf::RenderTarget& target)
{
	for (auto& it : this->buttons) {
		it.second->Render(target);
	}

	for (auto& it : this->drplist) {
		it.second->Render(target);
	}
}

void Settings::Render(sf::RenderTarget* target)
{
	if (!target)
		target = this->window;
	target->draw(this->BackGrnd);

	this->RenderGui(*target);
}


The full error message:
'
Error LNK2019

unresolved external symbol "public: __thiscall gui::Button::Button(float,float,float,float,class sf::Font *,class std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> >,unsigned int,class sf::Color,class sf::Color,class sf::Color,class sf::Color,class sf::Color,class sf::Color,class sf::Color,class sf::Color,class sf::Color,unsigned short)" (??0Button@gui@@QAE@MMMMPAVFont@sf@@V?$basic_strin g@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@IV Color@3@22222222G@Z) referenced in function "private: void __thiscall Settings::InitGui(void)" (?InitGui@Settings@@AAEXXZ)

Project:
Star Fire

File:
F:\Star Fire SFML\Star Fire\Settings.obj

Line:
1
'
Everything works perfectly before video 48,a Lnk2019 occurs right after i put more parameters into the 'gui::Button();' constructor in 'Gui.cpp' specifically the 'sf::color::' OutlIdle - Hover and Active parameters. As soon as i put them in the error occurs.

Can someone help me ?

What I have tried:

I've tried to run the project in release mode instead and it works fine.The Error only appears in Debug.
Posted
Updated 3-Nov-19 2:35am
Comments
Richard MacCutchan 3-Nov-19 3:47am    
Either the Gui.cpp module is not being compiled after the change, or you have a constructor call somewhere else with the wrong number of parameters.

I can see nothing wrong in your code. You can try clean the solution and rebuild the solution or project. Select the solution or project in the project explorer tab in VS and right-click to show the context-sensitive menu and select "Clean". Then use the same procedure to select "Build".
 
Share this answer
 
Comments
Richard MacCutchan 3-Nov-19 8:30am    
See below.
TankRockett 4-Nov-19 2:27am    
Thanks,that was unexpectedly dumb of me.
If you modify an existing constructor, you may break things everywhere the former constructor is used.

You can try to create an overload of the constructor instead, adding the parameters you want. This way, linker won't be disturbed, as it will be able to link to both the legacy constructor and the overload you have introduced.
 
Share this answer
 
In Settings.cpp you have:
C++
void Settings::InitGui()//Lnk2019
{
	this->buttons["Exit"] = new gui::Button(
		900.f, 880.f, 250.f, 50.f,
		&this->Fnt, "Back", 50,
		sf::Color(70, 70, 70, 200),
		sf::Color(150, 150, 150, 250),
		sf::Color(20, 20, 20, 50),
		sf::Color(70, 70, 70, 0),
		sf::Color(150, 150, 150, 0),
		sf::Color(20, 20, 20, 0), sf::Color(70, 70, 70, 0)); // 14 parameters
}


But your Button constructor from Gui.cpp is
C++
Button::Button(float x, float y, float w, float h,
sf::Font* Font, std::string Text,
unsigned CharSize,sf::Color TextIdl, sf::Color TextHover, sf::Color TextActive,
sf::Color Idle, sf::Color Hover, sf::Color Active,
sf::Color OutlIdle,
sf::Color OutlHover,
sf::Color OutlActive,
short unsigned Id)  // 17 parameters (although the 17th is zero if absent


The error message shows 17 parameters, so your project appears to be out of sync.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900