Page 1 of 1
Bullet keep following mouse please Help c++/sfml
Posted: Mon Dec 19, 2011 5:53 pm
by Fantasy
Hello
can you guys please please help me. I'm going insane here.
I wrote a piece of code that when you click on the mouse the bullet check for the mouse angle and fire in that direction.
but the problem is the bullet keep following the mouse. its not suppose to do that. it should check for the mouse position and angle and fire in that direction. can you please help.
Code: Select all
void Bullet::Draw(sf::RenderWindow &Game)
{
float ElapsedTime = Game.GetFrameTime()/60;
int MouseX = Game.GetInput().GetMouseX();
int MouseY = Game.GetInput().GetMouseY();
double PI =3.14159265;
if(Counter>=0)
{
for(int i=0; i<=Counter; i++)
{
float Speed = 10;
float BulletX = Sprite[i].GetPosition().x;
float BulletY = Sprite[i].GetPosition().y;
float AngleX = MouseX - BulletX;
float AngleY = MouseY - BulletY;
float vectorLength = sqrt(AngleX*AngleX + AngleY*AngleY);
float DirectionX = AngleX / vectorLength;
float DirectionY = AngleY / vectorLength;
float VelocityX = DirectionX * Speed;
float VelocityY = DirectionY * Speed;
Sprite[i].Move (VelocityX, VelocityY);
Game.Draw(Sprite[i]);
}
}
}
Re: Bullet keep following mouse please Help c++/sfml
Posted: Mon Dec 19, 2011 7:05 pm
by szdarkhack
Hmm, it seems that you're getting the mouse position every frame and that's why it keeps following the mouse. You should only get the input once (when you click) and calculate the velocity at that point, rather than on every redraw of the sprite.
I'm assuming here that you're calling Draw every frame. It also seems that you have a sort of "draw loop" inside this function. That's bad, it will lock up the game completely for as many frames as it takes to complete.
What you should do instead is to call another function (like OnMouseClick() or something) when the mouse button is clicked that calculates the direction and velocity and stores them. After that, remove all these calculations from your Draw() and use the stored values. Your Draw() should only contain the position update (you should move that out to an Update() preferably, but it's not too big a deal for something this simple) and the drawing code.
Re: Bullet keep following mouse please Help c++/sfml
Posted: Tue Dec 20, 2011 2:38 am
by Fantasy
Thank you the replay i really appreciate it. However i think i did what you said (not sure) and its still not working. I'm sorry but I'm a newbie i spent the last 4 hours reading, researching and coding trying to fix the stupid problem but i just can't. Now the problem is that the when i click the mouse the bullets move only 1 pixel and spawn new bullet.
I created a new function called createBullet() which handles the calculations and Init() get mouse X and Y positions. I call CreateBullet() when the mouse is clicked.
Bullet.h
Code: Select all
#include <SFML\Graphics.hpp>
#include <iostream>
#include <string>
#include <sstream>
class Bullet
{
public:
Bullet();
~Bullet();
void LoadFile(sf::RenderWindow &Game);
void Init(sf::RenderWindow &Game);
void SetPosition(sf::RenderWindow &Game);
void MouseEvent(sf::Event &Event);
void CreateBullet(sf::RenderWindow &Game);
void Draw(sf::RenderWindow &Game);
bool Clicked;
sf::RenderWindow Game;
private:
sf::Image Image;
sf::Sprite Sprite[101];
int Direction, Amenition, Amenitioncoco, MouseX, MouseY, Counter;
float BulletX, BulletY, AngleX, AngleY, vectorLength,
DirectionX, DirectionY, VelocityX, VelocityY, Speed;
double PI;
};
Bullet.cpp
Code: Select all
#include "Bullet.h"
#include "Player.h"
#include <math.h>
Player P;
Bullet::Bullet()
{
Clicked=false;
Speed = 10;
Counter = -1;
Amenition = 100;
PI =3.14159265;
}
Bullet::~Bullet()
{
}
void Bullet::LoadFile(sf::RenderWindow &Game)
{
Image.LoadFromFile("data/Images/Bullet.png");
}
void Bullet::Init(sf::RenderWindow &Game)
{
MouseX = Game.GetInput().GetMouseX();
MouseY = Game.GetInput().GetMouseY();
}
void Bullet::MouseEvent(sf::Event &Event)
{
Amenitioncoco = Amenition - Counter;
if(Event.Type == sf::Event::MouseButtonPressed && Event.MouseButton.Button == sf::Mouse::Left && Amenitioncoco !=0)
{
Clicked=true;
Counter++;
CreateBullet(Game);
}
}
void Bullet::SetPosition(sf::RenderWindow &Game)
{
P.Movement(Game);
if(Clicked==true)
{
for(int i=Counter; i<=Counter; i++)
{
Sprite[i].SetImage(Image);
Sprite[i].SetPosition(P.GetPlayerX(), P.GetPlayerY());
}
Clicked=false;
}
}
void Bullet::CreateBullet(sf::RenderWindow &Game)
{
float ElapsedTime = Game.GetFrameTime()/60;
if(Counter>=0)
{
for(int i=0; i<=Counter; i++)
{
BulletX = Sprite[i].GetPosition().x;
BulletY = Sprite[i].GetPosition().y;
AngleX = MouseX - BulletX;
AngleY = MouseY - BulletY;
vectorLength = sqrt(AngleX*AngleX + AngleY*AngleY);
DirectionX = AngleX / vectorLength;
DirectionY = AngleY / vectorLength;
VelocityX = DirectionX * Speed;
VelocityY = DirectionY * Speed;
Sprite[i].Move (VelocityX , VelocityY );
}
}
}
void Bullet::Draw(sf::RenderWindow &Game)
{
//Display Amo
std::stringstream out;
out << "Amo: " << Amenitioncoco;
std::string myString;
myString = out.str();
sf::Unicode::Text myText(myString);
sf::String Amo (myText, sf::Font::GetDefaultFont(), 15);
Amo.SetPosition(700,550);
Game.Draw(Amo);
if(Counter>=0)
{
for(int i=0; i<=Counter; i++)
{
Game.Draw(Sprite[i]);
}
}
}
Re: Bullet keep following mouse please Help c++/sfml
Posted: Tue Dec 20, 2011 5:14 am
by szdarkhack
Ok, let's see. If i understand correctly, when a mouse click occurs, you increase the counter by 1 and create a new bullet. However, if you look at your CreateBullet function, it loops over all the bullets. You only need to setup the new bullet, not change every single one. In fact, you don't seem to be actually creating new bullets (sprites) inside the function at all. Then, confusingly, you have a call to Move() *inside* of CreateBullet. That seems to be the only position update you do on the sprite, thus the "moving only 1 pixel" problem.
I suggest you structure this as follows:
CreateBullet <- Creates a NEW bullet (including sprite) and calculates its velocity. Called on mouseclick.
UpdateBullets <- loops through the existing bullets and updates their positions according to the velocities. Any collision detection you might add later would go here as well.
DrawBullets <- loops through the existing bullets and draws their sprites.
These should be your basic functions. Whenever you want a new bullet (when you click for example), you should call CreateBullet. The functions UpdateBullets and DrawBullets should be called every frame. If you do it this way, make sure that each function does what i listed here. You're not far off, but you need to fix a few things first.
Re: Bullet keep following mouse please Help c++/sfml
Posted: Tue Dec 20, 2011 10:08 am
by Van-B
I'm not sure if your DirectionX etc variables should be private... but that might just be me. I prefer to use STRUCTs, and compile GL meshes based on the struct arrays. That way the variables are easily accesible for other systems, like particle effects for instance that use a struct array.
I think as people have said, you need to update your bullets every loop, then you'll see yourself how it works after that - no point in doing anything else until you get the things moving properly.
Re: Bullet keep following mouse please Help c++/sfml
Posted: Wed Dec 21, 2011 7:24 am
by Fantasy
ok thank you guys very much that was very very helpful, and i really really appreciate your help :D
now when i click the mouse the bullet go in that direction :D so now it works.
just one last problem.
the thing is when I click on the mouse the counter get incremented and the bullet get created and move in the correct direction but if i click again the first bullet stops in its position and a new bullet get create and start moving.
i know and understand the problem but i don't know how to fix it.
here is my final code.
Code: Select all
void Bullet::Calculations(sf::RenderWindow &Game)
{
P.Movement(Game);
if(Clicked==true)
{
for(int i=Counter; i<=Counter; i++)
{
MouseX = Game.GetInput().GetMouseX();
MouseY = Game.GetInput().GetMouseY();
DistanceX = MouseX - P.GetPlayerX();
DistanceY = MouseY - P.GetPlayerY();
AngleRadian = atan2(DistanceY, DistanceX);
AngleDegree = AngleRadian * 180 / PI;
BulletX = cos(AngleRadian) * Speed ;
BulletY = sin(AngleRadian) * Speed ;
}
Clicked=false;
Sprite[Counter].Move (BulletX , BulletY );
}
std::cout<< " bx" << BulletX << "by " << BulletY;
}
every function is the same as the old code i just created this new function. this function is inside the game loop.
Re: Bullet keep following mouse please Help c++/sfml
Posted: Wed Dec 21, 2011 1:34 pm
by XianForce
Are you updating ALL of your bullets? Or just the most recently created one?
Re: Bullet keep following mouse please Help c++/sfml
Posted: Wed Dec 21, 2011 3:46 pm
by Fantasy
XianForce wrote:Are you updating ALL of your bullets? Or just the most recently created one?
I'm updating only recent bullets, because if I update all the bullets every bullet will keep changing its position when i move the mouse.
Re: Bullet keep following mouse please Help c++/sfml
Posted: Wed Dec 21, 2011 4:27 pm
by szdarkhack
You need to store the velocity of each bullet separately and keep updating all of them, each using its own velocity. So, for example, say you click and create a bullet. You calculate its direction and velocity. Now, for each frame you must update it's position in order for it to keep moving (note that i'm telling you to update the position, NOT the velocity. This bullet's velocity doesn't change once it's first calculated).
Next, you click once more and create one more bullet. Now you calculate its direction and velocity (completely independent of the previous bullet's velocity). Now, for each frame you must update the positions of both bullets, otherwise the bullets that you're not updating will stop moving.
I think the problem is that you're only using one velocity. That is very wrong, each bullet moves independently so each one will need its own velocity.