SFML community forums

Help => General => Topic started by: Noob on February 13, 2014, 07:21:54 pm

Title: Vector of projectile sprites problem
Post by: Noob on February 13, 2014, 07:21:54 pm
Ok, so I'm having major problems with creating and updating a vector of sprites that are meant to represent projectiles. Everything compiles fine, but my sprite, or should I say sprite, has other plans it seems...

The fireball is meant to be moving across the screen, but it doesn't.
(http://oi57.tinypic.com/5tw85c.jpg)

All relevant code, will compile to the above exe.:

Entity.h
#pragma once
#include "SFML/Graphics.hpp"
#include <Windows.h>

class Entity : public sf::Drawable, public sf::Transformable
{
public:
        void createTexture(const sf::Image& imageRef, int xTexturePosition, int yTexturePosition, int xTextureSize, int yTextureSize);
        void createSprite(int width, int height, int xPosition, int yPosition, float scale);

protected:
        sf::Texture texture;
        sf::Sprite sprite;

private:
        void draw(sf::RenderTarget& target, sf::RenderStates states) const
        {
                states.transform *= getTransform();

                target.draw(sprite, states);
        };
       
};

Entity.cpp
#include "Entity.h"

void Entity::createTexture(const sf::Image& imageRef, int xTexturePosition, int yTexturePosition, int xTextureSize, int yTextureSize)
{
        texture.loadFromImage(imageRef, sf::IntRect((xTexturePosition * xTextureSize), (yTexturePosition * yTextureSize), xTextureSize, yTextureSize));
}

void Entity::createSprite(int width, int height, int xPosition, int yPosition, float scale)
{
        sprite.setTexture(texture);
        sprite.setTextureRect(sf::IntRect(0, 0, width, height));
        sprite.setOrigin((width / 2), (height / 2));
        sprite.setScale(scale, scale);
        sprite.setPosition(xPosition, yPosition);
}

Fireball.h
#pragma once
#include "Entity.h"
#include <vector>

class Fireball : public Entity
{
public:
        void createFireball(sf::Keyboard& keyboard);

private:
        void draw(sf::RenderTarget& target, sf::RenderStates states) const
        {
                states.transform *= getTransform();

                for(unsigned int i = 0; i < fireball.size(); i++)
                {
                        target.draw(fireball[i], states);
                }
        };

        std::vector <sf::Sprite> fireball; // A vector of sprites called fireball.
};

Fireball.cpp
#include "Fireball.h"

void Fireball::createFireball(sf::Keyboard& keyboard)
{
        if( keyboard.isKeyPressed(keyboard.Space))
        {
                fireball.resize(fireball.size() + 1);
        }

        for (unsigned int i = 0; i < fireball.size(); i++)
        {
                fireball[i] = sprite; // Gives the fireball at [i] the properties of the protected sprite in Entity.

                fireball[i].move(1,1); // This seems to do nothing.

                if(fireball[i].getPosition().x > 700)
                {
                        fireball.erase(fireball.begin() + i);
                }

                fireball.shrink_to_fit();
        }
}

Game.h
#pragma once
#include "SFML/Graphics.hpp"

class Game
{
public:
        Game();
        void runGame();

private:
        int screenHeight;
        int screenWidth;

        sf::Clock clock;
        long float updateRate;
};

Game.cpp
#include "Game.h"
#include "Fireball.h"

Game::Game()
{
        screenWidth = 1600;
        screenHeight = screenWidth / 16 * 9;
}

void Game::runGame()
{
        sf::Keyboard keyboard;
        sf::Keyboard& keyboardRef = keyboard;

        sf::RenderWindow window(sf::VideoMode(screenWidth, screenHeight), "Y U NO WORK");
        sf::RenderWindow& windowRef = window;
       
        sf::Image spriteSheet;
        spriteSheet.loadFromFile("Main sprite sheet.png");
        sf::Image& imageRef = spriteSheet;


        Fireball fb;
        fb.createTexture(imageRef, 0, 8, 16, 16);
        fb.createSprite(16, 16, 150, 150, 4);

        long float updateRate = 1000.0f / 60.0f;       

    while (window.isOpen())
    {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        if (event.type == sf::Event::Closed || keyboard.isKeyPressed(keyboard.Escape))
                                window.close();
                }
                window.clear(sf::Color(0,0,0));
               
                if(clock.getElapsedTime().asMilliseconds() >= updateRate)
                {
                        clock.restart();
//      *       *       *       *       *       *       *       *       *       *       *       *       *       *       *       *       Game logic goes here
                        fb.createFireball(keyboardRef);

                        window.draw(fb);
                        window.display();
                }
        }
}

