开发者

Can't redraw an image in space

开发者 https://www.devze.com 2023-03-18 09:35 出处:网络
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 ca

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消