SFML: Снаряд останавливается

Я очень плохо знаком с 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);
}

Еще один вопрос, правильно ли я делаю с умножением на дельту? Пули действительно отстают и странные.

0

Решение

(Оригинальный ответ 🙂

У меня недостаточно репутации, чтобы комментировать, поэтому мне придется разместить ее здесь …

Так что, если я правильно понимаю, вы говорите, что хотите стрелять снарядами в направлении мыши, но не хотите, чтобы они следовали ее положению после выстрела? В этом случае:

Я вижу, у вас есть код для рисования снарядов внутри этого цикла for, что приводит меня к мысли, что вы вызываете цикл непрерывно. Но тот же цикл также содержит код, используемый для стрельбы снарядами, что означает, что вы также постоянно называете этот «огненный» код. Таким образом, вы направляете снаряды в направлении текущей позиции мыши в каждой итерации цикла, что означает, что они всегда будут следовать текущей позиции мыши.

Что вам нужно сделать, это переместить код, чтобы стрелять снарядами, и вызывать его только один раз (вы можете стрелять только один раз, верно?), Чтобы вектор направления снаряда не изменялся постоянно, что приводило к проблеме, о которой вы говорили.

И обязательно всегда разделяйте логику и рендеринг. В идеале вы должны обновлять физику (например, обновление снаряда) с фиксированным интервалом, чтобы игра работала одинаково на всех машинах и рисовала все свои вещи отдельно.

Если вы хотите, чтобы снаряды всегда следовали за мышью, вы можете использовать этот (полупсевдо) код (я использую этот код в одной из моих игр):

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_);
}
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]