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