Racket/Beginner Student Language Confusion - racket

I am trying to animate the word "floccinaucinihilipilification" letter by letter. Right now it displays the complete word in the animation window, but I am lost on how to animate it so it will count up from the first character to the last, looping back to 0.
(define LONG-WORD "floccinaucinihilipilification")
; cycle-spelling : String -> Image
; display an animation of a long
; word being spelled out
(define a (string-length LONG-WORD))
(define TXT
(text (substring LONG-WORD 0 a) 30 "black"))
(define BG
(empty-scene 400 400))
(define (cycle-spelling a)
(place-image TXT 200 200 BG))
(animate cycle-spelling)

See what animate does:
(animate create-image) → natural-number/c
create-image : (-> natural-number/c scene?)
opens a canvas and starts a clock that ticks 28 times per second. Every time the clock ticks, DrRacket applies create-image to the number of ticks passed since this function call. The results of these function calls are displayed in the canvas. The simulation runs until you click the Stop button in DrRacket or close the window. At that point, animate returns the number of ticks that have passed.
So you have to base your code on the number of ticks, passed to create-image function.
(animate cycle-spelling)
(define (cycle-spelling ticks) ... )
Start with (quotient ticks 28), value of this expression increases each second by 1.
Looping is created with modulo, so after some experimenting, you should have something like this:
(modulo (quotient ticks 28) (+ (string-length long-word) 1))
Rest of the code will be similar.
Following code animates given word letter by letter and then loops back to 0.
#lang racket
(require 2htdp/universe)
(require 2htdp/image)
(define long-word "floccinaucinihilipilification")
(define speed 3) ; try also 7, 14, 28 ...
(define bg
(empty-scene 400 400))
(define (cycle-spelling ticks)
(place-image (text (substring long-word 0
(modulo (quotient ticks speed)
(+ (string-length long-word) 1)))
30 "black")
200 200 bg))
(animate cycle-spelling)

Related

How to make a color changing sky in Racket?

I have a variable that controls the number of blue in (color R, G, B). Now I am confused about how to use that variable in (color R, G, B). Also, I am totally new to Racket. I know I can combine these functions together, but I don't know how :( The purpose of this code is to make a color changing scene in animate.
Here is my code:
(require 2htdp/image)
(define(Skycolor num)
(remainder num 510))
(define(skycolor num)
(abs(- 255(Skycolor num))))
(define(sky-color num)
(color 0 0 (skycolor num)))
(define (SKY num )
(square 200 "solid" (color 0 0 (sky-color num)))))
It's not very clear what do you mean with "color changing", but you can take some inspiration from following code. See also this similar question, where I explain how animate works.
#lang racket
(require 2htdp/universe)
(require 2htdp/image)
(define speed 5)
(define (sky-color ticks)
(color 0 (modulo (* speed (- 255 ticks)) 255) 255))
(define bg
(empty-scene 125 125))
(define (make-sky ticks)
(square 250 "solid" (sky-color ticks)))
(define (draw-image ticks)
(place-image (make-sky ticks) 0 0 bg))
(animate draw-image)

Animation in Racket

Running program window So I'm doing this exercise from pictured programs and I've got the program to do as the exercise wants, but the image in the interaction window looks like a bunch of stacked backgrounds. I'm missing something with this program and I don't know what it is. Interaction window after program runs
Also I might add that this must be done without conditionals, for loops etc... advanced functions.
You can see that it overlays a white background that keeps the program from populating that space and I can't seem to find a way around this. I've literally brute forced every possible combination that I can think of and this is the best I could come with at this moment.
Exercise explanation is below:
Write an animation that starts with a blank screen, and each half
second adds a small dot at a completely random location — both the x coordinate and the
y coordinate are chosen at random.
Hint: Since you need to keep all the previous dots and add one more, your “model”
should probably be an image rather than a number. How can you add a dot at a specified
location to an existing image?
Hint: It would be especially nice if you could start the animation with any image, of
any size or shape, and it would sprinkle dots at random all over that background, without
rewriting the handlers.
; Random dots
(define DOT
(circle 4 "solid" "black"))
(define blank-screen
(rectangle 200 200 "solid" "white"))
(define (next-dot x)
(overlay/xy x
(min 200 (random 200)) (min 200 (random 200))
(old-dot DOT)))
(define (old-dot x)
(overlay/xy x
(min 200 (random 200)) (min 200 (random 200))
blank-screen))
(big-bang DOT
(on-tick next-dot 1/2)
(on-draw old-dot 200 200))
; Random dots
(define DOT
(circle 4 "solid" "black"))
(define blank-screen
(rectangle 200 200 "solid" "white"))
(define (next-dot x)
(overlay/xy x
(random 200) (random 200)
DOT))
(define (old-dot x)
(overlay/xy x
(random 200) (random 200)
blank-screen))
(big-bang DOT
(on-tick next-dot 1/2)
(on-draw old-dot 200 200))

How can i control my clock speed using Racket?

