SFML community forums

Help => General => Topic started by: KyleTheCarpenter on June 28, 2021, 08:54:48 pm

Title: Would like tips on my Button class.
Post by: KyleTheCarpenter on June 28, 2021, 08:54:48 pm
Hello i am newish to Sfml. finished a c++ book thats what i know.. i made a class Button i like it.
im impressed with it but i wonder if i could make it better. its just a standard button you click.

#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string>

/**************************************************************************
                Title: Simple Button
                        Features: clickable button with a label. thats centerd shades when cursor is over.
                        is lockable and position can be moved

                Application:
                        ky::Button test1;   //default no data
                        ky::Button test2("eat my"); //name. position will be moved around after..
                        ky::Button test3("Butt",30,30); //name,locationX,LocationY
                        ky::Button test4("test3",30,30,1);//name,locationX,LocationY,scale

                        for scale 1small 6 big..
                inLoop:
                        if (event.type == sf::Event::MouseButtonPressed) {

                                if (event.mouseButton.button == sf::Mouse::Left) {
                                        if (test1.CheckState())
                                                std::cout << "clicked";//call function
                                                }
                                                }
                Display:
                test1.Update(MainWindow);
                MainWindow.draw(test1.Draw());
                MainWindow.draw(test1.Drawtext());

                Features:        #include "Button.hpp"
                                                .Locked() to lock
                                                .Unlock() to unlock
                                                .setPos(x,y) to move position
                                                .setSize(size) set size of button
                                                .CheckState() to check state
                                                .DisplayData() to display all credentials
**************************************************************************/


namespace ky{
        class Button {
        public:
                Button();  
                Button(std::string s);
                Button(std::string s, int localX, int localY);
                Button(std::string s, int localX, int localY, int Size);
                void Setup();
                void CenterTxt();
                void Update(sf::RenderWindow& MainWindow);
                sf::Sprite Draw() { return mySprite; }
                sf::Text Drawtext() { return myLabel; }
                void DisplayData();
                void setSize(int size) { scale = size; Setup(); }
                void setPos(int px, int py) {
                        mySprite.setPosition(px, py); CenterTxt();
               
               
                 }
                bool CheckState() { return State; }
                void Lock() { isLocked = true; }
                void Unlock() { isLocked = false; }
        private:
                sf::Vector2i mySize;
                sf::Font myFont;
                sf::Text myLabel;
                sf::Texture myTexture;
                sf::Sprite mySprite;
            bool State;
                bool isLocked;
                std::string myString;
                int scale;
        };
        void ky::Button::DisplayData()
        {
                std::string temp;
                if (isLocked)
                        temp = "Locked";
                if (!isLocked)
                        temp = "Unlocked";
                using namespace std;
                cout << "\n\tButton id: '" << myString << "' size is:\t width=" <<
                        mySprite.getLocalBounds().width*scale << "\theight= "<<
                        mySprite.getLocalBounds().height*scale;
                cout << "\n\tButton id: '" << myString << "' Position is:\t x:" <<
                        mySprite.getPosition().x << "\t y: " <<
                        mySprite.getPosition().y;
                cout << "\n\tButton id: '" << myString << "' Current State is:\t" <<
                        temp << endl << endl;
        }
        void ky::Button::Update(sf::RenderWindow& MainWindow) {
                auto mouse_pos = sf::Mouse::getPosition(MainWindow);
                auto translated_pos = MainWindow.mapPixelToCoords(mouse_pos);
                if (!isLocked) {
                        if (mySprite.getGlobalBounds().contains(translated_pos)) {
                                mySprite.setTextureRect(sf::IntRect(0, 15, 30, 15));
                                State = true;

                        }
                        else {
                                mySprite.setTextureRect(sf::IntRect(0, 0, 30, 15));
                                State = false;
                        }
                }
                if (isLocked) {
                        mySprite.setTextureRect(sf::IntRect(0, 0, 30, 15));
                        State = false;
                }
        }
       
        ky::Button::Button():scale(3), mySize(40,20),myString("test"),State(false)
        {
                Setup();
               
        }


        ky::Button::Button(std::string s) :mySize(40, 20), scale(3), myString(s), State(false)
        {
                Setup();
               
               
        }
        ky::Button::Button(std::string s, int localX, int localY) :
                scale(3),mySize(localX, localY), myString(s), State(false)
        {
                setPos(localX,localY);
                Setup();
                CenterTxt();
               
        }
        ky::Button::Button(std::string s, int localX, int localY,int size) :
                scale(size), mySize(localX, localY), myString(s), State(false)
        {
                setPos(localX, localY);
                Setup();
                CenterTxt();

        }
        void Button::CenterTxt() {
                int x = (myTexture.getSize().x / 2)*  scale;
                int y = (myTexture.getSize().y / 4) * scale;
                sf::FloatRect textRect = myLabel.getLocalBounds();
                myLabel.setOrigin(textRect.left + textRect.width / 2.0f,
                        textRect.top + textRect.height / 2.0f);
                myLabel.setPosition(mySprite.getPosition().x + (x), mySprite.getPosition().y + y);
        }
        void Button::Setup()
        {
                myTexture.loadFromFile("files\\kybutton.png");
                mySprite.setTexture(myTexture);
                mySprite.setScale(scale, scale);
                myFont.loadFromFile("files\\kyfont.otf");
                mySprite.setTextureRect(sf::IntRect(0, 0, 30, 15));
                myLabel.setFont(myFont);
                myLabel.setString(myString);
                isLocked = false;
                myLabel.setCharacterSize(6*scale);
                myLabel.setFillColor(sf::Color::Black);
                //myLabel.setPosition(mySprite.getGlobalBounds().width / 2, mySprite.getGlobalBounds().height / 2);
                //mySprite.setOrigin(myTexture.getSize().x / 2, myTexture.getSize().y / 2);
                CenterTxt();
        }
}
Title: Re: Would like tips on my Button class.
Post by: KyleTheCarpenter on June 28, 2021, 08:57:50 pm
My only issue with it is i have to Draw everything by refrencing the sprite and text. id like to be able to just draw(button);.
thanks to anyone that reads this
Title: Re: Would like tips on my Button class.
Post by: eXpl0it3r on July 01, 2021, 08:27:14 am
There are various things you could enhance.

Starting with consistent function name formatting, i.e. either PascalCase or camelCase.
Some functions don't need to be public if you just call them internally.
You can derive from sf::Drawable and implement the draw() method, that way you can just write window.draw(button).
You may want to pass in a font, instead of holding onto one directly, that way you can reuse the font across multiple objects and you can handle resource loading in something like a ResourceHolder (https://github.com/SFML/SFML-Game-Development-Book/tree/master/02_Resources/Include/Book)