Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] Draw function, Iterators, Bounds error  (Read 2908 times)

0 Members and 1 Guest are viewing this topic.

Ausche

  • Newbie
  • *
  • Posts: 19
    • View Profile
[SOLVED] Draw function, Iterators, Bounds error
« on: February 19, 2016, 03:54:23 am »
So I'm implementing a GUI system to my game.

The problem is, when I go to draw the rectangle shape and text, both contained in one structure, I'm getting a bounds error.

Relevant code:

Draw function found in GUIsystem.cpp
void GUI::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
//if the GUI isn't visible, return
        if(visible == false)
                return;

        states.transform *= getTransform();

//THE PROBLEM***
        for(Button* iterate : this->buttons)
        {
                std::cout << "drawing button" << std::endl;
                target.draw(iterate->buttonBackground);
                target.draw(iterate->buttonText);
//debugger breaks here, doesn't pass a single iteration but does display the "drawing button" to the console
//claims the problem is buttonText, getting a bounds error
        }

//ignore this chunk, same thing as above but not using an iterator
//same exact problem though (bounds error problem with buttonText)
        /*for(int i = 0; i < buttonReference-1; i++)
        {
                target.draw(buttons[i]->buttonBackground);
                target.draw(buttons[i]->buttonText);
        }
        */


//can't assume this is right, program breaks before this
        std::cout << "drawing background" << std::endl;
        target.draw(background);

}
 

Header for GUI class:
class GUI : public sf::Transformable, public sf::Drawable
{
public:
        GUI();
//dimensions, position, background color, border color
        GUI(sf::Vector2f dimensions, sf::Vector2f position, sf::Color BackgroundColor, sf::Color borderColor);

//returns a number as which refers to the button. Used in game loop to handle the players choice
//dimensions, position, text, button color, border color textcolor, font
        int addButton(sf::Vector2f dimensions, sf::Vector2f position, const std::string& text, sf::Color buttonColor, sf::Color borderColor, sf::Color textColor, sf::Font font);

//updates the entire GUI, iterates over all the buttons to check if mouse is hovering or not
        int update();

//simply switches visible bool
        void show();
        void hide();

//should draw the background, the button background and the button's text
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;

        bool visible;
private:

        sf::Vector2f dimensions;
        sf::Color backgroundColor;
        sf::Color borderColor;

        sf::RectangleShape background;

//IMPORTANT - vector of pointers to buttons **this is iterated through in the draw function
        std::vector<Button*> buttons;

//a reference used to know which button was clicked on
        int buttonReference;
};

The header for the Button class:
class Button
{
public:
        Button();

//constructs the button, this is called within the GUI constructor
        Button(sf::Vector2f dimensions, sf::Vector2f position, const std::string text, sf::Color buttonColor, sf::Color borderColor, sf::Color textColor, sf::Font font);

//handles when mouse is hovering over a button
        void hovering();

//handles when mouse is no longer hovering over a button
        void notHovering();
        friend GUI;
protected:

//the actual shape drawn
        sf::RectangleShape buttonBackground;

//the text drawn
        sf::Text buttonText;

        sf::Color textColor;
        sf::Font* textFont;
};
 

OUTPUT:
First-chance exception at 0x00007FF6503C035E in The game.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
Unhandled exception at 0x00007FF6503C035E in The game.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.

AUTOS:
+      this   0x0000008493f0ed00 {visible=true dimensions={x=0.000000000 y=0.000000000 } backgroundColor={r=0 '\0' ...} ...}   GUI *

I'm thinking it might have something to do with the Button class not inheriting "Drawable", yet it's member variables are trying to be drawn but through a class which does inherit "Drawable" (GUI), though I'm not sure.

I can link the entire source for this through github if it's necessary, I know the abstraction makes it harder to find the problem. If there's any specific thing I should also include let me know. Any help would be great.

Thanks!
« Last Edit: February 21, 2016, 06:02:07 am by Ausche »
Struggling to make a game happen!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Draw function, Iterators, Bounds error
« Reply #1 on: February 19, 2016, 04:10:26 am »
Button* iterator is a pointer to an instance of Button, while Button has the private members buttonBackground and buttonText. How do you expect to access private members? The code you provided should not compile, so my guess is that this is not the real/full code. ;)

If you can't figure out what goes out of range with the debugger, you could always make the for loop with normal iterators or an index and then see what is going on.

Also there's no need for the this->, you can access member variables directly.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ausche

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Draw function, Iterators, Bounds error
« Reply #2 on: February 19, 2016, 04:22:57 am »
Button* iterator is a pointer to an instance of Button, while Button has the private members buttonBackground and buttonText. How do you expect to access private members? The code you provided should not compile, so my guess is that this is not the real/full code. ;)

