SDL入门教程(五):4、让图片动起来!
作者:龙飞
4.1:再讨论简单的SDL event响应。
Uint8
*
SDL_GetKeyState(
int
*
numkeys);
要让图片动起来,最好是我们可以“操作”的动。按照一般思路,键盘的“上”“下”“左”“右”是不错的选择。在FPS游戏和模拟器中,我们可能更习惯wsad四个键,所以,让他们同时起作用吧。这个函数的一般用法,是把参数设置为空指针。我们还是先忽略细节。因为有了两个新的blit()重载方法的加入,我们设置要移动的图片在screen上的坐标是(xpos,ypos),则:
//
key event for up, down, left and right.
Uint8 * keys;
// moving image's coordinate.
int xpos = 0 ;
int ypos = 0 ;
控制图片移动的代码如下:
Uint8 * keys;
// moving image's coordinate.
int xpos = 0 ;
int ypos = 0 ;
//
key event to move image.
keys = SDL_GetKeyState( 0 );
if ( keys[SDLK_UP] || keys[SDLK_w] ){
ypos -= 1 ;
}
if ( keys[SDLK_DOWN] || keys[SDLK_s] ){
ypos += 1 ;
}
if ( keys[SDLK_LEFT] || keys[SDLK_a] ){
xpos -= 1 ;
}
if ( keys[SDLK_RIGHT] || keys[SDLK_d] ){
xpos += 1 ;
}
代码一目了然,不用多解释。具体对应的按键可参考:
keys = SDL_GetKeyState( 0 );
if ( keys[SDLK_UP] || keys[SDLK_w] ){
ypos -= 1 ;
}
if ( keys[SDLK_DOWN] || keys[SDLK_s] ){
ypos += 1 ;
}
if ( keys[SDLK_LEFT] || keys[SDLK_a] ){
xpos -= 1 ;
}
if ( keys[SDLK_RIGHT] || keys[SDLK_d] ){
xpos += 1 ;
}
http://www.libsdl.org/cgi/docwiki.cgi/SDLKey
4.2:对于第二种方法的分析。
我们前面讨论了总是把surface blit到screen上的情况。如果我们的思路是把其他surface先blit到一个作为背景画布的surface上,最后把背景画布blit到screen上呢?
我们将遇到的第一个疑问是,surface能不能把自己blit到自己上面?试验的结果是否定的,而SDL并没有给出官方的异常信息,即SDL_GetError()没有起作用。所以,异常得我们自己来抛出。另外一个后果是,我们必须建立背景画布的拷贝,把拷贝blit到背景画布上才是可行的。
class
DisplaySurface
{
public :
bool blitToSurface( const DisplaySurface & dst_surface,
int at_x = 0 , int at_y = 0 ) const ;
bool blitToSurface( const DisplaySurface & dst_surface,
int at_x, int at_y,
int from_x, int from_y, int w, int h,
int delta_x = 2 , int delta_y = 2 ) const ;
};
这和blit到screen是类似的,但是实际效果是完全不一样的。因为,没有被blit到screen上的surface,都不可能被flip显示出来。所以,虽然参数列表是不一样的,意味着我可以继续用blit()这个名字重载。但是为了表明他们的实际效果有区别,我重新用了方法名。
{
public :
bool blitToSurface( const DisplaySurface & dst_surface,
int at_x = 0 , int at_y = 0 ) const ;
bool blitToSurface( const DisplaySurface & dst_surface,
int at_x, int at_y,
int from_x, int from_y, int w, int h,
int delta_x = 2 , int delta_y = 2 ) const ;
};
bool
DisplaySurface::blitToSurface(
const
DisplaySurface
&
dst_surface,
int
at_x,
int
at_y)
const
{
SDL_Rect offset;
offset.x = at_x;
offset.y = at_y;
if ( & dst_surface == this )
throw " Cannot blit surface to itself! " ;
if ( SDL_BlitSurface(pSurface, 0 , dst_surface.point(), & offset) < 0 )
return false ;
else return true ;
}
bool DisplaySurface::blitToSurface( const DisplaySurface & dst_surface,
int at_x, int at_y,
int from_x, int from_y, int w, int h,
int delta_x, int delta_y) const
{
SDL_Rect offset;
offset.x = at_x - delta_x;
offset.y = at_y - delta_y;
SDL_Rect dest;
dest.x = from_x - delta_x;
dest.y = from_y - delta_y;
dest.w = w + delta_x * 2 ;
dest.h = h + delta_y * 2 ;
if ( & dst_surface == this )
throw " Cannot blit surface to itself! " ;
if ( SDL_BlitSurface(pSurface, & dest, dst_surface.point(), & offset) < 0 )
return false ;
else return true ;
}
{
SDL_Rect offset;
offset.x = at_x;
offset.y = at_y;
if ( & dst_surface == this )
throw " Cannot blit surface to itself! " ;
if ( SDL_BlitSurface(pSurface, 0 , dst_surface.point(), & offset) < 0 )
return false ;
else return true ;
}
bool DisplaySurface::blitToSurface( const DisplaySurface & dst_surface,
int at_x, int at_y,
int from_x, int from_y, int w, int h,
int delta_x, int delta_y) const
{
SDL_Rect offset;
offset.x = at_x - delta_x;
offset.y = at_y - delta_y;
SDL_Rect dest;
dest.x = from_x - delta_x;
dest.y = from_y - delta_y;
dest.w = w + delta_x * 2 ;
dest.h = h + delta_y * 2 ;
if ( & dst_surface == this )
throw " Cannot blit surface to itself! " ;
if ( SDL_BlitSurface(pSurface, & dest, dst_surface.point(), & offset) < 0 )
return false ;
else return true ;
}