获取玩家位置,由于包含循环而无法传递对象实例
Getting player position, cannot pass object instance over due to include loop
我目前正在使用 C++ 和 SFML 开发 Space Invaders 的克隆,并且玩家位置似乎有问题。
目前,入侵者射击时,玩家的hit-box仍然是记录为900、500的玩家的起始位置。这个hit-box不会移动玩家。我不确定为什么以及如何解决它。我知道我不能将 game.h 包含到 invaders.h 中,因为 game.h 包含 invaders.h 从而导致包含循环。我需要获取在 game.h 中创建的播放器实例,并将其传递给 invaders.h,以便玩家的 hit-box 也被传递。
这是与入侵者射击和玩家位置相关的代码。
Game.h
#include "Player.h"
#include "invaders.h"
class Game
{
private:
Player* player;
vector<Invaders*> vInvaders;
public:
void updateInputs();
};
Game.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;
}
}
Player.h
class Player
{
public:
const FloatRect getBounds() const;
void move(const float kfDirX, const float kfDirY);
};
Player.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.
}
Invaders.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();
};
Invaders.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);
}
}
}
}
将 Player
类型的成员放入 Invaders
意味着它是一个单独的对象,并且可能与 Game
使用的 Player
不同。所以最有可能的玩家移动发生在 Game
的 Player
,但入侵者的目标是他们自己的 Player
,而 Player
没有移动。
由于Invaders::updateBullets()
需要Player
对象,几个选项是:
- 将
Player&
或 Game&
传递给 updateBullets
函数。
- 使
Game
成为单例,使用 public 方法从任何上下文中获取 Game
对象及其 Player
对象。
- 在 class
Invaders
中保留一个 Player*
或 Game*
指针 - 但如果这些对象可能在 Invaders
对象之前被销毁,处理那个会很棘手。而且这个可能有点"wasteful".
一般来说,请记住,如果您只是处理指向 class 的指针或引用,则不需要 class 定义,这有助于减少所需的 #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"
// ...
我目前正在使用 C++ 和 SFML 开发 Space Invaders 的克隆,并且玩家位置似乎有问题。
目前,入侵者射击时,玩家的hit-box仍然是记录为900、500的玩家的起始位置。这个hit-box不会移动玩家。我不确定为什么以及如何解决它。我知道我不能将 game.h 包含到 invaders.h 中,因为 game.h 包含 invaders.h 从而导致包含循环。我需要获取在 game.h 中创建的播放器实例,并将其传递给 invaders.h,以便玩家的 hit-box 也被传递。
这是与入侵者射击和玩家位置相关的代码。
Game.h
#include "Player.h"
#include "invaders.h"
class Game
{
private:
Player* player;
vector<Invaders*> vInvaders;
public:
void updateInputs();
};
Game.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;
}
}
Player.h
class Player
{
public:
const FloatRect getBounds() const;
void move(const float kfDirX, const float kfDirY);
};
Player.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.
}
Invaders.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();
};
Invaders.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);
}
}
}
}
将 Player
类型的成员放入 Invaders
意味着它是一个单独的对象,并且可能与 Game
使用的 Player
不同。所以最有可能的玩家移动发生在 Game
的 Player
,但入侵者的目标是他们自己的 Player
,而 Player
没有移动。
由于Invaders::updateBullets()
需要Player
对象,几个选项是:
- 将
Player&
或Game&
传递给updateBullets
函数。 - 使
Game
成为单例,使用 public 方法从任何上下文中获取Game
对象及其Player
对象。 - 在 class
Invaders
中保留一个Player*
或Game*
指针 - 但如果这些对象可能在Invaders
对象之前被销毁,处理那个会很棘手。而且这个可能有点"wasteful".
一般来说,请记住,如果您只是处理指向 class 的指针或引用,则不需要 class 定义,这有助于减少所需的 #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"
// ...