diff --git a/boids.mjs b/boids.mjs
index 156e993..94f442c 100644
--- a/boids.mjs
+++ b/boids.mjs
@@ -1,8 +1,52 @@
-import Vector from './vector.mjs';
+import {Vector} from './geometry.mjs';
+
+// Outline of the shape of a boid when angled at 0 rad
+const boidShape = [
+    new Vector(1, 0),
+    new Vector(-.5, .5),
+    new Vector(-.5, -.5),
+    new Vector(1, 0),
+];
+const boidShapeLength = boidShape.length;
+
+class Boid
+{
+    constructor(params, center)
+    {
+        this.params = params;
+        this.pos = center.clone();
+        this.vel = new Vector(Math.random() - 0.5, Math.random() - 0.5);
+        this.register = new Vector(0, 0);
+    }
+
+    draw(ctx)
+    {
+        const transformed = this.register;
+        const angle = this.vel.angle();
+        let isFirst = true;
+
+        for (let j = 0; j < boidShapeLength; ++j)
+        {
+            transformed.x = boidShape[j].x;
+            transformed.y = boidShape[j].y;
+            transformed.rotate(angle).mul(this.params.radius).add(this.pos);
+
+            if (isFirst)
+            {
+                ctx.moveTo(transformed.x, transformed.y);
+                isFirst = false;
+            }
+            else
+            {
+                ctx.lineTo(transformed.x, transformed.y);
+            }
+        }
+    }
+}
 
 class Boids
 {
-    constructor(canvas, params = {})
+    constructor(canvas, obstacles, params = {})
     {
         this.canvas = canvas;
         this.ctx = canvas.getContext('2d');
@@ -27,13 +71,18 @@ class Boids
         this.height = canvas.height;
 
         // Current center point of the canvas
-        this.center = new Vector(canvas.width / 2, canvas.height / 2);
+        this.center = null;
 
         // Last time where the canvas was repainted
         this.lastTime = null;
 
         // List of active simulated boids
         this.boids = [];
+        this.boidsLength = 0;
+
+        // List of obstacles
+        this.obstacles = obstacles;
+        this.obstaclesLength = this.obstacles.length;
 
         // Vector registers used for holding temporary values
         this.registers = [
@@ -46,14 +95,7 @@ class Boids
         // otherwise, null
         this.animationId = null;
 
-        // Outline of the shape of a boid when angled at 0 rad
-        this.boidShape = [
-            new Vector(1, 0),
-            new Vector(-.5, .5),
-            new Vector(-.5, -.5),
-            new Vector(1, 0),
-        ];
-        this.boidShapeLength = this.boidShape.length;
+        this._afterResize();
     }
 
     /** Change the canvas’ dimensions */
@@ -64,16 +106,22 @@ class Boids
 
         this.width = width;
         this.height = height;
-        this.center = new Vector(width / 2, height / 2);
+
+        this._afterResize();
+    }
+
+    _afterResize()
+    {
+        this.center = new Vector(this.width / 2, this.height / 2);
+        this.ctx.resetTransform();
+        this.ctx.translate(this.center.x, this.center.y);
     }
 
     /** Introduce a new boid in the simulation. */
     add(center)
     {
-        this.boids.push({
-            pos: center.clone(),
-            vel: new Vector(Math.random() - 0.5, Math.random() - 0.5),
-        });
+        this.boids.push(new Boid(this.params, center));
+        this.boidsLength += 1;
     }
 
     /** Start the simulation. */
@@ -125,9 +173,9 @@ class Boids
      */
     _update(delta)
     {
-        const length = this.boids.length;
+        const boidsLength = this.boidsLength;
 
-        for (let i = 0; i < length; ++i)
+        for (let i = 0; i < boidsLength; ++i)
         {
             const me = this.boids[i];
 
@@ -137,7 +185,9 @@ class Boids
 
             let visibles = 0;
 
-            for (let j = 0; j < length; ++j)
+            // Compute mean flock position and velocity and compute
+            // the repel force
+            for (let j = 0; j < boidsLength; ++j)
             {
                 if (i != j)
                 {
@@ -188,6 +238,17 @@ class Boids
                                   .mul(this.params.matchAccel));
             }
 
+            // Avoid obstacles
+            for (let j = 0; j < this.obstaclesLength; ++j)
+            {
+                const obstacle = this.obstacles[j];
+
+                if (obstacle.intersect(me.pos, this.params.radius))
+                {
+                    me.vel.sub(obstacle.center).add(me.pos);
+                }
+            }
+
             // Do not surpass maximum speed
             const speed = me.vel.normSquared();
 
@@ -207,42 +268,32 @@ class Boids
      */
     _draw()
     {
-        const length = this.boids.length;
-        const transformed = this.registers[0];
+        const boidsLength = this.boidsLength;
+        const obstaclesLength = this.obstaclesLength;
 
-        this.ctx.clearRect(0, 0, this.width, this.height);
+        this.ctx.clearRect(
+            -this.width / 2, -this.height / 2,
+            this.width, this.height
+        );
 
-        // Draw each boid’s head following the angle of its course
+        // Draw obstacles
+        this.ctx.fillStyle = '#dddddd';
         this.ctx.beginPath();
-        this.ctx.fillStyle = this.params.color;
 
-        for (let i = 0; i < length; ++i)
+        for (let i = 0; i < obstaclesLength; ++i)
         {
-            const boid = this.boids[i];
-            const angle = boid.vel.angle();
-            let isFirst = true;
+            this.obstacles[i].draw(this.ctx);
+        }
 
-            for (let j = 0; j < this.boidShapeLength; ++j)
-            {
-                transformed.x = this.boidShape[j].x;
-                transformed.y = this.boidShape[j].y;
+        this.ctx.fill();
 
-                transformed
-                    .rotate(angle)
-                    .mul(this.params.radius)
-                    .add(this.center)
-                    .add(boid.pos);
+        // Draw boids
+        this.ctx.fillStyle = this.params.color;
+        this.ctx.beginPath();
 
-                if (isFirst)
-                {
-                    this.ctx.moveTo(transformed.x, transformed.y);
-                    isFirst = false;
-                }
-                else
-                {
-                    this.ctx.lineTo(transformed.x, transformed.y);
-                }
-            }
+        for (let i = 0; i < boidsLength; ++i)
+        {
+            this.boids[i].draw(this.ctx);
         }
 
         this.ctx.fill();
diff --git a/vector.mjs b/geometry.mjs
similarity index 57%
rename from vector.mjs
rename to geometry.mjs
index d26fb8c..d1dcda5 100644
--- a/vector.mjs
+++ b/geometry.mjs
@@ -1,4 +1,4 @@
-class Vector
+export class Vector
 {
     constructor(x = 0, y = 0)
     {
@@ -82,4 +82,52 @@ class Vector
     }
 }
 
-export default Vector;
+export class Rectangle
+{
+    constructor(x, y, w, h)
+    {
+        this.x = x;
+        this.y = y;
+        this.w = w;
+        this.h = h;
+        this.center = new Vector(x + w / 2, y + h / 2);
+    }
+
+    intersect(point, radius)
+    {
+        return (
+            point.x >= this.x - radius
+            && point.x < this.x + this.w + radius
+            && point.y >= this.y - radius
+            && point.y < this.y + this.h + radius
+        );
+    }
+
+    draw(ctx)
+    {
+        ctx.rect(this.x, this.y, this.w, this.h);
+    }
+}
+
+export class Circle
+{
+    constructor(x, y, r)
+    {
+        this.r = r;
+        this.center = new Vector(x, y);
+    }
+
+    intersect(point, radius)
+    {
+        return (
+            Vector.distSquared(this.center, point)
+            <= (this.r + radius) * (this.r + radius)
+        );
+    }
+
+    draw(ctx)
+    {
+        ctx.moveTo(this.center.x + this.r, this.center.y);
+        ctx.arc(this.center.x, this.center.y, this.r, 0, 2 * Math.PI, false);
+    }
+}
diff --git a/index.html b/index.html
index 4a36eb3..bdaa98d 100644
--- a/index.html
+++ b/index.html
@@ -25,17 +25,21 @@