final commit

This commit is contained in:
2022-11-20 21:54:08 -05:00
parent 6f6fda5b1b
commit 8264cccb7a
51 changed files with 6299 additions and 2 deletions

26
src/pigeons/App.java Normal file
View File

@@ -0,0 +1,26 @@
package pigeons;
public class App {
/**
* Fonction Main permettant de lancer l'application
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
Park park = new Park(500, 500);
new Bird(12, 123, park);
new Bird(102, 235, park);
new Bird(321, 421, park);
new Bird(126, 231, park);
new Bird(411, 34, park);
new Bird(245, 333, park);
UI ui = new UI(park);
while (true) {
ui.draw();
Thread.sleep(1);
}
}
}

184
src/pigeons/Bird.java Normal file
View File

@@ -0,0 +1,184 @@
package pigeons;
import java.awt.Color;
/**
* Classe permettant de gérer un oiseau
*
* Implemente l'interface Runnable, ce qui permet d'executer les actions d'un
* oiseau dans un thread.
*
* @author Valentin THEDON
* @author Nathan AMSELLEM
*
* @version %I%, %G%
* @since 1.0
*/
public class Bird implements Runnable {
/**
* Positiion de l'oiseau
*/
private Position position;
/**
* Parc de rattachement de l'oiseau
*/
private Park park;
private boolean isAlive = true;
/**
* Couleur d'un oiseau
*/
public static Color COLOR = Color.BLACK;
/**
* Temps de raffraichissement d'un oiseau (en ms)
*/
public static int REFRESH_TIME = 20;
/**
* Vitesse d'un oiseau
*/
public static int VELOCITY = 10;
/**
* Constructeur de l'objet oiseau
*
* @param position position de l'oiseau
* @param park parc de rattachement de l'oiseau
*/
public Bird(Position position, Park park) {
this.position = position;
this.park = park;
this.park.addBird(this);
}
/**
* Constructeur de l'objet oiseau
*
* @param x position sur l'axe des abscisses de l'oiseau
* @param y position sur l'axe des ordonnées de l'oiseau
* @param park parc de rattachement de l'oiseau
*/
public Bird(int x, int y, Park park) {
this(new Position(x, y), park);
}
/**
* Detecte la nourriture la plus proche de l'oiseau
*
* @return Food L'objet representant la nourriture la plus proche
*/
public Food findNearestFood() {
Food nearestFood = null;
int minDistance = Integer.MAX_VALUE;
for (Food f : park.getFoods()) {
if (this.position.distance(f.getPosition()) < minDistance && f.isFresh()) {
nearestFood = f;
minDistance = this.position.distance(f.getPosition());
}
}
return nearestFood;
}
@Override
public void run() {
while (isAlive) {
Food nearestFood = findNearestFood();
if (nearestFood != null) {
this.moveTo(nearestFood);
Food onFood = this.getOnFood();
if (onFood != null && onFood.isFresh()) {
this.park.removeFood(onFood);
}
}
try {
Thread.sleep(REFRESH_TIME);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Deplace un oiseau vers une position
*
* @param toMove La position vers laquelle nous devous nous deplacer
*/
public void moveTo(Position toMove) {
if (this.position.distance(toMove) <= ((VELOCITY * REFRESH_TIME * 0.01))) {
this.position.moveTo(toMove.getX(), toMove.getY());
} else {
float x = this.position.getX()
+ ((VELOCITY * REFRESH_TIME * 0.01f)
* ((toMove.getX() - this.position.getX()) / (float) this.position.distance(toMove)));
float y = this.position.getY()
+ (((VELOCITY * REFRESH_TIME * 0.01f))
* ((toMove.getY() - this.position.getY()) / (float) this.position.distance(toMove)));
this.position.moveTo(Math.round(x), Math.round(y));
}
}
/**
* Deplacer l'oiseau vers une nourriture
*
* @param food La nourriture vers laquelle l'oiseau doit se diriger
*/
public void moveTo(Food food) {
this.moveTo(food.getPosition());
}
/**
* Effraie l'oiseau, a pour but de le déplacer à une position aléatoire
*/
public void frighten() {
this.position.moveTo(Math.round((float) Math.random() * park.getWidth()),
Math.round((float) Math.random() * park.getHeight()));
;
}
/**
* @return Food Renvoie la nourriture sur laquelle nous nous situons, ou null si nous sommes sur aucune nourriture
*/
public Food getOnFood() {
for (Food f : park.getFoods()) {
if (this.position.distance(f.getPosition()) == 0)
return f;
}
return null;
}
/**
* Obtenir le parc dans lequel l'oiseau evolue
*
* @return Le parc dans lequel l'oiseau évolue
*/
public Park getPark() {
return park;
}
/**
* Définir un parc dans lequel l'oiseau evoluera
*
* @param park Le parc dans lequel l'oiseu évoluera
*/
public void setPark(Park park) {
this.park = park;
}
/**
*
* @return boolean vrai si l'oiseau est en vie, faux sinon.
*/
public boolean isAlive() {
return this.isAlive;
}
/**
* Obtenir la position de l'oiseau
*
* @return Position la position actuelle de l'oiseau
*/
public Position getPosition() {
return this.position;
}
}

140
src/pigeons/Food.java Normal file
View File

@@ -0,0 +1,140 @@
package pigeons;
import java.awt.Color;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Classe permettant de gérer une nourriture
*
* @author Valentin THEDON
* @author Nathan AMSELLEM
*
* @version %I%, %G%
* @since 1.0
*/
public class Food {
/**
* Position de la nourriture
*/
private Position position;
/**
* Consommabilité de la nourriture
*/
private boolean isFresh;
/**
* Temps restant de fraicheur de la nourriture
*/
private long freshTimeLeft = 2000;
/**
* Nombre de thread travaillant en ecriture sur l'objet
*/
private AtomicInteger numWriter = new AtomicInteger();
/**
* Couleur de la nourriture
* - Rouge si non consommable
* - Jaune si consommable
*/
public Color color;
/**
* Constructeur de l'objet representant une nourriture
*
* @param position Position de la nourriture
*/
public Food(Position position) {
this.position = position;
this.isFresh = true;
this.color = Color.YELLOW;
}
/**
* Constructeur de l'objet representant une nourriture
*
* @param x position sur l'axe des abscisses de la nourriture
* @param y postiion sur l'axe des ordonnées de la nourriture
*/
public Food(int x, int y) {
this(new Position(x, y));
}
/**
* Obtenir la position de la nourriture
*
* @return position de la nourriture
*/
public Position getPosition() {
return position;
}
/**
* Reduit le temps de fraicheur de la nourriture.
* Si le temps restants de fraicheur, la nourriture est consideré comme non
* consommable et la variable {@link Food#isFresh} vaut desormais
* <code>true</code>. Par ailleurs la couleur d'une nourriture devient rouge
*
* @param toReduce Temps à retirer du temps restant de fraicheur
*/
public synchronized void reduceFreshTimeLeft(long toReduce) {
this.numWriter.incrementAndGet();
this.freshTimeLeft -= toReduce;
if (this.freshTimeLeft < 0) {
this.isFresh = false;
this.color = Color.RED;
}
this.numWriter.decrementAndGet();
notifyAll();
}
/**
* Obtenir la couleur associé une nourriture
*
* @return La couleur associé à la nouritture, jaune si consommable, rouge sinon
*/
public Color getColor() {
return color;
}
/**
* Obtenir le temps de fraicheur restant à une nourriture
*
* Cette méthode est executé avec un verrou ce qui permet aux oiseaux de
* recuperer la propriété en étant sur que la variable n'est pas en cours de
* modification
*
* @return Temps de fraicheur restant à la nourriture
*/
public synchronized long getFreshTimeLeft() {
while (numWriter.get() != 0)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return freshTimeLeft;
}
/**
* Obtenir la consommabité de la nourriture
*
* Cette fonction est executé avec un verrou ce qui permet aux oiseaux de
* recuperer la propriété en étant sur que la variable n'est pas en cours de
* modification
*
* @return boolean
*
*/
public synchronized boolean isFresh() {
while (numWriter.get() != 0)
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return isFresh;
}
}

246
src/pigeons/Park.java Normal file
View File

@@ -0,0 +1,246 @@
package pigeons;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JPanel;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.Color;
import java.awt.Graphics;
/**
* Classe permettant de gérer un parc d'oiseaux
*
* Ce parc permet de gerer un parc contenant des oiseaux, vous pouvez nourrir
* ces oiseaux en cliquant sur votre interface, vos oiseaux seront effrayer de
* manière aléatoire. Ce park peut
* etre affiché à l'aide d'une <code>JFrame</code>.
*
* @author Valentin THEDON
* @author Nathan AMSELLEM
*
* @version %I%, %G%
* @since 1.0
*/
public class Park extends JPanel implements MouseListener {
/**
* Oiseaux présent dans le parc
*/
private ArrayList<Bird> birds;
/**
* Nourritures présente dans le parc
*/
private ArrayList<Food> foods;
/**
* Probabilité d'effrayer les oiseaux, decroit à chaque actualisation du parc
*/
private int frightenProbaility = 20000;
/**
* Nombre de thread travaillant en ecriture sur l'objet
*/
private AtomicInteger numWriter = new AtomicInteger();
/**
* Constructeur de l'objet representant un parc
*
* @param width longueur du parc
* @param height hauteur du parc
*/
public Park(int width, int height) {
super();
super.setSize(width, height);
this.addMouseListener(this);
this.birds = new ArrayList<Bird>();
this.foods = new ArrayList<Food>();
}
/**
* Obtenir les oiseaux du parc
*
* @return la liste contenant les oiseaux du parcs
*/
public ArrayList<Bird> getBirds() {
return birds;
}
/**
* Obtenir la nourriture du parc
*
* Cette méthode est executé avec un verrou ce qui permet aux oiseaux de
* recuperer la propriété en étant sur que la variable n'est pas en cours de
* modification
*
* @return la liste contenant les nourritures du parc
*/
public synchronized ArrayList<Food> getFoods() {
try {
while (numWriter.get() != 0) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return foods;
}
/**
* Ajouter une nourriture dans le parc
*
* Cette méthode est executé avec un verrou ce qui permet de modifier la
* propriété, tout en bloquant les lectures eventuelles de la propriété.
* L'ecriture est prioritaire sur la lecture.
*
* @param toAdd nourriture a ajouter au parc
*/
public synchronized void addFood(Food toAdd) {
numWriter.incrementAndGet();
this.foods.add(toAdd);
numWriter.decrementAndGet();
notifyAll();
}
/**
* Ajouter un oiseau dans le parc
*
* @param toAdd Oiseau à ajouter au parc
*/
public void addBird(Bird toAdd) {
this.birds.add(toAdd);
Thread t = new Thread(toAdd);
t.start();
}
/**
* Supprimer des nourriture présente sur le parc
*
* Cette méthode est executé avec un verrou ce qui permet de modifier la
* propriété, tout en bloquant les lectures eventuelles de la propriété.
* L'ecriture est prioritaire sur la lecture.
*
* @param foods liste de nourriture à supprimer du parc
*/
public synchronized void removeFoods(ArrayList<Food> foods) {
numWriter.incrementAndGet();
this.foods.removeAll(foods);
numWriter.decrementAndGet();
notifyAll();
}
/**
* Supprimer une nourriture du parc
*
* Cette méthode est executé avec un verrou ce qui permet de modifier la
* propriété, tout en bloquant les lectures eventuelles de la propriété.
* L'ecriture est prioritaire sur la lecture.
*
* @param food nourriture à ajouter
*/
public synchronized void removeFood(Food food) {
numWriter.incrementAndGet();
this.foods.remove(food);
numWriter.decrementAndGet();
notifyAll();
}
@Override
public void paintComponent(Graphics g) {
refreshPark();
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
for (Bird b : birds) {
if (b.isAlive()) {
g.setColor(Bird.COLOR);
g.fillRect(b.getPosition().getX(), b.getPosition().getY(), 15, 15);
}
}
synchronized (foods) {
try {
while (numWriter.get() != 0) {
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
for (Food f : foods) {
g.setColor(f.getColor());
g.fillOval(f.getPosition().getX(), f.getPosition().getY(), 5, 5);
}
}
}
@Override
public void mouseClicked(MouseEvent e) {
Food f = new Food(e.getX(), e.getY());
this.addFood(f);
for (Bird b : birds) {
synchronized (b) {
b.notify();
}
}
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
/**
* @param index index de liste de l'oiseau à supprimer
*/
public void removeBird(int index) {
this.birds.remove(index);
}
/**
* Rafraichir le parc, supprime les nourriture périmés depuis un certain temps,
* réduit le temps de fraicheurs des nourritures et essaye d'effrayer les
* oiseaux du park
*/
private void refreshPark() {
ArrayList<Food> foodToRemove = new ArrayList<Food>();
for (Food f : foods) {
f.reduceFreshTimeLeft(1);
if (f.getFreshTimeLeft() <= -5000) {
foodToRemove.add(f);
}
}
this.removeFoods(foodToRemove);
if (Math.floor(Math.random() * (--frightenProbaility)) == 0) {
for (Bird b : birds) {
b.frighten();
this.frightenProbaility = 20000;
}
}
}
}

109
src/pigeons/Position.java Normal file
View File

@@ -0,0 +1,109 @@
package pigeons;
/**
* Classe representant un position
*
* @author Valentin THEDON
* @author Nathan AMSELLEM
*
* @version %I%, %G%
* @since 1.0
*/
public class Position {
/**
* Coordonnée sur l'axe des abscisses
*/
private int x;
/**
* Coodonnée sur l'axe des ordonées
*/
private int y;
/**
* Constructeur de l'objet representant une position
*
* @param x position sur l'abscisse
* @param y position sur l'ordonée
*/
public Position(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Constructeur de l'objet representant une position
*
* Position fixé à l'origine (0 ; 0)
*/
public Position() {
this(0, 0);
}
/**
* Calculer la distance entre 2 positions
*
* @param position postion distante
* @return distance entre les 2 points
*/
public int distance(Position position) {
return (int) Math.sqrt(Math.pow(Math.abs(this.x - position.x), 2) + Math.pow(Math.abs(this.y - position.y), 2));
}
/**
* Déplacer la position
*
* @param x nouvelle position sur l'axe des abscisses
* @param y nouvelle position sur l'axe des abscisses
*/
public void moveTo(int x, int y) {
this.x = x;
this.y = y;
}
/**
* Déplacer la position
*
* @param toMove nouvelle position
*/
public void moveTo(Position toMove) {
this.moveTo(toMove.getX(), toMove.getY());
}
/**
* Obtenir la position sur l'axe des abscisses
*
* @return coordonnée sur l'abscisses
*/
public int getX() {
return this.x;
}
/**
* Définir une coordonée d'abscisse
*
* @param x nouvelle coordonnée d'abscisse
*/
public void setX(int x) {
this.x = x;
}
/**
* Obtenir la position sur l'axe des ordonées
*
* @return coordonnée sur l'ordonnée
*/
public int getY() {
return this.y;
}
/**
* Définir une coordonée d'ordonée
*
* @param y nouvelle coordonnée d'ordonée
*/
public void setY(int y) {
this.y = y;
}
}

65
src/pigeons/UI.java Normal file
View File

@@ -0,0 +1,65 @@
package pigeons;
import javax.swing.JFrame;
/**
* Classe d'interface utilisateur de l'application
*
* @author Valentin THEDON
* @author Nathan AMSELLEM
*
* @version %I%, %G%
* @since 1.0
*/
public class UI extends JFrame {
/**
* Parc de l'application
*/
private Park park;
/**
* Constructeur de l'interface graphique
*
* La taille de l'interface sera la même que celle du parc
*
* @param park le parc attaché à cette interface
*/
public UI(Park park) {
super();
this.park = park;
this.setSize(park.getSize());
this.setVisible(true);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Pigeons");
this.setContentPane(park);
}
/**
* Obtenir le park associé à l'intefrace graphique
*
* @return parc de l'application
*/
public Park getPark() {
return park;
}
/**
* Définir un parc pour l'interface graphique
*
* @param park parc de l'application
*/
public void setPark(Park park) {
this.park = park;
}
/**
* Dessiner l'interface
*/
public void draw() {
this.park.repaint();
}
}