SFML community forums

Help => Graphics => Topic started by: tiago221 on September 11, 2009, 01:08:00 am

Title: Bullets in SFML.
Post by: tiago221 on September 11, 2009, 01:08:00 am
This is what I currently have:

Projectile.h
Code: [Select]

#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML/Graphics.hpp>


class Projectile
{
public:
sf::Image BulletImage;
static sf::Sprite Bullet;

public:

void SetDirection(sf::Sprite);

void SetSpeed(float);

};

#endif



Projectile.cpp
Code: [Select]

#include "Projectile.h"
#include <SFML/Graphics.hpp>

sf::Sprite Projectile::Bullet;

void Projectile::SetDirection(sf::Sprite Reference)
{
float TargetRotation = Reference.GetRotation();
Bullet.SetRotation(static_cast<float>(fmod(TargetRotation, 360)));
float BulletRotation = Bullet.GetRotation();
if (BulletRotation < 0)
Bullet.SetRotation(BulletRotation + 360.f);
}

void Projectile::SetSpeed(float SpeedMultiplier)
{
BulletImage.LoadFromFile("bullet.png");
Bullet.SetImage(BulletImage);

float BulletX = Bullet.GetPosition().x;
float BulletY = Bullet.GetPosition().y;

Bullet.SetX(BulletX * SpeedMultiplier);
Bullet.SetY(BulletY * SpeedMultiplier);
}


main.cpp
Code: [Select]

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Projectile.h"
#define PI 3.1415926535

int WINAPI WinMain(      
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
)
{

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Zombie Game Alpha");
sf::Image PlayerImage;
sf::Image Background;
Background.LoadFromFile("background.png");
PlayerImage.LoadFromFile("player.png");
sf::Sprite Player(PlayerImage);
sf::Sprite BackgroundS(Background);
sf::Sprite* follow = &Player;
Player.SetPosition(400,300);
Projectile Bullet;

sf::View Camera(sf::Vector2f(400.f, 300.f), sf::Vector2f(400.f, 300.f));  
sf::Vector2f PPos = Player.GetPosition();

sf::Music InGameMusic;
InGameMusic.OpenFromFile("in_game.ogg");


while(Window.IsOpened())
{
sf::Event Event;
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
Window.Close();
}

Bullet.SetDirection(Player);
Bullet.SetSpeed(2);

float ElapsedTime = Window.GetFrameTime();
sf::Vector2f MousePos = Window.ConvertCoords(Window.GetInput().GetMouseX(), Window.GetInput().GetMouseY());
Window.Clear();
if (Window.GetInput().IsKeyDown(sf::Key::W))  Player.Move(0, -425 * ElapsedTime);  
        if (Window.GetInput().IsKeyDown(sf::Key::S))  Player.Move(0,  425 * ElapsedTime);  
if (Window.GetInput().IsKeyDown(sf::Key::A))  Player.Move(-425 * ElapsedTime, 0);
if (Window.GetInput().IsKeyDown(sf::Key::D))  Player.Move(425 * ElapsedTime, 0);  
if (Window.GetInput().IsKeyDown(sf::Key::N))  InGameMusic.Play();
if (Window.GetInput().IsKeyDown(sf::Key::M))  InGameMusic.Stop();
if (Window.GetInput().IsMouseButtonDown(sf::Mouse::Left))  Window.Draw(Projectile::Bullet);
Player.SetCenter(Player.GetSize() / 2.f);
Player.SetRotation(((-1* 360 / PI *(atan2(static_cast<double>(Player.GetPosition().y - MousePos.y), static_cast<double>(Player.GetPosition().x - MousePos.x))))/2)+90);


Camera.SetCenter(follow->GetPosition());
Window.SetView(Camera);
Window.Draw(BackgroundS);
Window.Draw(Player);
Window.Display();
InGameMusic.SetLoop(true);
}
}



Now, when I press the left mouse button, nothing works, what should I do?

Oh, and if someone has any suggestions to improve the coding, please say them.

Thanks in advance.
Title: Bullets in SFML.
Post by: 93interactive on September 11, 2009, 06:39:33 am
*edit* i overlooked a little detail, so forget what i wrote here before

i think why your bullet is not drawn, is because you have a static sprite but no static image. so the sprite loses reference of the image.

in general you draw the bullet only, on mouse down, so it is not visible if the user releases the mouse.

the quickest way to fix your problem would be to add (outside of the while loop) a boolean like

bool shotFired=false;

and then replace:

Code: [Select]

if (Window.GetInput().IsMouseButtonDown(sf::Mouse::Left))  Window.Draw(Projectile::Bullet);


with

Code: [Select]

if (Window.GetInput().IsMouseButtonDown(sf::Mouse::Left))  shotFired=true;

if (shotFired) {
   Window.Draw(Bullet.spriteThatYouNeedToAdd);
}


unless your player is a proffessional hitman - its good to give your player a chance to fire more then one bullet, so it would be better not to have one single Bullet instance, but to manage a list of instances.

Best probably would be to user c++ vector or similar.
Title: Bullets in SFML.
Post by: tiago221 on September 11, 2009, 02:39:38 pm
It's now like this:
Code: [Select]

if (Window.GetInput().IsMouseButtonDown(sf::Mouse::Left))  shotFired = true;

if (shotFired == true)
{
Window.Draw(Bullet.Bullet);
shotFired = false;
}


It still doesn't work.
Title: Bullets in SFML.
Post by: K-Bal on September 11, 2009, 03:08:18 pm
You have to keep shotFired true until the bullet is destroyed.
Title: Bullets in SFML.
Post by: Nexus on September 11, 2009, 04:50:24 pm
To be flexible, you can put all current bullets into a STL container (std::vector, for example). Like this it's no problem to have multiple bullets at the same time, to destroy all bullets at once, and so on.

Pseudocode (just one possibility, I personally like to separate removing and drawing further):
Code: [Select]
Container AllBullets;

if (new bullet created)
{
    add bullet to the container
}

for each bullet in AllBullets
{
   
    if (current bullet is destroyed)
    {
        remove it from container AllBullets
    }
    else
    {
        draw current bullet
    }
}
Title: Bullets in SFML.
Post by: tiago221 on September 12, 2009, 06:10:40 pm
Code: [Select]

if (shotFired == true)
{
BulletClip.push_back(BulletP);
}

for (int i = 0; i < BulletClip.size(); i++)
{
if ( i = 0 )
{
BulletClip.pop_back();
}

else
{
Window.Draw(BulletP);
}
}



BulletClip is an std::vector
BulletP is Projectile* BulletP = new Bullet;
Bullet is a Projectile


