我目前对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);
}
}
在这些物体产生后移动或摧毁这些物体的最佳方法是什么?
如果这种方法完全错误或者我根本不应该使用这种方法,请告诉我。
谢谢您的帮助。
因此,首先stackoverflow不是代码审查的正确站点。如果您寻求完整的评论,请咨询codereview。但是,我注意到以下一些事情:
rand
或srand
。如果你想让RNG使用<random>
(通常是uniform_int_distribution
或uniform_real_distribution
)。locationsX
上使用原生数组? std::vector
似乎更合理。WallSpawn
,而WallSpawn
本身每次都会创建一个新的向量sf::CircleShape
,可以避免)。稍后会详细介绍。std::vector
为vector.reserve()
预分配空间。auto
而不是std::vector<sf::CircleShape>::iterator
提高了可读性。通常游戏循环看起来像这样:
例如,你的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
在容器方面是一个坚实的allrounder。
当您不再需要实体时,请务必销毁它们。例如,如果您的墙壁点离开视口(并且您确定它们不会再次进入),请将其移除到容器中。
考虑到我上面写的所有内容,你的游戏循环现在可能是这样的:
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);
}
}