一个选单大致是这样:
1.可以被以某种形式呼叫出来,如按下esc;
2.在这个选单中功能键有不同的定义,如原本方向键控制走路,但现在改为控制光标的位置;
3.按下确定键后有对应功能被执行;
4.可以被关闭。
那么我的办法是编写两个子程,其中一个处理选单中的事件,另外一个专门负责画选单。
在从步行切换到选单的时候,可能需要清除当前的键值。如果步行中使用了SDL_EnableKeyRepeat方法把键盘的频率变高,对于选单来说就太快了。所以可能要在调用选单之前写上:
SDL_EnableKeyRepeat(0, 0);
event.key.keysym.sym := 0;
这样降低了键盘的反应,同时清除当前的键值,要不然呼出选单之后它可能还会自己转一会(如果之前用了PollEvent方式,我还没搞清楚原因)。不过如果在行走中使用的是WaitEvent方式,事情就会简单很多。PollEvent方式看来是太快了,在选单中不合适。
处理选单事件的子程:
procedure MenuSystem;
var
menu: integer;
begin
while (SDL_WaitEvent(@event) >= 0) do
begin
case event.type_ of
SDL_QUITEV: //这里处理窗口退出事件
if messagebox(0, 'Are you sure to quit?', 'KYS Windows', MB_OKCANCEL) = IDOK then Quit;
SDL_KEYUP:
begin
if (event.key.keysym.sym = sdlk_down) then
begin
menu := menu+1;
if menu > 3 then menu := 0; //按下下键的溢出
showMenusystem(menu); //每次当前选中发生变化时, 均重画选单
end;
if (event.key.keysym.sym = sdlk_up) then
begin
menu := menu-1;
if menu < 0 then menu := 3; //按下上键的溢出
showMenusystem(menu);
end;
if (event.key.keysym.sym = sdlk_escape) then
begin
break; //按下退出键
end;
if (event.key.keysym.sym = sdlk_return) or (event.key.keysym.sym = sdlk_space) then
begin //按下确定键
case menu of
2: MenuQuit;
1: MenuSave;
0: Menuload;
end;
end;
end;
end;
end;
end;
显示选单的子程,里面有一些其他的东西,不必太在意:
procedure ShowMenuSystem(menu: integer);
var
word: array[0..2] of Widestring;
i: integer;
begin
Word[0] := ' 读取';
Word[1] := ' 存档';
Word[2] := ' 退出';
if fullscreen = 1 then Word[2] := ' 窗口';
ReDraw; //你需要自己写一个清屏子程
for i := 0 to 3 do
if i = menu then
begin
drawtext(screen, @word[i][1], 64, 32+22*i, $FFFFFF)); //当前的项显示为不同的颜色
end
else begin
drawtext(screen, @word[i][1], 64, 32+22*i, $00FFFF);
end;
SDL_UpdateRect(screen, 80, 30, 47, 93); //根据区域而定,如果觉得麻烦就更新全屏
end;
No comments:
Post a Comment