【问题标题】:C++ SFML how to make bullets spawn with thier own individual physics?C ++ SFML如何使子弹产生具有自己独特的物理特性?
【发布时间】:2020-02-25 22:19:03
【问题描述】:

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

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

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

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

【问题讨论】:

  • 你已经为敌人创建了一个类,为什么不也为子弹创建一个类呢?更好的是,敌人和子弹应该有自己的 Update() 函数,你可以在每一帧中调用它们。它们可以包含只关心自己的逻辑。你熟悉OOP吗?将所有子弹实例保存在一个向量中是一个好主意,您可以简单地 Update() 每个带有一个循环的实例。

标签: c++ sfml


【解决方案1】:

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

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

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

最后说明:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    相关资源
    最近更新 更多