diff --git a/src/main/java/lab/BulletAnimated.java b/src/main/java/lab/BulletAnimated.java
index 02b9a3208dfb390973e21995e808951864d11bae..cc7d236ffe7f1320897d2958303506ac5842c994 100644
--- a/src/main/java/lab/BulletAnimated.java
+++ b/src/main/java/lab/BulletAnimated.java
@@ -1,6 +1,7 @@
 package lab;
 
 import javafx.geometry.Point2D;
+import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 
@@ -19,6 +20,7 @@ public class BulletAnimated {
 
 	public void draw(GraphicsContext gc) {
 		gc.drawImage(image, getPosition().getX(), getPosition().getY(), SIZE, SIZE);
+		gc.strokeRect(position.getX(), position.getY(), SIZE, SIZE);
 	}
 
 	private final Point2D acceleration;
@@ -35,4 +37,8 @@ public class BulletAnimated {
 		return position;
 	}
 
+	public Rectangle2D getBoundingBox() {
+		return new Rectangle2D(position.getX(), position.getY(), SIZE,SIZE); 
+	}
+
 }
diff --git a/src/main/java/lab/Ufo.java b/src/main/java/lab/Ufo.java
new file mode 100644
index 0000000000000000000000000000000000000000..472c4f1920b7d8b5289eb3b998b7f5a35c198255
--- /dev/null
+++ b/src/main/java/lab/Ufo.java
@@ -0,0 +1,50 @@
+package lab;
+
+import java.util.Random;
+
+import javafx.geometry.Point2D;
+import javafx.geometry.Rectangle2D;
+import javafx.scene.canvas.GraphicsContext;
+import javafx.scene.image.Image;
+
+public class Ufo {
+
+	private static final Random RANDOM = new Random();
+	private Image image = new Image(this.getClass().getResourceAsStream("ufo-small.gif"));
+	private final World world;
+	private Point2D position;
+	private Point2D velocity;
+
+	public Ufo(World world) {
+		this(world, 
+				new Point2D(RANDOM.nextDouble(world.getWidth()), 
+						RANDOM.nextDouble(0, world.getHeight()*0.3)), 
+				new Point2D(RANDOM.nextDouble(70, 150), 0));
+	}
+
+	public Ufo(World world, Point2D position, Point2D velocity) {
+		this.world = world;
+		this.position = position;
+		this.velocity = velocity;
+	}
+
+	public void draw(GraphicsContext gc) {
+		gc.drawImage(image, getPosition().getX(), getPosition().getY());
+	}
+
+	public void changeDirection(){
+		velocity = velocity.multiply(-1);
+	}
+	public void simulate(double deltaT) {
+		position = position.add(velocity.multiply(deltaT));
+		position = new Point2D(position.getX()%world.getWidth(), position.getY());
+	}
+
+	protected Point2D getPosition() {
+		return position;
+	}
+	
+	public Rectangle2D getBoundingBox() {
+		return new Rectangle2D(position.getX(), position.getY(), image.getWidth(), image.getHeight()); 
+	}
+}
diff --git a/src/main/java/lab/World.java b/src/main/java/lab/World.java
index 3417a426a6350a8de5e55c437b5c22aa381d7225..6abd918876c6fdc2cd0552120a9b929735388ad9 100644
--- a/src/main/java/lab/World.java
+++ b/src/main/java/lab/World.java
@@ -1,5 +1,7 @@
 package lab;
 
+import java.util.Iterator;
+
 import javafx.geometry.Point2D;
 import javafx.scene.canvas.GraphicsContext;
 
