作者:龙飞
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
;
控制图片移动的代码如下:
//
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
;
}
代码一目了然,不用多解释。具体对应的按键可参考:
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()这个名字重载。但是为了表明他们的实际效果有区别,我重新用了方法名。
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
;
}