diff --git a/src/main/java/lab/Bullet.java b/src/main/java/lab/Bullet.java
index c8deeffecfa583112be32435adb9fa8957c12e01..2172d11a30b2cf2499ded7076f1a283fe755e799 100644
--- a/src/main/java/lab/Bullet.java
+++ b/src/main/java/lab/Bullet.java
@@ -1,36 +1,47 @@
 package lab;
 
 import javafx.geometry.Point2D;
+import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.paint.Color;
 
-public class Bullet {
+public class Bullet extends WorldEntity implements Collisionable{
 	private static final double SIZE = 20;
 
-	private final Point2D acceleration;
-
-	private final World world;
-	private Point2D position;
-	private Point2D velocity;
+	protected final Point2D acceleration;
+	protected Point2D velocity;
 
 	public Bullet(World world, Point2D position, Point2D velocity, Point2D acceleration) {
-		this.world = world;
-		this.position = position;
+		super(world, position);
 		this.velocity = velocity;
 		this.acceleration = acceleration;
 	}
 
-	public void draw(GraphicsContext gc) {
+	@Override
+	public void drawInternal(GraphicsContext gc) {
 		gc.setFill(Color.SILVER);
 		gc.fillOval(position.getX(), position.getY(), SIZE, SIZE);
 	}
 
+	@Override
 	public void simulate(double deltaT) {
 		position = position.add(velocity.multiply(deltaT));
 		velocity = velocity.add(acceleration.multiply(deltaT));
 	}
 
-	protected Point2D getPosition() {
-		return position;
+	@Override
+	public Rectangle2D getBoundingBox() {
+		return new Rectangle2D(position.getX(), position.getY(), SIZE, SIZE);
+	}
+
+	@Override
+	public boolean intersect(Rectangle2D another) {
+		return getBoundingBox().intersects(another);
 	}
+
+	@Override
+	public void hitBy(Collisionable another) {
+		
+	}
+
 }
diff --git a/src/main/java/lab/BulletAnimated.java b/src/main/java/lab/BulletAnimated.java
index cc7d236ffe7f1320897d2958303506ac5842c994..2134c1292e28308fbcac0caed6348e36c8b33412 100644
--- a/src/main/java/lab/BulletAnimated.java
+++ b/src/main/java/lab/BulletAnimated.java
@@ -5,40 +5,35 @@ import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 
-public class BulletAnimated {
+public class BulletAnimated extends Bullet {
 
 	private static final double SIZE = 40;
-	private final World world;
+	private final Point2D initVelocity;
+	private Cannon cannon;
 	private Image image = new Image(this.getClass().getResourceAsStream("fireball-transparent.gif"));
 
-	public BulletAnimated(World world, Point2D position, Point2D velocity, Point2D acceleration) {
-		this.world = world;
-		this.position = position;
-		this.velocity = velocity;
-		this.acceleration = acceleration;
+	public BulletAnimated(World world, Cannon cannon, Point2D position, Point2D velocity, Point2D acceleration) {
+		super(world, position, velocity, acceleration);
+		this.initVelocity = velocity;
+		this.cannon = cannon;
 	}
 
-	public void draw(GraphicsContext gc) {
+	@Override
+	public void drawInternal(GraphicsContext gc) {
 		gc.drawImage(image, getPosition().getX(), getPosition().getY(), SIZE, SIZE);
 		gc.strokeRect(position.getX(), position.getY(), SIZE, SIZE);
 	}
 
-	private final Point2D acceleration;
-
-	private Point2D position;
-	private Point2D velocity;
-
-	public void simulate(double deltaT) {
-		position = position.add(velocity.multiply(deltaT));
-		velocity = velocity.add(acceleration.multiply(deltaT));
-	}
-
-	protected Point2D getPosition() {
-		return position;
+	@Override
+	public void hitBy(Collisionable another) {
+		if (another instanceof Ufo) {
+			reload();
+		}
 	}
 
-	public Rectangle2D getBoundingBox() {
-		return new Rectangle2D(position.getX(), position.getY(), SIZE,SIZE); 
+	public void reload() {
+		position = cannon.getPosition();
+		velocity = initVelocity;
 	}
 
-}
+}
\ No newline at end of file
diff --git a/src/main/java/lab/Cannon.java b/src/main/java/lab/Cannon.java
index 0a1cf1746c5f2b37865d7231ec375ff705478e5a..59f6d2172d4e7debc36115666702dabde6e353cc 100644
--- a/src/main/java/lab/Cannon.java
+++ b/src/main/java/lab/Cannon.java
@@ -6,31 +6,27 @@ import javafx.scene.paint.Color;
 import javafx.scene.transform.Affine;
 import javafx.scene.transform.Transform;
 
-public class Cannon {
+public class Cannon extends WorldEntity{
 
 	private static final double LENGTH = 60;
 	private static final double WIDTH = 15;
-	private final World world;
-	private Point2D position;
 	private double angle;
 	private double angleDelta = -25;
 
 	public Cannon(World world, Point2D position, double angle) {
-		this.world = world;
-		this.position = position;
+		super(world, position);
 		this.angle = angle;
 	}
 
-	public void draw(GraphicsContext gc) {
-		gc.save();
+	@Override
+	public void drawInternal(GraphicsContext gc) {
 		gc.transform(new Affine(Transform.rotate(angle, position.getX(), position.getY() + WIDTH / 2)));
 		gc.setFill(Color.BROWN);
 		gc.fillRect(position.getX(), position.getY(), LENGTH, WIDTH);
-		gc.restore();
 	}
 
+	@Override
 	public void simulate(double deltaT) {
-		// do nothing yet
 		angle += angleDelta * deltaT;
 		if (angle >= 0 || angle <= -90) {
 			angleDelta = -angleDelta;
diff --git a/src/main/java/lab/Collisionable.java b/src/main/java/lab/Collisionable.java
new file mode 100644
index 0000000000000000000000000000000000000000..40a81570906acfe0a433fcda9f2bd47757b7cdf6
--- /dev/null
+++ b/src/main/java/lab/Collisionable.java
@@ -0,0 +1,13 @@
+package lab;
+
+import javafx.geometry.Rectangle2D;
+
+public interface Collisionable {
+
+	Rectangle2D getBoundingBox();
+
+	boolean intersect(Rectangle2D another);
+
+	void hitBy(Collisionable another);
+
+}
diff --git a/src/main/java/lab/DrawableSimulable.java b/src/main/java/lab/DrawableSimulable.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5b5d45871e5124a9aa526115a50d5e2e64fb401
--- /dev/null
+++ b/src/main/java/lab/DrawableSimulable.java
@@ -0,0 +1,9 @@
+package lab;
+
+import javafx.scene.canvas.GraphicsContext;
+
+public interface DrawableSimulable {
+	void draw(GraphicsContext gc);
+
+	void simulate(double deltaT);
+}
diff --git a/src/main/java/lab/Ufo.java b/src/main/java/lab/Ufo.java
index 472c4f1920b7d8b5289eb3b998b7f5a35c198255..78ea525119625e1f61f338e2811b29e1c7ee946d 100644
--- a/src/main/java/lab/Ufo.java
+++ b/src/main/java/lab/Ufo.java
@@ -7,44 +7,54 @@ import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 
-public class Ufo {
+public class Ufo extends WorldEntity implements Collisionable {
 
 	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)), 
+		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;
+		super(world, position);
 		this.velocity = velocity;
 	}
 
-	public void draw(GraphicsContext gc) {
+	@Override
+	public void drawInternal(GraphicsContext gc) {
 		gc.drawImage(image, getPosition().getX(), getPosition().getY());
 	}
 
-	public void changeDirection(){
+	public void changeDirection() {
 		velocity = velocity.multiply(-1);
 	}
+
+	@Override
 	public void simulate(double deltaT) {
 		position = position.add(velocity.multiply(deltaT));
-		position = new Point2D(position.getX()%world.getWidth(), position.getY());
+		position = new Point2D(position.getX() % world.getWidth(), position.getY());
+		if(position.getX() < -image.getWidth()) {
+			position = new Point2D(world.getWidth(), position.getY());
+		}
 	}
 
-	protected Point2D getPosition() {
-		return position;
-	}
-	
+	@Override
 	public Rectangle2D getBoundingBox() {
-		return new Rectangle2D(position.getX(), position.getY(), image.getWidth(), image.getHeight()); 
+		return new Rectangle2D(position.getX(), position.getY(), image.getWidth(), image.getHeight());
+	}
+
+	@Override
+	public boolean intersect(Rectangle2D another) {
+		return getBoundingBox().intersects(another);
+	}
+
+	@Override
+	public void hitBy(Collisionable another) {
+		if(another instanceof BulletAnimated || another instanceof Bullet) {
+			changeDirection();
+		}
 	}
 }
diff --git a/src/main/java/lab/World.java b/src/main/java/lab/World.java
index 6abd918876c6fdc2cd0552120a9b929735388ad9..253af0e99f6b6c1fcba88942cfb83f8052757639 100644
--- a/src/main/java/lab/World.java
+++ b/src/main/java/lab/World.java
@@ -11,20 +11,19 @@ public class World {
 
 	private final double height;
 
-	private final Bullet bullet;
-	private final BulletAnimated bullet2;
-	private final Cannon cannon;
-	private Ufo[] ufos;
+	private DrawableSimulable[] entities;
 
 	public World(double width, double height) {
 		this.width = width;
 		this.height = height;
-		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);
+		entities = new DrawableSimulable[8];
+		Cannon cannon = new Cannon(this, new Point2D(0, height - 20), -45);
+		entities[0] = cannon;
+		entities[1] = new Bullet(this, new Point2D(0, height), new Point2D(30, -30), new Point2D(0, 9.81));
+		entities[2] = new BulletAnimated(this, cannon, new Point2D(0, height), new Point2D(50, -80),
+				new Point2D(0, 9.81));
+		for (int i = 3; i < entities.length; i++) {
+			entities[i] = new Ufo(this);
 		}
 	}
 
@@ -32,25 +31,26 @@ public class World {
 		gc.clearRect(0, 0, width, height);
 
 		gc.save();
-		bullet.draw(gc);
-		bullet2.draw(gc);
-		cannon.draw(gc);
-		for (int i = 0; i < ufos.length; i++) {
-			ufos[i].draw(gc);
+		for (DrawableSimulable entity : entities) {
+			entity.draw(gc);
 		}
 		gc.restore();
 	}
 
 	public void simulate(double deltaT) {
-		bullet.simulate(deltaT);
-		bullet2.simulate(deltaT);
-		cannon.simulate(deltaT);
-		for (int i = 0; i < ufos.length; i++) {
-			ufos[i].simulate(deltaT);
+		for (DrawableSimulable entity : entities) {
+			entity.simulate(deltaT);
 		}
-		for (Ufo ufo : ufos) {
-			if(ufo.getBoundingBox().intersects(bullet2.getBoundingBox())) {
-				ufo.changeDirection();
+		for (int i = 0; i < entities.length; i++) {
+			if (entities[i] instanceof Collisionable c1) {
+				for (int j = i + 1; j < entities.length; j++) {
+					if (entities[j] instanceof Collisionable c2) {
+						if (c1.intersect(c2.getBoundingBox())) {
+							c1.hitBy(c2);
+							c2.hitBy(c1);
+						}
+					}
+				}
 			}
 		}
 	}
@@ -62,5 +62,5 @@ public class World {
 	public double getHeight() {
 		return height;
 	}
-	
+
 }
\ No newline at end of file
diff --git a/src/main/java/lab/WorldEntity.java b/src/main/java/lab/WorldEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..83228945ad45686a47585875f8cf626578e55f68
--- /dev/null
+++ b/src/main/java/lab/WorldEntity.java
@@ -0,0 +1,30 @@
+package lab;
+
+import javafx.geometry.Point2D;
+import javafx.scene.canvas.GraphicsContext;
+
+public abstract  class WorldEntity implements DrawableSimulable{
+
+	protected final World world;
+	protected Point2D position;
+
+	public WorldEntity(World world, Point2D position) {
+		this.world = world;
+		this.position = position;
+	}
+
+	@Override
+	public final void draw(GraphicsContext gc) {
+		gc.save();
+		drawInternal(gc);
+		gc.restore();
+	}
+	
+	public abstract void drawInternal(GraphicsContext gc);
+
+	public Point2D getPosition() {
+		return position;
+	}
+
+	
+}