Lab 2 - Images, Animations and Worlds
Telling DrRacket that you want Images and Animations
For any DrRacket program for which you would like to create/manipulate images and also create animations we will add the following lines at the top of the definitions window
(require 2htdp/image) (require 2htdp/universe)
Open the DrRacket documentation for 2htdp/image and read the documentation for the following functions
circle; create examples of circles in DrRackettext; create examples of text in DrRacketsquare; create examples of squares in DrRacketrectangle; create examples of rectangles in DrRacketoverlay/xy; create composite image using circles and rectangles, e.g., a simple car where a rectangle represents the car's body and 2 circles represent the car's wheels.
Creating Snapshots
Open DrRacket's documentation for 2htdp/image and read the section "Placing Images & Scenes".
- Create an empty scene first.
- Create a shape (e.g., a circle) and place it in the center of your scene.
- Place the composite image that you created in the previous section and place it in the bottom right corner of your scene.
- Create Snapshots of a ball that is placed in the center of your scene and moves horizontally from left to right. Create at least 5 snapshots.
Animations from Snapshots and the concept of a world
Open the DrRacket documentation for 2htdp/universe and read the documentation stating at section "Interactions"
-
Our "world" will represent the number of ticks passed
;; World is a positive number (current time)
-
Create a function that will calculate the next world
;; World -> World ;; calculates the next world (increments the time) (define (next-world w) (add1 w))
-
Create a function that will create an image snapshot from a world
;; World -> Image ;; draw the image for snapshot time w in the middle ;; of a 200x200 scene (define (world-draw w) (place-image (circle w "solid" "black") 100 100 (empty-scene 200 200))) -
Genesis! Lookup
big-bangin DrRacket's documentation.;; We start at time 1, use next-world to update the world at each ;; tick, and use world-draw to render the world as a scene: (big-bang 1 (on-tick next-world) (on-draw world-draw))
- The circle does not grow in size but it remains of the same size in the center of the scene.
- Every tick of the clock makes the circle move horizontally (left to right) by 15 points.
- Every tick of the clock makes the circle move vertically (bottom to top) by 15 points.
The world is not enough!
Read the documentation on Posns
-
Using the second animation from the preceding question (moving the ball horizontally), alter your program to use a
posnin order to represent the location of you ball. Change your representation of theWorldto be thisposn. Update all function so that the animation is working as before. Note: Use the Design Recipe! -
Using the third animation from the preceding question (moving the ball vertically), alter your program to use a
posnin order to represent the location of you ball. Change your representation of theWorldto be thisposn. Update all function so that the animation is working as before. Note: Use the Design Recipe!
Bonus Round: A simple Game
Paste the following code in a new definitions window
(require 2htdp/universe)
(require 2htdp/image)
(define ball (circle 10 'outline 'red))
(define canvas (empty-scene 500 500))
(define speed 5)
;; Direction is one of:
;; - 'up
;; - 'down
;; - 'left
;; - 'right
;; World contains position, speed and direction
;; where
;; - position is a Posn
;; - speed is a Number
;; - direction is a Direction
(define-struct w (coord speed direction))
;; initial-wold has the ball in the center, speed and moving to the left
(define initial-world
(make-w (make-posn 250 250)
speed
'left))
;; tick : World -> World
;; Given a world w create a new world w' that has the same speed and direction as w but update
;; its position using using speed and direction.
(define (tick world)
(make-w (change-position (w-coord world) (w-speed world) (w-direction world))
(w-speed world)
(w-direction world)))
;; change-position : Posn Speed Direction -> Posn
;; given a posn, speed and direction return the new position (as a Posn)
;; moved due to speed and direction
;; Examples
;; (change-position (make-posn 1 1) 10 'left) => (make-posn -9 1)
;; (change-position (make-posn 1 1) 10 'right) => (make-posn 11 1)
;; (change-position (make-posn 1 1) 10 'up) => (make-posn 1 -9)
;; (change-position (make-posn 1 1) 10 'down) => (make-posn 1 11)
(define (change-position coord speed direction)
(cond
[(symbol=? direction 'right) (make-posn (+ (posn-x coord) speed)
(posn-y coord))]
[(symbol=? direction 'left) (make-posn (- (posn-x coord) speed)
(posn-y coord))]
[(symbol=? direction 'up) (make-posn (posn-x coord)
(- (posn-y coord) speed))]
[(symbol=? direction 'down) (make-posn (posn-x coord)
(+ (posn-y coord) speed))]))
(check-expect (change-position (make-posn 1 1) 10 'left)
(make-posn -9 1))
(check-expect (change-position (make-posn 1 1) 10 'right)
(make-posn 11 1))
(check-expect (change-position (make-posn 1 1) 10 'up)
(make-posn 1 -9))
(check-expect (change-position (make-posn 1 1) 10 'down)
(make-posn 1 11))
;; draw-scene : World -> Image
(define (draw-scene w)
(place-image ball
(posn-x (w-coord w))
(posn-y (w-coord w))
canvas))
(big-bang initial-world
(on-tick tick)
(on-draw draw-scene))
Save the code and run.
-
Read the documentation on on-key.
Design a function called
keypressthat consumes aWorldand akeyand produces a newWorldsuch that- if the
keyis the string"up"then the ball must movespeedunits up in the scene - if the
keyis the string"down"then the ball must movespeedunits down in the scene - if the
keyis the string"left"then the ball must movespeedunits left in the scene - if the
keyis the string"right"then the ball must movespeedunits right in the scene
- if the
- Read the documentation on stop-when. Change your program so that the game terminates when the ball hits the bounds of the scene.