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

Author Topic: SFML game dev book. Stuck at implementing the fire mechanic  (Read 1856 times)

0 Members and 1 Guest are viewing this topic.

jonathansty

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Hello everyone,

I'm currently working through the SFML game dev book but I stumbled upon a problem that I can't seem to fix.
This is the method that handles initializing the actions.
void Player::initializeActions()
{
    m_ActionBinding[MoveRight].action = derivedAction<Aircraft>(AircraftMover(1, 0.f));
    m_ActionBinding[MoveLeft].action = derivedAction<Aircraft>(AircraftMover(-1, 0.f));
    m_ActionBinding[MoveUp].action = derivedAction<Aircraft>(AircraftMover(0.f, -1));
    m_ActionBinding[MoveDown].action = derivedAction<Aircraft>(AircraftMover(0.f, 1));
    m_ActionBinding[Fire].action = derivedAction<Aircraft>(std::bind(&Aircraft::fire, std::placeholders::_1));
}
 
When I compile I get this error:
Error   1       error C3848: expression having type 'const std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Aircraft::* )(void),void,Aircraft,>,std::_Ph<1> &>' would lose some const-volatile qualifiers in order to call 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall Aircraft::* )(void),void,Aircraft,>,std::_Ph<1> &>::operator ()<GameObject&,sf::Time&>(GameObject &,sf::Time &)'      e:\_gamedevelopment\sfml\sfml_flyinggame\command.h      24
 

this is the method I'm trying to bind:
void Aircraft::fire()
{
    if (Table[m_Type].fireInterval != sf::Time::Zero)
    {
        m_IsFiring = true;
    }
}

I'm using Visual studio 2013 ( and it's compiler).

Thanks in advance.

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 878
    • View Profile
Re: SFML game dev book. Stuck at implementing the fire mechanic
« Reply #1 on: July 24, 2015, 09:05:32 pm »
This essentially means you've got a const pointer to an object but you're trying to call a non-const member function on it. It's a bit cryptic, since it's triggered by a combination of template and STL code.

Following is speculation from similar error messages I've had in the past and since I don't have the book (nor have I tried the code), this might actually be totally wrong. :)

In general, MSVC doesn't like you creating objects on the heap right inside parameters and passing them by reference (because they're essentially instantly destroyed again, possibly causing all kind of nasty side effects). Other compilers like GCC won't complain.

So fixing your code might be as simple as moving the object creation into its own line and essentially caching the passed object for a bit:

Code: [Select]
{
    auto &shotbinding = std::bind(&Aircraft::fire, std::placeholders::_1);
    m_ActionBinding[Fire].action = derivedAction<Aircraft>(shotbinding);
}

jonathansty

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: SFML game dev book. Stuck at implementing the fire mechanic
« Reply #2 on: July 25, 2015, 09:16:31 am »

So fixing your code might be as simple as moving the object creation into its own line and essentially caching the passed object for a bit:

Code: [Select]
{
    auto &shotbinding = std::bind(&Aircraft::fire, std::placeholders::_1);
    m_ActionBinding[Fire].action = derivedAction<Aircraft>(shotbinding);
}

I tried moving it right now to a different line seems like the actual binding it doesn't give a problem. Passing it to the template gives the problem. It's not fixed with changing it to a seperate line.

This is the code for the template
template <typename GameObject, typename Function>
Command::Action derivedAction(Function fn)
{
    return[=](SceneNode& node, sf::Time dt)
    {
        //Check if cast is safe
        assert(dynamic_cast<GameObject*>(&node) != nullptr);

        //Downcast node and invoke function on it;
        fn(static_cast<GameObject&>(node), dt);
    };
}

edit:
What I did for now was make a struct like this
struct FireMech
{
    FireMech()
    {

    }
    void operator() (Aircraft& aircraft, sf::Time dt) const
    {
        aircraft.fire();
    }
};
This works and the fire method executes and I can link it. Although I'm still hoping there is a solution for the std::bind problem.
« Last Edit: July 25, 2015, 10:50:49 am by jonathansty »

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 878
    • View Profile
Re: SFML game dev book. Stuck at implementing the fire mechanic
« Reply #3 on: July 25, 2015, 10:53:33 am »
What happens if you change the lambda to pass variables (here fn) by reference (changing [=] to [&])?

But besides that, anything stopping you from just defining another functor similar to the others?

jonathansty

  • Newbie
  • *
  • Posts: 4
    • View Profile
    • Email
Re: SFML game dev book. Stuck at implementing the fire mechanic
« Reply #4 on: July 25, 2015, 12:49:36 pm »
What happens if you change the lambda to pass variables (here fn) by reference (changing [=] to [&])?

But besides that, anything stopping you from just defining another functor similar to the others?
Changing the lambda to pass by reference breaks it. It compiles and launches after a couple of actions it gives an error.

Nothing is stopping me from creating functors at the moment.
Thanks :)

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: SFML game dev book. Stuck at implementing the fire mechanic
« Reply #5 on: July 26, 2015, 11:58:12 pm »
void Aircraft::fire()

...
derivedAction<Aircraft>(  std::bind(&Aircraft::fire, std::placeholders::_1)  );
 
The signatures don't match. The function passed to derivedAction<Aircraft>() expects two arguments, your bind() call returns a nullary function.

For member functions, the first parameter to std::bind() is always the this pointer. The remaining parameters would then be the parameters of the actual function (Aircraft&, sf::Time).

Make sure you understand how std::bind() and std::placeholders work. If you struggle to find a matching expression directly, start with a functor and translate it step-by-step to a bind() expression.


In general, MSVC doesn't like you creating objects on the heap right inside parameters and passing them by reference (because they're essentially instantly destroyed again, possibly causing all kind of nasty side effects). Other compilers like GCC won't complain.
Binding temporary objects to non-const lvalue references is not allowed by C++. There is a MSVC extension that allows it, but usually the compiler warns. Nothing of this has to do with the heap.
« Last Edit: July 27, 2015, 12:00:29 am by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development: