C++ std::矢量精灵分割错误

C++ std::矢量精灵分割错误,c++,vector,sfml,C++,Vector,Sfml,在一个名为“开放教室”的法语论坛上尝试后,我在这里发帖,但没有答案,我也在这里发帖 所以我警告你,我是C++和SFML的新手,所以可能有一万个错误,我读的书看起来是一本很差的书,所以我试着用Bjarne Stroustrup的书来纠正。 我的问题如下: 我在按Enter键或空格键时创建投射物(同一键盘上有两个播放器)。每次我按下它,我就为新的射弹创建一个射弹精灵的副本,然后我们把它放入一个std::vector。问题是,当我启动游戏时,如果两名玩家同时按下射击键(回车和空格)(我的意思是,只要第

在一个名为“开放教室”的法语论坛上尝试后,我在这里发帖,但没有答案,我也在这里发帖

所以我警告你,我是C++和SFML的新手,所以可能有一万个错误,我读的书看起来是一本很差的书,所以我试着用Bjarne Stroustrup的书来纠正。 我的问题如下:

我在按Enter键或空格键时创建投射物(同一键盘上有两个播放器)。每次我按下它,我就为新的射弹创建一个射弹精灵的副本,然后我们把它放入一个
std::vector
。问题是,当我启动游戏时,如果两名玩家同时按下射击键(回车和空格)(我的意思是,只要第一颗射弹可见),游戏就会崩溃并显示
分段错误(内核转储)
。为了解决这个问题,我创建了两个精灵(每个玩家一个),并对其投射物产生影响。问题是当他们的攻击速度很快时,他们可以在第一颗子弹消失之前发射第二颗子弹,所以碰撞会有问题,因为同一个精灵有两次。。。第一种方法是行不通的。所以,为了解决这个问题,我想使用std::vector。顺便说一句,我不打算只为两名玩家解决这个问题,我计划再增加一些,所以我需要一些可以与1000名玩家一起使用的东西,例如(当然我不会与1000名玩家一起使用,但如果它与该数量一起使用,它也可以与5名玩家一起使用)

为了创建投射物,我使用了对对象精灵的引用,这要归功于我的类游戏中的一个方法。此引用是对std::vector中精灵的引用。我还意识到,如果我们发射第一颗炮弹,等待它消失,然后让两名玩家发射,它会正常工作(有时,它也会崩溃)。。。我不明白为什么,但大多数情况下,当我开始游戏时,它崩溃了

这是我的密码:

std::vector<sf::Sprite> sprites;

int main()
{
    Game game;

    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;
    sf::RenderWindow window(sf::VideoMode(1600, 900), "Bombardes", sf::Style::Default, settings);
    sf::Texture text;
    if (!text.loadFromFile("resources/projectile.png")) {
        logg.error("Could not create texture for projectile. Aborting.");
    }
    Bombard bomb(50, 150, &game, &pSprite, &movement2); // player class
    Bombard bomb2(1550, 850, &game, &pSprite2, &movement);
    std::vector<std::shared_ptr<Projectile>> p;
   while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    if (event.key.code == sf::Keyboard::Return) { // Player 2
                        auto current2 = std::chrono::steady_clock::now();
                        auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(current2 - last2);
                        if (elapsed2.count() >= 1000 / bomb2.getAttackSpeed()) { // Time the frequency of shots
                            last2 = std::chrono::steady_clock::now();
                            if (bomb2.getAmmo() > 0) { // Check if there's still ammo
                                sprites.push_back(sf::Sprite(text)); // New sprite in vector
                                p.push_back(std::make_shared<Projectile>(bomb2.getPos().getX(), bomb2.getPos().getY(), &sprites[sprites.size()-1], &game, bomb2.getProjectileMovement(), bomb2.getPenetration(),
                                bomb2.getSpeed())); // Create the projectile
                                bomb2.fire(); // Remove an ammo
                            }
                        }
                    }
                    else if (event.key.code == sf::Keyboard::Space) { // Player 1
                        auto current = std::chrono::steady_clock::now();
                        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current - last);
                        if (elapsed.count() >= 1000 / bomb.getAttackSpeed()) {
                            last = std::chrono::steady_clock::now();
                            if (bomb.getAmmo() > 0) {
                                sprites.push_back(sf::Sprite(text));
                                p.push_back(std::make_shared<Projectile>(bomb.getPos().getX(), bomb.getPos().getY(), &sprites[sprites.size()-1], &game, bomb.getProjectileMovement(), bomb.getPenetration(), bomb.getSpeed()));
                                bomb.fire();
                            }
                        }
                    }
                    break;
            }
        }
    }
    return 0;
}

谢谢你的帮助

已经发生了很多事情,所以我可能错过了一些事情

有一件事似乎很奇怪:两个玩家在射击时使用相同的
投射物
指针

玩家1射击:第一个射弹是堆分配,你把它的地址保存在
p
中。到目前为止还不错

然后球员2射门。您创建了一个新的投射物(具有正确的位置和精灵等…),但也将其地址存储在
p

除非您已将第一个投射物的地址保存在代码中的其他位置,否则如何访问它?你怎么知道它是否达到了目标(然后,玩家1应该得分)或者是否超出了屏幕(然后你可以删除它以清除内存)

我怀疑它周围有什么东西。也许您应该尝试将所有投射物存储在
std::vector
或更好的
std::vector
中。这样(如果我理解代码正确的话)玩家就可以发射多个炮弹

(如果您想知道
独特的部分,请不要介意询问)


让我们知道你做了什么,好吗

好吧,经过一天的努力,多亏了giant_茶壶的帮助,我想我终于解决了这个问题。但我不确定。 我不再尝试这个问题,但我不明白为什么

我决定使用智能指针,而不是使用原始指针。似乎没有更多的bug了。但是为什么呢?我什么也没变。有件事我不明白。但以下是更改后的代码:

std::vector<sf::Sprite> sprites;

