Can't redraw an image in space
I am getting some practice with SDL. I currently am drawing space with classes star, sun, and earth. I can get everything to render to the screen but when I move the sun with the right arrow key, I can't figure out how to delete the old sun to simulate that the view is rotating around the sun. It just creates a big line across the screen. I think I need to clear the screen, redraw the stars, sun, and earth every time the key is down. However, I can't redraw the stars because they fall out of scope and if I recreate them they will be in a different position since I use rand() to randomize their locations. I have hit a big wall and would appreciate any advice.
The code:
// Planet.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <SDL.h>
#include <SDL_gfxPrimitives.h>
#include <stdlib.h>
#include <time.h>
class Star
{
private:
int x,y,rad,r,g,b,a;
SDL_Surface* screen;
public:
Star(SDL_Surface* sc, int xx, int yy, int ra, int rr, int gg, int bb, int aa){screen=sc;x=xx;y=yy;rad=ra;r=rr;g=gg;b=bb;a=aa;}
~Star(){}
void Show()
{
filledCircleRGBA(screen, x, y, rad, r, g, b, a);
}
};
class Sun
{
private:
int x,y,rad,r,g,b,a;
SDL_Surface* screen;
public:
Sun(SDL_Surface* sc, int xx, int yy, int ra, int rr, int gg, int bb, int aa){screen=sc;x=xx;y=yy;rad=ra;r=rr;g=gg;b=bb;a=aa;}
~Sun(){}
void Show()
{
for (int light=10;light<241;light+=10){
filledCircleRGBA(screen, x, y, rad+(light/7), r, g, b+(light/2), a-light);
}
}
void Move(int a, int b)
{
x+=a;
y+=b;
}
};
class Earth
{
private:
int x,y,rad,r,g,b,a;
开发者_StackOverflow社区 SDL_Surface* screen;
public:
Earth(SDL_Surface* sc, int xx, int yy, int ra, int rr, int gg, int bb, int aa){screen=sc;x=xx;y=yy;rad=ra;r=rr;g=gg;b=bb;a=aa;}
~Earth(){}
void Show()
{
for (int light=10;light<241;light+=10){
filledCircleRGBA(screen, x, y, rad+(light/7), r, g, b+(light/2), a-(light/2));
}
for (double light=0;light<.25;light+=.01){
filledEllipseRGBA(screen, x, y-(rad*1.05), rad*(.60+light), rad*(.1+light), 170+(light*100), 170+(light*100), 170+(light*100), 255-(light*1000));
}
}
};
int main( int argc, char* args[] )
{
//Start SDL
SDL_Init( SDL_INIT_EVERYTHING );
SDL_Surface* screen = NULL;
screen = SDL_SetVideoMode( 1366, 768, 32, SDL_FULLSCREEN | SDL_SWSURFACE);
srand((unsigned)time(NULL));
//Stars
for (int x=0;x<1361;x+=25){
for (int y=0;y<766;y+=25){
int Special = rand()%3;
if(Special==0||Special==1){
Star star(screen, x+(rand()%30), y+(rand()%30), 0+(rand()%1), 235+rand()%21, 235+rand()%21, 235+rand()%21, 205+rand()%51);
star.Show();
}
if(Special==2){
Star star(screen, x+(rand()%30), y+(rand()%30), 0+(rand()%2), 235+rand()%21, 235+rand()%21, 235+rand()%21, 205+rand()%51);
star.Show();
}
}
}
//Sun
Sun sun(screen, 200, 300, 10, 255, 255, 0, 255);
sun.Show();
//Earth
Earth earth(screen, 700, 400, 100, 0, 80, 255, 255);
earth.Show();
SDL_Event event;
bool Running=1;
bool keysHeld[323]={false};
while (Running)
{
// Handle input
if (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
Running = false;
}
if (event.type == SDL_KEYDOWN)
{
keysHeld[event.key.keysym.sym] = true;
}
if (event.type == SDL_KEYUP)
{
keysHeld[event.key.keysym.sym] = false;
}
}
if ( keysHeld[SDLK_ESCAPE] )
{
Running = false;
}
if ( keysHeld[SDLK_LEFT] )
{
}
if ( keysHeld[SDLK_RIGHT] )
{
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
sun.Move(4,0);
sun.Show();
}
if ( keysHeld[SDLK_UP] )
{
}
if (keysHeld[SDLK_DOWN])
{
}
SDL_Flip(screen);
}
//Quit SDL
SDL_Quit();
return 0;
}
EDIT
Since my last answer was rubbish, I try again:
Yes, indeed, the stars are going out of scope since they are declared in the loop. What you could do is to save every star in an array, but this is a huge waste of bytes.
A better approach in my opinion is to draw all stars in a surface, and blit it on the screen every time you need it. This should be fast and memory efficient. I'll sho a short sample:
Uint32 rmask, gmask, bmask, amask;
/* SDL interprets each pixel as a 32-bit number, so our masks must depend
on the endianness (byte order) of the machine */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
#else
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
amask = 0xff000000;
#endif
SDL_Surface* star_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 1361, 766, 32, rmask, gmask, bmask, amask);
And now, you draw your stars into this surface:
...
Star star(star_surface, x+(rand()%30), y+(rand()%30), 0+(rand()%1), 235+rand()%21, 235+rand()%21, 235+rand()%21, 205+rand()%51);
star.Show();
...
Any time you need it, you blit this surface as a background to your screen using this function:
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
精彩评论