1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(26) : error C2061: syntax error : identifier 'Bullet'
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(68) : error C2664: 'std::vector<_Ty>::push_back' : cannot convert parameter 1 from 'Projectile *' to 'const Projectile &'
1>        with
1>        [
1>            _Ty=Projectile
1>        ]
1>        Reason: cannot convert from 'Projectile *' to 'const Projectile'
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(71) : warning C4018: '<' : signed/unsigned mismatch
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(80) : error C2664: 'sf::RenderTarget::Draw' : cannot convert parameter 1 from 'Projectile *' to 'const sf::Drawable &'
1>        Reason: cannot convert from 'Projectile *' to 'const sf::Drawable'
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
Title: Bullets in SFML.
Post by: Nexus on September 12, 2009, 06:30:50 pm
Why pointers inside containers? I just said something about them here (http://www.sfml-dev.org/forum/viewtopic.php?p=10504#10504). ;)

Code: [Select]
if (shotFired == true) The explizit comparison to true is not required, if (shotFired) is equivalent. But if this helps you, you can leave it.

Code: [Select]
if (i = 0)That's an assignment, not a comparison. Use operator==.

Code: [Select]
BulletClip.pop_back();This removes the last bullet in the container. Are you sure you always want to remove the last one (that's normally the one you just inserted)? Otherwise, try the function erase().

For example:
Code: [Select]
// Checks whether a bullet is destroyed and can be deleted from the container.
bool IsDestroyed(const Bullet& b);

std::vector<Bullet> AllBullets;

// Rather use iterators than indizes, this allows you to switch easily to other containers like std::list
for (std::vector<Bullet>::iterator Itr = AllBullets.begin(), End = AllBullets.end(); Itr != End; )
{
if (IsDestroyed(*Itr))
{
// reassign the iterator, after the current element is removed.
Itr = BulletClip.erase(Itr);
}

else
{
Window.Draw(*Itr);
++Itr;
}
}

If you aren't used to iterators and the STL, you should learn it now because the Standard Template Library is a very important part of the C++ standard library. I think, a reference like www.cplusplus.com can help you lookup the used classes and functions. There are also some tutorials.
Title: Bullets in SFML.
Post by: tiago221 on September 12, 2009, 06:36:25 pm
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(26) : error C2061: syntax error : identifier 'Bullet'
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(68) : error C2664: 'std::vector<_Ty>::push_back' : cannot convert parameter 1 from 'Projectile *' to 'const Projectile &'
1>        with
1>        [
1>            _Ty=Projectile
1>        ]
1>        Reason: cannot convert from 'Projectile *' to 'const Projectile'
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(72) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(72) : error C2143: syntax error : missing ',' before '&'
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(74) : error C2923: 'std::vector' : 'Bullet' is not a valid template type argument for parameter '_Ty'
1>        c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(24) : see declaration of 'Bullet'
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(77) : error C2923: 'std::vector' : 'Bullet' is not a valid template type argument for parameter '_Ty'
1>        c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(24) : see declaration of 'Bullet'
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(81) : error C2664: 'std::_Vector_iterator<_Ty,_Alloc> std::vector<_Ty>::erase(std::_Vector_const_iterator<_Ty,_Alloc>)' : cannot convert parameter 1 from 'std::_Vector_iterator<_Ty,_Alloc>' to 'std::_Vector_const_iterator<_Ty,_Alloc>'
1>        with
1>        [
1>            _Ty=Projectile,
1>            _Alloc=std::allocator<Projectile>
1>        ]
1>        and
1>        [
1>            _Ty=int,
1>            _Alloc=std::allocator<int>
1>        ]
1>        and
1>        [
1>            _Ty=Projectile,
1>            _Alloc=std::allocator<Projectile>
1>        ]
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(86) : error C2664: 'sf::RenderTarget::Draw' : cannot convert parameter 1 from 'int' to 'const sf::Drawable &'
1>        Reason: cannot convert from 'int' to 'const sf::Drawable'
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
Title: Bullets in SFML.
Post by: Nexus on September 12, 2009, 07:50:08 pm
Quote from: "tiago221"
1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(26) : error C2061: syntax error : identifier 'Bullet'
I already gave you a complete example, I believe, you can think by yourself. :roll:

At least I don't feel like helping you, if you just post your error messages and don't want to spend any time trying to fix them. By the way, you should know C++ well if you work with SFML. For example, I already told you not to work with pointers and therefore new.
Title: Bullets in SFML.
Post by: tiago221 on September 12, 2009, 08:13:10 pm
Please don't think I'm just posting error messages and waiting for someone to fix them, it's just that I'm still learning and I think the best way to learn is by doing, and if I don't understand the error messages or something my next step is to post them so I can be able to understand them. Still, thanks for the example.

And I think it's really unnecessary to go through this much trouble just to create a working bullet system.


EDIT:


I fixed most of it, only I got to this one and I don't have any idea about it.

1>c:\users\darkspirit\documents\visual studio 2008\projects\zombie\zombie\main.cpp(84) : error C2664: 'sf::RenderTarget::Draw' : cannot convert parameter 1 from 'Projectile' to 'const sf::Drawable &'
1>        Reason: cannot convert from 'Projectile' to 'const sf::Drawable'
Title: Bullets in SFML.
Post by: Nexus on September 12, 2009, 08:28:38 pm
Quote from: "tiago221"
And I think it's really unnecessary to go through this much trouble just to create a working bullet system.
The fact is, a solid understanding of the C++ programming language is really required in order to write acceptable programs with SFML. Even if you manage to make this bullet system working, the next problem is likely to come soon. I advise you'd order a C++ book and learn the essential language stuff - you cannot avoid this, if you plan to write bigger projects one day. This will also help you maintain your programs with reasonable effort. C++ is definitely not the language that can be learned only by doing. Theory is as important, too.

The first message means your Bullet is not declared. And declarations are one of the very first lessions in every book and tutorial, that's why I am worried because you don't know how to treat this issue. The second one suggests that you called push_back() with a pointer - that's what I wanted you to avoid.
Title: Bullets in SFML.
Post by: tiago221 on September 12, 2009, 08:36:27 pm
yeah, I also, edited my post so please check the edit.

Also, I know if I get the bullet system working another problem will come soon, and when it comes, I'll need to fix it, when it's fixed I'll have learned new stuff, I'll have learned how to fix it, like how I have learned about vectors, creating classes like they should be created, etc, with this bullet system. I'm only afraid of reading a book because my attention span is not high enough for it. I always drop off after I get bored, I never got this far into a programming language, and that's because I'm actually working on something while I'm doing it. I know it's not going to be the best game ever, not even close to it, but I'll be happy when I finish it, it'll be my first game, it'll be my work, I had learned and fixed most of the problems that appeared. I'll have a feeling of accomplishment, that will boost me up so I can make better stuff, work better on it.

I tried Python, Lua, C, HTML (even HTML, seriously), etc... And I never could do anything with them besides a simple printing program or a calculator of some sort (to which it applies).

So, yeah, pretty much.
Title: Bullets in SFML.
Post by: e_barroga on September 12, 2009, 09:21:32 pm
If you're creating new bullet objects at runtime you'll want your container to store pointers:
Code: [Select]

std::vector<Bullet*> bulletList;


Example of creating the bullet:
Code: [Select]

bulletList.push_back(new Bullet());


When destroying the bullet:
Code: [Select]

delete bulletList[i]; //Of course, you would actually want an iterator.
bulletList.erase(i);
Title: Bullets in SFML.
Post by: Nexus on September 13, 2009, 12:20:13 am
tiago221, it's ok if you can manage it like this. But after a while, a lot of people lose their whole motivation just because they didn't spend time on theory. Some others are indeed able to create simple games, but with loads of unnecessary trouble (often, the game itsself shows such things, i.e. full cpu usage, memory leaks, bad performance, unstable runtime behaviour). I'd like to prevent this, but if you can handle it, you have to know.

About your error: Your Bullet is not a sf::Drawable, so you can't pass it to sf::RenderWindow::Draw(). Make your bullet contain a sf::Sprite and pass this sprite to Draw().

e_barroga, I had a reason to discourage the use of pointers in STL containers. :roll:
See the other thread (I posted its link), if you like to know it. The container can be used as follows:

Code: [Select]
std::vector<Bullet> AllBullets;

AllBullets.push_back(Bullet(/* constructor arguments */););

std::vector<Bullet>::iterator Itr = ...; // initialize iterator
AllBullets.erase(Itr);
Title: Bullets in SFML.
Post by: efeX on September 13, 2009, 12:44:53 am
Quote from: "e_barroga"
If you're creating new bullet objects at runtime you'll want your container to store pointers:
Code: [Select]

std::vector<Bullet*> bulletList;


Example of creating the bullet:
Code: [Select]

bulletList.push_back(new Bullet());


When destroying the bullet:
Code: [Select]

delete bulletList[i]; //Of course, you would actually want an iterator.
bulletList.erase(i);


Uhh. No.

Use a boost ptr container or a smartptr. Not a vector of pointers that would require manual destruction and dirtier code.
Title: Bullets in SFML.
Post by: Nexus on September 13, 2009, 01:03:29 am
efeX, in this case I think, a container of instances - std::vector<Bullet> - would be appropriate, since the Bullet class doesn't require any particular semantics. Anyway, thanks for the support, I felt a little bit surrounded by raw-pointer-in-container-users. ;)
Title: Bullets in SFML.
Post by: Spidyy on September 13, 2009, 01:11:27 am
Does the boost/smart ptr allow to use the inheritance advantages? (Having a pointer on base class and instantiate her inheriting class)
Title: Bullets in SFML.
Post by: Nexus on September 13, 2009, 02:14:56 am
Quote from: "Spidyy"
Does the boost/smart ptr allow to use the inheritance advantages? (Having a pointer on base class and instantiate her inheriting class)
Yes, both of them allow that, as they are saving normal raw pointers inside. The advantage is, you don't get into trouble with copying or freeing.
Title: Bullets in SFML.
Post by: efeX on September 13, 2009, 02:25:15 am
Quote from: "Nexus"
efeX, in this case I think, a container of instances - std::vector<Bullet> - would be appropriate, since the Bullet class doesn't require any particular semantics. Anyway, thanks for the support, I felt a little bit surrounded by raw-pointer-in-container-users. ;)


Well sure in this case it would be more appropriate. I was just pointing out that a raw pointer in STL containers isn't a very good idea.
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 03:00:35 am
Nexus, the class is Projectile, Bullet is a Projectile. :P

Also, Bullet.Bullet is a sf::sprite (about the Drawable problem) and if I get Bullet.Bullet in Window.Draw(); I get an unresolved external error from the linker regarding the IsDestroyed boolean variable., and I'm pretty sure I've got all the includes and everything set up.
Title: Bullets in SFML.
Post by: Nexus on September 13, 2009, 03:07:00 am
Quote from: "tiago221"
Nexus, the class is Projectile, Bullet is a Projectile. :P
Oh sorry, I got that wrong.

Quote from: "tiago221"
Also, Bullet.Bullet is a sf::sprite (about the Drawable problem) and if I get Bullet.Bullet in Window.Draw(); I get an unresolved external error from the linker regarding the IsDestroyed boolean variable., and I'm pretty sure I've got all the includes and everything set up.
Hm, could you post some relevant code (classes, instances, functions) and the error message? It would be nice if the code still reproduced the problem. ;)
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 03:10:47 am
http://www.mediafire.com/download.php?yx5muy1ywxm

The whole source code I have currently.


Error:

1>main.obj : error LNK2019: unresolved external symbol "bool __cdecl IsDestroyed(class Projectile const &)" (?IsDestroyed@@YA_NABVProjectile@@@Z) referenced in function _WinMain@16
1>C:\Users\DarkSpirit\Documents\Visual Studio 2008\Projects\zombie\Debug\zombie.exe : fatal error LNK1120: 1 unresolved externals
Title: Bullets in SFML.
Post by: Nexus on September 13, 2009, 03:27:24 am
Ah, I just posted the declaration of the function
Code: [Select]
bool IsDestroyed(const Projectile& b);
You can now write its definition with a specific implementation:
Code: [Select]
bool IsDestroyed(const Projectile& b)
{
    // return whether the Projectile object passed by const-reference
    // is already destroyed or not
}

Hence, you should have a criterion to mark destroyed projectiles. A simple approach would be a bool member-variable and a member-function void Projectile::Destroy() which sets the variable to true. Don't forget to initialize it with false in the constructor. ;)
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 03:29:27 am
Thanks, if I have any problems I'll post. :D
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 06:46:21 am
Projectile.h

Code: [Select]

#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML/Graphics.hpp>


class Projectile
{
public:
sf::Image BulletImage;
static sf::Sprite Bullet;
bool BulletState;

public:

void SetDirection(sf::Sprite);

void SetSpeed(float);

void Destroy(void);

bool IsDestroyed(const Projectile& b);

};

#endif


Projectile.cpp
Code: [Select]

#include "Projectile.h"
#include <SFML/Graphics.hpp>

sf::Sprite Projectile::Bullet;

void Projectile::SetDirection(sf::Sprite Reference)
{
float TargetRotation = Reference.GetRotation();
Bullet.SetRotation(static_cast<float>(fmod(TargetRotation, 360)));
float BulletRotation = Bullet.GetRotation();
if (BulletRotation < 0)
Bullet.SetRotation(BulletRotation + 360.f);
}

void Projectile::SetSpeed(float SpeedMultiplier)
{
BulletImage.LoadFromFile("bullet.png");
Bullet.SetImage(BulletImage);

float BulletX = Bullet.GetPosition().x;
float BulletY = Bullet.GetPosition().y;

Bullet.SetX(BulletX * SpeedMultiplier);
Bullet.SetY(BulletY * SpeedMultiplier);
}

void Projectile::Destroy()
{
BulletState = true;
}

bool Projectile::IsDestroyed(const Projectile& b)
{
if(BulletState)
{
return true;
}
else
{
return false;
}
}



main.cpp
Code: [Select]

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Projectile.h"
#define PI 3.1415926535


int WINAPI WinMain(      
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
)
{

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Zombie Game Alpha");
sf::Image PlayerImage;
sf::Image Background;
Background.LoadFromFile("background.png");
PlayerImage.LoadFromFile("player.png");
sf::Sprite Player(PlayerImage);
sf::Sprite BackgroundS(Background);
sf::Sprite* follow = &Player;
Player.SetPosition(400,300);

Projectile Bullet;

Bullet.BulletImage.LoadFromFile("bullet.png");
Bullet.Bullet.SetImage(Bullet.BulletImage);

std::vector <Projectile>  BulletClip;

sf::View Camera(sf::Vector2f(400.f, 300.f), sf::Vector2f(400.f, 300.f));  
sf::Vector2f PPos = Player.GetPosition();

sf::Music InGameMusic;
InGameMusic.OpenFromFile("in_game.ogg");

bool shotFired = false;
std::vector<Projectile*> AllBullets;


while(Window.IsOpened())
{
sf::Event Event;
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
Window.Close();
}

Bullet.SetDirection(Player);
Bullet.SetSpeed(2);
Window.Clear();
float ElapsedTime = Window.GetFrameTime();
sf::Vector2f MousePos = Window.ConvertCoords(Window.GetInput().GetMouseX(), Window.GetInput().GetMouseY());

if (Window.GetInput().IsKeyDown(sf::Key::W))  Player.Move(0, -425 * ElapsedTime);  
        if (Window.GetInput().IsKeyDown(sf::Key::S))  Player.Move(0,  425 * ElapsedTime);  
if (Window.GetInput().IsKeyDown(sf::Key::A))  Player.Move(-425 * ElapsedTime, 0);
if (Window.GetInput().IsKeyDown(sf::Key::D))  Player.Move(425 * ElapsedTime, 0);  
if (Window.GetInput().IsKeyDown(sf::Key::N))  InGameMusic.Play();
if (Window.GetInput().IsKeyDown(sf::Key::M))  InGameMusic.Stop();
if (Window.GetInput().IsMouseButtonDown(sf::Mouse::Left))  shotFired = true;

if (shotFired)
{
BulletClip.push_back(Bullet);
Bullet.BulletState = false;
}


for (std::vector<Projectile>::iterator Itr = BulletClip.begin(), End = BulletClip.end(); Itr != End; )
{
if (Bullet.IsDestroyed(*Itr))
{
Itr = BulletClip.erase(Itr);
}

else
{
Window.Draw(Bullet.Bullet);
++Itr;
}
}

Player.SetCenter(Player.GetSize() / 2.f);
Player.SetRotation(((-1* 360 / PI *(atan2(static_cast<double>(Player.GetPosition().y - MousePos.y), static_cast<double>(Player.GetPosition().x - MousePos.x))))/2)+90);

Camera.SetCenter(follow->GetPosition());
Window.SetView(Camera);
Window.Draw(BackgroundS);
Window.Draw(Player);
Window.Display();
InGameMusic.SetLoop(true);
}
}


