{
  "attachments": [
    "248c3837f026.jpg",
    "509065bf8ee4.jpg",
    "4320aae7d49c.jpg"
  ],
  "title": "Parsec Patrol Diaries: How To Avoid Smashing Into Things",
  "author": "lmorchard",
  "layout": "post",
  "permalink": "/2014/01/18/ppd-avoidance",
  "dsq_thread_id": [
    2140934375
  ],
  "categories": [
    "Uncategorized"
  ],
  "tags": [
    "html5",
    "parsecpatrol",
    "webdev"
  ],
  "year": "2014",
  "month": "01",
  "day": "18",
  "isDir": true,
  "slug": "ppd-avoidance",
  "type": "entry",
  "date": "2014-01-18T19:00:00.000Z",
  "postName": "2014-01-18-ppd-avoidance",
  "html": "<div id=\"toc_container\" class=\"toc_wrap_right no_bullets\">\n  <p class=\"toc_title\">\n    Contents\n  </p>\n  \n  <ul class=\"toc_list\">\n    <li>\n      <a href=\"#Where_to_start\"><span class=\"toc_number toc_depth_1\">1</span> Where to start?</a>\n    </li>\n    <li>\n      <a href=\"#Waypoint_Graphs_Navigation_Meshes\"><span class=\"toc_number toc_depth_1\">2</span> Waypoint Graphs &amp; Navigation Meshes</a>\n    </li>\n    <li>\n      <a href=\"#A_Search\"><span class=\"toc_number toc_depth_1\">3</span> A* Search</a>\n    </li>\n    <li>\n      <a href=\"#Trigonometry_Refresher\"><span class=\"toc_number toc_depth_1\">4</span> Trigonometry Refresher</a>\n    </li>\n    <li>\n      <a href=\"#Spaceships_with_Whiskers\"><span class=\"toc_number toc_depth_1\">5</span> Spaceships with Whiskers</a>\n    </li>\n    <li>\n      <a href=\"#Functions_with_Potential\"><span class=\"toc_number toc_depth_1\">6</span> Functions with Potential</a>\n    </li>\n    <li>\n      <a href=\"#Further_research\"><span class=\"toc_number toc_depth_1\">7</span> Further research</a>\n    </li>\n  </ul>\n\n\n</div>\n\n\n\n<p>I made a hero ship with beam weapons. I even built drifting asteroids that handle smashing into things. What gave me trouble was finding a way to teach enemy ships how to <em>avoid</em> smashing into things. You know, not perfectly, but just well enough to seem vaguely cunning and worth pretending to outsmart in a video game.</p>\n<!--more-->\n\n\n\n<p>In developing Parsec Patrol, I’ve never had plans or specifications so much as doodles &amp; daydreams. One day I imagined this scene where I’m piloting the hero ship through a shifting maze of asteroids, a dozen enemy scout ships in fast pursuit. I dodge &amp; weave through the rocks, just barely negotiating the gaps. One by one, the baddies vanish in bursts of light &amp; debris: Some succumb to my beam weapons, while others smash into rocks or bungle into each other. Classic space dogfight material, here.</p>\n<h3 id=\"where-to-start\"><span id=\"Where_to_start\">Where to start?</span></h3>\n<p>From years of playing &amp; tinkering with shooters like Unreal &amp; Quake, I had a vague notion of bots needing “pathfinding” algorithms to find their way around levels. So, I started hitting Google, looking to see what I could find and understand just well enough to eliminate from consideration or flag for a deeper dive.</p>\n<h3 id=\"waypoint-graphs--navigation-meshes\"><span id=\"Waypoint_Graphs_Navigation_Meshes\">Waypoint Graphs &amp; Navigation Meshes</span></h3>\n<p>Some of the first pathfinding tools I started reading about were *waypoint graphs *and <em>navigation meshes</em>. It turns out that some bots rely on cheat sheets: map-specific and manually placed points or polygons, traversed to get from point A to point B. Generally it’s a cheap way to make bots seem like they know where they’re going, because a human being does most of the work up front.</p>\n<div style=\"width: 322px\" class=\"wp-caption alignleft\">\n  <a href=\"http://www.ai-blog.net/archives/000152.html\"><img class=\"    \" alt=\"\" src=\"248c3837f026.jpg\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    Waypoint graph\n  </p>\n</div>\n\n\n\n<div style=\"width: 322px\" class=\"wp-caption alignleft\">\n  <a href=\"www.ai-blog.net/archives/000152.html\"><img class=\"    \" alt=\"\" src=\"509065bf8ee4.jpg\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    Navigation mesh\n  </p>\n</div>\n\n\n\n<p>Unfortunately, an asteroid field is not like a Quake map. In Parsec Patrol, the clusters of rocks are randomly generated and only get more chaotic as the rocks drift and collide. There’s just no way to handcraft a map for robots in this scenario.</p>\n<h3 id=\"a-search\"><span id=\"A_Search\">A* Search</span></h3>\n<div style=\"width: 220px\" class=\"wp-caption alignright\">\n  <a href=\"http://en.wikipedia.org/wiki/A*_search_algorithm\"><img class=\"   \" alt=\"\" src=\"http://upload.wikimedia.org/wikipedia/commons/5/5d/Astar_progress_animation.gif\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    A* Search animation from Wikipedia\n  </p>\n</div>\n\n\n\n<p>Another approach I found was the <a href=\"http://en.wikipedia.org/wiki/A*_search_algorithm\">A* Search algorithm</a>. There are some <a href=\"http://buildnewgames.com/astar/\">great write-ups on this algorithm</a> out there, so I won’t try making a hash of it here. You can also <a href=\"http://easystar.nodejitsu.com/demo.html\">try out some implementations in JavaScript</a>.</p>\n<p>This algorithm seems best suited for navigating graphs with few connections between nodes – a 2D grid, for example, with 8 exits per cell. If I ever wrote a roguelike dungeon crawler, this would be my jam.</p>\n<p>Unfortunately, the world of Parsec Patrol uses a continuous coordinate system, rather than a map of discrete grid cells. And, it seems like a waste to try to find a complete path from point A to point B for this game – because that path is likely to be made obsolete from moment to moment. So, how about trying to work out the best move for just the next moment?</p>\n<h3 id=\"trigonometry-refresher\"><span id=\"Trigonometry_Refresher\">Trigonometry Refresher</span></h3>\n<div style=\"width: 203px\" class=\"wp-caption alignright\">\n  <a href=\"http://www.hyperionedge.com/2010/04/tron-13-lightcycle-game-grid.html\"><img class=\"     \" alt=\"\" src=\"4320aae7d49c.jpg\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    Right angles only, for Light Cycles\n  </p>\n</div>\n\n\n\n<p>I took a short break from research and decided to see what I could come up with on my own. What does it mean to avoid an obstacle?</p>\n<p>One way to avoid a collision is to make a full right angle turn, into a perpendicular course. That works on the Light Cycle Grid, but it’s a bit extreme. So, I need an angle between 0 and 90 degrees with respect to the ship’s vector and the obstacle.</p>\n<p>So, I decided to give myself a refresher course in trigonometry:</p>\n<div id=\"attachment_1206\" style=\"width: 510px\" class=\"wp-caption aligncenter\">\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/trig2.png\"><img class=\"size-full wp-image-1206 \" alt=\"I am not good at math\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/trig2.png\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    I am not good at math\n  </p>\n</div>\n\n\n\n<p>These scribblings are not meant to impress. Rather, this shows how much I forgot about high school trigonometry. Nonetheless, I worked out how to <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1034\">calculate an appropriate target angle that would miss the obstacle by a defined distance</a>. Having that angle meant that I could turn less drastically while steering for avoidance.</p>\n<p>It was a small victory – and now I remember <a href=\"http://www.mathwords.com/s/sohcahtoa.htm\">SOHCAHTOA</a> again.</p>\n<h3 id=\"spaceships-with-whiskers\"><span id=\"Spaceships_with_Whiskers\">Spaceships with Whiskers</span></h3>\n<p>Now that I had a way to calculate a steering angle that avoided smashing into something, I needed a way to know when I was headed for a collision.</p>\n<p>If I were trying to build a physical robot, I might add some whiskers to detect the nearest obstacle and trigger a turn. But, how to do that in the virtual game world? A little bit of research brought me to the notion of using <a href=\"https://www.google.com/search?q=collision+detection+ray+casting\">raycasting combined with collision detection</a>, something like this:</p>\n<div id=\"attachment_1191\" style=\"width: 394px\" class=\"wp-caption aligncenter\">\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/2014-01-16-21.18.36.jpg\"><img class=\"wp-image-1191 \" alt=\"\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/2014-01-16-21.18.36-1024x768.jpg\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    Spaceships with whiskers!\n  </p>\n</div>\n\n\n\n<p><a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L987\">The algorithm I came up with</a> constructs a vector on each side of the ship. <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1008\">I project circles along the vectors</a>, with a radius based on the margin by which I hoped to avoid obstacles. In order from nearest to farthest, <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1015\">I run collision detection for each of the circles</a>. The search stops with the first hit, using the nearest obstacle found.</p>\n<p>So, when my ship finds an obstacle with the whiskers, calculate the avoidance angle, and set that as the steering target for the current game tick. This ends up much more lightweight than finding a complete optimal path, and it can react from moment to moment to the changing game environment.</p>\n<div id=\"attachment_1203\" style=\"width: 510px\" class=\"wp-caption aligncenter\">\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/whiskers-twitch-3.gif.gif\"><img class=\"size-full wp-image-1203 \" alt=\"Whiskers are twitchy\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/whiskers-twitch-3.gif.gif\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    My whiskers are wiggly\n  </p>\n</div>\n\n\n\n<p>Unfortunately, this scheme looks funny in action: Since <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1085\">I revert back to target seeking after resolving obstacle avoidance</a>, the enemy ships wiggle as they oscillate between the two strategies. Tracking straight toward the target often brings the ship into collision course – so once an avoidance course is achieved, target tracking turns right back into the obstacle.</p>\n<h3 id=\"functions-with-potential\"><span id=\"Functions_with_Potential\">Functions with Potential</span></h3>\n<p>What I really wanted was some way for these ships to take many nearby obstacles into account along with seeking toward the target, and come up with a smoothly changing steering angle that seemed not entirely stupid or goofy looking.</p>\n<p>After some further research, I started reading <a href=\"http://www.amazon.com/gp/product/0596005555/ref=as_li_ss_tl?ie=UTF8&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596005555&amp;linkCode=as2&amp;tag=0xdecafbad01-20\">AI for Game Developers</a><img class=\"tvatbijdbdexywujcjjd svuitzfraxzoondqiznf pybiawadmcxjgjpdvhto\" style=\"border: none !important; margin: 0px !important;\" alt=\"\" src=\"http://ir-na.amazon-adsystem.com/e/ir?t=0xdecafbad01-20&amp;l=as2&amp;o=1&amp;a=0596005555\" width=\"\" height=\"\" border=\"0\"> by David M. Bourg and Glenn Seemann. In Chapter 5, I found code using <a href=\"http://en.wikipedia.org/wiki/Lennard-Jones_potential\">the Lennard-Jones potential function</a> to drive avoidance of multiple obstacles and target seeking all in one algorithm.</p>\n<div style=\"width: 442px\" class=\"wp-caption aligncenter\">\n  <a href=\"http://chemwiki.ucdavis.edu/Physical_Chemistry/Quantum_Mechanics/Atomic_Theory/Intermolecular_Forces/Lennard-Jones_Potential\"><img alt=\"\" src=\"http://chemwiki.ucdavis.edu/@api/deki/files/8914/Figure_B.jpg\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    Serious business, this potential function\n  </p>\n</div>\n\n\n\n<p>A thumbnail sketch of this function with respect to the game goes something like this: Entities can repel &amp; attract each other. Repulsion &amp; attraction change over distance. For example, swarming entities can attract at long distance and repel when too close.</p>\n<p>Here’s what <a href=\"http://en.wikipedia.org/wiki/Lennard-Jones_potential#AB_form\">the simplified AB form of this function</a> looks like in my code:</p>\n<p><code>U = (-A/Math.pow(d,n)) + (B/Math.pow(d,m))</code></p>\n<p>There are 4 constants in this function:</p>\n<ul>\n<li><code>A</code> – magnitude of attraction</li>\n<li><code>n</code> – attenuation of attraction over distance</li>\n<li><code>B</code> – magnitude of repulsion</li>\n<li><code>m</code> – attenuation of repulsion over distance</li>\n</ul>\n<p>Pick values for these constants, and you’ve got a function that yields a positive (repulsion) or negative (attraction) value for any given distance (<code>d</code>). So far, <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/sketches/steering.coffee#L85\">I’ve just used trial &amp; error to find values for these constants</a>.</p>\n<p>To apply this function, <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L904\">I search for obstacles within a certain radius of the ship</a>. That limits the number of calculations, because far-flung obstacles have no significant influence. For each nearby obstacle, <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L868\">I calculate distance and apply the potential function</a>. I then <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L877\">calculate a unit vector from each obstacle to the ship and multiply by the result of the potential function</a>.</p>\n<p>Repeat all the above for targets, regardless of range, and with function constants that yield attraction rather than repulsion.</p>\n<p>That leaves me with a collection of vectors, each with a direction and a magnitude representing the weighted urgency of heading in that direction right now. I sum all these vectors, <a href=\"https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L932\">leaving a single vector with an angle useful as a steering goal</a>. I ignore the magnitude, because it was only useful during addition for influencing the angle.</p>\n<p><span class=\"embed-youtube\" style=\"text-align:center; display: block;\"></span></p>\n<p>Now, perhaps I’ve come off sounding smart after having written the above. But, I’ve already established that I’m not good at math. It’s quite possible I’ve abused &amp; misused this function entirely. That said, <a href=\"http://lmorchard.github.io/parsec-patrol/sketches/steering.html\">I think it’s produced a satisfying result</a>.</p>\n<div id=\"attachment_1238\" style=\"width: 485px\" class=\"wp-caption aligncenter\">\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/potential5.gif\"><img class=\"size-full wp-image-1238 \" alt=\"Smoother steering\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/potential5.gif\" width=\"\" height=\"\"></a><p class=\"wp-caption-text\">\n    Smoother steering with math!\n  </p>\n</div>\n\n\n\n<p>The <a href=\"http://lmorchard.github.io/parsec-patrol/sketches/steering.html\">demo sketch</a> has a debug mode full of confusing circles and lines, but it might help illustrate how the function works on they fly. In a nutshell, this means that closer obstacles have a greater influence on causing the ship to steer away. Meanwhile, there’s a constant influence pulling the ship back toward the target, whenever the mass of obstacles nearby do not dominate steering.</p>\n<p>I want to tinker some more, maybe see if I can make the ships swarm with each other while also avoiding obstacles and heading toward the target. I’d also like to find a way to stop guessing and calculate the function constants based on the speed &amp; steering characteristics of a given ship. That is, fast &amp; nimble ships should be able to navigate tighter spaces, while big &amp; clumsy ships should start working to avoid collisions from farther away.</p>\n<h3 id=\"further-research\"><span id=\"Further_research\">Further research</span></h3>\n<p>I’ve been thinking I need to look into <a href=\"http://gamedevelopment.tutsplus.com/tutorials/goal-based-vector-field-pathfinding--gamedev-9007\">vector fields</a> and <a href=\"http://www.red3d.com/cwr/boids/\">flocking behaviors</a> next. I’m still looking for more options to make this work, too. If you’ve made it this far reading this post, feel free to toss some suggestions &amp; critique my way. I have basically no idea what I’m doing, nor even what terms to use in searching for this stuff.</p>\n<p>Still, these are some pretty fun results stumbling along from daydreams to code.</p>\n",
  "body": "<div id=\"toc_container\" class=\"toc_wrap_right no_bullets\">\r\n  <p class=\"toc_title\">\r\n    Contents\r\n  </p>\r\n  \r\n  <ul class=\"toc_list\">\r\n    <li>\r\n      <a href=\"#Where_to_start\"><span class=\"toc_number toc_depth_1\">1</span> Where to start?</a>\r\n    </li>\r\n    <li>\r\n      <a href=\"#Waypoint_Graphs_Navigation_Meshes\"><span class=\"toc_number toc_depth_1\">2</span> Waypoint Graphs & Navigation Meshes</a>\r\n    </li>\r\n    <li>\r\n      <a href=\"#A_Search\"><span class=\"toc_number toc_depth_1\">3</span> A* Search</a>\r\n    </li>\r\n    <li>\r\n      <a href=\"#Trigonometry_Refresher\"><span class=\"toc_number toc_depth_1\">4</span> Trigonometry Refresher</a>\r\n    </li>\r\n    <li>\r\n      <a href=\"#Spaceships_with_Whiskers\"><span class=\"toc_number toc_depth_1\">5</span> Spaceships with Whiskers</a>\r\n    </li>\r\n    <li>\r\n      <a href=\"#Functions_with_Potential\"><span class=\"toc_number toc_depth_1\">6</span> Functions with Potential</a>\r\n    </li>\r\n    <li>\r\n      <a href=\"#Further_research\"><span class=\"toc_number toc_depth_1\">7</span> Further research</a>\r\n    </li>\r\n  </ul>\r\n</div>\r\n\r\nI made a hero ship with beam weapons. I even built drifting asteroids that handle smashing into things. What gave me trouble was finding a way to teach enemy ships how to *avoid* smashing into things. You know, not perfectly, but just well enough to seem vaguely cunning and worth pretending to outsmart in a video game.\r\n\r\n<!--more-->\r\n\r\nIn developing Parsec Patrol, I&#8217;ve never had plans or specifications so much as doodles & daydreams. One day I imagined this scene where I&#8217;m piloting the hero ship through a shifting maze of asteroids, a dozen enemy scout ships in fast pursuit. I dodge & weave through the rocks, just barely negotiating the gaps. One by one, the baddies vanish in bursts of light & debris: Some succumb to my beam weapons, while others smash into rocks or bungle into each other. Classic space dogfight material, here.\r\n\r\n### <span id=\"Where_to_start\">Where to start?</span>\r\n\r\nFrom years of playing & tinkering with shooters like Unreal & Quake, I had a vague notion of bots needing &#8220;pathfinding&#8221; algorithms to find their way around levels. So, I started hitting Google, looking to see what I could find and understand just well enough to eliminate from consideration or flag for a deeper dive.\r\n\r\n### <span id=\"Waypoint_Graphs_Navigation_Meshes\">Waypoint Graphs & Navigation Meshes</span>\r\n\r\nSome of the first pathfinding tools I started reading about were *waypoint graphs *and *navigation meshes*. It turns out that some bots rely on cheat sheets: map-specific and manually placed points or polygons, traversed to get from point A to point B. Generally it&#8217;s a cheap way to make bots seem like they know where they&#8217;re going, because a human being does most of the work up front.\r\n\r\n<div style=\"width: 322px\" class=\"wp-caption alignleft\">\r\n  <a href=\"http://www.ai-blog.net/archives/000152.html\"><img class=\"    \" alt=\"\" src=\"248c3837f026.jpg\" width=\"312\" height=\"250\" /></a><p class=\"wp-caption-text\">\r\n    Waypoint graph\r\n  </p>\r\n</div>\r\n\r\n<div style=\"width: 322px\" class=\"wp-caption alignleft\">\r\n  <a href=\"www.ai-blog.net/archives/000152.html\"><img class=\"    \" alt=\"\" src=\"509065bf8ee4.jpg\" width=\"312\" height=\"250\" /></a><p class=\"wp-caption-text\">\r\n    Navigation mesh\r\n  </p>\r\n</div>\r\n\r\nUnfortunately, an asteroid field is not like a Quake map. In Parsec Patrol, the clusters of rocks are randomly generated and only get more chaotic as the rocks drift and collide. There&#8217;s just no way to handcraft a map for robots in this scenario.\r\n\r\n### <span id=\"A_Search\">A* Search</span>\r\n\r\n<div style=\"width: 220px\" class=\"wp-caption alignright\">\r\n  <a href=\"http://en.wikipedia.org/wiki/A*_search_algorithm\"><img class=\"   \" alt=\"\" src=\"http://upload.wikimedia.org/wikipedia/commons/5/5d/Astar_progress_animation.gif\" width=\"210\" height=\"210\" /></a><p class=\"wp-caption-text\">\r\n    A* Search animation from Wikipedia\r\n  </p>\r\n</div>\r\n\r\nAnother approach I found was the [A* Search algorithm][1]. There are some [great write-ups on this algorithm][2] out there, so I won&#8217;t try making a hash of it here. You can also [try out some implementations in JavaScript][3].\r\n\r\nThis algorithm seems best suited for navigating graphs with few connections between nodes &#8211; a 2D grid, for example, with 8 exits per cell. If I ever wrote a roguelike dungeon crawler, this would be my jam.\r\n\r\nUnfortunately, the world of Parsec Patrol uses a continuous coordinate system, rather than a map of discrete grid cells. And, it seems like a waste to try to find a complete path from point A to point B for this game &#8211; because that path is likely to be made obsolete from moment to moment. So, how about trying to work out the best move for just the next moment?\r\n\r\n### <span id=\"Trigonometry_Refresher\">Trigonometry Refresher</span>\r\n\r\n<div style=\"width: 203px\" class=\"wp-caption alignright\">\r\n  <a href=\"http://www.hyperionedge.com/2010/04/tron-13-lightcycle-game-grid.html\"><img class=\"     \" alt=\"\" src=\"4320aae7d49c.jpg\" width=\"193\" height=\"136\" /></a><p class=\"wp-caption-text\">\r\n    Right angles only, for Light Cycles\r\n  </p>\r\n</div>\r\n\r\nI took a short break from research and decided to see what I could come up with on my own. What does it mean to avoid an obstacle?\r\n\r\nOne way to avoid a collision is to make a full right angle turn, into a perpendicular course. That works on the Light Cycle Grid, but it&#8217;s a bit extreme. So, I need an angle between 0 and 90 degrees with respect to the ship&#8217;s vector and the obstacle.\r\n\r\nSo, I decided to give myself a refresher course in trigonometry:\r\n\r\n<div id=\"attachment_1206\" style=\"width: 510px\" class=\"wp-caption aligncenter\">\r\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/trig2.png\"><img class=\"size-full wp-image-1206 \" alt=\"I am not good at math\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/trig2.png\" width=\"500\" height=\"558\" /></a><p class=\"wp-caption-text\">\r\n    I am not good at math\r\n  </p>\r\n</div>\r\n\r\nThese scribblings are not meant to impress. Rather, this shows how much I forgot about high school trigonometry. Nonetheless, I worked out how to [calculate an appropriate target angle that would miss the obstacle by a defined distance][4]. Having that angle meant that I could turn less drastically while steering for avoidance.\r\n\r\nIt was a small victory &#8211; and now I remember [SOHCAHTOA][5] again.\r\n\r\n### <span id=\"Spaceships_with_Whiskers\">Spaceships with Whiskers</span>\r\n\r\nNow that I had a way to calculate a steering angle that avoided smashing into something, I needed a way to know when I was headed for a collision.\r\n\r\nIf I were trying to build a physical robot, I might add some whiskers to detect the nearest obstacle and trigger a turn. But, how to do that in the virtual game world? A little bit of research brought me to the notion of using [raycasting combined with collision detection][6], something like this:\r\n\r\n<div id=\"attachment_1191\" style=\"width: 394px\" class=\"wp-caption aligncenter\">\r\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/2014-01-16-21.18.36.jpg\"><img class=\"wp-image-1191 \" alt=\"\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/2014-01-16-21.18.36-1024x768.jpg\" width=\"384\" height=\"288\" /></a><p class=\"wp-caption-text\">\r\n    Spaceships with whiskers!\r\n  </p>\r\n</div>\r\n\r\n[The algorithm I came up with][7] constructs a vector on each side of the ship. [I project circles along the vectors][8], with a radius based on the margin by which I hoped to avoid obstacles. In order from nearest to farthest, [I run collision detection for each of the circles][9]. The search stops with the first hit, using the nearest obstacle found.\r\n\r\nSo, when my ship finds an obstacle with the whiskers, calculate the avoidance angle, and set that as the steering target for the current game tick. This ends up much more lightweight than finding a complete optimal path, and it can react from moment to moment to the changing game environment.\r\n\r\n<div id=\"attachment_1203\" style=\"width: 510px\" class=\"wp-caption aligncenter\">\r\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/whiskers-twitch-3.gif.gif\"><img class=\"size-full wp-image-1203 \" alt=\"Whiskers are twitchy\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/whiskers-twitch-3.gif.gif\" width=\"500\" height=\"380\" /></a><p class=\"wp-caption-text\">\r\n    My whiskers are wiggly\r\n  </p>\r\n</div>\r\n\r\nUnfortunately, this scheme looks funny in action: Since [I revert back to target seeking after resolving obstacle avoidance][10], the enemy ships wiggle as they oscillate between the two strategies. Tracking straight toward the target often brings the ship into collision course &#8211; so once an avoidance course is achieved, target tracking turns right back into the obstacle.\r\n\r\n### <span id=\"Functions_with_Potential\">Functions with Potential</span>\r\n\r\nWhat I really wanted was some way for these ships to take many nearby obstacles into account along with seeking toward the target, and come up with a smoothly changing steering angle that seemed not entirely stupid or goofy looking.\r\n\r\nAfter some further research, I started reading [AI for Game Developers][11]<img class=\"tvatbijdbdexywujcjjd svuitzfraxzoondqiznf pybiawadmcxjgjpdvhto\" style=\"border: none !important; margin: 0px !important;\" alt=\"\" src=\"http://ir-na.amazon-adsystem.com/e/ir?t=0xdecafbad01-20&l=as2&o=1&a=0596005555\" width=\"1\" height=\"1\" border=\"0\" /> by David M. Bourg and Glenn Seemann. In Chapter 5, I found code using [the Lennard-Jones potential function][12] to drive avoidance of multiple obstacles and target seeking all in one algorithm.\r\n\r\n<div style=\"width: 442px\" class=\"wp-caption aligncenter\">\r\n  <a href=\"http://chemwiki.ucdavis.edu/Physical_Chemistry/Quantum_Mechanics/Atomic_Theory/Intermolecular_Forces/Lennard-Jones_Potential\"><img alt=\"\" src=\"http://chemwiki.ucdavis.edu/@api/deki/files/8914/Figure_B.jpg\" width=\"432\" height=\"324\" /></a><p class=\"wp-caption-text\">\r\n    Serious business, this potential function\r\n  </p>\r\n</div>\r\n\r\nA thumbnail sketch of this function with respect to the game goes something like this: Entities can repel & attract each other. Repulsion & attraction change over distance. For example, swarming entities can attract at long distance and repel when too close.\r\n\r\nHere&#8217;s what [the simplified AB form of this function][13] looks like in my code:\r\n\r\n`U = (-A/Math.pow(d,n)) + (B/Math.pow(d,m))`\r\n\r\nThere are 4 constants in this function:\r\n\r\n*   `A` &#8211; magnitude of attraction\r\n*   `n` &#8211; attenuation of attraction over distance\r\n*   `B` &#8211; magnitude of repulsion\r\n*   `m` &#8211; attenuation of repulsion over distance\r\n\r\nPick values for these constants, and you&#8217;ve got a function that yields a positive (repulsion) or negative (attraction) value for any given distance (`d`). So far, [I&#8217;ve just used trial & error to find values for these constants][14].\r\n\r\nTo apply this function, [I search for obstacles within a certain radius of the ship][15]. That limits the number of calculations, because far-flung obstacles have no significant influence. For each nearby obstacle, [I calculate distance and apply the potential function][16]. I then [calculate a unit vector from each obstacle to the ship and multiply by the result of the potential function][17].\r\n\r\nRepeat all the above for targets, regardless of range, and with function constants that yield attraction rather than repulsion.\r\n\r\nThat leaves me with a collection of vectors, each with a direction and a magnitude representing the weighted urgency of heading in that direction right now. I sum all these vectors, [leaving a single vector with an angle useful as a steering goal][18]. I ignore the magnitude, because it was only useful during addition for influencing the angle.\r\n\r\n<span class='embed-youtube' style='text-align:center; display: block;'></span>\r\n\r\nNow, perhaps I&#8217;ve come off sounding smart after having written the above. But, I&#8217;ve already established that I&#8217;m not good at math. It&#8217;s quite possible I&#8217;ve abused & misused this function entirely. That said, [I think it&#8217;s produced a satisfying result][19].\r\n\r\n<div id=\"attachment_1238\" style=\"width: 485px\" class=\"wp-caption aligncenter\">\r\n  <a href=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/potential5.gif\"><img class=\"size-full wp-image-1238 \" alt=\"Smoother steering\" src=\"http://blog.lmorchard.com/wp-content/uploads/2014/01/potential5.gif\" width=\"475\" height=\"375\" /></a><p class=\"wp-caption-text\">\r\n    Smoother steering with math!\r\n  </p>\r\n</div>\r\n\r\nThe [demo sketch][19] has a debug mode full of confusing circles and lines, but it might help illustrate how the function works on they fly. In a nutshell, this means that closer obstacles have a greater influence on causing the ship to steer away. Meanwhile, there&#8217;s a constant influence pulling the ship back toward the target, whenever the mass of obstacles nearby do not dominate steering.\r\n\r\nI want to tinker some more, maybe see if I can make the ships swarm with each other while also avoiding obstacles and heading toward the target. I&#8217;d also like to find a way to stop guessing and calculate the function constants based on the speed & steering characteristics of a given ship. That is, fast & nimble ships should be able to navigate tighter spaces, while big & clumsy ships should start working to avoid collisions from farther away.\r\n\r\n### <span id=\"Further_research\">Further research</span>\r\n\r\nI&#8217;ve been thinking I need to look into [vector fields][20] and [flocking behaviors][21] next. I&#8217;m still looking for more options to make this work, too. If you&#8217;ve made it this far reading this post, feel free to toss some suggestions & critique my way. I have basically no idea what I&#8217;m doing, nor even what terms to use in searching for this stuff.\r\n\r\nStill, these are some pretty fun results stumbling along from daydreams to code.\r\n\r\n [1]: http://en.wikipedia.org/wiki/A*_search_algorithm\r\n [2]: http://buildnewgames.com/astar/\r\n [3]: http://easystar.nodejitsu.com/demo.html\r\n [4]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1034\r\n [5]: http://www.mathwords.com/s/sohcahtoa.htm\r\n [6]: https://www.google.com/search?q=collision+detection+ray+casting\r\n [7]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L987\r\n [8]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1008\r\n [9]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1015\r\n [10]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L1085\r\n [11]: http://www.amazon.com/gp/product/0596005555/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=0596005555&linkCode=as2&tag=0xdecafbad01-20\r\n [12]: http://en.wikipedia.org/wiki/Lennard-Jones_potential\r\n [13]: http://en.wikipedia.org/wiki/Lennard-Jones_potential#AB_form\r\n [14]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/sketches/steering.coffee#L85\r\n [15]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L904\r\n [16]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L868\r\n [17]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L877\r\n [18]: https://github.com/lmorchard/parsec-patrol/blob/2e3f9afa2404fee54b09152e3d5746c4c4a2b4ca/app/scripts/systems.coffee#L932\r\n [19]: http://lmorchard.github.io/parsec-patrol/sketches/steering.html\r\n [20]: http://gamedevelopment.tutsplus.com/tutorials/goal-based-vector-field-pathfinding--gamedev-9007\r\n [21]: http://www.red3d.com/cwr/boids/",
  "parentPath": "./content/posts/archives/2014/2014-01-18-ppd-avoidance",
  "path": "2014/01/18/ppd-avoidance",
  "thumbnail": "/2014/01/18/ppd-avoidance/248c3837f026.jpg",
  "summary": "I made a hero ship with beam weapons. I even built drifting asteroids that handle smashing into things. What gave me trouble was finding a way to teach enemy ships how to avoid smashing into things. You know, not perfectly, but just well enough to seem vaguely cunning and worth pretending to outsmart in a video game.",
  "needsBuild": true,
  "prevPostPath": "2013/11/27/entity-component-system",
  "prevPostTitle": "Parsec Patrol Diaries: Entity Component Systems",
  "nextPostPath": "2014/09/29/1288"
}