Common lisp 更新窗口以响应CLIM frame命令
在想弄清楚克莱姆的时候,我遇到了一个问题。这是一个简单的迷宫游戏。作者声称已经在LispWorks中测试过它(甚至还有Common lisp 更新窗口以响应CLIM frame命令,common-lisp,clim,mcclim,Common Lisp,Clim,Mcclim,在想弄清楚克莱姆的时候,我遇到了一个问题。这是一个简单的迷宫游戏。作者声称已经在LispWorks中测试过它(甚至还有#+generas,这意味着这个程序可以在真正的Lisp机器上运行),但我正试图让它与McCLIM一起在SBCL中工作 在SBCL/McCLIM下,窗口会绘制,但按下移动键时不会出现任何可见的情况。非移动键导致文本与游戏说明一起输入窗格 我发现游戏命令键正在改变游戏的内部状态,所以唯一的问题是屏幕没有更新 然后我意识到您无法编写代码来从实现命令的代码范围中重新绘制迷宫。所有绘制的
#+generas
,这意味着这个程序可以在真正的Lisp机器上运行),但我正试图让它与McCLIM一起在SBCL中工作
在SBCL/McCLIM下,窗口会绘制,但按下移动键时不会出现任何可见的情况。非移动键导致文本与游戏说明一起输入窗格
我发现游戏命令键正在改变游戏的内部状态,所以唯一的问题是屏幕没有更新
然后我意识到您无法编写代码来从实现命令的代码范围中重新绘制迷宫。所有绘制的方法都从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+)))
但是处理击键的代码没有收到流
参数:
(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命令
宏中,如下所示:
(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上运行良好。我有几个问题:
在命令中绘制迷宫不是正确的方法。将迷宫流放入全局变量也是不好的。;-) 显示窗格有一个
:显示功能
。其思想是,在一个命令之后,整个应用程序框架将自动更新。例如,对于:显示时间
:命令循环
,显示窗格将在命令运行后自动更新。还有其他方法可以更新窗格,但在这种情况下,击键会运行一个命令,然后顶级循环只会调用每个适用窗格的显示功能。默认的顶级循环读取命令(通过鼠标、命令行、击键等),执行命令并更新应用程序框架(在循环中)
整个重新显示的过程非常复杂/强大。它允许从完全自动的重新显示机制到极细粒度的控制
您可以在此处阅读:。注意:规范和实现提供的内容之间可能有相当大的差异…听起来McCLIM中有一个bug。