If you can't figure out what goes out of range with the debugger, you could always make the for loop with normal iterators or an index and then see what is going on.

Also there's no need for the this->, you can access member variables directly.

Actually, the button class stores buttonBackground and buttonText as protected! Reread the header I posted.

On another note, I dug way deeper into the Autos report and found this-

+      buttons   { size=3 }   std::vector<Button,std::allocator<Button> >
+      iterate   {buttonBackground={m_size={x=160.000000 y=40.0000000 } } buttonText={m_string={m_string={...} } m_font=...} ...}   Button
+      iterate.buttonBackground   {m_size={x=160.000000 y=40.0000000 } }   sf::RectangleShape
-      iterate.buttonText   {m_string={m_string={...} } m_font=0x000000acdcf5ea48 {m_library=0x0000000000000000 m_face=0xcccccccccccccc00 ...} ...}   sf::Text
   +      sf::Drawable   {...}   sf::Drawable
   +      sf::Transformable   {m_origin={x=0.000000000 y=0.000000000 } m_position={x=473.000000  y=133.000000 } m_rotation=0.000000000 ...}   sf::Transformable
   +      m_string   {m_string={...} }   sf::String
    -      m_font   0x000000acdcf5ea48 {m_library=0x0000000000000000 m_face=0xcccccccccccccc00 m_streamRec=0xccccccccff000000 ...}   const sf::Font *
      m_library   0x0000000000000000   void *
      m_face   0xcccccccccccccc00   void *
      m_streamRec   0xccccccccff000000   void *
    +      m_refCount   0xcccccccccccccccc {???}   int *
    +      m_info   {family=<Error reading characters of string.> }   sf::Font::Info

I know it's a little crazy to read all that, but pay attention to the last line. I think that's the problem, did some googling and typically this arises when there was a temporary string sent to this object or something.
Struggling to make a game happen!

Ausche

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Draw function, Iterators, Bounds error
« Reply #3 on: February 19, 2016, 04:29:15 am »
I'll just post the github link to everything. https://github.com/AtomicAustin/TheBungus.git
Keep in mind I haven't been coding with readability in mind nor have I documented pretty much anything...

Though any criticism is welcome! This is my first real project and I welcome anything constructive.

This problem only involves level1.cpp and GUIsystem.cpp btw.
Struggling to make a game happen!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Draw function, Iterators, Bounds error
« Reply #4 on: February 19, 2016, 12:21:50 pm »
Actually, the button class stores buttonBackground and buttonText as protected! Reread the header I posted.
I see you friended the GUI class. Using the keyword friend does most of the time indicate a code smell, i.e. bad design, since friended classes break the encapsulation and there are usually better ways to go about things like that.

Your problem might well be, because of:
Button(..., sf::Font font);

You are making a copy of the font object, which gets destroyed as soon as the Button's constructor is left, leaving a reference in the text object to a non-existing font object.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Ausche

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Draw function, Iterators, Bounds error
« Reply #5 on: February 21, 2016, 01:33:22 am »
Actually, the button class stores buttonBackground and buttonText as protected! Reread the header I posted.
I see you friended the GUI class. Using the keyword friend does most of the time indicate a code smell, i.e. bad design, since friended classes break the encapsulation and there are usually better ways to go about things like that.

Your problem might well be, because of:
Button(..., sf::Font font);

You are making a copy of the font object, which gets destroyed as soon as the Button's constructor is left, leaving a reference in the text object to a non-existing font object.

Okay, I fixed the encapsulation thing, now they're separate but communicating, however it still won't draw the buttons to the screen.

The GUI background draws fine and works as intended, however the buttons can't be seen for some reason.
Here's the fixed draw function:

In GUIsystem.cpp
void GUI::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        if(visible == false)
                return;

        states.transform *= getTransform();
        target.draw(background);
        for(int i = 0; i < buttonReference; i++)
        {
                std::cout<< "drawing button " << i << std::endl;
                target.draw(buttons[i].buttonBackground);
                target.draw(buttons[i].buttonText);
        }

}
 

The "drawing button" iterates fine from 0-2 as it should, but the buttons can't be seen.
Here's the fixed header file and the segment where the draw function is called (might be relevant)

GUIsystem.h
class Button;
class GUI : public sf::Transformable, public sf::Drawable
{
public:
        GUI();
        //dimensions, position, background color, border color
        GUI(sf::Vector2f dimensions, sf::Vector2f position, sf::Color BackgroundColor, sf::Color borderColor);
        /*returns a number as which refers to the button. Used to handle choice logic
        dimensions, position, text, button color, border color textcolor, font name ".txt"
        */

