SFML community forums

Help => General => Topic started by: coltranenaima on April 22, 2018, 03:31:14 am

Title: Fire Bullet At Angle
Post by: coltranenaima on April 22, 2018, 03:31:14 am
Hello,

I am working on a game that so far has:

I am now trying to implement bullets that will fire in the direction the square (player) is rotated, I made a very simple system with the last game I made (thanks again Hapax) that only went in one direction.

The bullets fire (yay), just not at the right angle (boo). I debugged and looked at the rotation each time and the numbers matched....it just doesn't come out correctly visually.

Thanks!

This is main.cpp (I chopped a major chunk of code to isolate what the issue may be)

#include "Player.h"
#include "Bullet.h"
#include <iostream>

int main()
{
        //declare
        float delta, deltaCd, bulletTime, bulletCd, bulletSpeed, bulletAngle;
        float& dCd = deltaCd;
        sf::Clock gameClock, bulletClock;
        Player playerOne;
        Player& pO = playerOne;
        Bullet playerBullet;
        Bullet& pB = playerBullet;
        std::vector<sf::RectangleShape> bulletVector;
        std::vector<float> bulletAngleVector;

        //initialize
        delta = .0f;
        deltaCd = .25f;
        bulletTime = 1.0f;
        bulletCd = 2.0f;
        bulletSpeed = 1.5f;
        bulletAngle = .0f;

        playerBullet.bulletShape.setPosition(sf::Vector2f(playerOne.playerShape.getPosition().x,
       
        //window loop
        //TODO: Create game loop
        while (win.isOpen())
        {
                window.clear();
                delta = gameClock.restart().asSeconds();
                playerOne.PlayerRotation(win, pO.playerShape);
                playerBullet.BulletAngle(win, pB.bulletShape);

                if (sf::Mouse::isButtonPressed(sf::Mouse::Left) && bulletTime > bulletCd)
                {
                        bulletTime = bulletClock.restart().asSeconds();
                        playerBullet.bulletShape.setPosition(sf::Vector2f(playerOne.playerShape.getPosition().x, playerOne.playerShape.getPosition().y));
                        bulletAngle = playerBullet.bulletShape.getRotation();
                        bulletVector.push_back(playerBullet.bulletShape);
                        bulletAngleVector.push_back(bulletAngle);
                }              

                for (unsigned int i = 0; i < bulletVector.size(); i++)
                {
                        bulletVector[i].move(cos(bulletAngleVector[i]), sin(bulletAngleVector[i]));
                        window.draw(bulletVector[i]);
                }
               
                bulletTime = bulletClock.getElapsedTime().asSeconds();

                window.draw(pO.playerShape);
                window.display();
        }
}


bullet.cpp

#include "Bullet.h"

Bullet::Bullet()
{
        bulletSizeX = 5.f;
        bulletSizeY = 5.f;
        bulletShape.setSize(sf::Vector2f(bulletSizeX, bulletSizeY));
        bulletShape.setOrigin(sf::Vector2f(bulletShape.getGlobalBounds().width / 2.f, bulletShape.getGlobalBounds().height / 2.f));
        bulletShape.setFillColor(sf::Color::Red);
}

void Bullet::BulletAngle(sf::RenderWindow& win, sf::RectangleShape& bS)
{
        dx = 0.f;
        dy = 0.f;
        mouse = sf::Mouse::getPosition(win);
        mouseWorld = win.mapPixelToCoords(mouse);
        dx = mouseWorld.x - bS.getPosition().x;
        dy = mouseWorld.y - bS.getPosition().y;
        rotation = atan2(dy, dx) * 180 / PI;
        bS.setRotation(rotation);
}

bullet.h

#pragma once
#include <SFML/Graphics.hpp>

class Bullet
{
public:
        float bulletSizeX, bulletSizeY, dx, dy, rotation;
        const float PI = 3.14159265f;
        sf::Vector2i mouse;
        sf::Vector2f mouseWorld;
        sf::RectangleShape bulletShape;
        void BulletAngle(sf::RenderWindow& win, sf::RectangleShape& bS);
        Bullet();
};
Title: Re: Fire Bullet At Angle
Post by: coltranenaima on April 22, 2018, 09:26:55 pm
I recorded what is currently happening, see gif link below.

Thanks for reading and I appreciate any suggestions!

https://gfycat.com/LimpFrankBumblebee
Title: Re: Fire Bullet At Angle
Post by: Geheim on April 22, 2018, 11:29:28 pm
rotation = atan2(dy, dx) * 180 / PI;
should just be:
rotation = atan2(dy, dx);
atan2 already gives you radians.  ;)
Title: Re: Fire Bullet At Angle
Post by: coltranenaima on April 23, 2018, 12:01:02 am
rotation = atan2(dy, dx) * 180 / PI;
should just be:
rotation = atan2(dy, dx);
atan2 already gives you radians.  ;)

Thanks for your feedback! I tried your suggestion with the remaining code as is, unfortunately I am getting the same result. If that is the case where I do not need to convert from radians, maybe this piece of code is suspect?

                for (unsigned int i = 0; i < bulletVector.size(); i++)
                {
                        bulletVector[i].move(cos(bulletAngleVector[i]), sin(bulletAngleVector[i]));
                        window.draw(bulletVector[i]);
                }

I will be honest...I have not taken real trig classes....just simple review course on khan academy, soh cah toa! The movement is what I am leaning towards being the issue (with your suggestion in place).
Title: Re: Fire Bullet At Angle
Post by: coltranenaima on April 23, 2018, 02:04:00 am
I was able to get it to work, thanks Geheim. You mentioning radians helped fix the first issue and it helped me with tracking down the other issue by reading this thread:

https://en.sfml-dev.org/forums/index.php?topic=4951.0

from Nexus:

Quote
Note that the functions std::sin() and std::cos() take radians, not degrees.

cos and sin take radians, I was feeding it a rotation degree.

Thanks!!!!
Title: Re: Fire Bullet At Angle
Post by: Geheim on April 23, 2018, 01:35:49 pm
Just for your info: you can calculate pi with
const double pi = atan(1) * 4;