I am trying to draw a screen for a game in big-bang
2htdp an I’m running into performance problems, can anyone point me in the direction of a fast way to draw an ‘offscreen’ buffer without having to return a new image after every draw I do and then setting the screen variable to that new image. Sorry that didn’t come out very well, but I’m not sure how to describe it.
Code will explain better
#lang racket
(require 2htdp/universe
2htdp/image)
(define WIDTH 800)
(define HEIGHT 600)
(define CELL-SIZE 5)
(define CELLS-X (/ WIDTH CELL-SIZE))
(define CELLS-Y (/ HEIGHT CELL-SIZE))
(define FINISHED #f)
(define TILE (freeze (square 5 "outline" "red")))
(define (create-world-state)
(define world-state (make-vector CELLS-X (make-vector CELLS-Y)))
(for ([y (in-range CELLS-Y)])
(for ([x (in-range CELLS-X)])
(vector-set! (vector-ref world-state x) y 0)))
world-state)
(define world-state (create-world-state))
(define (render-world ws)
(define es (empty-scene WIDTH HEIGHT "black"))
(for ([y (in-range CELLS-Y)])
(for ([x (in-range CELLS-X)])
(set! es
(place-image TILE
(* CELL-SIZE x) (* CELL-SIZE y)
es))))
es)
(define (check-stop ws)
FINISHED)
(define (key-handler ws key-event)
(set! FINISHED #t))
(define (update-world ws)
world-state)
(big-bang world-state
(on-tick update-world)
(on-key key-handler)
(to-draw render-world)
(stop-when check-stop)
(close-on-stop #t))
I am trying to avoid the set!
in render-world
as I’m sure this may be slowing things down.
I am almost sure (define world-state (make-vector CELLS-X (make-vector CELLS-Y)))
is not what you intend. It will create one vector (make-vector CELLS-Y))
and store that vector in every cell of the vector (make-vector CELLS-X ...)
.
I think you’ll want to use build-vector
instead.
EEK! Thanks @soegaard2 hadn’t got as far as using the vectors yet, but it’s a good point that would have bitten me later.
The reason this becomes slow over time is that es holds the inial empty scene and then for each frame 25 tiles are attached.
So in frame 2 there are 50 tiles attached, in frame 3 there 75 and so on.
I think, you can fix it by adding: (set! es (freeze es))
in render-word
right before returning es
.
This will replace an image with attached smaller images into a single image.
Ok, I’ll look at that.
An alternative is to put es
outside render-world
: (define es ...)
. Then use (set! es (empty-schene ...))
inside render-world
. That way the “start image” has no attached sub images.
I’ll have a look at that too, thanks for the pointers.
This will erase the previous tiles - they are kept in your current version.
@soegaard2 Also place-images
might be a better fit rather that doing separate place-image
if I set up two lists first.