进行无尽的转轮游戏,最有效的方式来生成和销毁对象?

时间:2019-05-01 00:38:58

标签: c++ sfml

我现在对SFML还是很陌生,我想知道最有效的方法是根据相机位置在矢量中生成和销毁对象吗?目前,我正在实例化墙“点”的向量,该向量将在调试后链接在一起。我应该基于凸轮位置创建或销毁它们,还是将已经存在的凸轮移至正确的位置?

我也不会介意为此提供一些反馈。

保存Chaos.cpp

int main()
{
//get classes from CaveChaos.h
CaveChaos::Wall objWall;
CaveChaos::Player objPlayer;

//set render window size and name
sf::RenderWindow window(sf::VideoMode(800, 600), "CaveChaos");

//set the view
sf::View view1(sf::Vector2f(0.f, 0.f), sf::Vector2f(window.getSize().x, window.getSize().y));

//create the player object as a triangle 
sf::CircleShape Player(20, 3);

//initialise random 
srand(time(0));

//sets the player position to a good position based on camera size
objPlayer.posx = window.getSize().x / 2;
objPlayer.posy = window.getSize().y / 1.1;

Player.setPosition(objPlayer.posx, objPlayer.posy);

//used to instantiate wall points
int locationsX[numofpoints];

//add random x values to locations
for (int i = 0; i < numofpoints; i++)
{
    locationsX[i] = (rand() % 50) + 1;      
}

while (window.isOpen())
{
    sf::Event event;
    //clear the window with black color
    window.clear(sf::Color::Black);
    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed)
            window.close();
    }

    //calls wallspawn in Walls.cpp which creates the wall points
    WallSpawn(window, locationsX );

    //calls playermove in Player.cpp which move the player
    PlayerMove(window, Player);

    while (window.pollEvent(event))
    {
        if (event.type == sf::Event::Closed)
            window.close();
    }

    //set the player as the cam follow point
    view1.setCenter(Player.getPosition().x, Player.getPosition().y - objPlayer.posy / 3);
    //set the view to the player
    window.setView(view1);
    window.display();
}

return 0;
}

当前,当我调用WallSpawn()时,它将循环遍历10个对象并生成它们,是否有办法生成无限数量的对象呢?

Walls.cpp

void WallSpawn(sf::RenderWindow& window, int locationsX[] )
{
//initiate random 
srand(time(0));

//class objects
CaveChaos::Wall objWall;
CaveChaos::Player objPlayer;

//creates a vector of circleshapes 
std::vector<sf::CircleShape> points;

//defines and circle of size 5
sf::CircleShape shape(5);

//loop through all of the points 
for (int i = 0; i < numofpoints; i++)
{   
    //set the shape position to the random variable from CaveChaos.cpp
    shape.setPosition(locationsX[i], objPlayer.posy + i * 55);

    //set shape color to green
    shape.setFillColor(sf::Color(100, 250, 50));

    // copy shape to vector
    points.push_back(shape);
}

// iterate through vector
for (std::vector<sf::CircleShape>::iterator it = points.begin(); it != points.end(); ++it)
{
    //draw wall points on screen
    window.draw(*it);
}
}

在生成这些对象之后移动或销毁这些对象的最佳方法是什么?

我希望最后一点在我前进时被破坏或移到最前面: Position1

当我向前移动时,会发生以下情况: Position2

如果此方法完全错误,或者我根本不应该使用此方法,请告诉我。

感谢您的帮助。

1 个答案:

答案 0 :(得分:4)

代码审查

因此,首先stackoverflow不是进行代码检查的正确位置。如果您需要完整的评论,请询问codereview。但是,这是我注意到的一些事情:

  1. 请勿使用randsrand。如果要使用RNG,请使用<random>(通常为uniform_int_distributionuniform_real_distribution)。
  2. 您为什么要对locationsX使用本机数组? std::vector似乎更合理。
  3. 避免在性能关键循环内频繁分配(例如,每次游戏循环迭代都调用WallSpawnWallSpawn本身每次都会创建一个新的向量sf::CircleShape),这可以避免。稍后再讨论。
  4. 如果您估算了最终向量的大小,请使用std::vectorvector.reserve()预先分配空间。
  5. 为什么在窗口循环中为什么会有两个事件循环而不是一个?
  6. 使用auto代替std::vector<sf::CircleShape>::iterator可以提高可读性。

设计

通常,游戏循环如下所示:

  1. 轮询窗口事件并处理用户输入,
  2. 更新游戏状态(响应输入,应用物理,角色移动等),
  3. 绘制新的游戏状态。

例如,您的WallSpawn函数显示了不应执行的操作。您要生成新的游戏实体(墙点),然后在相同的函数中立即绘制它们。

我对SFML的经验有限,但是我知道有一个sf::Drawable基类,可以用于需要在窗口上绘制的所有内容。您不必使用它,但它旨在简化OOP开发。例如,您可以为您的墙点或整个墙创建类型(取决于您对这些点的实际用途):

class WallPoint : public sf::Drawable 
{
public:
    WallPoint(int x, int y) :
        position(x, y), circle(x, y, 5)
    {
    }

    /*
     * Getter and setter for position 
     */

    void draw(RenderTarget& target, RenderStates states) const override
    {
        target.draw(circle);
    }

private:
    sf::Point position;
    sf::CircleShape circle;
};

然后将这些点的集合保存在游戏循环之外的变量中。

实体管理

具有成千上万个游戏实体(车辆,树木,岩石,墙壁,武器,弹药,弹丸,人群,NPC等)的大型游戏存在以下问题:在管理方面,它们必须非常高效他们。但是,在您的情况下,只有几个简单的圆形,有效的管理并不是真正的问题。无需优化就不必优化。

您提供的有关游戏行为的信息太少,无法提出建议,所以这里有些猜测。

游戏进度如何影响您的实体?您的案例(亚军游戏)表明环境不断沿一个轴(左<>右或上<>下)运动。如果这是真的,则意味着您的墙尖始终在当前环境的边缘生成和消失。在这种情况下,std::deque是存储数据的理想容器。

通常,std::vector是涉及容器的可靠工具。

当您不再需要实体时,总会销毁它们。例如,如果您的墙尖离开视口(并且您确定它们不会再次进入视口),则将其移出容器。

把东西放在一起

考虑到我上面写的所有内容,您的游戏循环现在可能像这样:

int main() 
{        
    // Create window and init everything you need

    std::deque<WallPoint> wallPoints;
    // create some initial points

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            // event handling
        }   

        // update game state
        // add new wall points
        // remove old points
        // move the player

        // draw the new game state
        window.Clear();
        for (const auto& point : wallPoints)
            window.draw(point);
        window.draw(player);
    }
}