【问题标题】:Getting player position, cannot pass object instance over due to include loop获取玩家位置,由于包含循环,无法传递对象实例
【发布时间】:2020-04-07 13:14:48
【问题描述】:

我目前正在使用 C++ 和 SFML 制作 Space Invaders 的克隆,并且似乎对玩家的位置有疑问。

目前,当入侵者射击时,玩家的hit-box继续是玩家的起始位置,记录为900、500。这个hit-box不会移动玩家。我不确定为什么以及如何解决它。我知道我不能将 game.h 包含到inavivers.h 中,因为 game.h 包含了invenders.h,因此会导致包含循环。我需要获取在game.h中创建的玩家实例,并将其传递给inviders.h,以便玩家的hit-box也被传递。

这是与入侵者射击和玩家位置相关的代码。

游戏.h

#include "Player.h"
#include "invaders.h"
class Game
{
private:
Player* player;
vector<Invaders*> vInvaders;
public:
void updateInputs();
};

游戏.cpp

#include "Game.h"
void Game::updateInputs()
{
    //Updates player movement.
    player->updateInputs();

    //Creating bullets.
    if ((Keyboard::isKeyPressed(Keyboard::Space)) && (this->player->bCanAttack()))
    {
        this->vBullets.push_back(new Bullet(this->textures["BULLET"], this->player->getPos().x, this->player->getPos().y, 0.f, -1.f, 5.f));
        SoundEngine::playShot();
    }
//Move player.
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        move(-1.f, 0);
        getBounds();
        //cout << player->getBounds().left << " " << player->getBounds().top << endl;
    }
    if (Keyboard::isKeyPressed(Keyboard::Right))
    {
        move(1.f, 0);
        getBounds();
        //cout << player->getBounds().left << " " << player->getBounds().top << endl;
    }
}

播放器.h

class Player
{
public:
const FloatRect getBounds() const;
void move(const float kfDirX, const float kfDirY);
};

播放器.cpp

#include "Player.h"
const FloatRect Player::getBounds() const
{
    return this->sprite.getGlobalBounds(); //Returns the bounding box of player.
}

void Player::move(const float kfDirX, const float kfDirY)
{
    this->sprite.move(this->fSpeed * kfDirX, 0); //Moves player across screen.
}

入侵者.h

#include "Player.h" //It is not needed, but doesn't work without it.
class Invaders
{
private:
Player player; //It is not needed, but does't work without it. Need the instance from Game.h, don't need to make a new instance here.
public:
void updateBullets();
};

入侵者.cpp

#include "Invaders.h"
void Invaders::updateBullets()
{
    unsigned int iCounter = 0;
    for (auto* invaderBullet : this->vInvaderBullets)
    {
        invaderBullet->update();

        for (size_t k = 0; k < this->vInvaderBullets.size(); k++)
        {
            //THIS DOES NOT WORK!!!!
            if (this->vInvaderBullets[k]->getBounds().intersects(player.getBounds()))
            {
                cout << player.getBounds().left << " " << player.getBounds().top << endl;
                this->vInvaderBullets.erase(this->vInvaderBullets.begin() + k);
                this->player.isDead(true);
                Variables::iLives--;
            }
            else
            {
                this->player.isDead(false);
            }
        }

        //Bullet culling at bottom of screen.
        if ((invaderBullet->getBounds().top + invaderBullet->getBounds().height) > 1100.f)
        {
            //std::cout << this->invaderBullets.size() << std::endl;
            delete this->vInvaderBullets.at(iCounter);
            this->vInvaderBullets.erase(this->vInvaderBullets.begin() + iCounter);
            iCounter--;
            //Check to see if bullets are deleted.
            //std::cout << this->invaderBullets.size() << std::endl;
        }
        iCounter++;

        for (size_t k = 0; k < this->vInvaderBullets.size(); k++)
        {
            if (this->vInvaderBullets[k]->getBounds().intersects(this->barrier.getBounds(1)))
            {
                SoundEngine::playBarrierHit();
                this->vInvaderBullets.erase(this->vInvaderBullets.begin() + k);
                this->barrier.barrierHit(1);
            }
            else if (this->vInvaderBullets[k]->getBounds().intersects(this->barrier.getBounds(2)))
            {
                SoundEngine::playBarrierHit();
                this->vInvaderBullets.erase(this->vInvaderBullets.begin() + k);
                this->barrier.barrierHit(2);
            }
            else if (this->vInvaderBullets[k]->getBounds().intersects(this->barrier.getBounds(3)))
            {
                SoundEngine::playBarrierHit();
                this->vInvaderBullets.erase(this->vInvaderBullets.begin() + k);
                this->barrier.barrierHit(3);
            }
            else if (this->vInvaderBullets[k]->getBounds().intersects(this->barrier.getBounds(4)))
            {
                SoundEngine::playBarrierHit();
                this->vInvaderBullets.erase(this->vInvaderBullets.begin() + k);
                this->barrier.barrierHit(4);
            }
        }
    }
}

【问题讨论】:

  • 您是否尝试过使用#pragma once 来打破包含循环?
  • 我有,但它无法解决循环
  • 您的代码不存在任何包含循环。 3 个标头中的任何一个都不需要任何其他标头才能工作,但很明显它们并不完整。请提供minimal reproducible example.cpp文件在这里可能没用,可以省略)
  • 这将有助于循环包括:stackoverflow.com/questions/625799/…
  • 我需要获取在 game.h 中创建的玩家实例,并将其传递给inviders.h,以便同时传递玩家的命中框。它现在编译的唯一原因是因为我在 inavders.h 中创建了一个新的 Player 实例。

标签: c++ sfml


【解决方案1】:

Player 类型的成员放入Invaders 意味着它是一个单独的对象,可能与Game 使用的Player 不同。所以最有可能的玩家移动发生在GamePlayer 上,但入侵者的目标是他们自己独特的Player 并没有移动。

由于Invaders::updateBullets() 需要Player 对象,因此有几个选项:

  • Player&amp;Game&amp; 传递给updateBullets 函数。
  • 使 Game 成为单例,使用公共方式从任何上下文中获取 Game 对象及其 Player 对象。
  • Invaders 类中保留Player*Game* 指针 - 但如果这些对象可能在Invaders 对象之前被销毁,那么处理它会很棘手。这可能有点“浪费”。

一般来说,记住如果您只是处理指向该类的指针或引用,则不需要类定义,这有助于减少所需的#include 指令。例如,您可以更改 Game.h 和 Game.cpp:

// Game.h
#ifndef GAME_H
#define GAME_H

#include <vector>

class Player;
class Invaders;

class Game
{
private:
    Player* player;
    std::vector<Invaders*> vInvaders;
public:
    void updateInputs();
};

#endif

// Game.cpp
#include "Game.h"
#include "Player.h"
#include "Invaders.h"

// ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多