I tried to write a program that counting down from 10 to 0 using Racket. It worked but the counting is going too fast, is there a way to implement a set time that count one second per turn? I've been working on it but couldn't find anyway. Thank for your time. Here's my code so far:
;; Functions:
;; countdown -> countdown
;; start the world with main at CTR-X CTR-Y
;;
(define (main cd)
(big-bang cd ; countdown
(on-tick advance-countdown) ; countdown -> countdown
(to-draw render) ; countdown -> Image
(on-key handle-key) ; countdown KeyEvent ->
countdown
(on-mouse handle-mouse))) ; Integer Integer MouseEvent
; -> countdown
;; countdown -> countdown
;; produce the next number by decrease by 1 from the previous number
(check-expect (advance-countdown 5) 4)
(check-expect (advance-countdown 0) 0)
;(define (advance-countdown cd) 0) ; stub
;;<use template from Countdown>
(define (advance-countdown cd)
(if (= cd 0)
0
(- cd 1)))
;; countdown -> Image
;; render ...
(check-expect (render 4) (place-image (text (number->string 4) TEXTSIZE
TEXT-COLOR) CTR-X CTR-Y MTS))
;(define (render cd) MTS) ; stub
(define (render cd)
(place-image (text (number->string cd) TEXTSIZE TEXT-COLOR)
CTR-X
CTR-Y
MTS))
;; countdown KeyEvent -> countdown
;; reset countdown to 10
(check-expect (handle-key 10 " ") 10)
(check-expect (handle-key 10 "a") 10)
;(define (handle-key cd ke) 0) ; stub
(define (handle-key cd ke)
(cond [(key=? ke " ") 10]
[else cd]))
What you are looking for is a 'Timer'. Racket has a few different notions of timer built into it, and you can even make your own. But two of the more prominent built in ones are:
timer% - from the racket/gui/base library, and
timer - from the web server library.
Or you could just make your own using alarm-evt and sync. (You can also make your own timer from more 'low level' primitives, but I would not recommend doing so, as its easy to make subtle mistakes and get the wrong time.
Since it looks like you are already using a gui (although the HTDP2 GUI rather than racket/gui), lets user timer%. Simply create a callback that decrements the timer, and stops when it reaches 0.
#lang racket
(require racket/gui/base)
(define count 10)
(displayln count)
(define the-timer
(new timer% [notify-callback
(lambda ()
(set! count (- count 1))
(displayln count)
(when (= count 0)
(send the-timer stop)))]
[interval 1000]))
Now, when you run this program, it should count from 10 to 0 1 second at a time. We can test this out with the current-milliseconds function. Simply grab the start time, the end time, and take the difference. When I ran this on my machine I got a total time of '10138' ms, or 10.138 seconds.

DrRacket: put two objects into big-bang

How can i put two objects with its own coordinates
(define padle1 (rectangle 10 30 "solid" "red"))
(define padle2 (rectangle 10 30 "solid" "red"))
(define (place-dot-at ... ) ...)
into bin-bang function
(big-bang ...
[to-draw place-dot-at])
Can i use list of padles
(define new-list (list padle1 padle2))
big-bang stores only one piece of information, usually called the "world state." All the functions that work with big-bang, like your drawing function, tick handler, and so on, must accept that world state as a single parameter.
It's up to you to decide what to store in your world state. If you want to store two locations (one for each paddle), a list or struct is the way to go. For instance, here is how you might define a struct called world that can hold two positions at once.
; Create a type called `world` that holds two locations.
(define-struct world [paddle1 paddle2])
; Create a variable to store the initial state of the world.
(define initial-world (make-world (make-posn 0 100) (make-posn 300 100)))
When you write your drawing function, it must accept the entire world state at once:
(define (draw-game world)
(place-image
paddle1
(posn-x (world-paddle1 world))
(posn-y (world-paddle1 world))
(place-image
paddle2
(posn-x (world-paddle2 world))
(posn-y (world-paddle2 world))
BACKGROUND)))
In your big-bang, treat the world state like any other kind of data:
(big-bang
initial-world
[to-draw draw-game])
I recommend making a draw-paddle function that draws a single paddle on top of an image i.
(define (draw-paddle p i)
(overlay/xy (rectangle ...) ; the paddle
50 70 ; coordinates on paddle on screen
i)) ; image of what's previously drawn
Then make a function that draws all paddles in a list on top of an image i.
(define (draw-paddles ps i)
(cond
[(empty? ps) i] ; no more paddles to draw
[else (draw-paddles
(rest ps) ; draw the rest of the paddles on top
(draw-paddle (first p) i))])) ; of the first paddle
; ontop of i
Then finally you can made:
(define (on-draw state)
(draw-paddles (list paddle1 paddle2) my-background))
If you don't have a background you can make one with empty-image or rectangle.

Smoother projectile motion in Racket?

I'm playing a little with Racket big-bang mechanism, but I cannot get both smooth and fast going projectile. There's so much ugly flickering. Here's my code:
(require 2htdp/universe
2htdp/image)
(define gx 0)
(define gy 0.35)
(struct ballstate (x y vx vy) #:transparent)
(define startstate (ballstate 10 590 7 -20))
(define (make-new-state old)
(define newvx (+ (ballstate-vx old) gx))
(define newvy (+ (ballstate-vy old) gy))
(ballstate (+ (ballstate-x old) newvx)
(+ (ballstate-y old) newvy)
newvx
newvy))
(define (main)
(big-bang startstate
[on-tick make-new-state]
[to-draw place-ball-at]
[on-key reset]))
(define (place-ball-at s)
(place-image (circle 10 "solid" "red")
(ballstate-x s)
(ballstate-y s)
(empty-scene 800 600)))
(define (reset s ke)
startstate)
(main)
The question is: how to make it better, faster, smoother and flicker-free?
Here are two things that might help:
The on-tick clause takes an optional parameter that determines the time between two ticks. The default is 1/28, so if you lower this you will get more frames resulting in a smoother animation.
If your program takes longer than the time between each tick to produce an image, you will see stuttering. Precomputing everything that can be precomputed is a good thing. For example, there is no reason to produce a new empty scene each time, so below I have simply stored it in a variable.
(define (main)
(big-bang startstate
[on-tick make-new-state 1/50]
[to-draw place-ball-at]
[on-key reset]))
(define background (empty-scene 800 600))
(define (place-ball-at s)
(place-image (circle 10 "solid" "red")
(ballstate-x s)
(ballstate-y s)
background))