Whenever I click mouse1 the game gets really laggy but nothing appears.

And how would I create some text that tells me how many bullets were fired? Since only sf::string is drawable.
Title: Bullets in SFML.
Post by: K-Bal on September 13, 2009, 10:57:22 am
You are setting shotFired to true but never again to false so you are adding a bullet every frame which makes your program kill your RAM.

For the text, you can put everything in a std::stringstream and construct an sf::string from the resulting std::string.
Title: Bullets in SFML.
Post by: efeX on September 13, 2009, 11:02:14 am
-snip-
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 01:01:34 pm
The lag stopped, but I can't see any bullets, are they too fast to see or is the image incorrectly set up?
Title: Bullets in SFML.
Post by: K-Bal on September 13, 2009, 01:34:24 pm
What are you expecting? You never draw them on the screenbuffer.
Title: Bullets in SFML.
Post by: Spidyy on September 13, 2009, 01:52:49 pm
Your speed calculation is weird and wrong. :/ (If I correctly readed your code...)

For each frame, you take the position of your sprite, and multiply by 2 this position. I say at each frame, so between 300 to 5000 time by second. Far too fast!

Their is a difference from setting the speed and moving your sprite. The movement of your sprite is determined by its speed.

Your object should be something like that :

Code: [Select]
#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML/Graphics.hpp>


