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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Athenian Hoplite

Pages: [1] 2
1
General / Re: UI click detection
« on: May 26, 2020, 02:08:36 pm »
I thought it was more common to go a "bottom-up" approach. That you detect the clicks on whatever elements are shown to the user and then each UI element can be configured to consume or propagate the event to their parent.

That is indeed what I do. When a UI element has subscribed to a certain event he gets notified and then can choose to either consume or propagate upwards. My event system is indeed "bottom-up". When I was talking from top to bottom I was referring to how to detect which UI element is being directly manipulated, in which case my system behaves as a sort of tree where I only go down one level if mouse position is within bounds of the Rect of that node int the tree (UI element) and as such I find always the deepest-in-the-hierarchy element. Which is exactly my issue since I want to be able to place elements outside the bounds of their parents.

Edit: I also do realize that I could simply ignore this and do these checks in the relevant event functions themselves but then if I have 50 subscribers to "onClick" I will run 50 on event functions for If I'm lucky only 1 of them to actually fire (the element over which the mouse was at the time of clicking).

2
General / Re: UI click detection
« on: May 26, 2020, 11:40:26 am »
Although that does make sense I have no way of concatenating the child's bounds into the parent just like that since I'm using a simple sf::Rect as the bounding box. My worst case scenario solution is to change the isWithinBounds(pos) function of my UIElement class that I use to search and return true if it is within its own bounds or one of its children since that would certainly fix it but that is already O(n) complexity just for that. I'd end up with O(n^2) complexity UI mouse detection and that jiggles my nerves. That is basically my last option if I don't get any better ideas

3
General / UI click detection
« on: May 26, 2020, 12:09:29 am »
Hey,

In implementing my UI I have come to a standstill.
Right now to detect which UI element is being being focused I simply transverse my UI layers top to bottom and check to see if the mouse position is inside the UI elements rect. If it is I check to see if it also is inside one of its children's rect, that way I can always focus the deepest-in-the-hierarchy element.

Consider this simple hierarchy:
- Panel
    - TextBox

If my textbox is actually placed outside of the rect of its parent (either the whole textbox or even a part of it) then I will never be able to focus it since I always check from top to bottom in the UI hierarchy. This could be fixed if I forced child UI elements to be inside their parent's rect but I don't like that restriction since it takes away too much flexibility.

Now to solve this I could change my system to use a quad tree in which I would place my UI elements and not only would the whole process be probably much faster but I would get around this last issue. However it would bring about the new issue where I could no longer guarantee that the focused UI element is the deepest in the hierarchy, and this would put me at the mercy of clicking in a text box inside a panel and having the system return me the panel as the focused element instead of the text box.

Any ideas ?

Thanks in advance,
AH

4
Graphics / Re: sf::Text and "\n"
« on: May 25, 2020, 10:30:35 pm »
Scrap that. I was adding a "\n" in the middle of the text so that its was actually letter spacing that was making this happen.
My bad !

5
Graphics / sf::Text and "\n"
« on: May 25, 2020, 10:15:09 pm »
Hi,

When playing around with sf::Text today I noticed that when adding "\n" to the text's string it's width increased by 1. Is this always the case ? Or is it related to character size or character spacing in any way ?

Thanks in advance,
AH

6
Graphics / Re: FFMpeg and SFML
« on: May 25, 2020, 09:45:44 pm »
Have you checked out sfeMovie ?

7
System / Re: sf::Event::keyReleased dosent respond
« on: May 25, 2020, 03:31:12 pm »
Key events have a delay already so you don't need to wait to prevent multiple events from a single click (if that is why you are using the delay). You can simply catch a sf::Event::KeyReleased and toggle your pause variable since the way you are doing it ANY events during pause get no answer.

Regardless of this the main point was: is this the only place you are looping window events ? If not you are loosing them somewhere else.

