更新 window 以响应 CLIM 框架命令

Updating the window in response to CLIM frame commands

在尝试弄清楚 CLIM 时,我 运行 变成了 this example program。这是一个简单的迷宫游戏。作者声称已经在 LispWorks 中对其进行了测试(甚至其中有 #+Genera,暗示该程序可以在真正的 Lisp 机器上运行),但我正在尝试使用 McCLIM 使其在 SBCL 中运行。

在SBCL/McCLIM下,window绘制,但是当你按下移动键时没有任何可见的东西发生。非移动键导致文本与游戏说明一起输入到窗格中。

我发现游戏命令键正在改变游戏的内部状态,所以唯一的问题是屏幕没有更新。

然后我意识到您无法编写代码来从实现命令的代码范围内重新绘制迷宫。所有绘制方法都从 CLIM 接收一个 stream 参数,该参数必须传递给图形基元。例如:

(defun draw-stone (stream x y cell-width cell-height)
  (let ((half-cell-width (/ cell-width 2))
        (half-cell-height (/ cell-height 2)))
    (draw-ellipse* stream
                   (+ (* x cell-width) half-cell-width)
                   (+ (* y cell-height) half-cell-height)
                   half-cell-width 0
                   0 half-cell-height
                   :ink +red+)))

但是处理击键的代码没有收到 stream 参数:

(defmacro define-stone-move-command (name keystroke dx dy)
  `(define-maze-frame-command (,name :keystroke ,keystroke) ()
     (let ((maze-array (maze-array *application-frame*)))
       (move-stone maze-array ,dx ,dy)
       (check-for-win maze-array))))

我最终要做的是将第一次(也是唯一一次)调用 draw-maze-arraystream 参数保存到一个全局变量中,这样我就可以将更新代码添加到define-stone-command宏如下:

(defmacro define-stone-move-command (name keystroke dx dy)
  `(define-maze-frame-command (,name :keystroke ,keystroke) ()
     (let ((maze-array (maze-array *application-frame*)))
       (move-stone maze-array ,dx ,dy)
       (check-for-win maze-array)
       (draw-maze-array *application-frame* *maze-stream*))))

这种细微的改动在 SBCL 和 McCLIM 上提供了所需的行为,但这似乎不正确。毕竟,作者声称代码在 LispWorks 上运行良好。我有几个问题:

  1. 拥有 LispWorks 的人能否确认此程序在 LispWorks 上按原样运行?
  2. 我对代码的更改会导致它在 LispWorks 上失败吗?
  3. 在 CLIM 应用程序中处理屏幕更新的可接受方式是什么?

在命令中画迷宫不是正确的做法。将 maze-stream 放入全局变量中也很糟糕。 ;-)

显示窗格有一个 :display-function。这个想法是,在一个命令之后,整个应用程序框架会自动更新。例如,对于 :display-time :command-loop,显示窗格将在命令运行后自动更新。还有其他方法可以更新窗格,但在这种情况下,击键会运行一个命令,然后顶级循环只会为每个适用的窗格调用 display-function。默认的顶层循环读取命令(通过鼠标、命令行、击键……),执行它并更新应用程序框架 - 在一个循环中。

整个重新显示的东西非常tricky/powerful。它允许从全自动魔法重新显示机制到极其细粒度的控制。

您可以在这里阅读:CLIM 2 Spec。注意:规范和实现提供的内容之间可能存在相当大的差异...