Move Zorb
Zorb starts at (4, 4). Watch out for the rocks!
# Moving Around a Grid and Avoiding Obstacles by [kirupa](https://www.kirupa.com/me/index.htm) | filed under [Data Structures and Algorithms](https://www.kirupa.com/data_structures_algorithms/index.htm) In the [previous article](https://www.kirupa.com/data_structures_algorithms/moving_around_a_grid.htm), we took our first major look at working with grids. We learned how to move an element around and keep the movement constrained to the grid's boundaries. In this article, we are going to go one step further. We are going to get into the fun world of collision detection where our movement will be constrained by obstacles in the grid's path. The best part is that we are going to build upon everything we learned and even retain our propose, validate, and commit heuristic with only a few minor tweaks. Zorb is definitely in for an adventure. Onwards! ## What We're Going to Build Before we get all into it, let's play with the finished example first. Zorb is back at (4, 4), but his world now contains rocks: Interactive example: [Move Zorb around a 10 by 10 grid while avoiding rock obstacles and staying inside its boundaries](https://www.kirupa.com/data_structures_algorithms/examples/grid_movement_obstacles.htm?v=20260826-1) Try moving Zorb around just like before by using the arrow keys or WASD on a desktop. On a touch device, swipe across the grid or use the direction buttons. You can also [open our obstacle example in its own window](https://www.kirupa.com/data_structures_algorithms/examples/grid_movement_obstacles.htm?v=20260826-1)! A lot of the movement will be familiar to us from earlier, including not being able to leave the boundaries of our grid. What is new is that we now have obstacles inside the grid that Zorb can't go through. Try moving Zorb through a rock. You can't. The rock is an obstacle that you can only move around but not through. In the following sections, we'll learn more about how to detect obstacles within our grid and ensure Zorb isn't able to go through them. We are going to get a bit into the fun world of ***collision detection***. #### Note: What is Collision Detection? The textbook definition of ***collision*** detection is when two or more objects in a two-dimensional plane overlap or intersect:  This is not to be mistaken with ***Collison*** detection. Collison detection is an advanced algorithm that can detect Stripe Cofounders Patrick or John Collison in any static visual or moving scene ([image source](https://www.rte.ie/news/business/2025/1010/1537907-stripe-co-founders-receive-the-2025-impact-ireland-award/)):  Aren't you glad you are learning serious topics here and not on some other resource? ## Detecting Obstacles When we had Zorb moving around our grid initially, the entire grid was wide open. The only place he couldn't move through was an area outside of the grid itself. By adding obstacles like the rocks into our grid, we added an extra constraint that we need to handle. The way we handle it is by modifying our logic for evaluating each candidate cell. If you remember from earlier, the candidate cell is the cell we ***intend*** to move to but haven't ***actually committed*** to moving to yet. As part of evaluating each candidate cell, we now ask ourselves the following additional question: Is the candidate cell already occupied by something Zorb can't move through? The reason we ask this question is that a cell can now exist within our boundary and still be off-limits. For example, take a look at the following 5-by-5 grid:  Let's take the position (2, 2). This position is safely within our grid, so it passes our boundary check. But, this position does happen to contain a rock. This means Zorb still can't enter it:  This gives every requested move two possible collision checks: - A **boundary collision** check to see if the candidate is outside the grid - An **obstacle collision** check to see if the candidate is inside the grid but occupied If either check returns an invalid move, we reject the candidate and leave Zorb's current position untouched. This entire sequence can be visualized as follows:  Getting back to our grid, suppose Zorb is standing at (2, 1) and we ask him to move right:  The right offset is [1, 0], so our existing movement math proposes (3, 1) as Zorb's new position:  This is just a candidate position, so we haven't actually moved Zorb yet. We are just inspecting the destination to see if it can be a valid move or not. When we do our collision checks, the ***boundary check*** answers true because (3, 1) exists within our grid. Our new ***obstacle check*** answers true because a rock occupies it. Because that second check stops the move, our candidate position is rejected. ## Putting it All Together Now that we have seen how to detect obstacles inside our grid, let's get into the implementation a bit and talk about how we will want to represent obstacles in the first place. Put differently, our code needs to know where the obstacles are. The approach we will take is one where we store each rock's coordinate in a Set: ```js const obstacles = new Set([ "1,1", "2,1", "3,1", "5,4", "1,5", "2,5", "3,5" ]); ``` Each coordinate becomes a string with the horizontal position first and the vertical position second. The rock at (5, 4) is stored as "5,4". Why use a Set? We repeatedly need to ask one yes-or-no question: Does this exact coordinate appear in our obstacle collection? A Set is built for that kind of membership check. It also prevents duplicate coordinates from creating duplicate obstacles. You can learn more about sets in my [Diving into Sets](https://www.kirupa.com/javascript/sets.htm) article. It may seem strange to use a string to represent numerical coordinates. To simplify our detection logic and not worry about strings, we will hide the string formatting inside a small helper: ```js function isObstacle(x, y) { return obstacles.has(`${x},${y}`); } ``` The rest of our movement code can work with normal x and y values. It doesn't need to care how the obstacle collection stores them. ### Starting With Our Boundary Example We are going to build directly on the final example from the earlier boundary tutorial. If you already completed that version, make a copy of your file and keep going. Otherwise, create a new file named grid_movement_obstacles.htm and add the following starter code: ```html
Zorb starts at (4, 4). Watch out for the rocks!