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-bang
in 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
posn
in order to represent the location of you ball. Change your representation of theWorld
to 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
posn
in order to represent the location of you ball. Change your representation of theWorld
to 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
keypress
that consumes aWorld
and akey
and produces a newWorld
such that- if the
key
is the string"up"
then the ball must movespeed
units up in the scene - if the
key
is the string"down"
then the ball must movespeed
units down in the scene - if the
key
is the string"left"
then the ball must movespeed
units left in the scene - if the
key
is the string"right"
then the ball must movespeed
units 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.