What makes my image look half as wide as intended? - racket

I am trying to place a vertically positioned rectangle and another object on an empty-scene using place-images in Beginning Student Language. However, when I run the function, the rectangle only takes up half the scene horizontally when its width is set equal to the width of the scene.
I checked what happens to my code using Stepper and found where the image-width halves but I do not know why. Probably it's to do with cons which I am not very familiar with.
Here's the full code:
(require 2htdp/image)
(define WIDTH 400)
(define HEIGHT 300)
(define HMAX 100)
(define SCENE (empty-scene WIDTH HEIGHT))
(define-struct vcham [x h c])
(define c (make-vcham 0 100 "white"))
(define (render ch)
(place-images (list (rectangle (* 1 WIDTH (/ (vcham-h ch) HMAX)) 50 "solid" "maroon")
(rectangle 1 1 "solid" "blue"))
(list (make-posn 0 0) (make-posn 20 20))
SCENE))
(render c)
I have simplified this code as much as a I could, thus the 1×1 rectangle. I am also interested in elegant alternatives to implement this, but am most interested in finding out why this happens.

place-images is like place-image :
Places image onto scene with its center at the coordinates (x,y)
and crops the resulting image so that it has the same size as
scene. The coordinates are relative to the top-left of scene.
you can change (make-posn 0 0) to (make-posn 200 25), or try place-images/align
(define (render ch)
(place-images/align (list (rectangle (* 1 WIDTH (/ (vcham-h ch) HMAX)) 50 "solid" "maroon")
(rectangle 1 1 "solid" "blue"))
(list (make-posn 0 0) (make-posn 20 20))
"left" "top" SCENE))

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

Racket: How do I keep an image from going off screen to appear on the other side?

I'm currently making a game where your character must dodge objects going on and off the scene.
My problem is that, when the objects go off the scene, they do not reappear on the other side.
Each object is represented by a posn structure, and they move a certain distance on the scene each time there's a tick from left to right and vise versa. I've attached which part of the code I think needs to be edited.
For clarity, a world is a struct containing a chicken and car, both of which are structs containing x and y posns.
And MOVE-CAR is a constant set to (add1 (random 49)) that determines how fast or slow the car will move during gameplay.
;update-world: world -> world
;purpose: updates the position of the car
(define (update-world a-world)
(make-world (world-chicken a-world) (move-horiz (world-car a-world) (* -1 MOVE-CAR))))
;move-horiz: posn number -> posn
;purpose: moves the posn left or right
(define (move-horiz a-posn delta-x)
(make-posn (+ delta-x (posn-x a-posn)) (posn-y a-posn)))
If more code is necessary, I will try and sift through the rest of what I have.
Any help is much appreciated.
To calculate the new x position, you are currently using:
(+ delta-x (posn-x a-posn))
If the result is between 0 and the width, this gives the correct result.
If the result is greater than the width, then the new x should be 0.
If the result is less than 0, then the new x should be the width.
Let's write a function adjust-x that adjusts the x-position you have calculated:
(define WIDTH 100)
(define (adjust-x x)
(cond
[(and (<= 0 x) (<= x WIDTH)) x]
[(> x WIDTH) 0]
[(< x 0) WIDTH]
Then you can change move-horiz to:
(define (move-horiz a-posn delta-x)
(make-posn (adjust-x (+ delta-x (posn-x a-posn)))
(posn-y a-posn)))

Why doesn't the UFO touch the flatbed rock at the bottom of the scene? Why does it stop before?

This is my program
; constants
(define SCENE-WIDTH 200)
(define SCENE-HEIGHT 200)
(define BGR-COLOR "blue")
(define FLAT-ROCKBED (rectangle 100 10 "solid" "black"))
(define MTSCN (place-image FLAT-ROCKBED
(/ SCENE-WIDTH 2) SCENE-HEIGHT
(empty-scene SCENE-WIDTH SCENE-HEIGHT BGR-COLOR)))
[define UFO
[overlay [circle 10 "solid" "green"]
[rectangle 40 4 "solid" "green"]]]
(define X-POS (/ SCENE-WIDTH 2))
(define UFO-PADDING
(- SCENE-HEIGHT
(/ (image-height UFO) 2)
(image-height FLAT-ROCKBED)))
; functions
[define [ufo-landing height]
[cond
[[<= height UFO-PADDING]
(place-image UFO X-POS height MTSCN)]
[[> height UFO-PADDING]
(place-image UFO X-POS UFO-PADDING MTSCN)]]]
It is from the first chapter of the How to Design Programs, 2nd Edition.
When I call the (animate ufo-landing) function in the interactions area this is the output I get
The UFO does not touch the flatbed rock.
How do I make it do that?
Edit 1:
The ordinate for placing UFO on the scene is dependent on two factors.
The height of the FLATBED-ROCK over which it has to land so that the UFO just touches its surface.
The center of UFO; its placement takes up 10 px above and below its center coordinate since its height is 20 px.
The UFO-PADDING constant accounts for the two factors I described above and is used to place the UFO on the scene. Thus, I expect the UFO to stop when it barely touches the surface of the FLATBED-ROCK. But it does not! Is there any other factor that affects the ordinate of the UFO? What am I missing?
I believe the issue is because when you do:
(define UFO-PADDING
(- SCENE-HEIGHT
(/ (image-height UFO) 2)
(image-height FLAT-ROCKBED)))
What you're doing is saying the padding of the center of the UFO is the HEIGHT - (image-height UFO / 2) - the image-height FLAT-ROCKBED. I believe that you should also do:
(/ (image-height FLAT-ROCKBED) 2)
Otherwise you'd be subtracting too much.
The construct animate calls ufo-landing with numbers 0, 1, 2, ...
You can try this expression in the interaction window (the repl) to
see the end image.
(ufo-landing 1000)
With a height of say 1000, ufo-landing uses this clause:
[[> height UFO-PADDING]
(place-image UFO X-POS UFO-PADDING MTSCN)]]]
The y-coordinate is UFO-PADDING .
To move the end position of the ufo adjust UFO-PADDING.
(define UFO-PADDING
(+ ?
(- SCENE-HEIGHT
(/ (image-height UFO) 2)
(image-height FLAT-ROCKBED))))
Try different numbers at the spot marked with the question mark.

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