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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Draugr

Pages: [1]
1
SFML projects / Re: Procedurally generated starfield
« on: August 21, 2013, 02:31:30 pm »
Big thanks for adding the video preview, I added it to the opening post. I took one with FFMPEG, but didn't have anything to cut the video. :)

2
SFML projects / Re: Procedurally generated starfield
« on: August 21, 2013, 12:16:41 pm »
Thanks a lot for the useful hints Nexus, I'm in the middle of finding back into C++ right now, so exactly such code reviews is what I need :)

Also thanks for posting the screenshot, even though the primary aim - the parallax effect - does not get over. I will try to record a video and put it on youtube, to embed it here or post the link.

Anyone knows a good Linux screen capture tool?

3
SFML projects / Re: Procedurally generated starfield
« on: August 21, 2013, 10:34:35 am »
Thanks for the input, good points :)

I think making the image taller will be hard when I want to add various space objects of which I do not yet know the size. Currently I think the best general strategy is to define each objects size and use it to specify the range in which a new object of that type will be placed. E.g. large stars with a horizontal size of 4 pixels will only be created in the range of [0, 596].

Thanks a lot for pointing out that updating over the edges is undefined behaviour. Checking the space for updating images is pretty unconvenient, though. I remember using directX about 10 years ago where you could define masks for this purpose where everything overlapping the defined area was simply cut off. I guess this was the reason why I assumed this would work.

4
SFML projects / Re: Procedurally generated starfield
« on: August 21, 2013, 02:27:58 am »
Thanks for the comments :)

I'm developing on Linux and compiling with gcc. Guess I'll have to get MSVC on Windows and try it to learn a bit about keeping the code portable.

The code is compiling for me exactly as I posted it, so I'm not sure if that with remove_if and for_each is another MS related thing.

I haven't had any crashes so far, even when keeping it running for 10 minutes, so I'm not sure why it crashes in some cases. Any further help or comments would be very much appreciated.

Also a question: is there really a good reason for keeping declaration and definition separated in two files? I find it annoying when I have to switch between files and haven't found a good reason so far.

5
SFML projects / Procedurally generated starfield
« on: August 21, 2013, 01:51:21 am »
Hello all,

for a vertical shoot 'em up game I created a scrolling background with stars. I wanted it to have a parallax effect with differently sized stars, scrolling in different speed. I also wanted it to be created procedurally and completely random since I intend to expand it to be more beautiful in my game in the end (with procedurally created galaxies and stuff). It uses C++11 stuff from <random> and Lambdas, so you will have to enable it for your compiler. Asides from this the project does not use any files so you can just paste and compile the code. :)

I post this for anyone to use and, more importantly, to get comments on how it is done. This is my first try with sfml, so please tell me if I use something wrong or in a way that causes bad performance.

Thanks for any comments and best regards
Draugr

Here's a video preview - thanks to eXpl0it3r!



Here comes the code:

#include <SFML/Graphics.hpp>
#include "Starfield.hpp"

int main() {

        sf::Vector2u screenDimensions(800, 600);
        sf::RenderWindow window(sf::VideoMode(screenDimensions.x, screenDimensions.y, 32), "Game main window", sf::Style::Titlebar | sf::Style::Close);

        window.setSize(screenDimensions);
        window.setFramerateLimit(60);

        //create an empty black image onto which the starfield will be painted every frame
        sf::Image starsImage;
        starsImage.create(screenDimensions.x, screenDimensions.y, sf::Color::Black);

        sf::Texture starsTexture;
        starsTexture.loadFromImage(starsImage);
        starsTexture.setSmooth(false);

        sf::Sprite starsSprite;
        starsSprite.setTexture(starsTexture);
        starsSprite.setPosition(0, 0);

        Starfield backgroundStars(screenDimensions.x, screenDimensions.y);

        //Game loop
        while (window.isOpen()) {
                sf::Event event;

                while (window.pollEvent(event)) {

                    switch (event.type) {
                        case sf::Event::Closed:
                            window.close();
                            break;

                        //Keypress related events
                        case sf::Event::KeyPressed:
                            if(event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Return){
                                window.close();
                            }
                            break;

                        default:
                            break;
                    }
                }

                starsTexture.loadFromImage(starsImage);
                backgroundStars.drawStarfield(starsTexture);

                window.clear(sf::Color(0, 0, 0));
                window.draw(starsSprite);
                window.display();

                backgroundStars.updateStarfield();
        }

        return 0;

}
 

#ifndef STARFIELD_H
#define STARFIELD_H

#include "Star.hpp"
#include <SFML/Graphics.hpp>
#include <random>
#include <vector>
#include <ctime>

using std::vector;

class Starfield
{
    public:
        Starfield();
        Starfield(int, int);
        ~Starfield() {}

        void updateStarfield();
        void drawStarfield(sf::Texture&);

    protected:

        int maxSmallStars;
        int maxMediumStars;
        int maxLargeStars;

        sf::Uint16 x_Size;
        sf::Uint16 y_Size;

        vector<Star> smallStars;
        vector<Star> mediumStars;
        vector<Star> largeStars;

        std::default_random_engine re_x;
        std::default_random_engine re_y;
        std::uniform_int_distribution<int> my_distribution_x;
        std::uniform_int_distribution<int> my_distribution_y;

        sf::Image smallStarImage;
        sf::Image mediumStarImage;
        sf::Image largeStarImage;
};

//starfield won't work without proper data
Starfield::Starfield(): maxSmallStars(0), maxMediumStars(0), maxLargeStars(0), x_Size(800), y_Size(600)
{
}

