1

所以我正在努力开发一个平台风格的游戏,用 C 语言编写并使用 GTK 作为我的图形工具包。现在我有一个程序可以在屏幕上放置三个块。其中两个是平台,第三个可以通过按左/右箭头键横向移动。(我还没有绘制任何精灵,所以现在我的游戏的英雄是一个蓝色矩形)。我还实现了按“z”键跳跃,你可以在平台上跳跃和降落。

然而,在跳跃时横向移动是相当困难的。我相信这是因为我的程序无法识别同时按下的两个键,因此您必须释放左箭头或右箭头,按 z,然后释放 z 并再次按右箭头或左箭头以在空中横向移动。我希望能够按住左或右并同时按 z 让英雄横向跳跃。

GDK 参考手册为您提供 GDK 密钥代码列表的“gdk/gdkkeysyms.h”(在我的系统上位于 /usr/include/gtk-3.0/gdk/gdkkeysyms.h),但没有给出任何同时使用两个键的指导。GTK/GDK 能否识别同时按下两个键的事件(GDK、GTK,无论哪一个,我都不清楚两者之间的界限在哪里,但我想这是另一个问题的主题......)?你会如何应用它?(对于单个键,您可以通过执行类似的操作来获取代码

key = event->keyval;

但我真的不知道这对于两个键会是什么样子)。

谢谢你的帮助!

4

2 回答 2

2

键盘不是这样工作的:每个键都会产生一个单独的中断,这将产生一个单独的窗口系统事件,所以你必须自己保持状态。

一些键实际上是特殊的,并且充当其他键的修饰符:Control、Shift、Alt,是修饰符,因此被区别对待——即如果它们被按下,它们的状态将与实际键分开记录到事件数据结构中被压。尽管如此,它们也会产生单独的关键事件。

您可以简单地记录按键,并稍后检查状态是否保持,例如:

static gboolean is_a_pressed = FALSE;
static gboolean is_b_pressed = FALSE;

static gboolean on_key_press (GtkWidget *w, GdkEvent *e)
{
  /* acquire key A */
  if (e->key.symbol == GDK_KEY_a)
    is_a_pressed = TRUE;

  /* acquire key B */
  if (e->key.symbol == GDK_KEY_b)
    is_b_pressed = TRUE;

  /* both keys have been pressed */
  if (is_a_pressed && is_b_pressed)
    do_something_amazing ();

  /* let the event propagate further */
  return GDK_EVENT_PROPAGATE;
}

static gboolean on_key_release (GtkWidget *w, GdkEvent *e)
{
  /* release key A */
  if (e->key.symbol == GDK_KEY_a)
    is_a_pressed = FALSE;

  /* release key B */
  if (e->key.symbol == GDK_KEY_b)
    is_b_pressed = FALSE;

  return GDK_EVENT_PROPAGATE;
}
于 2013-04-22T20:10:46.267 回答
1

有两种情况需要注意。

一些特殊键称为修饰键,它们会导致设置修饰位,event->state因此您可以进行检查if (event->state & GDK_CONTROL_MASK)

只有少数常见的修饰符以这种方式设置标志。对于其他键,您需要自己跟踪单独的按下和释放事件,这将允许您确定当另一个键到达时是否仍然按下一个键。小部件信号是按键事件和按键释放事件。

可能还有其他因素给您带来麻烦,一个好的方法是创建一个小的单文件独立可编译测试用例来显示问题。您可能仅通过制作测试用例就可以解决,但如果没有,测试用例将帮助其他人帮助您。(因为他们可以使用它来重现问题。)

于 2013-04-22T04:40:15.307 回答