Программирование Breakout в Racket (BSL) с использованием большого взрыва. Ошибка при размещении весла

Цель состоит в том, чтобы сделать игру Breakout и делать это по шагам. У меня уже есть проблемы с первым шагом, который реализует весло. Мяч и отскок мяча уже были предопределены и заданы. Я хочу поместить его в (define (render ball)) вот так:

(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)))

Однако я получаю сообщение об ошибке «to-draw: ожидаемая функция одного аргумента в качестве первого аргумента; заданная функция двух аргументов». Я не уверен, как я могу улучшить код. Вот как выглядит мой код до сих пор. Мяч уже предопределен, как и галочка. Пока я даже не могу поставить ракетку, но мяч подпрыгивает (кирпичи еще не реализованы)

(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)

Я ценю любые данные советы!


person Delight Wang    schedule 16.12.2017    source источник


Ответы (2)


Я заметил, что ваша подпись функции «рендеринга»

Состояние мира -> Изображение

но рендер получает 2 параметра:

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

Подписи используются для проверки типа и лучшего документирования вашей работы для понимания другими, в данном случае это помогло мне быстро найти проблему :)

В соответствии с ошибкой, которую вы указали:

(to-draw render)

в функции main ожидается, что render будет функцией, которая получает только 1 параметр, в то время как в вашем коде она определена как функция, которая принимает 2 параметра:

Ознакомьтесь с визуализацией и отрисовкой здесь: [email protected]

person ghosh    schedule 17.12.2017
comment
Я так понимаю при выполнении (to-draw...) или (on-tick...) принимается только один параметр? или он примет 2 параметра, если я дам ему два параметра, например (to-draw render render2)? - person Delight Wang; 17.12.2017
comment
Обе эти функции перегружены, to-draw может принимать 1 или 3 параметра. Из документации в моем ответе: (to-draw render-expr) = ... вызовите функцию render-expr... Ее размер определяется размером первого сгенерированного изображения. или вы можете использовать: (to-draw render-expr width-expr height-expr) = ...используйте ширину-expr by height-expr canvas вместо того, который определяется первым сгенерированным изображением. Проверьте в тике тоже. - person ghosh; 18.12.2017

Функция render принимает только состояние мира в качестве параметра, и вы не можете добавить больше параметров.
У вас уже есть ракетка в состоянии, и вы можете извлечь из нее мяч и ракетку:

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

Возможно, вы захотите написать отдельные функции рендеринга для компонентов:

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

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

(define (render-world world)
    (render-ball (world-state-ball world))
    (render-paddle (world-state-paddle world))
person molbdnilo    schedule 17.12.2017
comment
Итак, если у меня есть эти разные рендеры, а затем, в конце концов, я поместил мир рендеринга в этом случае в мое (определить (основное состояние)), все должно появиться? :D Я правильно понимаю? - person Delight Wang; 17.12.2017
comment
@DelightWang Ну, они должны, но я ничего не обещаю ;-) (Создание отдельных функций пригодится, когда вы хотите добавить режим с несколькими мячами или режим для двух игроков. ) - person molbdnilo; 18.12.2017