int main()
{
        Game game;
        game.runGame();
    return 0;
}

I've been stuck on this problem for what seems like an age. I think the problem is something to do with the draw function that is being used. Is window.draw(fb) using the draw function from Entity or the one in Fireball?
Also, shouldn't the fireball.move() in Fireball be doing something? The sprite just sits there.

I'm no C++ pro so plz help a noob out.
Title: Re: Vector of projectile sprites problem
Post by: zsbzsb on February 13, 2014, 07:33:25 pm
For starters how does updating the vector of fireballs only when a new one is created work out for ya?

Try moving them every frame.  ;)
Title: Re: Vector of projectile sprites problem
Post by: Noob on February 13, 2014, 08:38:36 pm
(http://i1.kym-cdn.com/photos/images/original/000/284/709/7ae.png)...

Ok, so after commiting suicide I added
if(!fireball[i].spriteIsSet)
                {
                        fireball[i] = sprite;
                        fireball[i].spriteIsSet = true;
                }
to Fireball.cpp and put 'bool spriteIsSet' into the Sprite SFML header file and set it to false, but now...

(http://oi57.tinypic.com/vg34t1.jpg)
What the...? O_o
Pressing space adds new elements to the vector and they show up and start moving, but if quickly tapping on the space key some of the sprites go like that. It happens randomly upon key presses.
I have no idea where to begin with this.
Title: Re: Vector of projectile sprites problem
Post by: Grimshaw on February 13, 2014, 08:48:11 pm
You always call clear, but not always display on the window. That's wrong. Every frame you need to clear and display. That should solve the issue
Title: Re: Vector of projectile sprites problem
Post by: Hapax on February 13, 2014, 08:59:34 pm
In fact, you should call clear, display, AND draw each time (in order: clear, draw, display), regardless of whether the clock is telling you to update the position.
Title: Re: Vector of projectile sprites problem
Post by: Noob on February 13, 2014, 09:02:56 pm
What do you mean?

I'm only calling window.display() once every update as it seems pointless to call it if nothing has changed.



Am I going to have to redo a lot of code to make it fall into the 'Update' and 'Draw' paradigm?
Title: Re: Vector of projectile sprites problem
Post by: Nexus on February 13, 2014, 09:48:04 pm
I'm only calling window.display() once every update as it seems pointless to call it if nothing has changed.
Don't assume things, read tutorials.

http://www.sfml-dev.org/tutorials/2.1/graphics-draw.php
There's a big red box explaining why you shouldn't do it the way you do ;)
Title: Re: Vector of projectile sprites problem
Post by: Hapax on February 13, 2014, 09:51:21 pm
I'm only calling window.display() once every update as it seems pointless to call it if nothing has changed.
You should be, on every loop, be calling clear, draw, and display. Get used to it; it works wonders  ;D
Title: Re: Vector of projectile sprites problem
Post by: Noob on February 13, 2014, 10:56:35 pm
Ok, so I've done that and I've gave to documentation a good seeing to but none of it seems to have remedied the visual artifacts seen in the second screenshot.
Title: Re: Vector of projectile sprites problem
Post by: Hapax on February 13, 2014, 11:34:55 pm
Ok, so I've done that and I've gave to documentation a good seeing to but none of it seems to have remedied the visual artifacts seen in the second screenshot.
I have to ask. Are all three (clear, draw, display) now outside of this conditional:
if(clock.getElapsedTime().asMilliseconds() >= updateRate)
{
}
Title: Re: Vector of projectile sprites problem
Post by: Noob on February 13, 2014, 11:59:06 pm
Yep, my loop looks like this now:
        if(clock.getElapsedTime().asMilliseconds() > updateRate)
                {
                        clock.restart();
//      *       *       *       *       *       *       *       *       *       *       *       *       *       *       *       *       Update logic stuff here
                        fb.updateFireballs(keyboardRef);
                }
                window.clear(sf::Color::Black);
//      *       *       *       *       *       *       *       *       *       *       *       *       *       *       *       *       Draw stuff here
                window.draw(fb);

                window.display();
        }

But the thing is, none of that was the problem (though I'm sure it would have gave me problems in the future).

After an hour of just messing about trying random stuff, I realised it was something to do with the locations of my exe. and the Spritesheet that it needed.
The flickering/warped sprites problem only happens when I run the program from the exe. in my Release folder (I'm using VC2010, Release mode, static SFML config btw) which also has the Spritesheet in it that the exe. is looking for.

When I run from VC itself there are no problems at all.