SFML:弹丸停止

时间:2016-12-06 20:36:54

标签: c++ sfml projectile

我是SFML和C ++的新手。我的问题是我成功向小鼠发射射弹。然而,当我移动鼠标时,射弹也会移动。

编辑:

好的,我解决了以前的问题。然而,当弹丸到达鼠标位置时,弹丸停止。子弹如何继续超越目的地?

代码:

    if (isFiring == true) {

        sf::Vector2f startPos = sf::Vector2f(myPipe.getX(), myPipe.getY());
        sf::Vector2i mousePos = sf::Mouse::getPosition(window);
        sf::Vector2f endPos = sf::Vector2f(mousePos.x, mousePos.y);

        double projSpeed{0.3};
        //float projSpeed = projSpeed * (myPipe.getY() - mousePos.y) / 100;
        Projectile newProjectile(20, startPos, endPos, projSpeed);
        projVec.push_back(newProjectile);
        isFiring = false;
    }   

    for (int i = 0; i < projVec.size(); i++) {

        projVec[i].fire(delta.asMilliseconds());
        projVec[i].draw(window);
        clock.restart();

    }

消防功能:

   void fire( float delta) {
    sf::Vector2f pos = projectile.getPosition();
    float veloX = (_end.x - pos.x);
    float veloY = (_end.y - pos.y);
    float distance = sqrt((veloX*veloX + veloY * veloY));

    float dx = veloX / distance;
    float dy = veloY / distance;
    projectile.move(dx * delta, dy * delta);
}

还有一个问题,我是否正确加倍增量?子弹真的很迟钝而且很奇怪。

1 个答案:

答案 0 :(得分:1)

(原件回复:)

我没有足够的声誉来评论,所以我必须把它放在这里...

所以,如果我理解正确,你说你想要将射弹射向鼠标的位置,但是一旦被解雇,他们不希望它们跟随它的位置?在这种情况下:

我看到你有代码在for循环中绘制射弹,这让我相信你在不断地调用循环。但同样的循环还包含用于射击射弹的代码,这意味着你也在不断地召唤这个&#34; fire&#34;码。因此,您在每次循环迭代中将射弹转向当前鼠标位置,这意味着它们将始终跟随当前鼠标位置。

你应该做的是移动代码来射击射弹并且只召唤一次(你只能射击一次,对吧?)因此射弹的方向向量不会经常改变,导致你说的问题。

确保始终将逻辑和渲染分开。理想情况下,您应该以固定的间隔更新物理(例如射弹更新),以便游戏在所有机器上运行相同,并分别绘制所有内容。

如果您确实希望射弹始终跟随鼠标,您可以使用此(半伪)代码(我在其中一个游戏中使用此代码):

sf::Vector2f normalizedVector = normalize(mousePos - projectilePos);
normalizedVector.x *= speed * deltaTime;
normalizedVector.y *= speed * deltaTime;

projectile.move(normalizedVector);

(适用编辑:)

我制作了一个有效的快速示例项目。这并没有使用您的所有代码,但希望能让您知道如何完成。

这是一段简短视频,展示了以下代码的作用:https://webmshare.com/play/jQqvd

的main.cpp

#include <SFML/Graphics.hpp>

#include "projectile.h"

