1 #include <QApplication>
2 #include <DrawingWindow.h>
9 /* Note : les coordonnées réelles vont de -100 à +100 en abscisse, et
10 * de -10 à +140 en ordonnée
13 const float PI = 4.0 * atan(1.0);
15 const float rXMin = -100.0;
16 const float rXMax = 100.0;
17 const float rYMin = -10.0;
18 const float rYMax = 140.0;
20 const float hauteurMin = 10;
21 const float hauteurMax = 130;
22 const float largeurMin = 40;
23 const float largeurMax = 150;
25 const float ventMax = 30;
27 const float largeurChateau = 8.5;
28 const float hauteurChateau = 7;
30 const float positionChateau1 = -85.0;
31 const float positionChateau2 = 85.0;
34 const float k = 0.005;
35 const float dt = 0.05;
45 /* Retourne un nombre pseudo-aléatoire compris entre le paramètre
46 * 'min' (inclus) et le paramètre 'max' (exclus)
48 float frand(float min, float max)
50 static bool first = true;
55 return min + (max - min)* (rand() / (RAND_MAX + 1.0));
58 float deg2rad(float deg)
60 return deg * PI / 180.0;
63 // conversion coordonnées réelles -> coordonnées fenêtre
64 int rtowX(const DrawingWindow& w, float rx)
66 return (int )roundf((w.width - 1) * (rx - rXMin) / (rXMax - rXMin));
69 int rtowY(const DrawingWindow& w, float ry)
71 return (int )roundf((w.height - 1) * (rYMax - ry) / (rYMax - rYMin));
74 // conversion coordonnées fenêtre -> coordonnées réelles
75 float wtorX(const DrawingWindow& w, int wx)
77 return (rXMax - rXMin) * wx / (w.width - 1) + rXMin;
80 float wtorY(const DrawingWindow& w, int wy)
82 return -(rYMax - rYMin) * wy / (w.height - 1) + rYMax;
85 float hauteurMontagne(float largeur, float hauteur, float x)
87 float rx = 2.0 * x / largeur;
88 return hauteur * (1.0 - rx * rx);
91 void dessineTerrain(DrawingWindow& w, float largeur, float hauteur)
93 int y0 = rtowY(w, 0) + 1;
94 int xmin = rtowX(w, -largeur / 2.0) - 1;
95 int xmax = rtowX(w, largeur / 2.0) + 1;
96 w.setColor("forestgreen");
97 for (int x = xmin; x <= xmax; x++) {
98 float rx = wtorX(w, x);
99 float ry = hauteurMontagne(largeur, hauteur, rx);
100 int y = rtowY(w, ry);
102 w.drawLine(x, y0, x, y);
104 w.setColor("maroon");
105 w.fillRect(0, y0 + 1, w.width - 1, w.height - 1);
108 void dessineChateau(DrawingWindow& w, float position)
111 w.setColor("darkslategray");
112 int y1 = rtowY(w, 0);
113 int h0 = rtowY(w, 3);
114 int h1 = rtowY(w, 4);
115 for (int i = 0; i < 7; i++) {
116 int h = i % 2 ? h0 : h1;
117 int x1 = rtowX(w, position + i - 3.5);
118 int x2 = rtowX(w, position + i - 2.5) - 1;
119 w.fillRect(x1, y1, x2, h);
121 w.setColor("dimgray");
124 for (int i = 0; i < 5; i++) {
125 int h = i % 2 ? h0 : h1;
126 int x1 = rtowX(w, position + i - 8.5);
127 int x2 = rtowX(w, position + i - 7.5) - 1;
128 w.fillRect(x1, y1, x2, h);
129 x1 = rtowX(w, position + i + 3.5);
130 x2 = rtowX(w, position + i + 4.5) - 1;
131 w.fillRect(x1, y1, x2, h);
135 void dessineVent(DrawingWindow &w, float vitesse)
137 int lg = rtowX(w, vitesse) - rtowX(w, 0);
138 int dir = lg > 0 ? 1 : -1;
142 w.drawCircle(w.width / 2, y, 4);
144 int x1 = (w.width - lg) / 2;
145 int x2 = (w.width + lg) / 2;
146 w.drawLine(x1 - dir, y - 1, x2 - dir, y - 1);
147 w.drawLine(x1, y, x2, y);
148 w.drawLine(x1 - dir, y + 1, x2 - dir, y + 1);
149 for (int i = 0; i < 3; i++) {
150 w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y - 4);
151 w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y + 4);
156 void dessineExplosion(DrawingWindow& w, float rx, float ry)
158 const int maxray = rtowX(w, 2.5) - rtowX(w, 0);
159 // 1/2 rouge -> rouge -> jaune
160 const int x = rtowX(w, rx);
161 const int y = rtowY(w, ry);
163 for (i = 0; i <= maxray / 3; i++) {
164 w.setColor(0.5 + 3.0 * i / (2.0 * maxray), 0.0, 0.0);
165 w.drawCircle(x, y, i);
168 for (/* i */; i < maxray; i++) {
169 w.setColor(1.0, 1.5 * i / maxray - 0.5, 0.0);
170 w.drawCircle(x, y, i);
173 w.setColor("skyblue");
174 for (i = 0; i < maxray; i++) {
175 w.drawCircle(x, y, i);
178 // w.fillCircle(x, y, maxray - 1);
181 void dessineFlammes(DrawingWindow& w, float x0, float y0)
183 for (int i = 0; i < 70; i++) {
185 float vx = frand(-2.5, 2.5);
186 float vy = frand(5, 17);
189 float red = frand(0.5, 1);
190 float green = frand(0, red);
192 w.setColor(red, green, blue);
194 w.drawPoint(rtowX(w, x), rtowY(w, y));
203 void initialise(DrawingWindow& w)
205 largeurMont = frand(largeurMin, largeurMax);
206 hauteurMont = frand(hauteurMin, hauteurMax);
207 wnd = frand(-ventMax, ventMax);
208 w.setBgColor("skyblue");
210 dessineTerrain(w, largeurMont, hauteurMont);
212 dessineChateau(w, positionChateau1);
213 dessineChateau(w, positionChateau2);
215 w.drawText(rtowX(w, positionChateau1), rtowY(w, 0) + 8, "Joueur 1",
217 w.drawText(rtowX(w, positionChateau2), rtowY(w, 0) + 8, "Joueur 2",
220 s << score1 << " / " << score2;
221 w.drawText(rtowX(w, 0), rtowY(w, 0) + 8, s.str(),
225 /* Retour : numéro du perdant, 0 sinon
226 x et y contiennent les coordonnées de la collision
228 int tir(DrawingWindow& w,
229 float x0, float y0, float v0, float alpha, float& x, float &y)
231 float vx = v0 * cos(alpha);
232 float vy = v0 * sin(alpha);
237 int wx = rtowX(w, x);
238 int wy = rtowY(w, y);
240 w.fillCircle(wx, wy, 2);
242 float vxr = vx - wnd;
243 float kvr = -k * sqrt(vxr * vxr + vy * vy);
244 float ax = kvr * vxr;
245 float ay = kvr * vy - g;
253 w.setColor("skyblue");
254 w.fillCircle(wx, wy, 2);
255 // w.setColor("black");
256 // w.drawPoint(wx, wy);
260 } else if (y < hauteurChateau) {
261 if (positionChateau1 - largeurChateau <= x
262 && positionChateau1 + largeurChateau >= x)
264 else if (positionChateau2 - largeurChateau <= x
265 && positionChateau2 + largeurChateau >= x)
269 float h = hauteurMontagne(largeurMont, hauteurMont, x);
273 } while (!collision);
274 return collision == 3 ? 0 : collision;
277 int jeu1(DrawingWindow& w)
287 std::cout << "-=| Joueur " << joueur << " |=-";
291 if (joueur <= nbJoueurs) {
292 std::cout << "\nangle ? ";
294 std::cout << "vitesse initiale ? ";
297 alpha = frand(10, 90);
299 std::cout << " [ " << (int )alpha << "° ; " << (int )v0 << " ]"
303 alpha = deg2rad(alpha);
306 x0 = positionChateau1 + 0.8 * largeurChateau;
308 x0 = positionChateau2 - 0.8 * largeurChateau;
311 float y0 = hauteurChateau + 1;
312 perdant = tir(w, x0, y0, v0, alpha, x, y);
313 dessineExplosion(w, x, y);
316 dessineFlammes(w, x, y);
317 std::stringstream msg;
318 msg << " Joueur " << perdant;
319 if (perdant == joueur)
320 msg << " s'est suicidé ! ";
322 msg << " a perdu ! ";
323 w.setColor("darkred");
324 w.setBgColor("white");
325 w.drawTextBg(w.width / 2, w.height / 3, msg.str(),
328 std::cout << msg.str() << std::endl;
332 void jeu(DrawingWindow& w)
336 int perdant = jeu1(w);
339 else if (perdant == 2)
341 std::cout << "### SCORE : " << score1 << " / " << score2 << " ###"
348 std::cout << "Recommencer (o/n) ? ";
350 } while (std::cin.good() && r != 'o' && r != 'n');
357 int main(int argc, char *argv[])
359 QApplication application(argc, argv);
362 nbJoueurs = atoi(argv[1]);
364 DrawingWindow window(jeu, 640, 480);
366 return application.exec();