我正在 Racket 中开展我的第一个项目。我认为该语言包含一个跨平台 GUI 工具包真是太棒了,我想集中精力思考如何让它表现良好。
我尝试制作一个小画布,绘制白色和黑色方块的网格,每一帧都会随机化。当您运行下面的程序并按下键盘上的某个键时,它会退出并转储出总体测量的 FPS。
在当前状态下,它在我的 MacBook M1 上以约 20fps 的速度运行。我真的希望能够以至少 60 fps 的速度运行。有人有一些建议可以帮助我到达那里吗?
#lang racket
(require racket/gui)
(require racket/random)
(define *width* 64)
(define *height* 32)
(define *scale* 10)
(define *counted-frames* 0)
(define *start-time* 0)
(define *end-time* 0)
(define *timer*
(new timer%
[notify-callback
(lambda ()
(update-grid!)
(send *canvas* refresh-now)
(flush-output))]))
(define *grid*
(for/vector ([i (in-range (* *height* *width*))])
#f))
(define (update-grid!)
(for ([i (vector-length *grid*)])
(if (zero? (random 2))
(vector-set! *grid* i #f)
(vector-set! *grid* i #t))))
(define (sample-grid)
(for ([i (in-range 10)])
(println (vector-ref *grid* i))))
(define (get-element x y)
(vector-ref *grid* (+ (* y *width*) x)))
(define *frame*
(new frame% [label "Checkboard Grid"]
[width (* *scale* *width*)]
[height (* *scale* *height*)]))
(define rect-canvas%
(class canvas%
(inherit get-dc)
(super-new)
(define/override (on-char event)
(begin
(fprintf (current-error-port)
"Received key event: ~a, quitting\n" event)
(set! *end-time* (current-inexact-milliseconds))
(println (format "FPS: ~a"
(/ (* 1000 *counted-frames*)
(- *end-time* *start-time*))))
(exit)))
(define/override (on-paint)
(set! *counted-frames* (+ 1 *counted-frames*))
(let ((dc (get-dc)))
(for* ([x (in-range *width*)] [y (in-range *height*)])
(if (get-element x y)
(begin
(send dc set-pen "black" 1 'solid)
(send dc set-brush "black" 'solid))
(begin
(send dc set-pen "white" 1 'solid)
(send dc set-brush "white" 'solid)))
(send dc draw-rectangle (* x 10) (* y 10) 10 10))))))
(define *canvas* (new rect-canvas% [parent *frame*]))
(define (run)
(set! *start-time* (current-inexact-milliseconds))
(send *frame* show #t)
(send *timer* start 1))
(run)
在球拍话语上回答过,引用如下:
“我不认为,在不做更少的绘制工作的情况下,你会看到更高的 fps。
这可能会给你带来一点收获:
(define black-pen (new pen% [color "black"] [width 1] [style 'solid]))
(define white-pen (new pen% [color "white"] [width 1] [style 'solid]))
(define black-brush (new brush% [color "black"] [style 'solid]))
(define white-brush (new brush% [color "white"] [style 'solid]))
(define dc (get-dc))
(define/override (on-paint)
(set! *counted-frames* (+ 1 *counted-frames*))
(for* ([x (in-range *width*)] [y (in-range *height*)])
(if (get-element x y)
(begin
(send dc set-pen black-pen)
(send dc set-brush black-brush))
(begin
(send dc set-pen white-pen)
(send dc set-brush white-brush)))
(send dc draw-rectangle (* x 10) (* y 10) 10 10)))
如果您的游戏是具有 10x10“像素”的复古游戏,那么您可以获得加速 通过使用低分辨率的位图,例如 100x80,然后 通过在屏幕上绘制位图的缩放副本来进行绘制完成。
这里使用了这个技术:
https://github.com/soegaard/sketching/blob/main/sketching-examples/examples/pacman/maze-game.rkt
[虽然不是 60 fps。]
如果这还不够快,您需要了解如何使用 GPU - 要么 直接或使用可用的库之一。”