Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
.
[graphlib.git] / chateaux / chateaux.cpp
1 #include <QApplication>
2 #include <DrawingWindow.h>
3 #include <cmath>
4 #include <iostream>
5 #include <ctime>
6 #include <cstdlib>
7
8 /* Note : les coordonnées réelles vont de -100 à +100 en abscisse, et
9  *  de -10 à +140 en ordonnée
10  */
11
12 const float rXMin = -100.0;
13 const float rXMax = 100.0;
14 const float rYMin = -10.0;
15 const float rYMax = 140.0;
16
17 const float hauteurMin = 10;
18 const float hauteurMax = 130;
19 const float largeurMin = 40;
20 const float largeurMax = 150;
21
22 const float largeurChateau = 8.5;
23 const float hauteurChateau = 7;
24
25 const float positionChateau1 = -85.0;
26 const float positionChateau2 = 85.0;
27
28 /* Retourne un nombre pseudo-aléatoire compris entre 0 et le paramètre
29  * 'max' (exclus)
30  */
31 float frand(float min, float max)
32 {
33     static bool first = true;
34     if (first) {
35         srand(time(NULL));
36         first = false;
37     }
38     return min + (max - min)* (rand() / (RAND_MAX + 1.0));
39 }
40
41 float deg2rad(float deg)
42 {
43     const float PI = 4.0 * atan(1.0);
44     return deg * PI / 180.0;
45 }
46
47 // conversion coordonnées réelles -> coordonnées fenêtre
48 int rtowX(const DrawingWindow& w, float rx)
49 {
50     return (int )roundf(w.width * (rx - rXMin) / (rXMax - rXMin + 1.0));
51 }
52
53 int rtowY(const DrawingWindow& w, float ry)
54 {
55     return (int )roundf(w.height * (rYMax - ry) / (rYMax - rYMin + 1.0));
56 }
57
58 // conversion coordonnées réelles -> coordonnées fenêtre
59 float wtorX(const DrawingWindow& w, int wx)
60 {
61     return (rXMax - rXMin + 1.0) * wx / w.width + rXMin;
62 }
63
64 float wtorY(const DrawingWindow& w, int wy)
65 {
66     return -(rYMax - rYMin + 1.0) * wy / w.height - rYMax;
67 }
68
69 float hauteurMontagne(float largeur, float hauteur, float x)
70 {
71     float rx = 2.0 * x / largeur;
72     return hauteur * (1.0 - rx * rx);
73 }
74
75 void dessineTerrain(DrawingWindow& w, float largeur, float hauteur)
76 {
77     int y0 = rtowY(w, 0) + 1;
78     int xmin = rtowX(w, -largeur / 2.0) - 1;
79     int xmax = rtowX(w, largeur / 2.0) + 1;
80     w.setColor("forestgreen");
81     for (int x = xmin; x <= xmax; x++) {
82         float rx = wtorX(w, x);
83         float ry = hauteurMontagne(largeur, hauteur, rx);
84         int y = rtowY(w, ry);
85         if (y <= y0)
86             w.drawLine(x, y0, x, y);
87     }
88     w.setColor("maroon");
89     w.fillRect(0, y0 + 1, w.width - 1, w.height - 1);
90 }
91
92 void dessineChateau(DrawingWindow& w, float position)
93 {
94     w.setColor("black");
95     w.setColor("darkslategray");
96     int y1 = rtowY(w, 0);
97     int h0 = rtowY(w, 3);
98     int h1 = rtowY(w, 4);
99     for (int i = 0; i < 7; i++) {
100         int h = i % 2 ? h0 : h1;
101         int x1 = rtowX(w, position + i - 3.5);
102         int x2 = rtowX(w, position + i - 2.5) - 1;
103         w.fillRect(x1, y1, x2, h);
104     }
105     w.setColor("dimgray");
106     h0 = rtowY(w, 6);
107     h1 = rtowY(w, 7);
108     for (int i = 0; i < 5; i++) {
109         int h = i % 2 ? h0 : h1;
110         int x1 = rtowX(w, position + i - 8.5);
111         int x2 = rtowX(w, position + i - 7.5) - 1;        
112         w.fillRect(x1, y1, x2, h);
113         x1 = rtowX(w, position + i + 3.5);
114         x2 = rtowX(w, position + i + 4.5) - 1;        
115         w.fillRect(x1, y1, x2, h);
116     }
117 }
118
119 void dessineVent(DrawingWindow &w, float vitesse)
120 {
121     int lg = rtowX(w, vitesse) - rtowX(w, 0);
122     int dir = lg > 0 ? 1 : -1;
123     int y = 20;
124     w.setColor("black");
125     if (lg == 0) {
126         w.drawCircle(w.width / 2, y, 4);
127     } else {
128         int x1 = (w.width - lg) / 2;
129         int x2 = (w.width + lg) / 2;
130         w.drawLine(x1 - dir, y - 1, x2 - dir, y - 1);
131         w.drawLine(x1, y, x2, y);
132         w.drawLine(x1 - dir, y + 1, x2 - dir, y + 1);        
133         for (int i = 0; i < 3; i++) {
134             w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y - 4);
135             w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y + 4);
136         }
137     }
138 }
139
140 void dessineExplosion(DrawingWindow& w, float rx, float ry)
141 {
142     const int maxray = rtowX(w, 3) - rtowX(w, 0);
143     // 1/2 rouge -> rouge -> jaune
144     const int x = rtowX(w, rx);
145     const int y = rtowY(w, ry);
146     int i;
147     for (i = 0; i <= maxray / 3; i++) {
148         w.setColor(0.5 + 3.0 * i / (2.0 * maxray), 0.0, 0.0);
149         w.drawCircle(x, y, i);
150         w.msleep(20);
151     }
152     for (/* i */; i < maxray; i++) {
153         w.setColor(1.0, 1.5 * i / maxray - 0.5, 0.0);
154         w.drawCircle(x, y, i);
155         w.msleep(20);
156     }
157     w.setColor("white");
158     for (i = 0; i < maxray; i++) {
159         w.drawCircle(x, y, i);
160         w.msleep(10);
161     }
162     w.fillCircle(x, y, maxray - 1);
163 }
164
165 void jeu(DrawingWindow& w)
166 {
167     const float largeurMont = frand(largeurMin, largeurMax);
168     const float hauteurMont = frand(hauteurMin, hauteurMax);
169
170     dessineTerrain(w, largeurMont, hauteurMont);
171     dessineChateau(w, positionChateau1);
172     dessineChateau(w, positionChateau2);
173
174     const float g = 9.81;
175     const float k = 0.005;
176     const float dt = 0.1;        
177     const float wnd = frand(-30, 30);
178     const float x0 = positionChateau1 + 8;
179     const float y0 = 8;
180
181     dessineVent(w, wnd);
182
183     while (1) {
184         const float v0 = frand(10, 100);
185         const float alpha = deg2rad(frand(10, 90));
186
187         float x = x0;
188         float y = y0;
189         float vx = v0 * cos(alpha);
190         float vy = v0 * sin(alpha);
191         w.setColor("black");
192         bool collision = false;
193         do {
194             int wx = rtowX(w, x);
195             int wy = rtowY(w, y);
196             w.fillCircle(wx, wy, 2);
197
198             float vxr = vx - wnd;
199             float kvr = -k * sqrt(vxr * vxr + vy * vy);
200             float ax = kvr * vxr;
201             float ay = kvr * vy - g;
202             x += vx * dt;
203             y += vy * dt;
204             vx += ax * dt;
205             vy += ay * dt;
206
207             w.msleep(10);
208             w.setColor("white");
209             w.fillCircle(wx, wy, 2);
210             w.setColor("black");
211             w.drawPoint(wx, wy);
212
213             if ((y <= 0) ||
214                 (y < hauteurChateau
215                  && ((positionChateau1 - largeurChateau <= x
216                       && positionChateau1 + largeurChateau >= x) ||
217                      (positionChateau2 - largeurChateau <= x
218                       && positionChateau2 + largeurChateau >= x)))) {
219                 collision = true;
220             } else {
221                 float h = hauteurMontagne(largeurMont, hauteurMont, x);
222                 if (h > 0 && y < h)
223                     collision = true;
224             }
225         } while (!collision);
226         dessineExplosion(w, x, y);
227     }
228 }
229
230 int main(int argc, char *argv[])
231 {
232     QApplication application(argc, argv);
233     DrawingWindow window(jeu, 640, 480);
234     window.show();
235     return application.exec();
236 }
237