From: Arnaud Giersch Date: Tue, 14 Oct 2014 20:18:20 +0000 (+0200) Subject: Add more examples (Chateaux). X-Git-Tag: extracted~19 X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/graphlib_java.git/commitdiff_plain/275a16639871c6a3c74e5ca079f1219ec3670231 Add more examples (Chateaux). --- diff --git a/MoreEx/Chateaux.java b/MoreEx/Chateaux.java new file mode 100644 index 0000000..d85946e --- /dev/null +++ b/MoreEx/Chateaux.java @@ -0,0 +1,340 @@ +import java.util.*; + +class Chateaux { + + static final Scanner input = new Scanner(System.in); + static final Random random = new Random(); + + /* Note : les coordonnées réelles vont de -100 à +100 en abscisse, et + * de -10 à +140 en ordonnée + */ + static final double rXMin = -100.0; + static final double rXMax = 100.0; + static final double rYMin = -10.0; + static final double rYMax = 140.0; + static final double hauteurMin = 10; + static final double hauteurMax = 130; + static final double largeurMin = 40; + static final double largeurMax = 150; + static final double ventMax = 30; + static final double largeurChateau = 8.5; + static final double hauteurChateau = 7; + static final double positionChateau1 = -85.0; + static final double positionChateau2 = 85.0; + static final double g = 9.81; + static final double k = 0.005; + static final double dt = 0.05; + static int nbJoueurs = 2; + static int score1 = 0; + static int score2 = 0; + static double largeurMont; + static double hauteurMont; + static double wnd; + + /* Retourne un nombre pseudo-aléatoire compris entre le paramètre + * 'min' (inclus) et le paramètre 'max' (exclus) + */ + static double frand(double min, double max) + { + return min + (max - min)* (random.nextDouble()); + } + + // conversion coordonnées réelles -> coordonnées fenêtre + static int rtowX(DrawingWindow w, double rx) + { + return (int)Math.round((w.width - 1) * (rx - rXMin) / (rXMax - rXMin)); + } + + static int rtowY(DrawingWindow w, double ry) + { + return (int )Math.round((w.height - 1) * (rYMax - ry) / (rYMax - rYMin)); + } + + // conversion coordonnées fenêtre -> coordonnées réelles + static double wtorX(DrawingWindow w, int wx) + { + return (rXMax - rXMin) * wx / (w.width - 1) + rXMin; + } + + static double wtorY(DrawingWindow w, int wy) + { + return -(rYMax - rYMin) * wy / (w.height - 1) + rYMax; + } + + static double hauteurMontagne(double largeur, double hauteur, double x) + { + double rx = 2.0 * x / largeur; + return hauteur * (1.0 - rx * rx); + } + + static void dessineTerrain(DrawingWindow w, double largeur, double hauteur) + { + int y0 = rtowY(w, 0) + 1; + int xmin = rtowX(w, -largeur / 2.0) - 1; + int xmax = rtowX(w, largeur / 2.0) + 1; + w.setColor("forestgreen"); + for (int x = xmin; x <= xmax; x++) { + double rx = wtorX(w, x); + double ry = hauteurMontagne(largeur, hauteur, rx); + int y = rtowY(w, ry); + if (y <= y0) + w.drawLine(x, y0, x, y); + } + w.setColor("maroon"); + w.fillRect(0, y0 + 1, w.width - 1, w.height - 1); + } + + static void dessineChateau(DrawingWindow w, double position) + { + w.setColor("black"); + w.setColor("darkslategray"); + int y1 = rtowY(w, 0) + 1; + int h0 = rtowY(w, 3); + int h1 = rtowY(w, 4); + for (int i = 0; i < 7; i++) { + int h = i % 2 != 0 ? h0 : h1; + int x1 = rtowX(w, position + i - 3.5); + int x2 = rtowX(w, position + i - 2.5) - 1; + w.fillRect(x1, y1, x2, h); + } + w.setColor("dimgray"); + h0 = rtowY(w, 6); + h1 = rtowY(w, 7); + for (int i = 0; i < 5; i++) { + int h = i % 2 != 0 ? h0 : h1; + int x1 = rtowX(w, position + i - 8.5); + int x2 = rtowX(w, position + i - 7.5) - 1; + w.fillRect(x1, y1, x2, h); + x1 = rtowX(w, position + i + 3.5); + x2 = rtowX(w, position + i + 4.5) - 1; + w.fillRect(x1, y1, x2, h); + } + } + + static void dessineVent(DrawingWindow w, double vitesse) + { + int lg = rtowX(w, vitesse) - rtowX(w, 0); + int dir = lg > 0 ? 1 : -1; + int y = 20; + w.setColor("black"); + if (lg == 0) { + w.drawCircle(w.width / 2, y, 4); + } else { + int x1 = (w.width - lg) / 2; + int x2 = (w.width + lg) / 2; + w.drawLine(x1 - dir, y - 1, x2 - dir, y - 1); + w.drawLine(x1, y, x2, y); + w.drawLine(x1 - dir, y + 1, x2 - dir, y + 1); + for (int i = 0; i < 3; i++) { + w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y - 4); + w.drawLine(x2 - i * dir, y, x2 - (6 + i) * dir, y + 4); + } + } + } + + static void dessineExplosion(DrawingWindow w, double rx, double ry) + { + final int maxray = rtowX(w, 2.5) - rtowX(w, 0); + // 1/2 rouge -> rouge -> jaune + final int x = rtowX(w, rx); + final int y = rtowY(w, ry); + int i; + for (i = 0; i <= maxray / 3; i++) { + w.setColor(0.5f + 3.0f * i / (2.0f * maxray), 0.0f, 0.0f); + w.drawCircle(x, y, i); + w.msleep(20); + } + for (/* i */; i < maxray; i++) { + w.setColor(1.0f, 1.5f * i / maxray - 0.5f, 0.0f); + w.drawCircle(x, y, i); + w.msleep(20); + } + w.setColor("skyblue"); + for (i = 0; i < maxray; i++) { + w.drawCircle(x, y, i); + w.msleep(10); + } + // w.fillCircle(x, y, maxray - 1); + } + + static void dessineFlammes(DrawingWindow w, double x0, double y0) + { + for (int i = 0; i < 70; i++) { + double dt = 0.05; + double vx = frand(-2.5, 2.5); + double vy = frand(5, 17); + double x = x0; + double y = y0; + float red = (float)frand(0.5, 1); + float green = (float)frand(0, red); + float blue = 0; + w.setColor(red, green, blue); + while (y >= 0.0) { + w.drawPoint(rtowX(w, x), rtowY(w, y)); + x += vx * dt; + y += vy * dt; + vy -= 9.81 * dt; + } + w.msleep(30); + } + } + + static void initialise(DrawingWindow w) + { + largeurMont = frand(largeurMin, largeurMax); + hauteurMont = frand(hauteurMin, hauteurMax); + wnd = frand(-ventMax, ventMax); + w.setBgColor("skyblue"); + w.clearGraph(); + dessineTerrain(w, largeurMont, hauteurMont); + dessineVent(w, wnd); + dessineChateau(w, positionChateau1); + dessineChateau(w, positionChateau2); + w.setColor("wheat"); + w.drawText(rtowX(w, positionChateau1 - largeurChateau), rtowY(w, 0) + 20, + "Joueur 1"); + w.drawText(rtowX(w, positionChateau2 - largeurChateau), rtowY(w, 0) + 20, + "Joueur 2"); + w.drawText(rtowX(w, 0) - 15, rtowY(w, 0) + 20, score1 + " / " + score2); + } + + /* Retour : numéro du perdant, 0 sinon + x et y contiennent les coordonnées de la collision + */ + static class ResTir { + int perdant; + double x; + double y; + } + static ResTir tir(DrawingWindow w, + double x0, double y0, double v0, double alpha) { + double vx = v0 * Math.cos(alpha); + double vy = v0 * Math.sin(alpha); + double x = x0; + double y = y0; + int collision = 0; + do { + int wx = rtowX(w, x); + int wy = rtowY(w, y); + w.setColor("black"); + w.fillCircle(wx, wy, 2); + double vxr = vx - wnd; + double kvr = -k * Math.sqrt(vxr * vxr + vy * vy); + double ax = kvr * vxr; + double ay = kvr * vy - g; + x += vx * dt; + y += vy * dt; + vx += ax * dt; + vy += ay * dt; + + w.msleep(10); +// w.sync(); + w.setColor("skyblue"); + w.fillCircle(wx, wy, 2); +// w.setColor("black"); +// w.drawPoint(wx, wy); + if (y <= 0) { + collision = 3; + } else if (y < hauteurChateau) { + if (positionChateau1 - largeurChateau <= x + && positionChateau1 + largeurChateau >= x) + collision = 1; + else if (positionChateau2 - largeurChateau <= x + && positionChateau2 + largeurChateau >= x) + collision = 2; + } + if (collision == 0) { + double h = hauteurMontagne(largeurMont, hauteurMont, x); + if (h > 0 && y < h) + collision = 3; + } + } while (collision == 0); + ResTir res = new ResTir(); + res.x = x; + res.y = y; + res.perdant = collision == 3 ? 0 : collision; + return res; + } + + static int jeu1(DrawingWindow w) + { + initialise(w); + int joueur = 2; + double x, y; + int perdant; + do { + joueur = 3 - joueur; + w.sync(); + System.out.println("-=| Joueur " + joueur + " |=-"); + double alpha; + double v0; + if (joueur <= nbJoueurs) { + System.out.print("\nangle ? "); + alpha = input.nextDouble(); + System.out.print("vitesse initiale ? "); + v0 = input.nextDouble(); + } else { + alpha = frand(10, 90); + v0 = frand(10, 100); + System.out.println(" [ " + (int )alpha + "° ; " + (int )v0 + " ]"); + } + alpha = Math.toRadians(alpha); + double x0; + if (joueur == 1) { + x0 = positionChateau1 + 0.8 * largeurChateau; + } else { + x0 = positionChateau2 - 0.8 * largeurChateau; + alpha = Math.PI - alpha; + } + double y0 = hauteurChateau + 1; + { + ResTir r = tir(w, x0, y0, v0, alpha); + x = r.x; + y = r.y; + perdant = r.perdant; + } + dessineExplosion(w, x, y); + dessineVent(w, wnd); + } while (perdant == 0); + dessineFlammes(w, x, y); + String msg = " Joueur " + perdant; + if (perdant == joueur) + msg += " s'est suicidé ! "; + else + msg += " a perdu ! "; + w.setColor("darkred"); + w.setBgColor("white"); + w.drawText(w.width / 2, w.height / 3, msg); + w.sync(); + System.out.println(msg); + return perdant; + } + + public static void main(String[] args) { + DrawingWindow w = new DrawingWindow("Chateaux", 640, 480); + + if (args.length > 0) + nbJoueurs = Integer.parseInt(args[0]); + + boolean rejouer = true; + do { + int perdant = jeu1(w); + if (perdant == 1) + score2++; + else if (perdant == 2) + score1++; + System.out.println("### SCORE : " + score1 + " / " + score2 + " ###"); + if (nbJoueurs == 0) + w.sleep(2); + else { + char r; + do { + System.out.println("Recommencer (o/n) ? "); + r = input.next().charAt(0); + } while (r != 'o' && r != 'n'); + rejouer = r == 'o'; + } + } while (rejouer); + w.closeGraph(); + } +} diff --git a/MoreEx/Makefile b/MoreEx/Makefile new file mode 100644 index 0000000..39f111a --- /dev/null +++ b/MoreEx/Makefile @@ -0,0 +1,16 @@ + +SRC = DrawingWindow.java $(wildcard *.java) +CLASS = $(SRC:%.java=%.class) + +.PHONY: all clean + +all: DrawingWindow.java + $(MAKE) -f ../../Makefile.generic $(CLASS) + +clean: + $(RM) *~ + $(RM) DrawingWindow.java + $(RM) *.class + +DrawingWindow.java: + ln -s ../DrawingWindow.java .