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

Author Topic: Rendering stars (example)  (Read 1899 times)

0 Members and 1 Guest are viewing this topic.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Rendering stars (example)
« on: January 13, 2012, 11:54:59 am »
Hey guys,

an user on IRC recently had some questions about rendering stars with parallex scrolling. I did a quick mashup out of fun and want to share it if anyone's looking for ideas on how to do it. ;) License is WTFPL. You can have multiple layers with different speeds and colors.



Code: [Select]
#include <SFML/Graphics.hpp>
#include <vector>
#include <ctime>
#include <cmath>
#include <iostream>
 
static const std::size_t NUM_TEXTURES = 4;
static const unsigned int TEXTURE_SIZE = 128;
static const std::size_t NUM_STARS_PER_TEXTURE = 20;
static const std::size_t NUM_LAYERS = 6;
static const float SPEED = 150.0f;
static const float SLOWDOWN_FACTOR = 0.5f;
static const float Y_SHIFT = 15.0f;
static const unsigned int COLOR_SHIFT = 40;
 
static const unsigned int SCREEN_WIDTH = 800;
static const unsigned int SCREEN_HEIGHT = 600;
 
struct Layer {
float speed;
sf::Vector2f offset;
std::size_t texture_id;
};
 
typedef std::vector<sf::Texture> TextureArray;
typedef std::vector<Layer> LayerArray;
 
int main() {
sf::RenderWindow window( sf::VideoMode( SCREEN_WIDTH, SCREEN_HEIGHT ), "Stars example" );
 
window.SetFramerateLimit( 60 );
 
// Init randomizer.
std::srand( static_cast<unsigned int>( std::time( 0 ) ) );
 
// Prepare textures.
TextureArray textures( NUM_TEXTURES );
 
for( std::size_t texture_id = 0; texture_id < NUM_TEXTURES; ++texture_id ) {
sf::Image image;
image.Create( TEXTURE_SIZE, TEXTURE_SIZE, sf::Color::Black );
 
// Set stars.
for( std::size_t star_id = 0; star_id < NUM_STARS_PER_TEXTURE; ++star_id ) {
sf::Vector2<unsigned int> star_pos(
std::rand() % TEXTURE_SIZE,
std::rand() % TEXTURE_SIZE
);
 
image.SetPixel( star_pos.x, star_pos.y, sf::Color::White );
image.CreateMaskFromColor( sf::Color::Black );
}
 
textures[texture_id].LoadFromImage( image );
}
 
// Prepare layers.
LayerArray layers( NUM_LAYERS );
 
for( std::size_t layer_id = 0; layer_id < NUM_LAYERS; ++layer_id ) {
layers[layer_id].offset = sf::Vector2f( 0, static_cast<float>( layer_id ) * Y_SHIFT );
layers[layer_id].speed = SPEED / static_cast<float>( layer_id + 1 ) * SLOWDOWN_FACTOR;
layers[layer_id].texture_id = layer_id % NUM_TEXTURES;
}
 
sf::Event event;
while( window.IsOpened() ) {
while( window.PollEvent( event ) ) {
if( event.Type == sf::Event::Closed ) {
window.Close();
}
}
 
float frame_time( static_cast<float>( window.GetFrameTime() ) / 1000.0f );
 
window.Clear();
 
// Update offsets and render.
for( int layer_id = NUM_LAYERS - 1; layer_id >= 0; --layer_id ) {
layers[layer_id].offset.x += layers[layer_id].speed * frame_time;
 
while( layers[layer_id].offset.x >= static_cast<float>( TEXTURE_SIZE ) ) {
layers[layer_id].offset.x -= static_cast<float>( TEXTURE_SIZE );
layers[layer_id].texture_id =
(
layers[layer_id].texture_id +
static_cast<std::size_t>( std::ceil( (static_cast<float>( SCREEN_HEIGHT ) + layers[layer_id].offset.y) / static_cast<float>( TEXTURE_SIZE ) ) ) +
1
) % NUM_TEXTURES
;
}
 
static std::size_t texture_id;
static sf::Vector2f target_pos;
static sf::Sprite sprite;
 
// Init initial texture ID and color.
texture_id = layers[layer_id].texture_id;
 
sprite.SetColor(
sf::Color(
static_cast<sf::Uint8>( 255 - layer_id * COLOR_SHIFT ),
static_cast<sf::Uint8>( 255 - layer_id * COLOR_SHIFT ),
static_cast<sf::Uint8>( 255 - layer_id * COLOR_SHIFT )
)
);
 
for( target_pos.x = -layers[layer_id].offset.x; target_pos.x < static_cast<float>( SCREEN_WIDTH + TEXTURE_SIZE ); target_pos.x += static_cast<float>( TEXTURE_SIZE ) ) {
for( target_pos.y = -layers[layer_id].offset.y; target_pos.y < static_cast<float>( SCREEN_HEIGHT + TEXTURE_SIZE ); target_pos.y += static_cast<float>( TEXTURE_SIZE ) ) {
sprite.SetTexture( textures[texture_id], true );
sprite.SetPosition( target_pos );
window.Draw( sprite );
 
texture_id = (texture_id + 1) % NUM_TEXTURES;
}
}
}
 
window.Display();
}
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Rendering stars (example)
« Reply #1 on: January 13, 2012, 12:15:52 pm »
The implementation would be simpler, more efficient, more dynamic and less constrained with vertex arrays of points instead of textures ;)
Laurent Gomila - SFML developer

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Rendering stars (example)
« Reply #2 on: January 13, 2012, 12:49:19 pm »
...it would be even more efficient with vertex buffer objects!