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

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

0 Members and 2 Guests are viewing this topic.

Nexus

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

Spidyy

  • Sr. Member
  • ****
  • Posts: 493
    • View Profile
Bullets in SFML.
« Reply #16 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)

Nexus

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

efeX

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

tiago221

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

Nexus

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

tiago221

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

Nexus

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

tiago221

  • Newbie
  • *
  • Posts: 24
    • View Profile
Bullets in SFML.
« Reply #23 on: September 13, 2009, 03:29:27 am »
Thanks, if I have any problems I'll post. :D

tiago221

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

K-Bal

  • Full Member
  • ***
  • Posts: 104
    • View Profile
    • pencilcase.bandcamp.com
    • Email
Bullets in SFML.
« Reply #25 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.
Listen to my band: pencilcase.bandcamp.com

efeX

  • Newbie
  • *
  • Posts: 13
    • View Profile
Bullets in SFML.
« Reply #26 on: September 13, 2009, 11:02:14 am »
-snip-

tiago221

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

K-Bal

  • Full Member
  • ***
  • Posts: 104
    • View Profile
    • pencilcase.bandcamp.com
    • Email
Bullets in SFML.
« Reply #28 on: September 13, 2009, 01:34:24 pm »
What are you expecting? You never draw them on the screenbuffer.
Listen to my band: pencilcase.bandcamp.com

Spidyy

  • Sr. Member
  • ****
  • Posts: 493
    • View Profile
Bullets in SFML.
« Reply #29 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.

 

anything