0
\$\begingroup\$

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:

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:

    #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);
}
\$\endgroup\$
  • \$\begingroup\$ You need to be more specific about the error. Lnk2019 is a linker error. You have called a function from external code which cannot be resolved. What function have you called? The error should tell you this. \$\endgroup\$ – Ian Young Nov 4 at 11:03
  • \$\begingroup\$ Nevermind,thanks.I've recently clean the project and it works fine now. \$\endgroup\$ – TankRocket Nov 11 at 8:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.