简体   繁体   中英

How can I get a reference of the values in a map in C++?

I want the player of my game to not move if it will collide with other entities. One solution I've thought would be keeping track of all entities in the game, and when trying to move, check if it will collide with any of those. The problem is that when looping the vector, I don't get a reference of the entities, but new values, so they have new IDs and I no more can check if the IDs check.

 // Actor.cpp
Actor::Actor(float x, float y) : x(x), y(y), m_MovementSpeed(1), m_Alive(true) {
    // ...
    EntityTracker::addEntity(*this);
    this->ID = EntityTracker::entityAmount();
}

void Actor::move(float _x, float _y) {
    for (auto& e : EntityTracker::entities()) {
        if (this->ID != e->ID && this->collides(*e)) {
            return;
        }
    }

    this->x = this->x + _x * m_MovementSpeed;
    this->y = this->y + _y * m_MovementSpeed;
    this->m_Sprite.move(_x * m_MovementSpeed, _y * m_MovementSpeed);
}

// EntityTracker.cpp
uint64_t EntityTracker::s_EntityAmount = 0;
std::map<uint64_t, Actor> EntityTracker::s_Entities {};

void EntityTracker::addEntity(const Actor& actor) {
    EntityTracker::s_Entities.insert(std::pair<uint64_t, Actor>(s_EntityAmount, actor));
    s_EntityAmount++;
}

std::vector<Actor*> EntityTracker::entities() {
    std::vector<Actor*> actors;

    for (auto& it : EntityTracker::s_Entities) {
        std::cout << it.second.ID << std::endl;
        std::cout << it.first << std::endl;
        actors.push_back(&it.second);
    }

    return actors;
}

// EntityTracker.h
class EntityTracker {
public:
    static void addEntity(const Actor& actor);
    static bool removeEntity(uint64_t ID);
    static uint64_t entityAmount();
    static std::vector<Actor*> entities();
private:
    static uint64_t s_EntityAmount;
    static std::map<uint64_t, Actor> s_Entities;
};

When I press a key the std::cout's print this:

1571901079888 // actor's internal ID from vector
0 // ID from vector
1571901079888
1
1571901079888
0
...

How can I solve this?

You can return vector of type std::vector<std::reference_wrapper<Actor>> from EntityTracker::entities() , an example of such use is below:

// Original data
std::vector<std::string> vec;
vec.push_back("one");
vec.push_back("two");

// Now its copied as references to rvec
std::vector< std::reference_wrapper<std::string>> rvec;
for(auto& r: vec)
    rvec.push_back(r);
    
// Now output original data using rvec references.
for(auto s: rvec)
    std::cout << s.get() << std::endl;

Then inside Actor::move you will have access to reference of real Actor instead of its copy. You may also consider keeping Actor s as a smart pointers using std::share_ptr .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM