首页 > 解决方案 > C ++ SFML如何用自己的物理特性使子弹产生?

问题描述

我正在用 C++ 和 SFML 制作一个简单的子弹地狱游戏,您可以在其中使用鼠标控制播放器,然后单击目标以增加分数。每次点击一个目标时,它都应该在远离玩家的位置生成一颗子弹,并且具有随机的行进角度。子弹从窗户边缘弹开,并没有消失。

我真的很困惑如何做到这一点,我可能想尝试的一种方法是将子弹数据存储到一个向量中,我还不确定该怎么做,但是,我怎样才能更新每个子弹的位置一旦他们在那里?那么我怎样才能让每个子弹与玩家碰撞检查呢?

这是我的代码,我用许多问号的注释标记了一些有问题的区域:

#include <ctime>
#include <sstream>
#include <vector>

using namespace sf;

//?????????????????????
class enemy{
public:

    int xpos, ypos, xvel, yvel;

    void spawnEnemy(){
        CircleShape enemyc(10);
        enemyc.setFillColor(Color::Red);
    }
};
//?????????????????????

int main(){

    RenderWindow window(VideoMode(800, 600), "SFMLbullet", Style::Close);
    window.setMouseCursorVisible(false);
    window.setFramerateLimit(60);

    srand(time(0));

    //?????????????????????
    std::vector<enemy> enemies;
    //?????????????????????

    //define target
    int targetx = rand() % 580 - 20;
    int targety = rand() % 580 - 20;
    bool tregen = false;
    CircleShape targetc(20);
    targetc.setFillColor(Color::Green);

    //define player
    CircleShape playerc(10);
    playerc.setFillColor(Color::Blue);
    playerc.setOrigin(10,10);

    //define score count
    int score = 0;
    std::stringstream scoreconv;
    Font scorefont;
    scorefont.loadFromFile("SLANT.TTF");
    Text scorecount;
    scorecount.setFont(scorefont);
    scorecount.setCharacterSize(50);
    scorecount.setFillColor(Color::White);
    scoreconv.str("0");

    //main Loop
    while(window.isOpen()){

        //when target is clicked
        if(Mouse::isButtonPressed(Mouse::Left) && !tregen && playerc.getGlobalBounds().intersects(targetc.getGlobalBounds())){

            //generate new target
            targetx = rand() % 780 - 20;
            targety = rand() % 580 - 20;

            //add score
            score++;
            scoreconv.str("");
            scoreconv << score;

            //?????????????????????
            enemy bullet;
            enemies.push_back(bullet);
            //?????????????????????

            tregen = true;
        }
        //don't regenerate target rapidly
        if(!Mouse::isButtonPressed(Mouse::Left)){
            tregen = false;
        }

        //window events
        Event event;
        while(window.pollEvent(event)){

            if(event.type == Event::Closed) window.close();
        }

        window.clear(Color::Black);

        //draw target
        targetc.setPosition(targetx, targety);
        window.draw(targetc);

        //draw player
        playerc.setPosition(Mouse::getPosition(window).x, Mouse::getPosition(window).y);
        window.draw(playerc);

        //?????????????????????
        //DRAW BULLETS HERE, ideally with enemyc.move()
        //?????????????????????

        //score count
        scorecount.setString(scoreconv.str());
        window.draw(scorecount);

        window.display();
    }

    return 0;
}

标签: c++sfml

解决方案


你已经拥有了子弹所需的数据,你称之为“敌人”。您已经有一个适当的集合来存储您的子弹,您选择使用矢量,这很好。

您只需要调整更新/绘制,并考虑一些简单的碰撞:

//update
targetc.setPosition(targetx, targety);
playerc.setPosition(Mouse::getPosition(window).x, Mouse::getPosition(window).y);

// you can place this in your enemy move function
for (Enemy enemy : enemies) {
    if (enemy.xpos < 0 || enemy.xpos > window.getSize().x) {
        enemy.xvel *= -1; // revert X velocity if touching side edges
    }
    if (enemy.ypos < 0 || enemy.ypos > window.getSize().y) {
        enemy.yvel *= -1; // revert Y velocity if touching top or bottom edges (don't know whether you want this)
    }

    enemy.xpos += enemy.xvel;
    enemy.ypos += enemy.yvel;
}

//draw
window.draw(targetc);
window.draw(playerc);
for (Enemy enemy : enemies) {
    window.draw(
}

还要为你的敌人考虑以下几点

class enemy{
public:
    int xpos, ypos, xvel, yvel;
    CircleShape enemyc;

    void spawnEnemy(){
        enemyc = CircleShape(10);
        enemyc.setFillColor(Color::Red);
    }
};

最后说明:

将您的更新与绘图分开,通常您只想在计算完所有内容后进行绘制。


推荐阅读