int main()
{
    Game game;

    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;
    sf::RenderWindow window(sf::VideoMode(1600, 900), "Bombardes", sf::Style::Default, settings);
    sf::Texture text;
    if (!text.loadFromFile("resources/projectile.png")) {
        logg.error("Could not create texture for projectile. Aborting.");
    }
    Bombard bomb(50, 150, &game, std::make_shared<sf::Sprite>(pSprite), &movement2);
    Bombard bomb2(1550, 850, &game, std::make_shared<sf::Sprite>(pSprite2), &movement);
    std::vector<std::shared_ptr<Projectile>> p;
   while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    if (event.key.code == sf::Keyboard::Return) { // Player 2
                        auto current2 = std::chrono::steady_clock::now();
                        auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(current2 - last2);
                        if (elapsed2.count() >= 1000 / bomb2.getAttackSpeed()) { // Time the frequency of shots
                            last2 = std::chrono::steady_clock::now();
                            if (bomb2.getAmmo() > 0) { // Check if there's still ammo
                                sprites.push_back(sf::Sprite(text)); // New sprite in vector
                                p.push_back(std::make_shared<Projectile>(bomb2.getPos().getX(), bomb2.getPos().getY(), std::make_shared<sf::Sprite>(sprites[sprites.size()-1]), &game, bomb2.getProjectileMovement(), bomb2.getPenetration(), bomb2.getSpeed())); // Create the projectile
                                bomb2.fire(); // Remove an ammo
                            }
                        }
                    }
                    else if (event.key.code == sf::Keyboard::Space) { // Player 1
                        auto current = std::chrono::steady_clock::now();
                        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current - last);
                        if (elapsed.count() >= 1000 / bomb.getAttackSpeed()) {
                            last = std::chrono::steady_clock::now();
                            if (bomb.getAmmo() > 0) {
                                sprites.push_back(sf::Sprite(text));
                                p.push_back(std::make_shared<Projectile>(bomb.getPos().getX(), bomb.getPos().getY(), std::make_shared<sf::Sprite>(sprites[sprites.size()-1]), &game, bomb.getProjectileMovement(), bomb.getPenetration(), bomb.getSpeed()));
                                bomb.fire();
                            }
                        }
                    }
                    break;
            }
        }
    }
    return 0;
}
std::矢量精灵;
int main()
{
游戏;
sf::上下文设置;
settings.antialiasingLevel=8;
sf::RenderWindow窗口(sf::VideoMode(1600900),“轰炸”,sf::Style::Default,设置);
sf::纹理文本;
如果(!text.loadFromFile(“resources/spolution.png”)){
logg.error(“无法为投射物创建纹理。正在中止”);
}
轰炸炸弹(50、150和游戏,标准::共享(pSprite)和移动2);
轰炸炸弹2(1550850和游戏,标准::共享(pSprite2)和移动);
std::向量p;
while(window.isOpen())
{
sf::事件;
while(window.pollEvent(事件))
{
开关(事件类型){
案例sf::事件::已结束:
window.close();
打破
案例sf::事件::按键:
如果(event.key.code==sf::Keyboard::Return){//Player 2
自动电流2=std::chrono::稳定时钟::现在();
自动elapsed2=std::chrono::duration\u cast(current2-last2);
如果(elapsed2.count()>=1000/bomb2.getAttackSpeed()){//计时放炮频率
last2=std::chrono::stable_clock::now();
如果(bomb2.getAmmo()>0){//检查是否还有弹药
Sprite.push_back(sf::Sprite(text));//矢量中的新Sprite
p、 向后推(std::make_shared(bomb2.getPos().getX(),bomb2.getPos().getY(),std::make_shared(精灵[sprites.size()-1]),&game,bomb2.getprojectlemovement(),bomb2.getpermission(),bomb2.getSpeed());//创建投射物
bomb2.fire();//移除弹药
}
}
}
如果(event.key.code==sf::Keyboard::Space){//Player 1
自动电流=标准::时钟::稳定时钟::现在();
自动运行=标准::计时::持续时间\u转换(当前-上次);
如果(经过的.count()>=1000/bomb.getAttackSpeed()){
last=std::chrono::stable_clock::now();
如果(bomb.getAmmo()>0){
Sprite.push_back(sf::Sprite(text));
std::vector<sf::Sprite> sprites;

int main()
{
    Game game;

    sf::ContextSettings settings;
    settings.antialiasingLevel = 8;
    sf::RenderWindow window(sf::VideoMode(1600, 900), "Bombardes", sf::Style::Default, settings);
    sf::Texture text;
    if (!text.loadFromFile("resources/projectile.png")) {
        logg.error("Could not create texture for projectile. Aborting.");
    }
    Bombard bomb(50, 150, &game, std::make_shared<sf::Sprite>(pSprite), &movement2);
    Bombard bomb2(1550, 850, &game, std::make_shared<sf::Sprite>(pSprite2), &movement);
    std::vector<std::shared_ptr<Projectile>> p;
   while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
                case sf::Event::KeyPressed:
                    if (event.key.code == sf::Keyboard::Return) { // Player 2
                        auto current2 = std::chrono::steady_clock::now();
                        auto elapsed2 = std::chrono::duration_cast<std::chrono::milliseconds>(current2 - last2);
                        if (elapsed2.count() >= 1000 / bomb2.getAttackSpeed()) { // Time the frequency of shots
                            last2 = std::chrono::steady_clock::now();
                            if (bomb2.getAmmo() > 0) { // Check if there's still ammo
                                sprites.push_back(sf::Sprite(text)); // New sprite in vector
                                p.push_back(std::make_shared<Projectile>(bomb2.getPos().getX(), bomb2.getPos().getY(), std::make_shared<sf::Sprite>(sprites[sprites.size()-1]), &game, bomb2.getProjectileMovement(), bomb2.getPenetration(), bomb2.getSpeed())); // Create the projectile
                                bomb2.fire(); // Remove an ammo
                            }
                        }
                    }
                    else if (event.key.code == sf::Keyboard::Space) { // Player 1
                        auto current = std::chrono::steady_clock::now();
                        auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current - last);
                        if (elapsed.count() >= 1000 / bomb.getAttackSpeed()) {
                            last = std::chrono::steady_clock::now();
                            if (bomb.getAmmo() > 0) {
                                sprites.push_back(sf::Sprite(text));
                                p.push_back(std::make_shared<Projectile>(bomb.getPos().getX(), bomb.getPos().getY(), std::make_shared<sf::Sprite>(sprites[sprites.size()-1]), &game, bomb.getProjectileMovement(), bomb.getPenetration(), bomb.getSpeed()));
                                bomb.fire();
                            }
                        }
                    }
                    break;
            }
        }
    }
    return 0;
}