SFML community forums

Help => Graphics => Topic started by: Prometheus on March 04, 2014, 09:23:18 am

Title: Object Rendering by sf::VertexArray (and assorted questions)
Post by: Prometheus on March 04, 2014, 09:23:18 am
Hey, guys.

I've been working on a side project of mine for a while now, and I've really taken to SFML -- it's lightweight and convenient to use. The project is, at its most fundamental level, a simple 2D top-down game based in space. It's fairly standard fare: the player controls a ship and flies around completing objectives.

I've got a few questions on methodology, however, that I would appreciate feedback on from the SFML community.


Code (suggestions and criticism welcome):

How stars are created:

void Starfield::CreateStar(const StarParameters& star_parameters) {
    ColorName color = FilterColor(star_parameters.color_value);
   
    unsigned int num_points = 0;
    sf::Vector2f center_position(star_parameters.position);
    center_position *= kLevelFactors[level_]; // parallax
    center_position += screen_size_ / 2.f;
   
    // determine the number of points by star size
    if (star_size_ == kSmall)
        num_points = 6U;
    else if (star_size_ == kMedium)
        num_points = 8U;
    else
        num_points = 11U;
   
    // center point for circle (combintion of triangles)
    sf::Vertex center(center_position, kStarColors[color]);
    // points along circumference
    sf::VertexArray outliers(sf::Points, num_points - 1);
   
    // figure out where the points lie along the circumference
    for (int index = 0; index < num_points - 1; ++index) {
        float rotation = to_Radians(to_SFMLDegrees((index + 1) * 360.f / (num_points - 1)));
        sf::Vector2f position(center_position.x + star_parameters.radius * cos(rotation),
                              center_position.y + star_parameters.radius * sin(rotation));
        outliers[index] = sf::Vertex(position, kStarColors[color]);
    }
   
    // append vertices in groups of three (triangles)
    for (int index = 0; index < num_points - 1; ++index) {
        stars_.append(center);
        stars_.append(outliers[index]);
        if (index == num_points - 2)
            stars_.append(outliers[1]);
        else
            stars_.append(outliers[index + 1]);
    }
   
    return;
}

How stars were moved prior to Version 3:

void Starfield::MoveStars(const sf::Vector2f& screen_offset) {
    quadtree_->Clear();
    // parallax
    sf::Vector2f scaled_offset = screen_offset * kLevelFactors[level_];

    // world bounds (really should use an sf::FloatRect here)
    float left_bound = half_screen_size_.x - half_field_size_;
    float right_bound = half_screen_size_.x + half_field_size_;
    float top_bound = half_screen_size_.y - half_field_size_;
    float bottom_bound = half_screen_size_.y + half_field_size_;
   
    for (Star* star : stars_) {
        // move star
        star->MoveStar(scaled_offset);
       
        sf::Vector2f loop_offset(0.f, 0.f);
       
        // check if star left world bounds
        if (star->position().x < left_bound)
            loop_offset.x += field_size_;
        else if (star->position().x > right_bound)
            loop_offset.x -= field_size_;
           
        if (star->position().y > bottom_bound)
            loop_offset.y -= field_size_;
        else if (star->position().y < top_bound)
            loop_offset.y += field_size_;
       
        // loop the star if needed
        if (loop_offset.x || loop_offset.y)
            star->MoveStar(loop_offset);

        // if the star is on screen, insert it in the quadtree for later rendering
        // (screen bounds check performed by Insert function)
        quadtree_->Insert(star);
    }
   
    return;
}

How stars are moved and drawn now:

void Starfield::MoveStars(const sf::Vector2f& screen_offset) {
    // no screen or world bounds check
    offset_.translate(screen_offset * kLevelFactors[level_]);

    return;
}

void Starfield::draw(sf::RenderTarget& target, sf::RenderStates states) const {
    states.transform = offset_;
    target.draw(stars_, states);
   
    return;
}



A final addendum: I'm aware of the existence of sf::View, and that it can be used for both scrolling the game world as well as looping the background. I'm not quite sure how it works -- I hadn't really considered it until just recently -- but I suppose I'm not opposed to its use. I'll give it a shot if there's general consensus that it would be a valuable addition. That said, I'm still looking for ideas on how to better utilize sf::VertexArrays and the like.

Thanks for taking the time to read through glance at my perhaps excessively long post.
Title: Re: Object Rendering by sf::VertexArray (and assorted questions)
Post by: Rhimlock on March 04, 2014, 12:18:02 pm
If you want to learn more about Views, you should look in the Tutorials:
http://www.sfml-dev.org/tutorials/2.1/graphics-view.php (http://www.sfml-dev.org/tutorials/2.1/graphics-view.php)

But since you use a single VertexArray and use a Translate to move the Stars, I'm not really sure if you would gain any advantage in using a View.
Title: Re: Object Rendering by sf::VertexArray (and assorted questions)
Post by: Prometheus on March 06, 2014, 04:47:09 am
But since you use a single VertexArray and use a Translate to move the Stars, I'm not really sure if you would gain any advantage in using a View.

Thanks for the comment. I was thinking that views may be a convenient method of wrapping the background/world around itself, but that's really just an addendum to the main topic at hand.

I'm looking forward to hearing from more of the community.
Title: Re: Object Rendering by sf::VertexArray (and assorted questions)
Post by: Prometheus on March 10, 2014, 09:02:48 pm
Perhaps bumping this thread is a bit premature, but I am still looking for feedback from the SFML community. (The thread was about to fall off the first page.)

Thanks.