Programming Breakout in Racket (BSL) using big-bang. Running into an error upon placing the paddle

1.3k Views Asked by At

The goal is to make the game Breakout and doing it by steps. I'm already having problems with the first step which is implementing a paddle. The ball and bouncing of the ball was already predefined and given. I wish to put it in the (define (render ball) like so:

(define (render ball worldstate)
(place-image BALL-IMG
           (posn-x (ball-loc ball))
           (posn-y (ball-loc ball))
(place-image PADDLE (posn-x (world-state-paddle worldstate)) (posn-y (world-state-paddle worldstate))
           SCENE)))

However I'm getting the error "to-draw: expected function of one argument as first argument; given function of 2 arguments " I'm not sure how I can make the code better. Here's what my code looks like so far. The ball is already predefined as well as the tick. So far I cannot even place the paddle in but the ball bounces around (no bricks yet implemented)

(require 2htdp/image)
(require 2htdp/universe)

(define WIDTH 200)
(define HEIGHT 200)
(define BALL-RADIUS 10)
(define BALL-IMG (circle BALL-RADIUS "solid" "red"))
(define SCENE (empty-scene WIDTH HEIGHT))

(define PADDLE (rectangle 60 10 "solid" "green"))
(define SPEED 4)

(define-struct vel (delta-x delta-y))
; a Vel is a structure: (make-vel Number Number)
; interp. the velocity vector of a moving object

(define-struct ball (loc velocity))
; a Ball is a structure: (make-ball Posn Vel)
; interp. the position and velocity of a object 

; Posn Vel -> Posn
; applies q to p and simulates the movement in one clock tick
(check-expect (posn+vel (make-posn 5 6) (make-vel 1 2))
              (make-posn 6 8))

(define (posn+vel p q)
  (make-posn (+ (posn-x p) (vel-delta-x q))
             (+ (posn-y p) (vel-delta-y q))))


; Ball -> Ball
; computes movement of ball in one clock tick
(check-expect (move-ball (make-ball (make-posn 20 30)
                                    (make-vel 5 10)))
              (make-ball (make-posn 25 40)
                     (make-vel 5 10)))

(define (move-ball ball)
  (make-ball (posn+vel (ball-loc ball)
                       (ball-velocity ball))
         (ball-velocity ball)))


; A Collision is either
; - "top"
; - "down"
; - "left"
; - "right"
; - "none"
; interp. the location where a ball collides with a wall

; Posn -> Collision
; detects with which of the walls (if any) the ball collides
(check-expect (collision (make-posn 0 12))  "left")
(check-expect (collision (make-posn 15 HEIGHT)) "down")
(check-expect (collision (make-posn WIDTH 12))  "right")
(check-expect (collision (make-posn 15 0)) "top")
(check-expect (collision (make-posn 55 55)) "none")

(define (collision posn)
  (cond
    [(<= (posn-x posn) BALL-RADIUS) "left"]
    [(<= (posn-y posn) BALL-RADIUS)  "top"]
    [(>= (posn-x posn) (- WIDTH BALL-RADIUS)) "right"]
    [(>= (posn-y posn) (- HEIGHT BALL-RADIUS)) "down"]
    [else "none"]))

; Vel Collision -> Vel  
; computes the velocity of an object after a collision
(check-expect (bounce (make-vel 3 4) "left")
              (make-vel -3 4))
(check-expect (bounce (make-vel 3 4) "top")
              (make-vel 3 -4))
(check-expect (bounce (make-vel 3 4) "none")
              (make-vel 3 4))

(define (bounce vel collision)
  (cond [(or (string=? collision "left")
         (string=? collision "right"))
     (make-vel (- (vel-delta-x vel))
               (vel-delta-y vel))]
    [(or (string=? collision "down")
         (string=? collision "top"))
     (make-vel (vel-delta-x vel)
               (- (vel-delta-y vel)))]
    [else vel]))

; WorldState is a Ball
; interp. the current state of the ball

; WorldState -> Image
; renders ball at its position
;(check-expect (image? (render INITIAL-BALL)) #true)

(define (render ball worldstate)
  (place-image BALL-IMG
           (posn-x (ball-loc ball))
           (posn-y (ball-loc ball))
           SCENE))

; WorldState -> WorldState
; moves ball to its next location
(check-expect (tick (make-ball (make-posn 20 12) (make-vel 1 2)))
              (make-ball (make-posn 21 14) (make-vel 1 2)))

(define (tick ball)
  (move-ball (make-ball (ball-loc ball)
                    (bounce (ball-velocity ball)
                            (collision (ball-loc ball))))))


(define-struct world-state (paddle speed ball))

;WorldState is a structure (make-world-state paddle speed Ball)

(define Example-world-state (make-world-state PADDLE SPEED (make-ball (make-posn 20 12)
                                                      (make-vel 1 2))))

;mouse
;Worldstate Number Number MouseEvent -> Worldstate
;moves the paddle
(define (mouse worldstate x y mouseEvent)
  (make-world-state (world-state-speed worldstate) (world-state-ball     worldstate)
                (cond
                  [(string=? mouseEvent "move")
                   (make-posn x y)]
                  [else (world-state-paddle worldstate)])))




(define INITIAL-BALL (make-ball (make-posn 20 12)
                            (make-vel 1 2)))

(define INITIAL-WORLD-STATE INITIAL-BALL)

(define (main state)
  (big-bang state (on-tick tick 0.01) (to-draw render) (on-mouse mouse)))

(main INITIAL-WORLD-STATE)

I appreciate any tips given!

2

There are 2 best solutions below

2
On

I noticed your 'render' function signature is

WorldState -> Image

but, render gets 2 parameters:

 `(define (render ball worldstate) ...)`

Signatures are used to type check and better document your work for others to understand, in this case it helped me quickly find the problem :)

According to the error you supplied:

(to-draw render)

in function 'main' is expecting render to be a funtion that receives only 1 parameter while in your code it is defined as a function that takes 2 params:

Check out render and to-draw here: [email protected]

2
On

The render function only takes the world state as a parameter, and you can't add more parameter.
You already have the paddle in the state, and you can retrieve the ball and the paddle from it:

(define (render world)
    (place-image BALL-IMG
           (posn-x (ball-loc (world-state-ball world))
           (posn-y (ball-loc (world-state-ball world))
    ...

You might want to write separate rendering functions for the components:

(define (render-ball ball)
     ...)

(define (render-paddle paddle)
     ...)

(define (render-world world)
    (render-ball (world-state-ball world))
    (render-paddle (world-state-paddle world))