bool paused = false;
sf::Event event;
while (window->pollEvent(event))
{
        if (event.type == sf::Event::KeyReleased)
        {
                if (event.key.code == SPACE)
                {
                          paused = ! paused;
                }
         }
}
 

This code will work if this is the only place you loop window events. How exactly you would then use the "paused" variable is actually another matter.

8
System / Re: sf::Event::keyReleased dosent respond
« on: May 25, 2020, 02:38:36 pm »
What is this code doing ? You check if the space was released and then if it is you check again if the space is released ? Really you should simply catch sf::Event::KeyReleased and toggle your pause variable/method. Also note that if this isn't the only place you are pumping the window then you might be loosing events. Besides the way that your implementing this will also cause loss of any events that happen while you wait for space to be released again which might be fine since the game is paused but then again it might not.

9
General discussions / Re: Init of static member object
« on: May 24, 2020, 07:39:43 pm »
Just

sf::RenderWindow A::window;

No need to copy-construct from a default-constructed instance ;)
whoops-a-daisy ;D ;D
edited

10
General discussions / Re: Init of static member object
« on: May 24, 2020, 06:05:18 pm »
What code is producing that error ? I have compiled the code with no errors so this is not what is giving you that.

11
General discussions / Re: Init of static member object
« on: May 24, 2020, 05:42:59 pm »
What I told you before works. sf::RenderWindow defines more than one constructor which can be used to instantiate static variables the way I described. You can also derive a class from sf::RenderWindow if you prefer but that is beside the point.

Note: C++ doesn't have "static constructors" like in C#.

This works:
class A
{
  public:
  static sf::RenderWindow window;
};

sf::RenderWindow A::window;
 

12
General discussions / Re: Init of static member object
« on: May 24, 2020, 05:12:54 pm »
Like all other static objects. In your cpp file I'd imagine. 

// Header file
class A
{
  public:
  static sf::RenderWindow window;
};

// Cpp file
sf::RenderWindow A::window;
 

You can use the default constructor and then at runtime use the sf::RenderWindow::create method to (re) create the window with the parameters you somehow got programmatically or replace "= sf::RenderWindow();" with the usual constructor and pass the arguments you want hardcoded.

13
Window / Re: Can't make CTRL + mouse wheel work
« on: May 24, 2020, 01:03:02 pm »
The sf::Event class stores its members in a union. If a sf::Event is of type sf::Event::MouseWheelMoved then it's defined member is "event.mouseWheel". To access the member "event.key" you need to have an event that is of type "sf::Event::KeyPressed" (or released).

A union is a region of memory that can be interpreted in different ways. When you access a member in a union you are requesting that memory to be given to you in that "interpretation". So although you are getting event.key the memory is actually meaningless because the memory stored in the union is for event.mouseWheel. Because of a stroke of luck it just so happens that when reading event.key the memory is layed out in such a way that it reads "true" for event.key.control.

https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1Event.php

To achieve what you want you first need to catch a sf::Event::KeyPressed and check to see if control is pressed (or not) and store that somewhere. Then in that code that you posted you need to check if your variable in which you stored if control is pressed is true.

14
General discussions / Re: sf::Thread (Loading Demo)
« on: May 24, 2020, 12:38:25 pm »
When creating the thread you are suposed to assign it a function to do work. What you posted here creates a thread that simply changes the value of "done" to true. My comment "// DOING HEAVY DUTY WORK HERE" actually was meant to be replaced by the work you wanted done there, meaning tile creation code.

The separate thread (meaning separate from the main thread), will build the tiles and when its done it will set "done" to true.
In the update loop while "done" is still false (meaning the separate thread has still not finished building the tiles since in the end it sets "done" to true) you draw the text. Your update loop keeps going checking every time time it loops if "done" is true. When the thread finishes your update loop will detect that "done" is now true and will draw the tiles instead.

Remember that you will need to reassign the sf::View you normally use because while "done" is false you are setting the default view to draw the text.

