无法在空间中重绘图像

时间:2011-07-05 20:33:17

标签: c++ sdl

我正在使用SDL练习。我目前正在用明星,太阳和地球这个班级画空间。我可以将所有内容渲染到屏幕上但是当我用右箭头键移动太阳时,我无法弄清楚如何删除旧太阳以模拟视图围绕太阳旋转。它只是在屏幕上创建了一条大线。我想我需要清理屏幕,每次按键时都要重新绘制星星,太阳和地球。但是,我不能重新绘制星星,因为它们超出范围,如果我重新创建它们,它们将处于不同的位置,因为我使用rand()来随机化它们的位置。我已经打了一堵大墙,并希望得到任何建议。

代码:

// 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;
    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; 
}

1 个答案:

答案 0 :(得分:0)

修改

由于我的上一个回答是垃圾,我再试一次:

是的,确实,星星已经超出范围,因为它们在循环中声明。你可以做的是保存一个数组中的每一颗星,但这是一个巨大的浪费的字节。

在我看来,更好的方法是在表面绘制所有星星,并在每次需要时在屏幕上显示它。这应该是快速和内存效率。我将简短的样本:

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

现在,你将星星画入这个表面:

...
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();
...

只要您需要它,您可以使用此功能将此表面作为屏幕背景进行blit:

int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);