int main() {
  const sf::FloatRect viewRect(0.0f, 0.0f, 800.0f, 600.0f);

  sf::RenderWindow window(sf::VideoMode(viewRect.width, viewRect.height), "Test");
  window.setFramerateLimit(120);
  window.setVerticalSyncEnabled(false);
  window.setKeyRepeatEnabled(false);

  sf::Clock deltaClock;
  const sf::Time timePerFrame = sf::seconds(1.0f / 60.0f);
  sf::Time timeSinceLastUpdate = sf::Time::Zero;

  std::vector<Projectile> projectiles;

  while (window.isOpen()) {

    timeSinceLastUpdate += deltaClock.restart();

    // process events
    {
      sf::Event evt;
      while (window.pollEvent(evt)) {
        switch (evt.type) {
          case sf::Event::Closed: { window.close(); } break;
          // shoot with left mouse button
          case sf::Event::MouseButtonPressed: { switch (evt.mouseButton.button) { case sf::Mouse::Button::Left:  { 
            const sf::Vector2f center(viewRect.left + viewRect.width / 2, viewRect.top + viewRect.height / 2);
            const sf::Vector2f mousePos(window.mapPixelToCoords(sf::Mouse::getPosition(window)));
            const float angle = atan2(mousePos.y - center.y, mousePos.x - center.x);
            projectiles.push_back(Projectile(center, angle));
          } break; default: {} break; } } break;
          default: {} break;
        }
      }
    }

    // update
    {
      while (timeSinceLastUpdate > timePerFrame) {
        timeSinceLastUpdate -= timePerFrame;
        // update projectiles
        {
          for (std::size_t i = 0; i < projectiles.size(); ++i) {
            Projectile &proj = projectiles[i];
            proj.update(timePerFrame);
            if (!viewRect.intersects(proj.getBoundingBox())) { proj.destroy(); }
          }
          projectiles.erase(std::remove_if(projectiles.begin(), projectiles.end(), [](Projectile const &p) { return p.getCanBeRemoved(); }), projectiles.end());
        }
      }
    }

    // render
    {
      window.clear();
      for (std::size_t i = 0; i < projectiles.size(); ++i) {
        window.draw(projectiles[i]);
      }
      window.display();
    }

  }

  return EXIT_SUCCESS;
}

projectile.h:

#ifndef PROJECTILE_H_INCLUDED
#define PROJECTILE_H_INCLUDED

#include <SFML/Graphics.hpp>

class Projectile : public sf::Drawable {
 public:
  Projectile();
  Projectile(const sf::Vector2f pos, const float angle);
  virtual ~Projectile();

  const bool &getCanBeRemoved() const;
  const sf::FloatRect &getBoundingBox() const;

  void destroy();
  void update(const sf::Time dt);

 private:
  virtual void draw(sf::RenderTarget &renderTarget, sf::RenderStates renderStates) const;

  bool canBeRemoved_;
  sf::FloatRect boundingBox_;
  float angle_;
  float speed_;

  sf::RectangleShape shape_;

};

#endif

projectile.cpp:

#include "projectile.h"

Projectile::Projectile() :
  canBeRemoved_(true),
  boundingBox_(sf::FloatRect()),
  angle_(0.0f),
  speed_(0.0f)
{
}

Projectile::Projectile(const sf::Vector2f pos, const float angle) {
  canBeRemoved_ = false;
  boundingBox_ = sf::FloatRect(pos, sf::Vector2f(10.0f, 10.0f));
  angle_ = angle;
  speed_ = 0.5f;

  shape_.setPosition(sf::Vector2f(boundingBox_.left, boundingBox_.top));
  shape_.setSize(sf::Vector2f(boundingBox_.width, boundingBox_.height));
  shape_.setFillColor(sf::Color(255, 255, 255));
}

Projectile::~Projectile() {
}

const bool &Projectile::getCanBeRemoved() const {
  return canBeRemoved_;
}

const sf::FloatRect &Projectile::getBoundingBox() const {
  return boundingBox_;
}

void Projectile::destroy() {
  canBeRemoved_ = true;
}

void Projectile::update(const sf::Time dt) {
  boundingBox_.left += static_cast<float>(std::cos(angle_) * speed_ * dt.asMilliseconds());
  boundingBox_.top += static_cast<float>(std::sin(angle_) * speed_ * dt.asMilliseconds());
  shape_.setPosition(boundingBox_.left, boundingBox_.top);
}

void Projectile::draw(sf::RenderTarget &renderTarget, sf::RenderStates renderStates) const {
  renderTarget.draw(shape_);
}