在试图弄清楚 CLIM 时,我遇到了这个示例程序。这是一个简单的迷宫游戏。作者声称已在 LispWorks 中对其进行了测试(甚至#+Genera
在其中进行了测试,暗示该程序可以在真正的 Lisp 机器上运行),但我正试图让它在带有 McCLIM 的 SBCL 中运行。
在 SBCL/McCLIM 下,窗口绘制,但是当您按下移动键时没有任何可见的反应。非移动键会导致文本与游戏说明一起输入到窗格中。
我发现游戏命令键正在改变游戏的内部状态,所以唯一的问题是屏幕没有更新。
然后我意识到您无法编写代码来从实现命令的代码范围内重新绘制迷宫。所有绘制的方法都接收stream
来自 CLIM 的参数,该参数必须传递给图形基元。例如:
(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))))
我最终要做的是将stream
第一次(也是唯一一次)调用中的参数保存draw-maze-array
到全局变量,以便我可以将更新代码添加到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*))))
这种轻微的改变在带有 McCLIM 的 SBCL 上提供了所需的行为,但这似乎并不正确。毕竟,作者声称该代码在 LispWorks 上运行良好。我有几个问题:
- 有 LispWorks 的人可以确认这个程序在 LispWorks 上按原样工作吗?
- 我对代码的更改是否使其在 LispWorks 上失败?
- 在 CLIM 应用程序中处理屏幕更新的公认方法是什么?