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 /* Retourne un nombre pseudo-aléatoire compris entre 0 et le paramètre
15  * 'max' (exclus)
16  */
17 float frand(float min, float max)
18 {
19     static bool first = true;
20     if (first) {
21         srand(time(NULL));
22         first = false;
23     }
24     return min + (max - min)* (rand() / (RAND_MAX + 1.0));
25 }
26
27 float deg2rad(float deg)
28 {
29     return deg * PI / 180.0;
30 }
31
32 const float rXMin = -100.0;
33 const float rXMax = 100.0;
34 const float rYMin = -10.0;
35 const float rYMax = 140.0;
36
37 const float hauteurMin = 10;
38 const float hauteurMax = 130;
39 const float largeurMin = 40;
40 const float largeurMax = 150;
41
42 const float largeurMont = frand(largeurMin, largeurMax);
43 const float hauteurMont = frand(hauteurMin, hauteurMax);
44
45 const float largeurChateau = 8.5;
46 const float hauteurChateau = 7;
47
48 const float positionChateau1 = -85.0;
49 const float positionChateau2 = 85.0;
50
51 const float g = 9.81;
52 const float k = 0.005;
53 const float dt = 0.05;
54 const float wnd = frand(-30, 30);
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 /* Retour : numéro du perdant, 0 sinon
197    x et y contiennent les coordonnées de la collision
198 */
199 int tir(DrawingWindow& w,
200         float x0, float y0, float v0, float alpha, float& x, float &y)
201 {
202     float vx = v0 * cos(alpha);
203     float vy = v0 * sin(alpha);
204     x = x0;
205     y = y0;
206     int collision = 0;
207     do {
208         int wx = rtowX(w, x);
209         int wy = rtowY(w, y);
210         w.setColor("black");
211         w.fillCircle(wx, wy, 2);
212
213         float vxr = vx - wnd;
214         float kvr = -k * sqrt(vxr * vxr + vy * vy);
215         float ax = kvr * vxr;
216         float ay = kvr * vy - g;
217         x += vx * dt;
218         y += vy * dt;
219         vx += ax * dt;
220         vy += ay * dt;
221
222         w.msleep(10);
223         w.setColor("white");
224         w.fillCircle(wx, wy, 2);
225 //         w.setColor("black");
226 //         w.drawPoint(wx, wy);
227
228         if (y <= 0) {
229             collision = 3;
230         } else if (y < hauteurChateau) {
231             if (positionChateau1 - largeurChateau <= x
232                 && positionChateau1 + largeurChateau >= x)
233                 collision = 1;
234             else if (positionChateau2 - largeurChateau <= x
235                        && positionChateau2 + largeurChateau >= x)
236                 collision = 2;
237         }
238         if (!collision) {
239             float h = hauteurMontagne(largeurMont, hauteurMont, x);
240             if (h > 0 && y < h)
241                 collision = 3;
242         }
243     } while (!collision);
244     return collision == 3 ? 0 : collision;
245 }
246
247 void jeu(DrawingWindow& w)
248 {
249     dessineTerrain(w, largeurMont, hauteurMont);
250     dessineChateau(w, positionChateau1);
251     dessineChateau(w, positionChateau2);
252     dessineVent(w, wnd);
253
254     int joueur = 2;
255     float x, y;
256     int perdant;
257     do {
258         float x0;
259         float y0 = 8;
260         float v0 = frand(10, 100);
261         float alpha = deg2rad(frand(10, 90));
262
263         joueur = 3 - joueur;
264         if (joueur == 1) {
265             x0 = positionChateau1 + 8;
266         } else {
267             x0 = positionChateau2 - 8;
268             alpha = PI - alpha;
269         }
270         perdant = tir(w, x0, y0, v0, alpha, x, y);
271         dessineExplosion(w, x, y);
272     } while (!perdant);
273     dessineFlammes(w, x, y);
274     std::cout << "Joueur " << perdant;
275     if (perdant == joueur)
276         std::cout << " s'est suicidé";
277     else
278         std::cout << " a perdu";
279     std::cout << " !\n";
280 }
281
282 int main(int argc, char *argv[])
283 {
284     QApplication application(argc, argv);
285     DrawingWindow window(jeu, 640, 480);
286     window.show();
287     return application.exec();
288 }