The following code draws a red rectangle bouncing between the borders of a white display. I'm not particularly happy with the update function:
(require 'lispbuilder-sdl)
(defun update-h-speed (state h-border top-left-border)
(if (or (< (cdr (assoc 'h-coord state)) top-left-border) ;;if too left
(> (cdr (assoc 'h-coord state)) h-border)) ;;if too right
;; negate the horizontal speed
(acons 'h-speed (- (cdr (assoc 'h-speed state))) state)
state))
(defun update-v-speed (state v-border top-left-border)
(if (or (< (cdr (assoc 'v-coord state)) top-left-border) ;;if too high
(> (cdr (assoc 'v-coord state)) v-border)) ;;if too low
;; negate the vertical speed
(acons 'v-speed (- (cdr (assoc 'v-speed state))) state)
state))
(defun update-coords (state)
(acons 'h-coord (+ (cdr (assoc 'h-coord state))
(cdr (assoc 'h-speed state)))
(acons 'v-coord (+ (cdr (assoc 'v-coord state))
(cdr (assoc 'v-speed state))) state)))
(defun update (state width height size)
(let ((h-border (- width (/ size 2)))
(v-border (- height (/ size 2)))
(top-left-border (/ size 2)))
(update-coords
(update-h-speed
(update-v-speed state v-border top-left-border) h-border top-left-border))))
(defun game (&optional (width 320) (height 240) (speed 2) (size 20))
(let ((decoy (pairlis (list 'h-coord 'v-coord 'h-speed 'v-speed)
(list (/ width 2) (/ height 2) speed speed))))
(sdl:with-init ()
(sdl:window width height :title-caption "My game")
(setf (sdl:frame-rate) 60)
(sdl:with-events ()
(:quit-event () t)
(:key-down-event (:key key)
(when (sdl:key= key :sdl-key-escape) (sdl:push-quit-event)))
(:idle ()
;; update state
(setq decoy (update decoy width height size))
(sdl:clear-display sdl:*white*)
;; draw the rectangle according to the updated state
(sdl:draw-box (sdl:rectangle-from-midpoint-*
(cdr (assoc 'h-coord decoy)) (cdr (assoc 'v-coord decoy)) size size)
:color sdl:*red*)
(sdl:update-display))))))
In fact, the big-bang function in Racket made such things quite easy. With big-bang, I usually created a structure to hold every object (just coordinates and speeds of the rectangles) and modified each part of the structure with separate functions.
Please note that this is not a question about making this animation work.
1) I would like to get advice about, how to refactor such programs to make the update function more functional, so that it is easier to expand (add new features) and debug.
2) I'm particularly confused about whether I should prefer special variables to hold the structures, or prefer to create them locally as is the case. Do you prefer one over the other during different cycles of programming (like development and distribution)?
Note: I preferred an assoc list in place of a hash table, because of the few number of pairs, and the acons enables a sort of history feature, if this thing will ever going to work.