@@ -12,6 +14,7 @@ public class World {
 	private final Bullet bullet;
 	private final BulletAnimated bullet2;
 	private final Cannon cannon;
+	private Ufo[] ufos;
 
 	public World(double width, double height) {
 		this.width = width;
@@ -19,6 +22,10 @@ public class World {
 		bullet = new Bullet(this, new Point2D(0, height), new Point2D(30, -30), new Point2D(0, 9.81));
 		bullet2 = new BulletAnimated(this, new Point2D(0, height), new Point2D(50, -80), new Point2D(0, 9.81));
 		cannon = new Cannon(this, new Point2D(0, height-20), -45);
+		ufos = new Ufo[5];
+		for (int i = 0; i < ufos.length; i++) {
+			ufos[i] = new Ufo(this);
+		}
 	}
 
 	public void draw(GraphicsContext gc) {
@@ -28,6 +35,9 @@ public class World {
 		bullet.draw(gc);
 		bullet2.draw(gc);
 		cannon.draw(gc);
+		for (int i = 0; i < ufos.length; i++) {
+			ufos[i].draw(gc);
+		}
 		gc.restore();
 	}
 
@@ -35,6 +45,14 @@ public class World {
 		bullet.simulate(deltaT);
 		bullet2.simulate(deltaT);
 		cannon.simulate(deltaT);
+		for (int i = 0; i < ufos.length; i++) {
+			ufos[i].simulate(deltaT);
+		}
+		for (Ufo ufo : ufos) {
+			if(ufo.getBoundingBox().intersects(bullet2.getBoundingBox())) {
+				ufo.changeDirection();
+			}
+		}
 	}
 
 	public double getWidth() {
diff --git a/src/main/resources/lab/ufo-small.gif b/src/main/resources/lab/ufo-small.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a1aca24e41f2d04912a45c703663c2b607f722dd
Binary files /dev/null and b/src/main/resources/lab/ufo-small.gif differ
diff --git a/src/main/resources/lab/ufo.gif b/src/main/resources/lab/ufo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..d07613c8999847572bffb44d7b161cffd874ca0f
Binary files /dev/null and b/src/main/resources/lab/ufo.gif differ
diff --git a/src/test/java/jez04/structure/test/ClassStructureTest.java b/src/test/java/jez04/structure/test/ClassStructureTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac5f14c0fe6cce1adc3586795317ea18888dc5fa
--- /dev/null
+++ b/src/test/java/jez04/structure/test/ClassStructureTest.java
@@ -0,0 +1,117 @@
+package jez04.structure.test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.jupiter.api.Test;
+import org.reflections.Configuration;
+import org.reflections.Reflections;
+import org.reflections.scanners.Scanners;
+import org.reflections.util.ConfigurationBuilder;
+
+import javafx.geometry.Rectangle2D;
+
+class ClassStructureTest {
+
+	@Test
+	void ufoClassEexistanceTest() {
+		Set<String> allClasses = getNameOfAllClasses();
+		assertTrue(allClasses.stream().anyMatch(c -> c.endsWith("Ufo")), "Class Ufo not found");
+	}
+
+	@Test
+	void ufoClassPropertiesTest() {
+		Set<String> allClasses = getNameOfAllClasses();
+		String ufoClassName = allClasses.stream().filter(c -> c.endsWith("Ufo")).findAny().orElse(null);
+		assertNotNull(ufoClassName, "Class Ufo not found");
+		try {
+			Class<?> ufoClass = Class.forName(ufoClassName);
+			List<Method> methods = Arrays.asList(ufoClass.getMethods());
+			assertTrue(methods.stream().anyMatch(m -> m.getName().contains("draw")), "No method draw");
+			assertTrue(methods.stream().anyMatch(m -> m.getName().contains("simulate")), "No method simulate");
+			assertTrue(methods.stream().anyMatch(m -> m.getName().contains("getBoundingBox")),
+					"No method getBoundingBox");
+			assertTrue(
+					methods.stream().filter(m -> m.getName().contains("getBoundingBox"))
+							.anyMatch(m -> m.getReturnType().equals(Rectangle2D.class)),
+					"Method getBoundingBox not return Rectangle2D");
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Test
+	void worldClassPropertyTest() {
+		Set<String> allClasses = getNameOfAllClasses();
+		String ufoClassName = allClasses.stream().filter(c -> c.endsWith("Ufo")).findAny().orElse(null);
+		String worldClassName = allClasses.stream().filter(c -> c.endsWith("World")).findAny().orElse(null);
+		assertNotNull(worldClassName, "Class World not found");
+		try {
+			Class<?> worldClass = Class.forName(worldClassName);
+			List<Field> fields = Arrays.asList(worldClass.getDeclaredFields());
+			Class<?> ufoClass = Class.forName(ufoClassName);
+			assertTrue(
+					fields.stream()
+							.anyMatch(f -> f.getType().isArray() && f.getType().getComponentType().equals(ufoClass)),
+					"No array of Ufo in World class");
+		} catch (ClassNotFoundException e) {
+			e.printStackTrace();
+		}
+	}
+
+	@Test
+	void drawingClassExistenceTest() {
+		Set<String> allClasses = getNameOfAllClasses();
+		int detectedClassCount = 0;
+		for (String className : allClasses) {
+			try {
+				Class<?> clazz = Class.forName(className);
+				List<Constructor<?>> constructorList = Arrays.asList(clazz.getConstructors());
+				List<Method> methodList = Arrays.asList(clazz.getMethods());
+				long drawMethodCount = methodList.stream().filter(m -> m.getName().contains("draw")).count();
+				long simulateMethodCount = methodList.stream().filter(m -> m.getName().contains("sim")).count();
+				if (!constructorList.isEmpty() && (drawMethodCount > 0 || simulateMethodCount > 0)) {
+					System.out.println("DETECT:" + className);
+					detectedClassCount++;
+				}
+			} catch (ClassNotFoundException e) {
+				System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage()));
+			}
+		}
+		assertTrue(detectedClassCount >= 2, "");
+	}
+
+	private Set<String> getNameOfAllClasses() {
+		List<String> initClassesName = Arrays.asList("lab.Routines", "lab.App", "lab.DrawingThread");
+		for (String className : initClassesName) {
+			try {
+				Class.forName(className);
+			} catch (ClassNotFoundException e) {
+				System.out.println(String.format("Class '%s' cannot be loaded: %s", className, e.getMessage()));
+			}
+		}
+		Set<String> allClasses = new HashSet<>();
+		for (Package p : Package.getPackages()) {
+			if (p.getName().startsWith("java.") || p.getName().startsWith("com.") || p.getName().startsWith("jdk.")
+					|| p.getName().startsWith("javafx.") || p.getName().startsWith("org.")
+					|| p.getName().startsWith("sun.") || p.getName().startsWith("javax.")
+					|| p.getName().startsWith("javassist")) {
+				continue;
+			}
+			System.out.println(p.getName());
+			Configuration conf = new ConfigurationBuilder().addScanners(Scanners.SubTypes.filterResultsBy(pc -> true))
+					.forPackages(p.getName());
+			Reflections reflections = new Reflections(conf);
+			allClasses.addAll(reflections.getAll(Scanners.SubTypes.filterResultsBy(c -> true)));
+		}
+		return allClasses;
+	}
+}