Note: Since you are creating the tiles on a separate thread with smart pointers they will go out of scope when the thread function finishes due to RAII. You need to actually allocate the memory for the tiles outside the thread function or move the created memory to a variable in a scope outside the thread to do this the vector itself would need to be wrapped in a smart pointer.

Example with memory allocation in main thead.

// Still in main thread
std::vector<std::shared_ptr<Tile>> tilesVector;
tilesVector.reserve(Map_Height * Map_Width); // This creates the tiles with default constructor ( Tile() )

std::atomic<bool> done(false);

// Create thread to execute the bellow code while main thread continues normal execution
std::thread t([&done, &tilesVector] {
// Tile creation IS the heavy duty work
for(auto y = 0; y < Map_Height; ++y)
{
    for (auto x = 0; x < Map_Width; ++x)
    {
       Tile * tile = tilesVector[y * Map_Width + x].get(); // Get a pointer to tile to change its attributes
       tile->spr.setSize(TILE_SIZE);
       tile->spr.setFillColor({ 0,255,0,15 });
       tile->spr.setOutlineColor(sf::Color::White);
       tile->spr.setOutlineThickness(1.f);
       tile->spr.setPosition(x * TILE_SIZE.x, y * TILE_SIZE.y);
       tile->spr.setOrigin(TILE_SIZE.x / 2.f, TILE_SIZE.y / 2.f);

       if (y >= 240 && y <= 260 && x >= 240 && x <= 260)
       {
             tile->spr.setFillColor({ 200,25,22 });
       }
                               
       // tiles.emplace_back(std::move(tile)); This line no longer needed, we already have our tile vector
    }
}

// After building the tiles we set variable to true to signal that our work
// (tile creation) on this separate thread is done.
done = true;

});

/* Meanwhile main thread continued to execute and do its thing */

/* ... Update loop ... */

while(window.open())
{
    /*
    ..... Any other stuff you do on the update loop here ....
    */


   window.clear();

   if ( ! done) // If the thread has not finished it's work yet
   {
      window.setView(window.getDefaultView());
      window.draw(text);
   }
   else
   {
       // Here tile drawing code
   }
   
   window.display();
}

 

15
General discussions / Re: sf::Thread (Loading Demo)
« on: May 21, 2020, 07:19:48 pm »
First off you should really be using std::thread or std::async. No reason to use SFML's implementation since C++11.

Other than that there are a few problems even discarding the error you get. First off always better to pass specifically what you wish to use in the lambda's capture (window& etc) instead of global reference (&).

The function you called in the thread should be the function that is doing all the work (creating the rectangles) and not the one drawing text on screen. Why create a thread for something so trivial as creating a text instance and calling draw on it? Further if you call draw on the text in the thread's function then after you call window.clear() in your update loop then you have to call draw on the text again.

What you want is for text to appear as the shape creation is being done. So you create shapes on a separate thread, while the main thread continues its execution and draws that text on screen. When creation is done the main thread removes loading text and goes on with its business.

Minimal example:
    // Atomic variable guarantes that only one thread messes with it at a time
    std::atomic<bool> done(false);

    // Create shapes on another thread
    std::thread t([&done] {
        // DOING HEAVY DUTY WORK HERE
        done = true; // Set variable in the end to signal that its done
    });

/* ......... */

   // Meanwhile in the game's update loop somewhere

   if (done)
   {
       // Remove loading text
       // Draw tiles with culling
   }
   else
   {
      window.draw(loadingText);
   }

/* ......... */

 

This is just one way (a very simple and bad way) to do this. Really this should be done using std::promise. Threads are a very interesting but also very difficult topic that brings it's own very wide set of challenges. If you want to learn more about threads (which I encourage you to do because it's a very interesting topic) you should really be doing that rather than learning about them with the use of SFML.

On a further note for culling in a 2D environment you are much better off using a quad tree in which you place your drawable entities as a more general approach.

Pages: [1] 2