Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
10c4d5e0836e0b8719be6f40d56aab491eaf181c
[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 PI = 4.0 * atan(1.0);
13
14 const float rXMin = -100.0;
15 const float rXMax = 100.0;
16 const float rYMin = -10.0;
17 const float rYMax = 140.0;
18
19 const float hauteurMin = 10;
20 const float hauteurMax = 130;
21 const float largeurMin = 40;
22 const float largeurMax = 150;
23
24 const float largeurChateau = 8.5;
25 const float hauteurChateau = 7;
26
27 const float positionChateau1 = -85.0;
28 const float positionChateau2 = 85.0;
29
30 const float g = 9.81;
31 const float k = 0.005;
32 const float dt = 0.05;
33
34 float largeurMont;
35 float hauteurMont;
36 float wnd;
37
38 /* Retourne un nombre pseudo-aléatoire compris entre 0 et le paramètre
39  * 'max' (exclus)
40  */
41 float frand(float min, float max)
42 {
43     static bool first = true;
44     if (first) {
45         srand(time(NULL));
46         first = false;
47     }
48     return min + (max - min)* (rand() / (RAND_MAX + 1.0));
49 }
50
51 float deg2rad(float deg)
52 {
53     return deg * PI / 180.0;
54 }
55
56 // conversion coordonnées réelles -> coordonnées fenêtre
57 int rtowX(const DrawingWindow& w, float rx)
58 {
59     return (int )roundf(w.width * (rx - rXMin) / (rXMax - rXMin + 1.0));
60 }
61
62 int rtowY(const DrawingWindow& w, float ry)
63 {
64     return (int )roundf(w.height * (rYMax - ry) / (rYMax - rYMin + 1.0));
65 }
66
67 // conversion coordonnées réelles -> coordonnées fenêtre
68 float wtorX(const DrawingWindow& w, int wx)
69 {
70     return (rXMax - rXMin + 1.0) * wx / w.width + rXMin;
71 }
72
73 float wtorY(const DrawingWindow& w, int wy)
74 {
75     return -(rYMax - rYMin + 1.0) * wy / w.height - rYMax;
76 }
77
78 float hauteurMontagne(float largeur, float hauteur, float x)
79 {
80     float rx = 2.0 * x / largeur;
81     return hauteur * (1.0 - rx * rx);
82 }
83
84 void dessineTerrain(DrawingWindow& w, float largeur, float hauteur)
85 {
86     int y0 = rtowY(w, 0) + 1;
87     int xmin = rtowX(w, -largeur / 2.0) - 1;
88     int xmax = rtowX(w, largeur / 2.0) + 1;
89     w.setColor("forestgreen");
90     for (int x = xmin; x <= xmax; x++) {
91         float rx = wtorX(w, x);
92         float ry = hauteurMontagne(largeur, hauteur, rx);
93         int y = rtowY(w, ry);
94         if (y <= y0)
95             w.drawLine(x, y0, x, y);
96     }
97     w.setColor("maroon");
98     w.fillRect(0, y0 + 1, w.width - 1, w.height - 1);
99 }
100
101 void dessineChateau(DrawingWindow& w, float position)
102 {
103     w.setColor("black");
104     w.setColor("darkslategray");
105     int y1 = rtowY(w, 0);
106     int h0 = rtowY(w, 3);
107     int h1 = rtowY(w, 4);
108     for (int i = 0; i < 7; i++) {
109         int h = i % 2 ? h0 : h1;
110         int x1 = rtowX(w, position + i - 3.5);
111         int x2 = rtowX(w, position + i - 2.5) - 1;
112         w.fillRect(x1, y1, x2, h);
113     }
114     w.setColor("dimgray");
115     h0 = rtowY(w, 6);
116     h1 = rtowY(w, 7);
117     for (int i = 0; i < 5; i++) {
118         int h = i % 2 ? h0 : h1;
119         int x1 = rtowX(w, position + i - 8.5);
120         int x2 = rtowX(w, position + i - 7.5) - 1;
121         w.fillRect(x1, y1, x2, h);
122         x1 = rtowX(w, position + i + 3.5);
123         x2 = rtowX(w, position + i + 4.5) - 1;
124         w.fillRect(x1, y1, x2, h);
125     }
126 }
127
128 void dessineVent(DrawingWindow &w, float vitesse)
129 {
130     int lg = rtowX(w, vitesse) - rtowX(w, 0);
131     int dir = lg > 0 ? 1 : -1;
132     int y = 20;
133     w.setColor("black");
134     if (lg == 0) {
135         w.drawCircle(w.width / 2, y, 4);
136     } else {
137         int x1 = (w.width - lg) / 2;
138         int x2 = (w.width + lg) / 2;
139         w.drawLine(x1 - dir, y - 1, x2 - dir, y - 1);
140         w.drawLine(x1, y, x2, y);
141         w.drawLine(x1 - dir, y + 1, x2 - dir, y + 1);
142         for (int i = 0; i < 3; i++) {
143             w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y - 4);
144             w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y + 4);
145         }
146     }
147 }
148
149 void dessineExplosion(DrawingWindow& w, float rx, float ry)
150 {
151     const int maxray = rtowX(w, 2.5) - rtowX(w, 0);
152     // 1/2 rouge -> rouge -> jaune
153     const int x = rtowX(w, rx);
154     const int y = rtowY(w, ry);
155     int i;
156     for (i = 0; i <= maxray / 3; i++) {
157         w.setColor(0.5 + 3.0 * i / (2.0 * maxray), 0.0, 0.0);
158         w.drawCircle(x, y, i);
159         w.msleep(20);
160     }
161     for (/* i */; i < maxray; i++) {
162         w.setColor(1.0, 1.5 * i / maxray - 0.5, 0.0);
163         w.drawCircle(x, y, i);
164         w.msleep(20);
165     }
166     w.setColor("white");
167     for (i = 0; i < maxray; i++) {
168         w.drawCircle(x, y, i);
169         w.msleep(10);
170     }
171     w.fillCircle(x, y, maxray - 1);
172 }
173
174 void dessineFlammes(DrawingWindow& w, float x0, float y0)
175 {
176     for (int i = 0; i < 70; i++) {
177         float dt = 0.05;
178         float vx = frand(-2.5, 2.5);
179         float vy = frand(5, 17);
180         float x = x0;
181         float y = y0;
182         float red = frand(0.5, 1);
183         float green = frand(0, red);
184         float blue = 0;
185         w.setColor(red, green, blue);
186         while (y >= 0.0) {
187             w.drawPoint(rtowX(w, x), rtowY(w, y));
188             x += vx * dt;
189             y += vy * dt;
190             vy -= 9.81 * dt;
191         }
192         w.msleep(30);
193     }
194 }
195
196 void initialise(DrawingWindow& w)
197 {
198     largeurMont = frand(largeurMin, largeurMax);
199     hauteurMont = frand(hauteurMin, hauteurMax);
200     wnd = frand(-30, 30);
201     w.clearGraph();
202     dessineTerrain(w, largeurMont, hauteurMont);
203     dessineChateau(w, positionChateau1);
204     dessineChateau(w, positionChateau2);
205     dessineVent(w, wnd);
206 }
207
208 /* Retour : numéro du perdant, 0 sinon
209    x et y contiennent les coordonnées de la collision
210 */
211 int tir(DrawingWindow& w,
212         float x0, float y0, float v0, float alpha, float& x, float &y)
213 {
214     float vx = v0 * cos(alpha);
215     float vy = v0 * sin(alpha);
216     x = x0;
217     y = y0;
218     int collision = 0;
219     do {
220         int wx = rtowX(w, x);
221         int wy = rtowY(w, y);
222         w.setColor("black");
223         w.fillCircle(wx, wy, 2);
224
225         float vxr = vx - wnd;
226         float kvr = -k * sqrt(vxr * vxr + vy * vy);
227         float ax = kvr * vxr;
228         float ay = kvr * vy - g;
229         x += vx * dt;
230         y += vy * dt;
231         vx += ax * dt;
232         vy += ay * dt;
233
234         w.msleep(10);
235         w.setColor("white");
236         w.fillCircle(wx, wy, 2);
237 //         w.setColor("black");
238 //         w.drawPoint(wx, wy);
239
240         if (y <= 0) {
241             collision = 3;
242         } else if (y < hauteurChateau) {
243             if (positionChateau1 - largeurChateau <= x
244                 && positionChateau1 + largeurChateau >= x)
245                 collision = 1;
246             else if (positionChateau2 - largeurChateau <= x
247                        && positionChateau2 + largeurChateau >= x)
248                 collision = 2;
249         }
250         if (!collision) {
251             float h = hauteurMontagne(largeurMont, hauteurMont, x);
252             if (h > 0 && y < h)
253                 collision = 3;
254         }
255     } while (!collision);
256     return collision == 3 ? 0 : collision;
257 }
258
259 void jeu1(DrawingWindow& w)
260 {
261     initialise(w);
262     int joueur = 2;
263     float x, y;
264     int perdant;
265     do {
266         float x0;
267         float y0 = 8;
268         float v0 = frand(10, 100);
269         float alpha = deg2rad(frand(10, 90));
270
271         joueur = 3 - joueur;
272         if (joueur == 1) {
273             x0 = positionChateau1 + 8;
274         } else {
275             x0 = positionChateau2 - 8;
276             alpha = PI - alpha;
277         }
278         perdant = tir(w, x0, y0, v0, alpha, x, y);
279         dessineExplosion(w, x, y);
280         dessineVent(w, wnd);
281     } while (!perdant);
282     dessineFlammes(w, x, y);
283     std::cout << "Joueur " << perdant;
284     if (perdant == joueur)
285         std::cout << " s'est suicidé";
286     else
287         std::cout << " a perdu";
288     std::cout << " !\n";
289 }
290
291 void jeu(DrawingWindow& w)
292 {
293     while (1) {
294         jeu1(w);
295         w.sleep(5);
296     }
297 }
298
299 int main(int argc, char *argv[])
300 {
301     QApplication application(argc, argv);
302     DrawingWindow window(jeu, 640, 480);
303     window.show();
304     return application.exec();
305 }