Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add more examples (Chateaux).
[graphlib_java.git] / MoreEx / Chateaux.java
1 import java.util.*;
2
3 class Chateaux {
4
5     static final Scanner input = new Scanner(System.in);
6     static final Random random = new Random();
7
8     /* Note : les coordonnées réelles vont de -100 à +100 en abscisse, et
9      *  de -10 à +140 en ordonnée
10      */
11     static final double rXMin = -100.0;
12     static final double rXMax = 100.0;
13     static final double rYMin = -10.0;
14     static final double rYMax = 140.0;
15     static final double hauteurMin = 10;
16     static final double hauteurMax = 130;
17     static final double largeurMin = 40;
18     static final double largeurMax = 150;
19     static final double ventMax = 30;
20     static final double largeurChateau = 8.5;
21     static final double hauteurChateau = 7;
22     static final double positionChateau1 = -85.0;
23     static final double positionChateau2 = 85.0;
24     static final double g = 9.81;
25     static final double k = 0.005;
26     static final double dt = 0.05;
27     static int nbJoueurs = 2;
28     static int score1 = 0;
29     static int score2 = 0;
30     static double largeurMont;
31     static double hauteurMont;
32     static double wnd;
33
34     /* Retourne un nombre pseudo-aléatoire compris entre le paramètre
35      * 'min' (inclus) et le paramètre 'max' (exclus)
36      */
37     static double frand(double min, double max)
38     {
39         return min + (max - min)* (random.nextDouble());
40     }
41
42     // conversion coordonnées réelles -> coordonnées fenêtre
43     static int rtowX(DrawingWindow w, double rx)
44     {
45         return (int)Math.round((w.width - 1) * (rx - rXMin) / (rXMax - rXMin));
46     }
47
48     static int rtowY(DrawingWindow w, double ry)
49     {
50         return (int )Math.round((w.height - 1) * (rYMax - ry) / (rYMax - rYMin));
51     }
52
53     // conversion coordonnées fenêtre -> coordonnées réelles
54     static double wtorX(DrawingWindow w, int wx)
55     {
56         return (rXMax - rXMin) * wx / (w.width - 1) + rXMin;
57     }
58
59     static double wtorY(DrawingWindow w, int wy)
60     {
61         return -(rYMax - rYMin) * wy / (w.height - 1) + rYMax;
62     }
63
64     static double hauteurMontagne(double largeur, double hauteur, double x)
65     {
66         double rx = 2.0 * x / largeur;
67         return hauteur * (1.0 - rx * rx);
68     }
69
70     static void dessineTerrain(DrawingWindow w, double largeur, double hauteur)
71     {
72         int y0 = rtowY(w, 0) + 1;
73         int xmin = rtowX(w, -largeur / 2.0) - 1;
74         int xmax = rtowX(w, largeur / 2.0) + 1;
75         w.setColor("forestgreen");
76         for (int x = xmin; x <= xmax; x++) {
77             double rx = wtorX(w, x);
78             double ry = hauteurMontagne(largeur, hauteur, rx);
79             int y = rtowY(w, ry);
80             if (y <= y0)
81                 w.drawLine(x, y0, x, y);
82         }
83         w.setColor("maroon");
84         w.fillRect(0, y0 + 1, w.width - 1, w.height - 1);
85     }
86
87     static void dessineChateau(DrawingWindow w, double position)
88     {
89         w.setColor("black");
90         w.setColor("darkslategray");
91         int y1 = rtowY(w, 0) + 1;
92         int h0 = rtowY(w, 3);
93         int h1 = rtowY(w, 4);
94         for (int i = 0; i < 7; i++) {
95             int h = i % 2 != 0 ? h0 : h1;
96             int x1 = rtowX(w, position + i - 3.5);
97             int x2 = rtowX(w, position + i - 2.5) - 1;
98             w.fillRect(x1, y1, x2, h);
99         }
100         w.setColor("dimgray");
101         h0 = rtowY(w, 6);
102         h1 = rtowY(w, 7);
103         for (int i = 0; i < 5; i++) {
104             int h = i % 2 != 0 ? h0 : h1;
105             int x1 = rtowX(w, position + i - 8.5);
106             int x2 = rtowX(w, position + i - 7.5) - 1;
107             w.fillRect(x1, y1, x2, h);
108             x1 = rtowX(w, position + i + 3.5);
109             x2 = rtowX(w, position + i + 4.5) - 1;
110             w.fillRect(x1, y1, x2, h);
111         }
112     }
113
114     static void dessineVent(DrawingWindow w, double vitesse)
115     {
116         int lg = rtowX(w, vitesse) - rtowX(w, 0);
117         int dir = lg > 0 ? 1 : -1;
118         int y = 20;
119         w.setColor("black");
120         if (lg == 0) {
121             w.drawCircle(w.width / 2, y, 4);
122         } else {
123             int x1 = (w.width - lg) / 2;
124             int x2 = (w.width + lg) / 2;
125             w.drawLine(x1 - dir, y - 1, x2 - dir, y - 1);
126             w.drawLine(x1, y, x2, y);
127             w.drawLine(x1 - dir, y + 1, x2 - dir, y + 1);
128             for (int i = 0; i < 3; i++) {
129                 w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y - 4);
130                 w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y + 4);
131             }
132         }
133     }
134
135     static void dessineExplosion(DrawingWindow w, double rx, double ry)
136     {
137         final int maxray = rtowX(w, 2.5) - rtowX(w, 0);
138         // 1/2 rouge -> rouge -> jaune
139         final int x = rtowX(w, rx);
140         final int y = rtowY(w, ry);
141         int i;
142         for (i = 0; i <= maxray / 3; i++) {
143             w.setColor(0.5f + 3.0f * i / (2.0f * maxray), 0.0f, 0.0f);
144             w.drawCircle(x, y, i);
145             w.msleep(20);
146         }
147         for (/* i */; i < maxray; i++) {
148             w.setColor(1.0f, 1.5f * i / maxray - 0.5f, 0.0f);
149             w.drawCircle(x, y, i);
150             w.msleep(20);
151         }
152         w.setColor("skyblue");
153         for (i = 0; i < maxray; i++) {
154             w.drawCircle(x, y, i);
155             w.msleep(10);
156         }
157         //    w.fillCircle(x, y, maxray - 1);
158     }
159
160     static void dessineFlammes(DrawingWindow w, double x0, double y0)
161     {
162         for (int i = 0; i < 70; i++) {
163             double dt = 0.05;
164             double vx = frand(-2.5, 2.5);
165             double vy = frand(5, 17);
166             double x = x0;
167             double y = y0;
168             float red = (float)frand(0.5, 1);
169             float green = (float)frand(0, red);
170             float blue = 0;
171             w.setColor(red, green, blue);
172             while (y >= 0.0) {
173                 w.drawPoint(rtowX(w, x), rtowY(w, y));
174                 x += vx * dt;
175                 y += vy * dt;
176                 vy -= 9.81 * dt;
177             }
178             w.msleep(30);
179         }
180     }
181
182     static void initialise(DrawingWindow w)
183     {
184         largeurMont = frand(largeurMin, largeurMax);
185         hauteurMont = frand(hauteurMin, hauteurMax);
186         wnd = frand(-ventMax, ventMax);
187         w.setBgColor("skyblue");
188         w.clearGraph();
189         dessineTerrain(w, largeurMont, hauteurMont);
190         dessineVent(w, wnd);
191         dessineChateau(w, positionChateau1);
192         dessineChateau(w, positionChateau2);
193         w.setColor("wheat");
194         w.drawText(rtowX(w, positionChateau1 - largeurChateau), rtowY(w, 0) + 20,
195                    "Joueur 1");
196         w.drawText(rtowX(w, positionChateau2 - largeurChateau), rtowY(w, 0) + 20,
197                    "Joueur 2");
198         w.drawText(rtowX(w, 0) - 15, rtowY(w, 0) + 20, score1 + " / " + score2);
199     }
200
201     /* Retour : numéro du perdant, 0 sinon
202        x et y contiennent les coordonnées de la collision
203     */
204     static class ResTir {
205         int perdant;
206         double x;
207         double y;
208     }
209     static ResTir tir(DrawingWindow w,
210                       double x0, double y0, double v0, double alpha) {
211         double vx = v0 * Math.cos(alpha);
212         double vy = v0 * Math.sin(alpha);
213         double x = x0;
214         double y = y0;
215         int collision = 0;
216         do {
217             int wx = rtowX(w, x);
218             int wy = rtowY(w, y);
219             w.setColor("black");
220             w.fillCircle(wx, wy, 2);
221             double vxr = vx - wnd;
222             double kvr = -k * Math.sqrt(vxr * vxr + vy * vy);
223             double ax = kvr * vxr;
224             double ay = kvr * vy - g;
225             x += vx * dt;
226             y += vy * dt;
227             vx += ax * dt;
228             vy += ay * dt;
229
230             w.msleep(10);
231 //             w.sync();
232             w.setColor("skyblue");
233             w.fillCircle(wx, wy, 2);
234 //             w.setColor("black");
235 //             w.drawPoint(wx, wy);
236             if (y <= 0) {
237                 collision = 3;
238             } else if (y < hauteurChateau) {
239                 if (positionChateau1 - largeurChateau <= x
240                     && positionChateau1 + largeurChateau >= x)
241                     collision = 1;
242                 else if (positionChateau2 - largeurChateau <= x
243                          && positionChateau2 + largeurChateau >= x)
244                     collision = 2;
245             }
246             if (collision == 0) {
247                 double h = hauteurMontagne(largeurMont, hauteurMont, x);
248                 if (h > 0 && y < h)
249                     collision = 3;
250             }
251         } while (collision == 0);
252         ResTir res = new ResTir();
253         res.x = x;
254         res.y = y;
255         res.perdant = collision == 3 ? 0 : collision;
256         return res;
257     }
258
259     static int jeu1(DrawingWindow w)
260     {
261         initialise(w);
262         int joueur = 2;
263         double x, y;
264         int perdant;
265         do {
266             joueur = 3 - joueur;
267             w.sync();
268             System.out.println("-=| Joueur " + joueur + " |=-");
269             double alpha;
270             double v0;
271             if (joueur <= nbJoueurs) {
272                 System.out.print("\nangle ? ");
273                 alpha = input.nextDouble();
274                 System.out.print("vitesse initiale ? ");
275                 v0 = input.nextDouble();
276             } else {
277                 alpha = frand(10, 90);
278                 v0 = frand(10, 100);
279                 System.out.println(" [ " + (int )alpha + "° ; " + (int )v0 + " ]");
280             }
281             alpha = Math.toRadians(alpha);
282             double x0;
283             if (joueur == 1) {
284                 x0 = positionChateau1 + 0.8 * largeurChateau;
285             } else {
286                 x0 = positionChateau2 - 0.8 * largeurChateau;
287                 alpha = Math.PI - alpha;
288             }
289             double y0 = hauteurChateau + 1;
290             {
291                 ResTir r = tir(w, x0, y0, v0, alpha);
292                 x = r.x;
293                 y = r.y;
294                 perdant = r.perdant;
295             }
296             dessineExplosion(w, x, y);
297             dessineVent(w, wnd);
298         } while (perdant == 0);
299         dessineFlammes(w, x, y);
300         String msg = " Joueur " + perdant;
301         if (perdant == joueur)
302             msg += " s'est suicidé ! ";
303         else
304             msg += " a perdu ! ";
305         w.setColor("darkred");
306         w.setBgColor("white");
307         w.drawText(w.width / 2, w.height / 3, msg);
308         w.sync();
309         System.out.println(msg);
310         return perdant;
311     }
312
313     public static void main(String[] args) {
314         DrawingWindow w = new DrawingWindow("Chateaux", 640, 480);
315
316         if (args.length > 0)
317             nbJoueurs = Integer.parseInt(args[0]);
318
319         boolean rejouer = true;
320         do {
321             int perdant = jeu1(w);
322             if (perdant == 1)
323                 score2++;
324             else if (perdant == 2)
325                 score1++;
326             System.out.println("### SCORE : " + score1 + " / " + score2 + " ###");
327             if (nbJoueurs == 0)
328                 w.sleep(2);
329             else {
330                 char r;
331                 do {
332                     System.out.println("Recommencer (o/n) ? ");
333                     r = input.next().charAt(0);
334                 } while (r != 'o' && r != 'n');
335                 rejouer = r == 'o';
336             }
337         } while (rejouer);
338         w.closeGraph();
339     }
340 }