/* _ _ _ _ _ __/\__ | |__ _ _| |__ | | ___ (_) __| |___ __/\__ \ / | '_ \| | | | '_ \| |/ _ \| |/ _` / __| \ / /_ _\ | |_) | |_| | |_) | | (_) | | (_| \__ \ /_ _\ \/ |_.__/ \__,_|_.__/|_|\___/|_|\__,_|___/ \/ nov. 2006 * emoc / Pierre Commenge * http://urzhiata.emoc.org */ int maxBub = 4; int maxTirs = 20, tirLibre = 0, maxDureeTir = 24; int maxExplosions = 16+1, explosionLibre = 0; int largeurEcran = 360, hauteurEcran = 480; int phase = 0, niveau = 1; int totalTableau = maxBub * 7; // le compteur qui permet de savoir que le tableau est terminé! boolean phase0_demarree = false; // initialisation des phases boolean phase1_demarree = false, phase2_demarree = false, phase3_demarree = false; int zzz = 0; // utile pour le tracé de la spirale phase 2 float spirale_angle = 0; // utile pour le tracé de la spirale phase 2 float coef_vitesse = 1; // coefficient de vitesse globale des asteroides Bubloid zeBub[] = new Bubloid[maxBub*7*8]; // dimensionné pour le max ! Fusee zeFusee = new Fusee(180,240,0,0,0); Tir zeTir[] = new Tir[maxTirs]; Score zeScore = new Score(0,0); Reserve zeReserve = new Reserve(2); Explosion zeExplosion[] = new Explosion[maxExplosions]; void setup() { size(360, 480); // defini pour l'applet, ça ne fonctionne pas en mettant des variables frameRate(25); stroke(255); strokeWeight(1.0); background(0); noFill(); noSmooth(); definirTirs(maxTirs); definirExplosions(maxExplosions); } void draw() { background(0); if (phase == 0) { noFill(); PImage ecrantitre; ecrantitre = loadImage("bub_start.png"); image(ecrantitre, 60, 90); if (phase0_demarree == false) { maxBub = 16; noFill(); placerBub(maxBub*7); phase0_demarree = true; } agiter_bubloids(); } else if (phase == 1){ phase0_demarree = false; fill(0); if (phase1_demarree == false) { remise_a_zero_globale(); demarrer_niveau(niveau); phase1_demarree = true; } agiter_bubloids(); for (int j=0; j < maxTirs; j++) { if (zeTir[j].visible == true) { zeTir[j].tester_collision(); zeTir[j].deplacer(); zeTir[j].afficher(); } } for (int j=0; j < maxExplosions; j++) { if (zeExplosion[j].visible == true) { zeExplosion[j].afficher(); } } zeFusee.tester_collision(); zeFusee.deplacer(); zeFusee.afficher(); zeScore.afficher(); zeReserve.afficher(); afficher_niveau(); if (totalTableau == 0) { // tableau fini remise_a_zero_globale(); phase = 2; } } else if (phase == 2){ if (phase2_demarree == false) { zzz = 0; phase2_demarree = true; } if (zzz == 50) { niveau ++; remise_a_zero_globale(); phase = 1; } else { zzz ++; afficher_spirale(zzz); fill(0); zeFusee.afficher(); zeScore.afficher(); zeReserve.afficher(); } } else if (phase == 3) { if (phase3_demarree == false) { zzz = 0; } if (zzz == 50) { remise_a_zero_globale(); } else { phase3_demarree = true; zzz ++; afficher_spirale(zzz); fill(0); zeScore.afficher(); } PFont zefonte; zefonte = loadFont("BitstreamVeraSans-Roman-18.vlw"); textFont(zefonte, 14); text("...game over...",130,220); text(" score " + zeScore.valeur,140,240); text(" press S \nto reStart",150,260); totalTableau = maxBub * 7; zeScore.afficher(); } } void afficher_spirale(int zzz) { for (int k=0; k < zzz; k++) { float x1 = zeFusee.x + cos(spirale_angle) * (k * 10 + 10); float y1 = zeFusee.y + sin(spirale_angle) * (k * 10 + 10); float x2 = zeFusee.x + cos(spirale_angle) * ((k + 1) * 10 + 10); float y2 = zeFusee.y + sin(spirale_angle) * ((k + 1) * 10 + 10); line(x1,y1,x2,y2); spirale_angle += 0.8; } } void agiter_bubloids() { for (int i=0; i < maxBub*7; i++) { if (zeBub[i].visible == true) { zeBub[i].deplacer(); zeBub[i].afficher(); } } } void demarrer_niveau (int niveau) { if (niveau < 17) { maxBub = 3 + niveau; placerBub(maxBub*7); totalTableau = maxBub * 7; } else { maxBub = 3 + niveau%16; coef_vitesse += 0.3 + floor(niveau / 2); } } void remise_a_zero_globale() { phase0_demarree = false; phase1_demarree = false; phase2_demarree = false; zzz = 0; spirale_angle = 0; for (int j=0; j < maxTirs; j++) { zeTir[j].duree = 0; zeTir[j].visible = false; } for (int j=0; j < maxExplosions; j++) { zeExplosion[j].duree = 0; zeExplosion[j].visible = false; } } void restart() { niveau = 1; maxBub = 4; placerBub(maxBub*7); phase = 0; remise_a_zero_globale(); zeScore.remettre_a_zero(); zeReserve.remettre_a_zero(); for (int j=0; j < maxTirs; j++) { zeTir[j].duree = 0; zeTir[j].visible = false; } for (int j=0; j < maxExplosions; j++) { zeExplosion[j].duree = 0; zeExplosion[j].visible = false; } } void start_crazy_mode() { // faut il conserver ????????????????????????? maxBub = 32; placerBub(maxBub*7); for (int j=0; j < maxTirs; j++) { zeTir[j].duree = 0; zeTir[j].visible = false; } } void afficher_niveau() { PFont zefonte; zefonte = loadFont("BitstreamVeraSans-Roman-18.vlw"); textFont(zefonte, 12); fill(255); text("level : " + niveau,150,16); } void game_over() { phase = 3; } void placerBub(int n) { // tous les asteroides sont definis au départ, les moyens et les petits // ne sont pas visibles, jusqu'à ce qu'il y ait explosion // les asteroides apparaissent alternativement dans les // zones carrées au coin de l'écran int[][] zones = { {0,0}, {220,0}, {0,380}, {220,380} }; int m = 0; // 'compteur' vers les 4 zones de l'écran for (int j=0; j < maxBub; j++) { for (int i=0; i < 7; i++) { int z = j*7+i; if (i == 0) { // gros asteroides visibles au départ int bubx = int(random(0,140)) + zones[m][0]; int buby = int(random(0,140)) + zones[m][1]; int bubangle = int(random(0,TWO_PI)); zeBub[z] = new Bubloid(bubx,buby,bubangle,3,40,true,z); m ++; if (m == 4) m = 0; } else if (i == 1 || i == 2) { // asteroides moyens invisibles au début zeBub[z] = new Bubloid(10,10,0,4,24,false,z); } else { // petites asteroides inivisibles au début zeBub[z] = new Bubloid(10,100,0,5,12,false,z); } } } } void definirTirs(int n) { for (int j=0; j < n; j++) { zeTir[j] = new Tir(0,0,0,0,false); } } void definirExplosions(int n) { for (int j=0; j < n; j++) { zeExplosion[j] = new Explosion(0,0,0,12,0,0,false); } } /* ********************************************************************************** */ void mousePressed() { zeFusee.accelerer(); } void keyPressed() { if (keyCode == UP) { zeFusee.accelerer(); } if (keyCode == LEFT) { zeFusee.rotater(-0.4); } if (keyCode == RIGHT) { zeFusee.rotater(0.4); } if (key == ' ') { if (zeFusee.fantome == 0) { zeFusee.tirer(); } if (phase == '2') { // phase = 1; } } if (key == '1') { phase = 1; // TEST-ONLY } if (key == '2') { phase = 2; } if (key == '+') { coef_vitesse += 0.3; } if (key == '-') { zeReserve.valeur --; } if ((key == 's' || key == 'S') && (phase == 0)) { // Start ! phase = 1; } if ((key == 's' || key == 'S') && (phase == 3)) { restart(); } if (key == 'c' || key == 'C') { // faut il garder ??????????????????????????? start_crazy_mode(); } } // ****************************************************************** class Bubloid { int taille,numid; float vitesse; float x, y, angle; boolean visible; Bubloid(float xn, float yn, float anglen, float vitessen, int taillen, boolean visiblen, int numidn) { this.x = xn; this.y = yn; this.angle = anglen; this.vitesse = vitessen; this.taille = taillen; this.visible = visiblen; this.numid = numidn; // identifiant, pas definitif / TEST } void afficher() { ellipse(this.x,this.y,this.taille,this.taille); } void deplacer() { this.x = this.x + cos(this.angle) * this.vitesse * coef_vitesse; this.y = this.y + sin(this.angle) * this.vitesse * coef_vitesse; if (this.x < 0) this.x += largeurEcran; if (this.x > largeurEcran) this.x = 0; if (this.y < 0) this.y += hauteurEcran; if (this.y > hauteurEcran) this.y = 0; } void scinder(int nBub) { int nb1 = nBub + 1; int nb2 = nBub + 2; if (nBub%7 == 0) { nb1 = nBub + 1; nb2 = nBub + 2; zeScore.augmenter(20); } else if (nBub%7 == 1) { nb1 = nBub + 2; nb2 = nBub + 3; zeScore.augmenter(50); } else { nb1 = nBub + 3; nb2 = nBub + 4; zeScore.augmenter(100); } zeBub[nBub].visible = false; zeBub[nb1].visible = true; zeBub[nb1].x = zeBub[nBub].x - 10; zeBub[nb1].y = zeBub[nBub].y; zeBub[nb1].angle = zeBub[nBub].angle + 4.7124; zeBub[nb2].visible = true; zeBub[nb2].x = zeBub[nBub].x + 10; zeBub[nb2].y = zeBub[nBub].y; zeBub[nb2].angle = zeBub[nBub].angle + 1.5708; } } class Fusee { float x, y, angle, vitessex, vitessey; float f1x,f1y,f2x,f2y,f3x,f3y; // coordonnées des sommets utiles pour les collisions int fantome; Fusee(float xn, float yn, float anglen, float vitessexn, float vitesseyn) { this.x = xn; this.y = yn; this.angle = radians(anglen); this.vitessex = vitessexn; this.vitessey = vitesseyn; this.fantome = 0; } void afficher() { // ellipse(this.x,this.y,40,40); if (this.fantome > 0) this.fantome --; else { this.f1x = this.x + (8 * cos(1.57+this.angle)); this.f1y = this.y + (8 * sin(1.57+this.angle)); this.f2x = this.x + (8 * cos(4.09+this.angle)); this.f2y = this.y + (8 * sin(4.09+this.angle)); this.f3x = this.x + (8 * cos(5.34+this.angle)); this.f3y = this.y + (8 * sin(5.34+this.angle)); triangle (f1x,f1y,f2x,f2y,f3x,f3y); } } void deplacer() { if (this.fantome > 0) this.fantome --; else { this.x = this.x + (this.vitessex * cos(this.angle+1.5708)); this.y = this.y + (this.vitessey * sin(this.angle+1.5708)); if (this.x < 0) this.x += largeurEcran; if (this.x > largeurEcran) this.x = 0; if (this.y < 0) this.y += hauteurEcran; if (this.y > hauteurEcran) this.y = 0; if (vitessex > 0.3) this.vitessex -= 0.3; else vitessex = 0; if (vitessey > 0.3) this.vitessey -= 0.3; else vitessey = 0; } } void accelerer() { zeFusee.vitessex = 10; zeFusee.vitessey = 10; } void rotater(float i) { this.angle += i; } void tirer() { boolean tirDone = false; if (tirLibre < maxTirs) { zeTir[tirLibre] = new Tir(this.f1x,this.f1y,this.angle,0,true); tirLibre ++ ; } else { int tt = 0; while (tirDone == false) { if (zeTir[tt].visible == false) { zeTir[tt].x = this.f1x; zeTir[tt].y = this.f1y; zeTir[tt].angle = this.angle; zeTir[tt].duree = 0; zeTir[tt].visible = true; tirDone = true; } tt ++; } } } void tester_collision() { for (int i=0; i < maxBub*7; i++) { if ((zeBub[i].visible == true) && (this.fantome == 0)) { float d1 = dist(this.f1x,this.f1y,zeBub[i].x,zeBub[i].y) - 2; float d2 = dist(this.f2x,this.f2y,zeBub[i].x,zeBub[i].y) - 2; float d3 = dist(this.f3x,this.f3y,zeBub[i].x,zeBub[i].y) - 2; if ((d1 < (zeBub[i].taille / 2)) || (d2 < (zeBub[i].taille / 2)) || (d3 < (zeBub[i].taille / 2))) { if (this.fantome == 0) { creer_explosion(this.f1x,this.f1y,50,12); this.detruire(); } } } } } void detruire() { this.fantome = 50; zeReserve.augmenter(-1); this.angle = 0; this.vitessex = 0; this.vitessey = 0; this.x = 180; this.y = 240; zeFusee.replacer(); } void replacer() { this.vitessex = 0; this.vitessey = 0; for (int i=0; i < maxBub*7; i++) { if ((zeBub[i].visible == true) && (this.fantome == 0)) { float d1 = 2 * dist(this.f1x,this.f1y,zeBub[i].x,zeBub[i].y) - 2; float d2 = 2 * dist(this.f2x,this.f2y,zeBub[i].x,zeBub[i].y) - 2; float d3 = 2 * dist(this.f3x,this.f3y,zeBub[i].x,zeBub[i].y) - 2; if ((d1 < (zeBub[i].taille)) || (d2 < (zeBub[i].taille)) || (d3 < (zeBub[i].taille))) { this.fantome = 1; } } } } } class Score { int valeur, dernierBonus; Score(int valeurn, int dernierBonusn) { this.valeur = valeurn; this.dernierBonus = 0; } void augmenter(int plus) { this.valeur += plus; if (this.valeur - dernierBonus > 9990) { zeReserve.augmenter(1); this.dernierBonus += 10000; println("dernierBonus : " + this.dernierBonus); } } void remettre_a_zero() { this.valeur = 0; } void afficher() { PFont zefonte; zefonte = loadFont("BitstreamVeraSans-Roman-18.vlw"); textFont(zefonte, 18); fill(255); text(this.valeur,20,20); } } class Reserve { int valeur; Reserve(int valeurn) { this.valeur = valeurn; } void augmenter(int plus) { if (this.valeur < 9) { this.valeur += plus; } if (this.valeur < 0) { game_over(); } } void remettre_a_zero() { this.valeur = 2; } void afficher() { for (int i=0; i < this.valeur; i++) { int j = i * 12 ; fill(0); triangle(240+j,18,248+j,18,244+j,6); } } } class Tir { float x, y, angle; float x1,y1,x2,y2; // coordonnées des sommets, utile pour les collisions int duree; boolean visible; Tir(float xn, float yn, float anglen, int dureen, boolean visiblen) { this.x = xn; this.y = yn; this.angle = anglen; this.duree = dureen; this.visible = true; } void afficher() { // ellipse(this.x,this.y,40,40); this.x1 = this.x + (4 * cos(1.57+this.angle)); this.y1 = this.y + (4 * sin(1.57+this.angle)); this.x2 = this.x + (4 * cos(4.71+this.angle)); this.y2 = this.y + (4 * sin(4.71+this.angle)); line (x1,y1,x2,y2); } void deplacer() { this.x = this.x + (12 * cos(this.angle+1.5708)); this.y = this.y + (12 * sin(this.angle+1.5708)); if (this.x < 0) this.x += largeurEcran; if (this.x > largeurEcran) this.x = 0; if (this.y < 0) this.y += hauteurEcran; if (this.y > hauteurEcran) this.y = 0; this.duree ++; if (this.duree > maxDureeTir) { this.duree = 0; this.visible = false; } } void tester_collision() { for (int i=0; i < maxBub*7; i++) { if (zeBub[i].visible == true) { float d1 = dist(this.x1,this.y1,zeBub[i].x,zeBub[i].y) - 2; // -2 variable d'ajustement float d2 = dist(this.x2,this.y2,zeBub[i].x,zeBub[i].y) - 2; if ((d1 < (zeBub[i].taille / 2)) || (d2 < (zeBub[i].taille / 2))) { creer_explosion(this.x,this.y,zeBub[i].taille,12); if (zeBub[i].taille > 12) { zeBub[i].scinder(i); totalTableau --; } else { // l'asteroide est déjà au dernier stade! on le détruit totalTableau --; zeBub[i].visible = false; zeScore.augmenter(100); // TODO pas tres logique d'avoir le score ici } this.visible = false; } } } } } class Explosion { float x, y, taille, angle; int duree,dureemax; boolean visible; // Explosion(float xn, float yn, int dureen, int dureemaxn, float taillen, float anglen, boolean visiblen) { this.x = xn; this.y = yn; this.duree = dureen; this.dureemax = dureemaxn; this.taille = taillen; this.visible = true; this.angle = 0; } void afficher() { this.duree ++; if (this.duree < this.dureemax) { this.angle += this.duree / 2; float angletemp = this.angle; float z = 0.02 + (0.98 / this.duree); for (int i=0; i < (this.duree - 1); i++) { float x1 = this.x + this.taille / 2 * cos(angletemp); float y1 = this.y + this.taille / 2 * sin(angletemp); float x2 = this.x + this.taille * z * cos(angletemp); float y2 = this.y + this.taille * z * sin(angletemp); line(x1,y1,x2,y2); angletemp += 0.5; } } else { this.duree = 0; this.visible = false; } } } void creer_explosion(float x, float y, float taille, int dureemax ) { boolean explosionDone = false; if (explosionLibre < maxExplosions) { zeExplosion[explosionLibre] = new Explosion(x,y,0,dureemax,taille,0,true); explosionLibre ++ ; } else { int tt = 0; while (explosionDone == false) { if (zeExplosion[tt].visible == false) { zeExplosion[tt].x = x; zeExplosion[tt].y = y; zeExplosion[tt].angle = 0; zeExplosion[tt].taille = taille; zeExplosion[tt].duree = 0; zeExplosion[tt].dureemax = 12; zeExplosion[tt].visible = true; explosionDone = true; } tt ++; } } }