io - 比喻Python iS_pressed in Common LISP?

标签 io common-lisp

我正在 Common Lisp 中制作一个简单的 LTK 游戏,并且想让玩家角色在按下空格键时跳跃。但是,该窗口不断更新,因此我无法等待用户输入。我想检查每一帧是否按下空格键。尽管用谷歌搜索了很多,我还是找不到在 Lisp 中做到这一点的方法。我发现的只是停止程序流程的传统 I/O 提示。

感谢您的帮助。

最佳答案

您使用的是 Tk Canvas 吗?也许您可以将事件处理程序绑定(bind)到按键?

(with-ltk ()
  (let ((canvas (make-canvas nil)))
    (grid canvas 1 1)
    (bind canvas 
          "<Left>" 
          (lambda (e)
             (message-box "Left" "Click" "okcancel" "info")))
    (focus canvas)))

当您收到按键时,您可以设置一个在处理帧时检查的变量。


This works fine for one button, but binding e.g. both the up arrow and the left arrow for movement only registers one at a time. Is there a way to fix that?

这是一个更详细的示例。 Tk 可以绑定(bind) KeyPressKeyRelease 事件。您只需管理要观察的按键的按下/未按下状态,并相应地设置正确的变量即可。

(with-ltk ()
  (let ((canvas (make-canvas nil))
        (x 50)
        (y 50)
        (speed 5)
        (w 10)
        (h 10)
        (dx 0)
        (dy 0))
    (grid canvas 1 1)
    (macrolet
        ((on (event expr)
           (check-type event string)
           (let ((evar (gensym)))
             `(bind canvas ,event
                    (lambda (,evar)
                      (declare (ignore ,evar))
                      ,expr)))))
      (on "<KeyPress-Left>" (decf dx))
      (on "<KeyPress-Right>" (incf dx))
      (on "<KeyRelease-Left>" (incf dx))
      (on "<KeyRelease-Right>" (decf dx))
      (on "<KeyPress-Up>" (decf dy))
      (on "<KeyPress-Down>" (incf dy))
      (on "<KeyRelease-Up>" (incf dy))
      (on "<KeyRelease-Down>" (decf dy)))
    (focus canvas)
    (let ((rectangle (create-rectangle canvas x y 10 10)))
      (labels ((game-loop ()
                 (incf x (* dx speed))
                 (incf y (* dy speed))
                 (set-coords canvas rectangle (list x y (+ x w) (+ y h)))
                 (after 50 #'game-loop)))
        (game-loop)))))

上述函数的第一部分创建一个 Canvas ,并为 KeyPressKeyReleaseLeftRight 键的 Down/Up 事件绑定(bind)事件处理程序。这有点冗长,但对于一个例子来说已经足够简单了。或者,您可以仅绑定(bind) "<KeyPress>""<KeyRelease>" 事件(字符串中没有其他键),并使用由键事件的 keycode 索引的表。

第二部分是游戏循环,其中增量 dxdy 实际上用于移动矩形;在游戏循环结束时,after 确保游戏循环在一段时间后再次运行。

事件处理程序不直接操作 Canvas 元素,它们仅用于将 UI 事件转换为游戏逻辑更改。您必须小心事件发生的方式和时间。例如上面的第一个版本用来做:

(on "<KeyPress-Left>" (setf dx -1))
(on "<KeyPress-Right>" (setf dx 1))
(on "<KeyRelease-Right>" (setf dx 0))
(on "<KeyRelease-Left>" (setf dx 0))

但这是错误的,因为顺序 press-leftpress-rightrelease-right 会使矩形停止。 p>

关于io - 比喻Python iS_pressed in Common LISP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53230492/

相关文章:

java - 如何在不保存到硬盘的情况下在Java中创建文件对象

java - 如何在java中覆盖文本文件?

lisp - Common Lisp 中的 "Invalid EXCL::PREDICATE argument"错误

lisp - 让我的 lisp 代码更健壮

format - sbcl 将有理数转换为十进制时尽可能保持精度

c - 程序写入socket后自动关闭

Ruby 文件 IO 挂起

java - Download 类是不可变性的糟糕候选者吗?

common-lisp - nodgui 和 SBCL(?) : How to avoid the type error "The value NIL is not of type STREAM when binding STREAM" right from the beginning?

lisp - 值 0 不是 STRING 类型 lisp 错误