Ada 如何在不暂停snake游戏的情况下读取输入?

Ada 如何在不暂停snake游戏的情况下读取输入?,ada,Ada,这是学校的作业。创建一个蛇游戏。 因此,我创建了两个包,一个用于图形,另一个用于snake。 蛇移动平稳,一切正常。但是我需要用键盘控制蛇。这是主要的程序: with Graphics; use Graphics; with Graphics.Snake; use Graphics.Snake; procedure Run_Snake is B : Buffer (1 .. 24, 1 .. 80); S : Snake_Type (1 .. 5) := ((10, 10),

这是学校的作业。创建一个蛇游戏。 因此,我创建了两个包,一个用于图形,另一个用于snake。 蛇移动平稳,一切正常。但是我需要用键盘控制蛇。这是主要的程序:

with Graphics; use Graphics;
with Graphics.Snake; use Graphics.Snake;

procedure Run_Snake is
   B : Buffer (1 .. 24, 1 .. 80);
   S : Snake_Type (1 .. 5) := ((10, 10),
                               (10, 11),
                               (10, 12),
                               (11, 12),
                               (12, 12));
   D : Duration := 0.07;
begin

  loop
      Empty (B);
      Draw_Rect (B, (1, 1), Width  => 80,
                 Height            => 24);
      Draw (B, S);
      Update (B);



      Move (S, 0, -1);
      delay D;

   end loop;

end Run_Snake;
在这行代码中,我控制蛇头旋转:

Move (S, x, y);  
其中x为x值,左为-1,右为1。
其中y为y值,向下为-1,向上为1

无论如何,我怎样才能在不暂停蛇移动的情况下读取输入?
谢谢

您可能需要使用多任务系统来解决您的问题

procedure Snake_Game is

   task Run_Snake is
      entry Input_Received (S : Snake_Type; x : Integer; y : Integer);
   end Run_Snake;

   task body Run_Snake is
      D : constant Duration := 0.07;
      B : Buffer (1 .. 24, 1 .. 80);
   begin
      loop
         select
            accept Input_Received (S : Snake_Type; x : Integer; y : Integer) do
               Move (S, x, y);
            end;
         or
            delay D;
            Empty (B);
            Draw_Rect (B, (1, 1), Width => 80, Height => 24);
            Draw (B, S);
            Update (B);
         end select;
      end loop;
   end Run_Snake;

   S : Snake_Type (1 .. 5) := ((10, 10),
                              (10, 11),
                              (10, 12),
                              (11, 12),
                              (12, 12));

begin
   loop
      Do_Whatever_You_Want_To_Get (x, y)
      Run_Snake.Input_Received(S, x, y);
   end loop;
end Snake_Game;
在这样的系统中,您的绘图过程处于单独的任务中。在“选择”行,任务等待对Input_Received()的调用。如果在持续时间D后未调用此项,则任务将执行所有绘图函数,循环将重新开始

希望能有所帮助。
干杯。

解决这类问题有两种基本方法

第一种是使用某种非阻塞调用,它检查输入,但立即返回是否找到任何输入。正如Simon Wright在评论中提到的,Ada提供了这样一个调用:。这个例程的一个小缺点是(当我上次检查时),大多数编译器实现它的方式仍然要求用户在其输入可用于该例程之前点击
enter
键。大多数操作系统也会对此类活动进行系统调用(没有烦人的回车键缺点),但阻塞通常是它们的首选行为,因此设置非阻塞输入通常很困难或神秘

我不知道你的
Graphics
包里有什么,但是你可能想看看它是否有这样的调用。我猜这是一个学校的程序设计作业,这是一个为这个作业而设计的软件包。如果是这样的话,可能有一些设施,在那里为这一点,否则你的教练没有想象你的游戏工作的方式

另一种方法是使用不同的控制线程来读取用户输入。这样,您就可以在一个线程中使用OS喜欢的阻塞调用,而在另一个线程中,让游戏的其余部分像它应该的那样愉快地运行。Ada通过任务来实现这一点(如tvuillemin的回答所示)。这里的问题是,这两个任务之间的任何交互(例如:将输入传递给游戏任务)都必须正确同步。此外,两个任务使用的任何包或设施都必须是任务安全的。对于Ada软件包,只要不尝试共享文件对象或其他东西,您就相当安全。但对于第三方软件包(如
Graphics
?),您通常最好只选择一个任务来“拥有”该软件包


大多数窗口系统以极其复杂的方式解决这个问题。它们实现自己的“主循环”,该循环应该接管您的控制线程,它将负责诸如刷新窗口内容和轮询输入之类的日常任务。如果你想做一些自定义的事情(例如:定期更新游戏状态),你必须将其放入例程并注册为“回调”。

我已经看过俄罗斯方块游戏,但该游戏使用的是GTKADA…你在使用什么?Win32?X窗口?还有什么吗?试试
Get\u Immediate
:@SimonWright-过去大多数编译器在用户按下回车键之前都不会返回任何内容。改变了吗?如果你在使用GtkAda,这里引用了一个
Gdk_Event_Key
示例……而且,他可能想验证在多个任务中使用的
图形
包中的任何代码都是任务安全的。谢谢。我对这个多任务解决方案非常感兴趣。但我不能让它工作:我这样做对吗?“x的实际值必须是变量”是什么意思?什么是真实的?@alexhum。。。我猜Move()函数的第一个参数类似于“ASnake:in-out Snake_Type”,不是吗?你能试试这个吗?非常感谢你的解释。是的,这是学校的作业。我们只得到了我发布的循环代码。我们会找出剩下的并创建包。立即工作,但它确实弄乱了图形。