通过预设功能从 Racket 中的 Big-Bang 访问世界状态

Accessing the world-state from Big-Bang in Racket from a preset function

我正在用 Racket 创建一个带有 big bang 函数和四个结构的小游戏。我的结构如下:

(define-struct game_main (tank missile UFO))
(define-struct tank (x aim-x aim-y))
(define-struct missile (x y vel))
(define-struct UFO (x y))
(define a-game 
  (make-game_main 
  (make-tank 370 100 100)
  (make-missile 500 500 1)
  (make-UFO 100 100)))

在为 big bang 函数创建键事件处理程序时,我使用 a 将坦克的 x 位置向左移动,d 将其向右移动,就像这样。附上big-bang函数供参考:

(define (controls a-game a-key)
  (cond
    [(key=? a-key "a")
     (struct-copy game_main a-game [tank (make-tank (- (tank-x (game_main-tank a-game)) 7)
                                                    (tank-aim-x (game_main-tank a-game))
                                                    (tank-aim-y (game_main-tank a-game)))])]
    [(key=? a-key "d")
     (struct-copy game_main a-game [tank (make-tank (+ (tank-x (game_main-tank a-game)) 7)
                                                    (tank-aim-x (game_main-tank a-game))
                                                    (tank-aim-y (game_main-tank a-game)))])]
    )
  )

(big-bang a-game (to-draw game_init) (on-key controls)) 

效果很好;但是,它很冗长。我想定义一个函数,例如 "move-tank-left",它只包含世界状态转换器,但定义在事件处理程序之外。但是,它没有直接编辑 big-bang 操纵的结构,而是返回到我全局设置的 a-game game_main 结构并恢复它开始的 x 值。 如何引用当前的 big-bang 函数世界状态,以便您可以在 big-bang 函数之外建立函数来编辑临时状态?

这里是有问题的函数:

(define move-tank-left
(make-tank
(- (tank-x (game_main-tank a-game)) 5)
(tank-aim-x (game_main-tank a-game))
(tank-aim-y (game_main-tank a-game))))

您无法引用当前 "big-bang" 状态,因为它不存在于 big-bang 之外。
(即使 big-bang 也没有真正编辑当前状态 –

(struct-copy game_main a-game ...

不修改 a-game 参数,而是创建一个新状态。)

您可以从 controls 函数传递整个游戏状态:

(define (controls a-game a-key)
  (cond
    [(key=? a-key "a")
     (struct-copy game_main a-game [tank (move-tank-left a-game)])]
    ... 

(define (move-tank-left game-state)
    (make-tank
       (- (tank-x (game_main-tank game-state)) 5)
       (tank-aim-x (game_main-tank game-state))
       (tank-aim-y (game_main-tank game-state))))

但只绕过坦克会产生更少的依赖性,让您更容易添加坦克:

(define (controls a-game a-key)
  (cond
    [(key=? a-key "a")
     (struct-copy game_main 
                  a-game 
                 [tank (move-tank-left (game_main-tank a-game))])]
    ...

(define (move-tank-left tank)
    (make-tank
       (- (tank-x tank) 5)
       (tank-aim-x tank)
       (tank-aim-y tank)))