Scheme 如何使用Racket';大爆炸`

Scheme 如何使用Racket';大爆炸`,scheme,racket,Scheme,Racket,我正在开发一个简单的小行星球拍游戏,一切都很好,除了我想让玩家移动和射击的同时 以下是控制键: 向左/向右旋转 向上/向下可加速、减速 发射空间 和我的键上的处理程序: (define (direct-ship w a-key) (define a-ship (world-ship w)) (define a-direction (+ (ship-direction a-ship) (cond [(key=? a-key "left") -5]

我正在开发一个简单的小行星球拍游戏,一切都很好,除了我想让玩家移动和射击的同时

以下是控制键:

  • 向左/向右旋转
  • 向上/向下可加速、减速
  • 发射空间
和我的
键上的
处理程序:

(define (direct-ship w a-key)
  (define a-ship (world-ship w))
  (define a-direction
    (+ (ship-direction a-ship)
    (cond
      [(key=? a-key "left") -5]
      [(key=? a-key "right") 5]
      [else 0])))
  (define a-speed
    (+ (ship-speed a-ship)
       (cond
         [(key=? a-key "up") 1]
         [(key=? a-key "down") -1]
         [else 0])))
  (define bullets
    (cond
      [(key=? a-key " ") (cons (new-bullet a-ship) (world-bullets w))]
      [else (world-bullets w)]))

  (world (world-asteroids w)
         (ship (ship-pos a-ship) a-direction a-speed)
         bullets
         (world-score w)))
考虑到这个进程的签名,我觉得它一次只能处理一个字符是有道理的。所以也许我需要使用不同的处理器?还是不同的钥匙

请参阅github上的完整源代码:
问题是每次只为一个键调用
on key
处理程序。即使您能够同时按下向右箭头和向上箭头,按键上的
也会被调用两次

处理此问题的一种方法是,每个键在全局表中存储有关该键是向上还是向下的信息。给定这样一个表,您可以在键上的
中使用它来检查当前正在处理的键以外的键的状态

以下是来自太空入侵者克隆的片段。首先是全局键盘表

;;; Keyboard
; The keyboard state is kept in a hash table. 
; Use key-down? to find out, whether a key is pressed or not.
(define the-keyboard (make-hasheq))
(define (key-down! k) (hash-set! the-keyboard k #t))
(define (key-up! k)   (hash-set! the-keyboard k #f))
(define (key-down? k) (hash-ref  the-keyboard k #f))
然后是事件的处理——由于上下文的关系,在没有大爆炸的情况下处理事件,但在这里重要的是想法

;;; Canvas
; Key events sent to the canvas updates the information in the-keyboard.
; Paint events calls draw-world. To prevent flicker we suspend flushing
; while drawing commences.
(define game-canvas%
  (class canvas%
    (define/override (on-event e) ; mouse events
      'ignore)
    (define/override (on-char e)  ; key event
      (define key     (send e get-key-code))
      (define release (send e get-key-release-code))
      (when (eq? release 'press)  ; key down?
        (key-down! key))
      (when (eq? key 'release)    ; key up?
        (key-up! release)
        (when (eq? release #\space)
          (play-sound "shoot.mp3" #t))))
    (define/override (on-paint)   ; repaint (exposed or resized)
      (define dc (send this get-dc))
      (send this suspend-flush)
      (send dc clear)
      (draw-world the-world dc)
      (send this resume-flush))
    (super-new)))
正如您所看到的,key事件处理程序只存储键是否向上和向下(出于某些奇怪的原因,播放“shot.mp3”示例)。那么玩家实际移动到哪里(根据箭头键)

实际移动在勾号上的
中处理(或其等效项)。

在勾选时处理
中的移动
可确保玩家在按键时不会移动额外的距离。

考虑使用
哈希集
,而不是在此答案中进行变异,以更符合HtDP/
大爆炸
的原则。新的工作代码如下: