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/DrawingThread.java b/src/main/java/lab/DrawingThread.java
index a53ad11bc787100d9ee9201b9edd4e831e80dd54..f5e0529bec78c3a83ae93743b43a80eff542258a 100644
--- a/src/main/java/lab/DrawingThread.java
+++ b/src/main/java/lab/DrawingThread.java
@@ -19,7 +19,7 @@ public class DrawingThread extends AnimationTimer {
 	}
 
 	/**
-	  * Draws objects into the canvas. Put you code here. 
+	 * Draws objects into the canvas. Put you code here.
 	 */
 	@Override
 	public void handle(long now) {
diff --git a/src/main/java/lab/Level.java b/src/main/java/lab/Level.java
index f4a0be293d3d4822b5a6bf4de70972303f7d0a8b..d6f9031fc674d48d37017570351da1a0f5501291 100644
--- a/src/main/java/lab/Level.java
+++ b/src/main/java/lab/Level.java
@@ -7,45 +7,45 @@ import javafx.scene.paint.Color;
 
 public class Level {
 
-	private NicerObstacle nicerObstacle;
-	private Obstacle obstacle1;
-	private Obstacle obstacle2;
-	private Player player;
 	private double width;
 	private double height;
-	private Monster[] monsters;
+	private DrawableSimulable[] entities;
 
 	public Level(double width, double height) {
 		this.width = width;
 		this.height = height;
-		nicerObstacle = new NicerObstacle(this, new Point2D(20, 150));
-		obstacle1 = new Obstacle(this, new Point2D(300, 200), new Dimension2D(80, 40));
-		obstacle2 = new Obstacle(this);
-		player = new Player(this, new Point2D(20, 250), new Point2D(100, -20));
-		monsters = new Monster[5];
-		for (int i = 0; i < monsters.length; i++) {
-			monsters[i] = new Monster(this);
+		entities = new DrawableSimulable[9];
+		entities[0] = new NicerObstacle(this, new Point2D(20, 150));
+		entities[1] = new Obstacle(this, new Point2D(300, 200), new Dimension2D(80, 40));
+		entities[2] = new Obstacle(this);
+		entities[3] =  new Player(this, new Point2D(20, 250), new Point2D(100, -20));
+		for (int i = 4; i < entities.length; i++) {
+			entities[i] = new Monster(this);
 		}
 	}
 
 	public void draw(GraphicsContext gc) {
 		gc.setFill(Color.WHITE);
 		gc.clearRect(0, 0, width, height);
-		nicerObstacle.draw(gc);
-		obstacle1.draw(gc);
-		obstacle2.draw(gc);
-		player.draw(gc);
-		for (Monster monster : monsters) {
-			monster.draw(gc);
+		for (DrawableSimulable entity : entities) {
+			entity.draw(gc);
 		}
 	}
 
 	public void simulate(double delay) {
-		player.simulate(delay);
-		for (Monster monster : monsters) {
-			monster.simulate(delay);
-			if (monster.getBoundingBox().intersects(player.getBoundingBox())) {
-				monster.changeDirection();
+		for (DrawableSimulable entity : entities) {
+			entity.simulate(delay);
+		}
+		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);
+						}
+					}
+				}
 			}
 		}
 	}
diff --git a/src/main/java/lab/Monster.java b/src/main/java/lab/Monster.java
index 88144d128fbcfe9ea6e9933c0ce4111c7553fda3..9c4cf34979afdae517461e55371771d050a57cd6 100644
--- a/src/main/java/lab/Monster.java
+++ b/src/main/java/lab/Monster.java
@@ -7,17 +7,15 @@ import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 
-public class Monster {
+public class Monster extends WorldEntity implements Collisionable {
 
 	private static final Random RANDOM = new Random();
 
-	private Level level;
 	private Image image;
-	private Point2D position;
 	private Point2D speed;
 
 	public Monster(Level level) {
-		this.level = level;
+		super(level, new Point2D(0, 0));
 		image = new Image(getClass().getResourceAsStream("red-monster.gif"));
 		position = new Point2D(level.getWidth() * 0.5 + RANDOM.nextDouble(level.getWidth() * 0.5 - image.getWidth()),
 				RANDOM.nextDouble(level.getHeight()));
@@ -25,25 +23,39 @@ public class Monster {
 	}
 
 	public Monster(Level level, Point2D position) {
-		this.level = level;
-		this.position = position;
+		super(level, position);
 		image = new Image(getClass().getResourceAsStream("spike.gif"));
 	}
 
-	public void draw(GraphicsContext gc) {
+	public void drawInternal(GraphicsContext gc) {
 		gc.drawImage(image, position.getX(), position.getY());
 	}
 
 	public void changeDirection() {
 		speed = speed.multiply(-1);
 	}
+
 	public void simulate(double delay) {
 		position = position.add(speed.multiply(delay / 1_000_000_000));
 		position = new Point2D(position.getX(), position.getY() % level.getHeight());
 	}
 
+	@Override
 	public Rectangle2D getBoundingBox() {
 		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 Player) {
+			changeDirection();
+		}
+
+	}
+
 }
diff --git a/src/main/java/lab/NicerObstacle.java b/src/main/java/lab/NicerObstacle.java
index fd3988696dd593f8f75148de0e3ee62687abd1a7..a0a6c27249d75faa000874c7393d9a86dd10be21 100644
--- a/src/main/java/lab/NicerObstacle.java
+++ b/src/main/java/lab/NicerObstacle.java
@@ -4,24 +4,21 @@ import javafx.geometry.Point2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.image.Image;
 
-public class NicerObstacle {
+public class NicerObstacle extends WorldEntity {
 
-	private Level level;
 	private Image image;
-	private Point2D position;
 
 	public NicerObstacle(Level level, Point2D position) {
-		this.level = level;
-		this.position = position;
+		super(level, position);
 		image = new Image(getClass().getResourceAsStream("spike.gif"));
 	}
 
-	public void draw(GraphicsContext gc) {
+	public void drawInternal(GraphicsContext gc) {
 		gc.drawImage(image, position.getX(), position.getY());
 	}
 
 	public void simulate(double delay) {
-		
+
 	}
 
 }
diff --git a/src/main/java/lab/Obstacle.java b/src/main/java/lab/Obstacle.java
index 0c0fe1dec4cff3b459b58f263f9f42e729bec719..09a46c321649bd33a91df746d60c5d356e1eb187 100644
--- a/src/main/java/lab/Obstacle.java
+++ b/src/main/java/lab/Obstacle.java
@@ -5,10 +5,8 @@ import javafx.geometry.Point2D;
 import javafx.scene.canvas.GraphicsContext;
 import javafx.scene.paint.Color;
 
-public class Obstacle {
+public class Obstacle extends WorldEntity {
 
-	private Level level;
-	private Point2D position;
 	private Dimension2D size;
 
 	public Obstacle(Level level) {
@@ -16,19 +14,16 @@ public class Obstacle {
 	}
 
 	public Obstacle(Level level, Point2D position, Dimension2D size) {
-		this.level = level;
-		this.position = position;
+		super(level, position);
 		this.size = size;
 	}
 
-	public void draw(GraphicsContext gc) {
-		gc.save();
+	public void drawInternal(GraphicsContext gc) {
 		gc.setFill(Color.BLUEVIOLET);
 		gc.setStroke(Color.RED);
 		gc.setLineWidth(3);
 		gc.fillRect(position.getX(), position.getY(), size.getWidth(), size.getHeight());
 		gc.strokeRect(position.getX(), position.getY(), size.getWidth(), size.getHeight());
-		gc.restore();
 	}
 
 	public void simulate(double delay) {
diff --git a/src/main/java/lab/Player.java b/src/main/java/lab/Player.java
index db14f4ad79dcf628d8f9d8717dab67b8a80bef06..7450176246da92dce064b66301358f373d964842 100644
--- a/src/main/java/lab/Player.java
+++ b/src/main/java/lab/Player.java
@@ -1,5 +1,7 @@
 package lab;
 
+import java.util.Random;
+
 import javafx.geometry.Point2D;
 import javafx.geometry.Rectangle2D;
 import javafx.scene.canvas.GraphicsContext;
@@ -7,19 +9,16 @@ import javafx.scene.paint.Color;
 import javafx.scene.transform.Affine;
 import javafx.scene.transform.Rotate;
 
-public class Player {
-	private Level level;
-	private Point2D position;
+public class Player extends WorldEntity implements Collisionable {
+	private static final Random RANDOM = new Random();
 	private Point2D speed;
 
 	public Player(Level level, Point2D position, Point2D speed) {
-		this.level = level;
-		this.position = position;
+		super(level, position);
 		this.speed = speed;
 	}
 
-	public void draw(GraphicsContext gc) {
-		gc.save();
+	public void drawInternal(GraphicsContext gc) {
 		Point2D center = position.add(10, 25);
 		double angle = speed.angle(1, 0);
 		if (speed.getY() < 0) {
@@ -33,16 +32,30 @@ public class Player {
 		gc.fillRect(center.getX(), center.getY(), 50, 1);
 		gc.fillRoundRect(position.getX(), position.getY(), 20, 50, 20, 20);
 		gc.strokeRoundRect(position.getX(), position.getY(), 20, 50, 20, 20);
-		gc.restore();
 	}
 
 	public void simulate(double delay) {
-		position = position.add(speed.multiply(delay/1_000_000_000));
+		position = position.add(speed.multiply(delay / 1_000_000_000));
 //		speed = speed.multiply(0.9994);
 	}
 
+	@Override
 	public Rectangle2D getBoundingBox() {
 		return new Rectangle2D(position.getX(), position.getY(), 20, 50);
 	}
 
+	@Override
+	public boolean intersect(Rectangle2D another) {
+		return getBoundingBox().intersects(another);
+	}
+
+	@Override
+	public void hitBy(Collisionable another) {
+		if (another instanceof Monster) {
+			position = new Point2D(RANDOM.nextDouble(0, level.getWidth() * 0.4),
+					RANDOM.nextDouble(level.getHeight() * 0.5, level.getHeight()));
+		}
+
+	}
+
 }
diff --git a/src/main/java/lab/WorldEntity.java b/src/main/java/lab/WorldEntity.java
new file mode 100644
index 0000000000000000000000000000000000000000..cdeebffe0ebfa084f70e09641748a84d761aa995
--- /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 Level level;
+	protected Point2D position;
+
+	public WorldEntity(Level level, Point2D position) {
+		this.level = level;
+		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;
+	}
+
+	
+}