最有效的方式产卵和摧毁对象无尽的赛跑游戏? [关闭]

问题描述 投票:-1回答:1

我目前对SFML很新,我想知道根据摄像头位置生成和销毁矢量中对象的最有效方法是什么?目前我正在实例化一个墙“向量”的向量,它将在调试后链接在一起。我应该根据凸轮位置创建和销毁它们还是将现有的位置移动到正确的位置?

我也不介意对我的代码提出一些反馈意见。

Cave 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

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

谢谢您的帮助。

c++ sfml
1个回答
4
投票

Code Review

因此,首先stackoverflow不是代码审查的正确站点。如果您寻求完整的评论,请咨询codereview。但是,我注意到以下一些事情:

  1. 不要使用randsrand。如果你想让RNG使用<random>(通常是uniform_int_distributionuniform_real_distribution)。
  2. 你为什么在locationsX上使用原生数组? std::vector似乎更合理。
  3. 避免在性能关键循环中频繁分配(例如,你在每次游戏循环迭代时调用WallSpawn,而WallSpawn本身每次都会创建一个新的向量sf::CircleShape,可以避免)。稍后会详细介绍。
  4. 如果您估计最终矢量大小,则使用std::vectorvector.reserve()预分配空间。
  5. 为什么在窗口循环中有两个事件循环而不是一个?
  6. 使用auto而不是std::vector<sf::CircleShape>::iterator提高了可读性。

Design

通常游戏循环看起来像这样:

  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;
};

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

Entity Management

拥有数千或数百万游戏实体(车辆,树木,岩石,墙壁,武器,弹药,射弹,人群,NPC ......)的大型游戏存在的问题是,在管理它们时它们必须非常高效。但是,在您的情况下,有一些简单的圆形,有效的管理并不是真正的问题。如果你不需要,不要优化。

你提供的关于游戏行为的信息太少,无法提出深入推荐,所以这里有一些猜测。

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

通常std::vector在容器方面是一个坚实的allrounder。

当您不再需要实体时,请务必销毁它们。例如,如果您的墙壁点离开视口(并且您确定它们不会再次进入),请将其移除到容器中。

Putting Things Together

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

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);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.