class Projectile
{
public:
    sf::Image BulletImage;
    static sf::Sprite Bullet;
    bool BulletState;
    float BulletSpeed; // ADDED The speed of your bullet, it will be counted in Pixel Per Second

public:

   void SetDirection(sf::Sprite);

   void SetSpeed(float);

   void Destroy(void);

   bool IsDestroyed(const Projectile& b);
   
};

#endif


Change your SetSpeed to :

Code: [Select]
void Projectile::SetSpeed(float NewSpeed)
{
    BulletSpeed = NewSpeed;
}


And in the while, add a function like this :

Code: [Select]

void Projectile::Calculate(sf::RenderWindow &app)
{
    sf::Vector2f offset;  // The offset we will add to the current position to move the sprite for ONE frame;

// Here we calculate the offset for each axis. We use the cos() function from <math.h> with the direction (wich is an Angle in Degree, we convert it in Radiant by multiplying it by PI/180)
// At this stade, we got a number between 0 and 1. We multiply it by the speed to have a number between 0 and BulletSpeed, and last, we multiply by the duration of the frame to have a correct offset for each frames.
    offset.x = static_cast<float>(cos(PI * GetRotation() / 180) * BulletSpeed * app.GetFrameTime();
    offset.y = static_cast<float>(sin(PI * GetRotation() / 180) * BulletSpeed * app.GetFrameTime();

//And we move our bullet
    Move(offset);
}


And in your main :

Code: [Select]

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Zombie Game Alpha");
...
while(Window.IsOpened())
   {
      sf::Event Event;
      while (Window.GetEvent(Event))
      {
       ...
      }

      Bullet.SetDirection(Player);
      Bullet.SetSpeed(2);
      Bullet.Calculate(Window); // ADDED
      Window.Clear();
     ...
   }


Do something like that, it would work better.

In other words, You should have a function "Calculate" or any name you want you call at each frames to actualize the properties of your sprite. The SetSpeed and SetDirection should change the properties of your sprite only when needed.

EDIT : I readed again your code, you already do that with the movement of the player. =p The movements of the bullet are no more different except it live by itself and not by listening to the inputs.
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 06:37:54 pm
I have a problem with the calculate function.

Code: [Select]

void Projectile::Calculate(sf::RenderWindow &app)
{
sf::Vector2f offset;

    offset.x = static_cast<float>(cos(PI * Bullet.GetRotation() / 180) * BulletSpeed * app.GetFrameTime());
    offset.y = static_cast<float>(sin(PI * Bullet.GetRotation() / 180) * BulletSpeed * app.GetFrameTime());

    Bullet.Move(offset);
}


It said Move is an undeclared identifier so I added sf::Sprite bullet to it so it would move the bullet. Now, GetRotation I think it's wrong, because I don't know what the function is supposed to get the rotation from, if it is the bullet and I did it right, it still doesn't draw the bullets.
Title: Bullets in SFML.
Post by: Spidyy on September 13, 2009, 07:09:20 pm
Well I think you should review all your bullet class. :\

And tell us what your programm should PRECISELY do :
- What we should have on screen
- What should happen when we use your controls

The more details we have, the more we can help you. :p
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 07:14:12 pm
Right now I have a sprite as the player that can walk around the screen and rotate towards the mouse, I have a camera that follows that sprite and I want to make it shoot bullets with Mouse1 or Left Mouse Button. Controls for walking are WASD.
It's a relatively simple top-down zombie survival game where there are some other sprites as zombies going at you (not implemented yet) and you have to kill them.

As simple as that.

I'm uploading the complete source code, including .pngs and everything.
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 07:33:45 pm
http://www.mediafire.com/?ym2nz05bh0f
Title: Bullets in SFML.
Post by: Nexus on September 13, 2009, 07:46:44 pm
You should really learn to post only the relevant code, as short as possible, but still reproducing the problem. Many people don't feel like downloading external files with a lot of unrelated code just to answer your questions.
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 07:49:39 pm
He asked the most details possible. :D

I can post relevant code. And I did before, but it seems like it's never enough.


Projectile.h (Bullet Class)

Code: [Select]

#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML/Graphics.hpp>


class Projectile
{
public:
sf::Image BulletImage;
static sf::Sprite Bullet;
bool BulletState;
float BulletSpeed;
     float BulletDirection;


public:

void SetDirection(sf::Sprite);

void SetSpeed(float);

void Destroy(void);

bool IsDestroyed(const Projectile& b);

void Calculate(sf::RenderWindow &app);

};

#endif


Projectile.cpp

Code: [Select]

#include "Projectile.h"
#include <SFML/Graphics.hpp>
#define PI 3.1415926535

sf::Sprite Projectile::Bullet;

void Projectile::SetDirection(sf::Sprite Reference)
{
float TargetRotation = Reference.GetRotation();
Bullet.SetRotation(static_cast<float>(fmod(TargetRotation, 360)));
float BulletRotation = Bullet.GetRotation();
if (BulletRotation < 0)
Bullet.SetRotation(BulletRotation + 360.f);
}

void Projectile::SetSpeed(float NewSpeed)
{
BulletSpeed = NewSpeed;
}

void Projectile::Destroy()
{
BulletState = true;
}

bool Projectile::IsDestroyed(const Projectile& b)
{
if(BulletState)
{
return true;
}
else
{
return false;
}
}

void Projectile::Calculate(sf::RenderWindow &app)
{
sf::Vector2f offset;

    offset.x = static_cast<float>(cos(PI * Bullet.GetRotation() / 180) * BulletSpeed * app.GetFrameTime());
    offset.y = static_cast<float>(sin(PI * Bullet.GetRotation() / 180) * BulletSpeed * app.GetFrameTime());

    Bullet.Move(offset);
}


main.cpp Game Loop

Code: [Select]

while(Window.IsOpened())
{
sf::Event Event;
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
Window.Close();
}

Bullet.SetDirection(Player);
        Bullet.SetSpeed(2);
        Bullet.Calculate(Window);
Window.Clear();
float ElapsedTime = Window.GetFrameTime();
sf::Vector2f MousePos = Window.ConvertCoords(Window.GetInput().GetMouseX(), Window.GetInput().GetMouseY());

if (Window.GetInput().IsKeyDown(sf::Key::W))  Player.Move(0, -425 * ElapsedTime);  
        if (Window.GetInput().IsKeyDown(sf::Key::S))  Player.Move(0,  425 * ElapsedTime);  
if (Window.GetInput().IsKeyDown(sf::Key::A))  Player.Move(-425 * ElapsedTime, 0);
if (Window.GetInput().IsKeyDown(sf::Key::D))  Player.Move(425 * ElapsedTime, 0);  
if (Window.GetInput().IsKeyDown(sf::Key::N))  InGameMusic.Play();
if (Window.GetInput().IsKeyDown(sf::Key::M))  InGameMusic.Stop();
if (Window.GetInput().IsMouseButtonDown(sf::Mouse::Left))  shotFired = true;

if (shotFired)
{
BulletClip.push_back(Bullet);
Bullet.BulletState = false;
}


for (std::vector<Projectile>::iterator Itr = BulletClip.begin(), End = BulletClip.end(); Itr != End; )
{
if (Bullet.IsDestroyed(*Itr))
{
Itr = BulletClip.erase(Itr);
}

else
{
Window.Draw(Bullet.Bullet);
++Itr;
}
}

shotFired = false;

Player.SetCenter(Player.GetSize() / 2.f);
Player.SetRotation(((-1* 360 / PI *(atan2(static_cast<double>(Player.GetPosition().y - MousePos.y), static_cast<double>(Player.GetPosition().x - MousePos.x))))/2)+90);

Camera.SetCenter(follow->GetPosition());
Window.SetView(Camera);
Window.Draw(BackgroundS);
Window.Draw(Player);
Window.Display();
InGameMusic.SetLoop(true);
}
Title: Bullets in SFML.
Post by: K-Bal on September 13, 2009, 08:14:02 pm
Quote from: "tiago221"

Code: [Select]

class Projectile
{
public:
sf::Image BulletImage;
static sf::Sprite Bullet;


This does not seem to make great sense. What are you trying to achieve here?
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 08:15:38 pm
Initialize the bullet sprite and image. Why doesn't it make sense?
Title: Bullets in SFML.
Post by: Spidyy on September 13, 2009, 08:15:46 pm
Okay.

I think you need to review some of basic concepts of C++ and Oriented Object Programming. :\

I'll give you the advices you need to complete your code. Think about it, review your object model, then when you got something else, post it again. =p

You need to review your projectile class. As it is now, it cannot work as a true object. Let's see what it is now :

Code: [Select]

#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML/Graphics.hpp>


class Projectile
{

// First of all, the attributes, meaning "where you store datas" must be in private. An object should be a "black box", its attributes hidden and with the function as "buttons" for the user. Member data are private by default. So we delete the first "public:"

public:

sf::Image BulletImage;  // Here, the image is a big array of pixels stored in memory. When drawing, the image is "copy/paste" on the screen. There is no need to create a new Image at each projectile.

static sf::Sprite Bullet;  // Also, the sf::Sprite already know its image as you have to give it in parameter when creating the sprite, or with a sprite.SetImage(); We don't need the "static" word.

bool BulletState;  // This is OK. We need to know if a bullet is done for before destroying it from the scene.

float BulletSpeed;  // This is OK. A bullet need to know at wich speed it move.

// Let see the functions.

public:
// Here, we need one or two constructors! How the object will know what to do and what are his attributes when we create it? :/

Projectile();  // Default constructor, even if we don't need it right know, it is always usefull to have it. It's rĂ´le is to give our basic attributes a default value at creation.

Projectile(sf::Image &image, sf::vector2f &position, float speed);  // A constructor with parametter for our projectile, all it need to know is what it looks like, from where he begin his course and at what speed.

void SetDirection(sf::vector2f &target);  //  To set the direction, you can use a reference's coordinates, to tell the bullet to wich ennemy it should go

void SetDirection(float angle);  // We can also set the direction with an angle, in degree

void SetSpeed(float);  // Here, you just update the speed of the bullet if it have to change.

void Destroy(bool);  // It's OK, we need to tell when the bullet hit its target

bool IsDestroyed(const Projectile& b);  // It's OK, we need to know if the bullet have hit something, you can also test if it is off the screen here. Don't need parametter.

void Calculate(sf::RenderWindow &app); // It's OK, we need to update the positions of the bullet at each frame with it.

};

#endif


With this, our projectile became more clear. We can also enhance it through the inheritance. Why? Because the sprite already have the data members of a moving object -> a reference to it's image, the xy coordinates and a direction. Why not use it?

Code: [Select]

#ifndef PROJECTILE_H
#define PROJECTILE_H
#include <SFML/Graphics.hpp>

// We make the Projectile class inherite from sf::Sprite
class Projectile : public sf::Sprite
{
sf::Sprite Bullet;  // Projectile became itself a sf::Sprite, we don't need to create another sprite anymore.

bool BulletState;

float BulletSpeed;

public:


Projectile();  // In the default constructor, we'll call for the default constructor of sf::Sprite

Projectile(sf::Image &image, sf::vector2f &position, float speed);  // In this constructor, we'ell call for the sf::Sprite constructor and pass to it the &image and the &position.

void SetDirection(sf::vector2f &target);  // The direction to a target is still interresting, but with an angle, you don't need anymore to have a SetDirection(float angle) function, you can use the sf::Sprite::SetRotation(float rotation).

//  Functions bellow are still needed
void SetSpeed(float);

void Destroy(bool);

bool IsDestroyed();

void Calculate(sf::RenderWindow &app);

};

#endif


At the end, you should have in your main one single sf::Image created before your game loop, your vector ready to receive bullets and a way to add bullet to your vector when pressing your "fire" button. (with insert())

Try to figure out what the function's definition will look like. If you don't know what I was saying in this exemple, review your C++ tutorials and lesson first. :\

If you can't find how to write the class tomorrow or later, I'll give you some answers, but it will meaningless if you don't try a bit more by yourself. :p

And if you don't want to take those advices, feel free to do. :o
Title: Bullets in SFML.
Post by: tiago221 on September 13, 2009, 08:21:37 pm
Of course I'll take them, and I'll start working on it right away, thanks. :D