所以我有一个矢量:
vector<Enemy*> enemies;
此向量包含在整个游戏中动态创建的敌人。
if(rand() % 1000 > 998)
{
Enemy * enemy = new Enemy(num_of_enemies);
enemies.push_back(enemy);
}
这个存在的问题是,即使敌人被删除,矢量也在不断增长,这会减慢我的游戏速度。
基本上我想将矢量的内容移动到一个新的,但只有实际拥有敌人的元素。
我读到有一个名为std::move
的东西但是我不确定如何正确实现它,或者它是否会成功移动包含敌人的元素,而不仅仅是整个向量。< / p>
非常感谢任何有关结构化代码实现的帮助。
答案 0 :(得分:1)
这是一个如何处理产卵和绝望的敌人的完整工作流程。请注意,根本没有指针。
产生敌人:
if (if random_float_between_0_and_1() < 0.002)
enemies.push_back(Enemy{arguments});
绝望的敌人;根据你在下面的评论,应该看起来像这样:
auto last_iter = std::remove_if(enemies.begin(), enemies.end(), is_dead);
enemies.erase(last_iter, enemies.end());
在这里,is_dead
是一个函数,它接受Enemy const&
并确定它是否与玩家或屏幕边界相撞:
bool is_dead(Enemy const& enemy) {
return outside_screen_area(enemy) or near_player(enemy);
}
函数outside_screen_area
和near_player
应该很容易实现。
要了解上述代码的工作原理,请参阅std::remove
和std::vector::erase
的文档。
另一件事:根据C ++ 11附带的标准库随机库实现函数random_float_between_0_and_1
。不要对整数随机数使用std::rand
或模运算,它们工作得很糟糕(即它们不是真正均匀分布的,会产生偏差的结果)。
答案 1 :(得分:0)
这个存在的问题是,即使敌人被删除,矢量也在不断增长......
基本上我想将矢量的内容移动到新的......
在我看来,更简单的方法是从原始向量中删除指向已删除对象的指针,而不是制作副本。
指向不再存在的已删除对象的指针与指向现有对象的指针之间没有区别。因此,您必须跟踪必须从矢量中删除的元素。最简单的解决方案是在删除元素后立即删除它。使用智能指针会变得更容易,因为删除指针也会自动删除对象。
std::move
无法帮助您解决此问题。
您可能想要考虑根本不使用手动动态分配。您可以将Enemy
个对象存储在向量中。
当敌人被删除时我会调用类析构函数,而不是[原文如此]我删除
delete
表达式调用析构函数。自己调用它也会有不确定的行为。
答案 2 :(得分:0)
首先,如果你想删除一个随机位置的单个元素,我建议你不要使用像 std :: vector 这样的数据结构。对于删除元素后的元素数,此操作的复杂性为线性 据我所知,你有许多敌人与一个(或许多)玩家并排移动2D屏幕。如果敌人被玩家击中或离开屏幕,它将被删除。你只需遍历敌人列表就可以看到这些条件得到满足 在这种情况下,我建议您使用 std :: map 来管理您创建的敌人对象 假设您的Enemy类具有检查删除条件的功能,例如:
bool Enemy::willbeDeleted() /* if true then will be deleted */
然后这是一个使用 std :: map 来管理敌人对象的类:
EnemyManager.hpp
#include <map>
class EnemyManager {
public:
/*
* Get the Enemy Manager
*/
static EnemyManager& Instance();
/*!
* Delete the instance of EnemyManager
*/
static void deleteInstance();
public:
/* Create an enemy object */
void createEnemy();
/* Check all enemy objects and delete any fulfulling condition */
void checkEnemy();
virtual ~EnemyManager();
private:
/* Make sure we can not call EnemyManager constructor directly */
EnemyManager();
EnemyManager(const EnemyManager& objManager);
/* Instance of EnemyManager */
static EnemyManager* enemyManager;
private:
/* List of current enemy objects */
std::map<int, A*> enemyList_;
/* Identity of already-create object, it increases on creating a new object */
int enemyIndex_;
};
EnemyManager.cpp
#include "EnemyManager.hpp"
#include <vector>
EnemyManager* EnemyManager::enemyManager = 0;
EnemyManager& EnemyManager::Instance()
{
if (0 == enemyManager)
{
enemyManager = new EnemyManager();
}
return *enemyManager;
}
void EnemyManager::deleteInstance()
{
if (0 != enemyManager) delete enemyManager;
}
EnemyManager::EnemyManager() : enemyList_(), enemyIndex_(0)
{}
EnemyManager::~EnemyManager() {
/* Nothing todo */
}
void EnemyManager::createEnemy()
{
enemyList_[enemyIndex_] = new Enemy();
++enemyIndex_;
}
void EnemyManager::checkEnemy()
{
std::map<int, A*>::const_iterator itb = enemyList_.begin(),
ite = enemyList_.end(), it;
// Vector containing id of enemy object to delete
std::vector<int> enemyToDelete;
for (it = itb; it != ite; ++it)
if ((it->second)->willbeDeleted())
enemyToDelete.push_back(it->first);
// Delete enemies and remove them from map
for (std::size_t idx = 0; idx < enemyToDelete.size(); ++idx)
{
delete enemyList_[enemyToDelete[idx]];
enemyList_.erase(enemyToDelete[idx]);
}
}
您可以使用此课程如下: 在main.cpp中
EnemyManager& enemyManager = EnemyManager::Instance();
if(rand() % 1000 > 998)
{
/* Create new enemy */
enemyManager.createEnemy();
}
/* Check all enemies */
enemyManager.checkEnemy();
有两个重要的功能: createEnemy 控制创建新Enemy对象的方式, checkEnemy 验证对象并在需要时删除它们并且enemyList_的大小不会永远增加:)
我相信通过这种方法,删除敌人不会再减慢程序的速度
这种方法的一个缺点是创建的对象的数量可以被限制为2 ^(8 * sizeof(enemyIndex _))