2
\$\begingroup\$

My player flies around the screen in any direction he wants, and the camera follows him. There are stars in the background. I can't figure out how to randomly generate the stars. I made a star class. There are a few different types of stars, and some have different depths than others, hence they move slower as the player moves around. I can create a stars around the player when the game starts, and when they get 100 pixels off the screen they are destroyed, but I can't figure out a good way to create new stars.

Here is my code: Star Class:

#pragma once

struct Star
{
int xposition, yposition;
int type;
int velocity;

bool alive;

Star()
{
    xposition = yposition = 0;
    type = 0;
    velocity = 0;
    alive = false;
}

void create( int p_xposition, int p_yposition, int p_velocity, int p_type )
{
    xposition = p_xposition;
    yposition = p_yposition;
    velocity = p_velocity;
    type = p_type;

    alive = true;
}

void destroy()
{
    alive = false;
}
};

Background Class:

#include "background.h"

void Background::init( Engine* p_engine, SDL_Rect* p_camera )
{
engine = p_engine;
camera = p_camera;

delta_time = SDL_GetTicks();

for ( int s = 0;  s < 100;  s++ )
{
    stars[s] = new Star;
}

image[0] = engine->load_image( "star 1.png" );
image[1] = engine->load_image( "star 2.png" );
image[2] = engine->load_image( "star 3.png" );
image[3] = engine->load_image( "star 4.png" );

for ( int s = 0;  s < 30;  s++ )
{
    for ( int s2 = 0;  s2 < 100;  s2++ )
    {
        if ( stars[s2]->alive == false )
        {
            stars[s2]->create( rand() % engine->screen_width, rand() % engine->screen_height, rand() % 30, rand() % 4 );
            break;
        }
    }
}
}

void Background::cleanup()
{
for ( int s = 0;  s < 100;  s++ )
{
    delete stars[s];
}

for ( int i = 0;  i < 4;  i++ )
{
    SDL_FreeSurface( image[i] );
}
}

void Background::logic()
{
delta_time = SDL_GetTicks() - delta_time;

  //destroy stars
for ( int s = 0;  s < 100;  s++ )
{
    if ( stars[s]->alive == true )
    {
        if ( stars[s]->xposition < camera->x - 100 || stars[s]->xposition > camera->x + camera->w + 100 )
        {
            stars[s]->destroy();
        }
    }

    if ( stars[s]->alive == true )
    {
        if ( stars[s]->yposition < camera->y - 100 || stars[s]->yposition > camera->y + camera->h + 100 )
        {
            stars[s]->destroy();
        }
    }
}

  //create stars
if ()
{

}

delta_time = SDL_GetTicks();
}

void Background::render()
{
for ( int s = 0;  s < 100;  s++ )
{
    if ( stars[s]->alive == true )
    {
        engine->apply_surface( image[stars[s]->type], engine->buffer, stars[s]->xposition - camera->x, stars[s]->yposition - camera->y );
    }
}
}
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

I've made a star field, much like the one you describe. I would recommend wrapping the stars. If a star goes off the screen on one side, have it reappear on the other. This worked for me, but I also had a bajillion stars, so nobody could notice. As a side-effect, the stars always look the same at any given view point.

Before I was wrapping stars, I used to recycle the star object and provide it with some new random properties on the other side of the screen; random properties included: position (only 1 axis, based on which edge it fell off), size, brightness, and speed. This worked well, but I came across problems when my screen was moved very quickly, causing stars to bunch up along the edges of the screen. The reason for the bunching up was twofold. First, I was doing a direct assignment of the star's new position on the other side of the screen instead of taking into account how far the star was off screen, and secondly: what if you move the screen multiple screen-sizes away and you randomly generate the stars' speed. Just some stuff to think about if you end up taking this route, and why I switched to basic wrapping.

But I would recommend not deleting your star objects because allocating and releasing memory is a relatively expensive task, especially when you can just recycle your stars.

\$\endgroup\$
0
2
\$\begingroup\$

I suggest another solution to this, instead of keeping a lot of star objects, draw them to a large framebuffer once, and draw this framebuffer looped on the screen. If you want stars to have different speeds, create a few framebuffers, draw them all at the same time, but scroll at different speeds. This has a few advantages:

1) Simple - you only have to generate starfield once and you don't have to worry about memory-managing your star objects

2) Nice from the memory point of view - you make less dynamic allocations, the only memory you allocate is likely to be video memory

3) I think it will be faster to draw the contents of a framebuffer once than constantly asking the video device to draw one star here, one star there.

\$\endgroup\$
5
  • \$\begingroup\$ Or the same framebuffer at different scales? Good suggestion though, +1 i did a similar thing to create rain once \$\endgroup\$ Aug 14, 2012 at 22:29
  • 2
    \$\begingroup\$ (3) is immensely dependent on the details of the graphics hardware, but in general for relatively modest numbers of stars (and a couple thousand certainly qualifies) I'd expect it to be faster to draw individual stars than to draw a largeish frame buffer. For instance, the iPad1 has a 'draw rate' of roughly 2 million triangles per second, meaning that you could draw 3000 stars in 1.5ms. By contrast, I'm seeing benchmarks in the range of 100M pixels per second - which means that a single 1024x768 frame buffer would take roughly 8ms, and 3 frame buffer draws would eat a whole frame's time. \$\endgroup\$ Aug 14, 2012 at 22:33
  • \$\begingroup\$ I'm by no means a graphics programmer, but this seems a bit odd to me. If we render the contents of the framebuffer to a texture once, and then just draw a large textured quad every time, (which means just two textured triangles), can it really be that slow compared to drawing a lot of little textured quads? why is that so? \$\endgroup\$
    – user6705
    Aug 14, 2012 at 23:47
  • \$\begingroup\$ Grigory: basically, because the primary cost isn't in the number of items drawn, it's in the number of pixels drawn. 'Triangles are free', give or take - you can blast so many triangles through a graphics pipeline at this point that they're simply not a relevant measurement. Pixels, on the other hand, take memory writes - and for these pixels, a read+write cycle, which is even more expensive. They're bound by memory bandwidth, rather than CPU speed. \$\endgroup\$ Aug 15, 2012 at 1:08
  • \$\begingroup\$ Essentially, it's the difference between drawing 3000 triangles and 12K pixels, and drawing 2 triangles but 1000K pixels. Once upon a time the tradeoff actually went the other way and pre-rendering to a full-sized frame buffer was the right idea, but that's simply not the case any more on virtually any hardware. \$\endgroup\$ Aug 15, 2012 at 1:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .