我正在使用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;
}
答案 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);