Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Bullets in SFML.  (Read 33282 times)

0 Members and 1 Guest are viewing this topic.

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« 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.

93interactive

  • Newbie
  • *
  • Posts: 39
    • View Profile
    • http://93-interactive.com
Bullets in SFML.
« Reply #1 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.

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« Reply #2 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.

K-Bal

  • Full Member
  • ***
  • Posts: 104
    • View Profile
    • pencilcase.bandcamp.com
    • Email
Bullets in SFML.
« Reply #3 on: September 11, 2009, 03:08:18 pm »
You have to keep shotFired true until the bullet is destroyed.
Listen to my band: pencilcase.bandcamp.com

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Bullets in SFML.
« Reply #4 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
    }
}
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« Reply #5 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

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Bullets in SFML.
« Reply #6 on: September 12, 2009, 06:30:50 pm »
Why pointers inside containers? I just said something about them here. ;)

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.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« Reply #7 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

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Bullets in SFML.
« Reply #8 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.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« Reply #9 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'

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Bullets in SFML.
« Reply #10 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.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« Reply #11 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.

e_barroga

  • Jr. Member
  • **
  • Posts: 76
    • View Profile
Bullets in SFML.
« Reply #12 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);

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Bullets in SFML.
« Reply #13 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);
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

efeX

  • Newbie
  • *
  • Posts: 13
    • View Profile
Bullets in SFML.
« Reply #14 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.