Starfield::Starfield(int xResolution, int yResolution)
{

    x_Size = xResolution;
    y_Size = yResolution;

    //size of the different star sizes in pixels
    sf::Uint16 smallSize = 1;
    sf::Uint16 mediumSize = 2;
    sf::Uint16 largeSize = 4;

    //create the images that will be used to update the background texture
    smallStarImage.create(smallSize, smallSize, sf::Color::White);
    mediumStarImage.create(mediumSize, mediumSize, sf::Color::White);
    largeStarImage.create(largeSize, largeSize, sf::Color::White);

    //init random generator
    my_distribution_x = std::uniform_int_distribution<int>(0, xResolution);
    my_distribution_y = std::uniform_int_distribution<int>(0, yResolution);

    re_x.seed(std::time(0));
    re_y.seed(std::time(0)+24);

    //The higher reduceStars the fewer stars; classDifference sets the proportionality between small, medium and large stars. The higher the number, the fewer stars in each larger class.
    int reduceStars = 8;
    int classDifference = 3;

    maxSmallStars = (xResolution / (reduceStars * 10)) * (yResolution / reduceStars);
    maxMediumStars = (xResolution / (reduceStars * 10 * classDifference)) * (yResolution / (reduceStars * classDifference));
    maxLargeStars = (xResolution / (reduceStars * 10 * classDifference * classDifference)) * (yResolution / (reduceStars * classDifference * classDifference));

    //generate a start set of stars
    while((int)smallStars.size() <= maxSmallStars){
        smallStars.push_back(Star(my_distribution_x(re_x), my_distribution_y(re_y)));
    }

    while((int)mediumStars.size() <= maxMediumStars){
        mediumStars.push_back(Star(my_distribution_x(re_x), my_distribution_y(re_y)));
    }

    while((int)largeStars.size() <= maxLargeStars){
        largeStars.push_back(Star(my_distribution_x(re_x), my_distribution_y(re_y)));
    }
}

void Starfield::updateStarfield()
{

    //remove all stars that have exceeded the lower screen border
    smallStars.erase(remove_if(smallStars.begin(), smallStars.end(), [&](Star& p_Star){
        return (p_Star.getYPos() > y_Size);
    }
    ), smallStars.end());

    mediumStars.erase(remove_if(mediumStars.begin(), mediumStars.end(), [&](Star& p_Star){
        return (p_Star.getYPos() > y_Size);
    }
    ), mediumStars.end());

    largeStars.erase(remove_if(largeStars.begin(), largeStars.end(), [&](Star& p_Star){
        return (p_Star.getYPos() > y_Size);
    }
    ), largeStars.end());

    //move every star, according to its size to create a parallax effect
    for_each(smallStars.begin(), smallStars.end(), [&](Star& p_Star){
        p_Star.addYPos(1);
    }
    );

    for_each(mediumStars.begin(), mediumStars.end(), [&](Star& p_Star){
        p_Star.addYPos(2);
    }
    );

    for_each(largeStars.begin(), largeStars.end(), [&](Star& p_Star){
        p_Star.addYPos(4);
    }
    );

    //create new stars until the set limit is reached
    while((int)smallStars.size() <= maxSmallStars){
        smallStars.push_back(Star(my_distribution_x(re_x), 0));
    }

    while((int)mediumStars.size() <= maxMediumStars){
        mediumStars.push_back(Star(my_distribution_x(re_x), 0));
    }

    while((int)largeStars.size() <= maxLargeStars){
        largeStars.push_back(Star(my_distribution_x(re_x), 0));
    }
}

//update a target texture with all stars contained in this starfield
void Starfield::drawStarfield(sf::Texture& p_Texture)
{
    for(vector<Star>::iterator it = smallStars.begin(); it != smallStars.end(); ++it){
        p_Texture.update(smallStarImage, it->getXPos(), it->getYPos());
    }

    for(vector<Star>::iterator it = mediumStars.begin(); it != mediumStars.end(); ++it){
        p_Texture.update(mediumStarImage, it->getXPos(), it->getYPos());
    }

    system("clear");
    for(vector<Star>::iterator it = largeStars.begin(); it != largeStars.end(); ++it){
        p_Texture.update(largeStarImage, it->getXPos(), it->getYPos());
    }
}
#endif // STARFIELD_H
 

#ifndef STAR_H
#define STAR_H

#include <SFML/Graphics.hpp>

class Star
{
    public:
        Star() {}
        Star(sf::Uint16, sf::Uint16);
        ~Star() {}
        sf::Uint16 getXPos();
        sf::Uint16 getYPos() const;
        void setXPos(sf::Uint16);
        void setYPos(sf::Uint16);
        void addYPos(sf::Uint16);

    private:
        sf::Uint16 xPos;
        sf::Uint16 yPos;
};

Star::Star(sf::Uint16 p_X_Pos, sf::Uint16 p_Y_Pos)
{
    xPos = p_X_Pos;
    yPos = p_Y_Pos;
}

sf::Uint16 Star::getXPos()
{
    return xPos;
}

sf::Uint16 Star::getYPos() const
{
    return yPos;
}

void Star::setXPos(sf::Uint16 x)
{
    xPos = x;
    return;
}

void Star::setYPos(sf::Uint16 y)
{
    yPos = y;
    return;
}

void Star::addYPos(sf::Uint16 y)
{
    yPos += y;
    return;
}
#endif // STAR_H
 

Pages: [1]
anything