        int addButton(sf::Vector2f dimensions, sf::Vector2f position, const std::string& text, sf::Color buttonColor, sf::Color borderColor, sf::Color textColor, sf::Font* font);
        int update(sf::Vector2f &);
        void show();
        void hide();
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;

        bool visible;
        std::vector<Button> buttons;
private:
        sf::Vector2f dimensions;
        sf::Color backgroundColor;
        sf::Color borderColor;

        sf::RectangleShape background;
        int buttonReference;
};

class Button
{
public:
        Button();
        Button(sf::Vector2f dimensions, sf::Vector2f position, const std::string& text, sf::Color buttonColor, sf::Color borderColor, sf::Color textColor, sf::Font* font);
        bool checkHovering(sf::Vector2i);
        void hovering();
        void notHovering();
        sf::RectangleShape getButtonBackground();
        sf::Text getButtonText();

        sf::RectangleShape buttonBackground;
        sf::Text buttonText;

private:
        sf::Color textColor;
        sf::Font* textFont;
};
 

In level1.cpp
        gameWindow.setView(view);
        gameWindow.clear();
        gameWindow.draw(smap);
        gameWindow.draw(*player);
        gameWindow.draw(*enemy);
        gameWindow.draw(*tree);
        gameWindow.draw(pauseMenu);

        gameWindow.display();
 

I imagine it's a problem with the draw function, maybe the shape/text objects I'm trying to draw don't exist or something?

**EDIT**
I whipped up a simple version of the GUI system in another application and it works completely fine...

Here's that source

main.cpp
        sf::RenderWindow renderWindow(sf::VideoMode(640,480), "Color");
        sf::Event event;

        GUI menu(sf::Vector2f(50,150), sf::Vector2f(250,50));
        menu.addButton(sf::Vector2f(40,15), sf::Vector2f(255, 60));
        menu.addButton(sf::Vector2f(40,15), sf::Vector2f(255, 80));
        menu.addButton(sf::Vector2f(40,15), sf::Vector2f(255, 100));

        renderWindow.setFramerateLimit(30);

        while (renderWindow.isOpen())
        {
                while(renderWindow.pollEvent(event))
                {
                        if(event.type == sf::Event::EventType::Closed)
                                renderWindow.close();
                        if(event.type == sf::Event::KeyPressed)
                        {
                                if(event.key.code == sf::Keyboard::Escape)
                                {
                                        if(menu.visible)
                                                menu.hide();
                                        else
                                                menu.show();
                                }
                        }
                }


                renderWindow.clear();
               
                renderWindow.draw(menu);

                renderWindow.display();
 

GUI.h

#include "SFML\Graphics.hpp"

class Button;
class GUI : public sf::Transformable, public sf::Drawable
{
public:
        GUI();
        //dimensions, position, background color, border color
        GUI(sf::Vector2f dimensions, sf::Vector2f position);
       
        //dimensions, position, text, button color, border color textcolor, font name ".txt"
        void addButton(sf::Vector2f dimensions, sf::Vector2f position);
        void show();
        void hide();

        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;

        bool visible;
        std::vector<Button> buttons;
private:
        sf::RectangleShape background;
};

class Button
{
public:
        Button();
        Button(sf::Vector2f dimensions, sf::Vector2f position);
        sf::RectangleShape buttonBackground;
};
 

GUI.cpp
#include "GUI.h"

GUI::GUI()
{}
GUI::GUI(sf::Vector2f dimensions, sf::Vector2f position)
{
        background.setPosition(position);
        background.setSize(dimensions);
        background.setFillColor(sf::Color::Green);
        visible = false;
}
void GUI::addButton(sf::Vector2f dimensions, sf::Vector2f position)
{
        buttons.push_back(Button(dimensions,position));
}
void GUI::show()
{
        visible = true;
}
void GUI::hide()
{
        visible = false;
}
void GUI::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
        if(!visible)
                return;

        states.transform *= getTransform();
        target.draw(background);
        for(int i = 0; i < 3; i++)
        {
                target.draw(buttons[i].buttonBackground);
        }
}
Button::Button(sf::Vector2f dimensions, sf::Vector2f position)
{
        buttonBackground.setSize(dimensions);
        buttonBackground.setPosition(position);
        buttonBackground.setFillColor(sf::Color::Blue);
}
 

Really not sure what the problem is here. Thanks for all the help so far by the way, everything's been cake since. Not sure why this system is messing with me so much.
« Last Edit: February 21, 2016, 02:12:30 am by Ausche »
Struggling to make a game happen!

Ausche

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Draw function, Iterators, Bounds error
« Reply #6 on: February 21, 2016, 06:01:45 am »
Okay, it seems I've solved my problem and I'm not sure how. Everything works as it should, finally!

Thanks again for all the help. +1
Struggling to make a game happen!