-
Notifications
You must be signed in to change notification settings - Fork 60
/
Copy pathinfo1_lab09.Rmd
108 lines (91 loc) · 4.61 KB
/
info1_lab09.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
---
number: 9
course: Informatyka I
material: Instrukcja 9
author: B. Górecki
---
# Oblężenie zamku
Poznaliśmy już wszystkie instrukcje zaplanowane na ten kurs języka C.
Wykorzystamy je dziś do zilustrowania oblężenia zamku.
Twoim zadaniem będzie napisanie programu, który będzie symulował ostrzał zamku przez armaty (kule poruszają się wg. wzorów na rzut ukośny).
Program powinien:
- Otwierać okno graficzne o wymiarach $800 \times 600$.
- W pętli głównej:
- wczytywać z klawiatury wartość prędkości wylotowej kuli $V_0$, kąta odchylenia lufy od poziomu $\alpha$ oraz położenia armaty na osi $x$ (wylot armaty zawsze ma się znajdować $50$ pikseli powyżej poziomu ziemi).
- ustawiać i rysować schematycznie armatę jako linię (należy sprawdzać czy w danym miejscu da się postawić armatę -- mur zamku znajduje się w obszarze $x \geq 550$ (dla uproszczenia radzimy rysować armatę, jako linię o górnym wierzchołku w punkcie $(x, 50)$ i dolnym wierzchołku zależnym od kąta wychylenia).
- w wewnętrznej pętli służącej do animacji strzału:
- rysować zamek, który będzie ostrzeliwany (kod funkcji rysującej zamek możesz znaleźć na końcu instrukcji).
- wykonywać strzał kulą i rysować jej tor za pomocą gęsto rozłożonych okręgów o małym promieniu (użyj funkcji `animate()` w celu uzyskania efektu płynnego ruchu kuli -- przykład użycia funkcji `animate()` znajdziesz na końcu instrukcji).
Tor rzutu ukośnego zadany jest wzorami:
$$
x(t) = x_0 + V_0 \cos(\alpha)t
$$
$$
y(t) = y_0 + V_0 \sin(\alpha)t - \frac{gt^2}{2}.
$$
Program powinien sprawdzać w wewnętrznej pętli czy kula nie uderzyła w pierwszą, pionową ścianę zamku.
Jeśli tak, kula ma się na niej zatrzymać, a pętla ulec przerwaniu.
W przeciwnym razie, program ma tak długo rysować ruch kuli, aż ta znajdzie się poniżej poziomu ziemi.
Ściana zamku zawiera się w przedziale $550 \leq x \leq 600$ a jej górna powierzchnia ma współrzędną $y = 300$.
Pamiętaj o przeliczeniu współrzędnych fizycznych (pionowej) na współrzędną w układzie współrzędnych ekranu oraz przeliczeniu kąta podawanego w stopniach na kąt podany w radianach na potrzeby funkcji trygonometrycznych.
- zapytać, po wykonanym strzale, czy udało się trafić w zamek.
Jeśli odpowiesz twierdząco, program powinien wyjść z pętli głównej i zakończyć działanie.
Jeśli przecząco, program powinien pozwolić wybrać nowe parametry i ponowny strzał.
## Oczekiwany wynik
Spodziewamy się, że wynikiem działania Twojego programu będzie rysunek zbliżony do poniższego:
```{r, echo = FALSE}
plot(NA, NA, xlim = c(0, 400), ylim = c(0, 300), xlab = "", ylab = "",
xaxt = 'n', yaxt = 'n', asp = 1, frame.plot = FALSE)
lines(c(0, 400, 400, 0, 0), c(0, 0, 300, 300, 0))
lines(c(275, 275, 275, 300, 300, 300, 300, 330, 330, 330, 330, 320, 320, 350, 350, 380, 380, 370, 370, 370, 370, 400),
c(150, 0, 150, 150, 150, 50, 50, 50, 50, 100, 100, 100, 100, 125, 125, 100, 100, 100, 100, 50, 50, 50))
lines(c(10, 60), c(0,50))
t <- seq(0, 5.3, len = 80)
ball_x <- 60 + 40 * t
ball_y <- 50 + 40 * t - 5 * t ^2
lines(ball_x, ball_y, type = "p", pch = 1)
t <- seq(0, 5.6, len = 80)
ball_x <- 60 + 20 * t
ball_y <- 50 + 20 * t - 5 * t ^2
lines(ball_x, ball_y, type = "p", pch = 1)
t <- seq(0, 6.9, len = 80)
ball_x <- 60 + 28 * t
ball_y <- 50 + 28 * t - 5 * t ^2
lines(ball_x, ball_y, type = "p", pch = 1)
```
## Dodatki
Funkcja rysująca zamek:
```c++
void RysujZamek() {
line(550, 300, 550, 600);
line(550, 300, 600, 300);
line(600, 300, 600, 500);
line(600, 500, 660, 500);
line(660, 500, 660, 400);
line(660, 400, 640, 400);
line(640, 400, 700, 350);
line(700, 350, 760, 400);
line(760, 400, 740, 400);
line(740, 400, 740, 500);
line(740, 500, 800, 500);
}
```
Funkcja `animate()` tak naprawdę jedynie spowalnia wykonywanie pętli `while` tak, aby kółka nie rysowały się zbyt szybko.
Argument funkcji to wartość mówiąca o liczbie wykonań ciała pętli w ciągu sekundy.
Uwaga: wartość zero mówi o wykonaniu ciała pętli bez opóźnienia.
Przykład jej użycia w naszym programie wygląda następująco:
```c++
while(1) { // petla glowna
// wczytaj x0, V0 i kat alpha
while(animate(100)) { // petla animujaca lot kuli
// narysuj zamek i armate
// oblicz nowe wspolrzedne x i y
// narysuj okrag w odpowiednim miejscu
// zwieksz parametr t
// zawrzyj warunek przerwania petli animujacej,
// gdy kula uderza w sciane lub spada na ziemie
}
// zapytaj czy kula trafila w mur i jesli tak
// wyjdz z petli glownej
}
```