{"id":13744547,"url":"https://github.com/euske/planpathplat","last_synced_at":"2026-03-16T00:38:08.901Z","repository":{"id":66084363,"uuid":"13098236","full_name":"euske/planpathplat","owner":"euske","description":"Experimental Path Planning for Platformer","archived":false,"fork":false,"pushed_at":"2014-04-10T13:34:10.000Z","size":1019,"stargazers_count":33,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-12-26T02:59:14.872Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"ActionScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/euske.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-09-25T15:53:54.000Z","updated_at":"2021-12-18T22:23:07.000Z","dependencies_parsed_at":"2023-02-19T22:30:35.392Z","dependency_job_id":null,"html_url":"https://github.com/euske/planpathplat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/euske/planpathplat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/euske%2Fplanpathplat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/euske%2Fplanpathplat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/euske%2Fplanpathplat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/euske%2Fplanpathplat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/euske","download_url":"https://codeload.github.com/euske/planpathplat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/euske%2Fplanpathplat/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30557500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-15T23:30:23.986Z","status":"ssl_error","status_checked_at":"2026-03-15T23:28:43.564Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T05:01:11.587Z","updated_at":"2026-03-16T00:38:08.862Z","avatar_url":"https://github.com/euske.png","language":"ActionScript","readme":"Path Planning (AI) in Platformer Games: A Layered Approach\r\n==========================================================\r\n\r\nI've been working on path planning (path finding) for platformer games\r\nfor a while. My original intention was to create a reusable framework\r\nfor scripting characters in a platformer, but it can have other\r\ninteresting applications. I have a working prototype and its source\r\ncode. The source code is published under MIT/X License (i.e. it's free).\r\n\r\n * \u003ca href=\"http://ludumdare.tabesugi.net/ppp/\"\u003ePlayable prototype\u003c/a\u003e\r\n * \u003ca href=\"https://github.com/euske/planpathplat/\"\u003eGitHub\u003c/a\u003e\r\n\r\n\r\nHandling Continuous Space\r\n-------------------------\r\n\r\nThe first problem that we need to address is the continuous nature of\r\na platformer game. In a typical path planning, a problem is usually\r\nreprespented as a discrete space. However, in a platformer game where\r\ncharacters often are affected by gravity, handling its continuous\r\nmovement is crucial. We addressed this issue by dividing the problem\r\ninto two layers: macro-level planning and micro-level planning. The\r\nmacro-level planning takes care of a coarse-grained plan such as \"go\r\nto this block\" or \"jump here and try to land at that block\". The\r\nmicro-level planning takes care of more fine-tuned movement that\r\ninvolves a continuous 2-D space. The macro-level planning is done by\r\nusing typical AI techniques like a navigation mesh, constructing a set\r\nof possible actions at each discrete location. The micro-level\r\nplanning is done in a more greedy manner, by taking care of physical\r\ncollisions and character coordinates.\r\n\r\nThe macro-level planning can be implemented with a pretty\r\nstraightforward Dijkstra or A* search. It starts from the goal\r\nposition, and iteratively searches all the possible movements until it\r\nreaches the initial state (the position of the character).  Each\r\naction is associated to its next action until it reaches the goal,\r\nforming a DAG structure. A plan graph can be dynamically constructed\r\nand periodically updated based on the current state of the game.\r\nAdditional restrictions (e.g. space constraints and ladders) are also\r\nconsidered.\r\n\r\n[plangraph.png]\r\n\r\nWhen each action is executed, a character is entirely controlled by\r\nthat action, and the character cannot execute the next action until\r\nthe current action is finished. Each action only considers the\r\nstarting and ending point, and it moves the character in a rather\r\nstraightforward way.  When the macro-level planner detects the\r\nsituation change (e.g. the goal is moved) during the execution, the\r\ncurrent plan is abandaned after the action is finished and a new plan\r\ngraph is created.\r\n\r\n\r\nJumping / Falling\r\n-----------------\r\n\r\nJumping and falling is the key element of platformer games and the\r\ncore of its planning problem. It has so many parameters that using\r\nnaive methods will easily lead to computational explosion. In the\r\nproposed method, the macro-level planner only takes care of its\r\nstarting point and ending point in the block coordinates. The planner\r\nhas to know in advance the speed of a character in question and its\r\njump impulse, as well as the gravity acceleration, so that it can know\r\nwhere it will exactly land. The macro-level planner uses two bounding\r\nboxes (a jumping part and a falling part) to approximate the clearance\r\nthat a character needs, but it doesn't take care of an actual\r\ntrajectory of the character.\r\n\r\nAn actual jump action is divided into three steps.  First, it tries to\r\nmove the character to its starting position (Set), maneuver the\r\ncharacter movement during ascending (Ascend), and then land the\r\ncharacter to the ending position (Land).  It takes a precise\r\n(pixel-wise) control of the character at each frame update.\r\n\r\n[jumping.png]\r\n\r\n\r\nLanding Prediction\r\n------------------\r\n\r\nThe planner can find a solution only when the path planning is\r\nsolvable. When a character is following another character that is\r\njumping or falling, the goal position is often considered unreachable,\r\nmaking it impossible to find a solution. In a case like this, the\r\nplanner can optionally make a guess of the final landing position\r\nbased on the current speed of the character.\r\n\r\n[prediction.png]\r\n\r\n\r\nMoving Platforms, Sprinting, Double Jumping, etc.\r\n-------------------------------------------------\r\n\r\nA path finding is based on an assumption that the floor map\r\nyou're planning on is static. When there are some parts that are\r\nchanging dynamically, those parts need to be handled specially by \r\nthe micro-level planner. In this case, the macro-level planner only \r\ntakes care of moving into that part and getting out of it.\r\n\r\n[movingplatform.png]\r\n\r\nHandling moves like sprinting or double jumping can be more tricky,\r\nbecause such actions depend on the current state of a character.  In\r\nother words, a plan becomes context-dependent. Now we would have\r\nto consider multiple possible states at each grid, making the search\r\nspace several times larger. I am not sure if we can find a really good\r\nsolution for this kind of planning, but in theory we can still take\r\nthis into account in the current framework.\r\n\r\n\r\nSource Code Structure\r\n---------------------\r\n\r\nThe prototype is written in ActionScript. However, the planning parts\r\nare separated from the UI and I believe it's relatively easy to port them to\r\nanother language. Here are a couple of important classes:\r\n\r\n * Actor\r\n   This is an object that the planner takes control of.\r\n   The object needs to support methods like \u003ccode\u003emove(x, y)\u003c/code\u003e, \u003ccode\u003ejump()\u003c/code\u003e\r\n   to perform actions on each character, as well as query methods such as \r\n   \u003ccode\u003ebounds()\u003c/code\u003e.\r\n\r\n * TileMap\r\n   An object that stores a 2D map that a planner can use.\r\n   This is basically a two dimensional array of tile numbers.\r\n   The class needs to handle a query like \u003ccode\u003egetTile(x, y)\u003c/code\u003e as well as\r\n   range queries like \"if there's a certain block within this area\" in order to\r\n   serve the efficient planning.\r\n\r\n * PlanMap\r\n   A macro-level planner that has a plan graph and its constructor.\r\n   It maintains a grid of actions, which correspond to each tile in \r\n   a \u003ccode\u003eTileMap\u003c/code\u003e object, so that an \u003ccode\u003eActor\u003c/code\u003e can query\r\n   a possible action to take at each place. An action, which is a \r\n   \u003ccode\u003ePlanAction\u003c/code\u003e object, is represented as an edge of a plan graph. \r\n   There's one important method \u003ccode\u003eaddPlan()\u003c/code\u003e, which fills the grid \r\n   according to the given parameters and the associated\u003ccode\u003eTileMap\u003c/code\u003e.\r\n   A plan graph can be shared and reused as long as the goal is not changed\r\n   and all the \u003ccode\u003eActor\u003c/code\u003es has the same property (e.g. speed, gravity, etc.).\r\n\r\n * PlanAction\r\n   This object represents a single action planned by the macro-level planner.\r\n   An action object has a detailed information about the action such as a\r\n   starting and ending point, the type of the action, and the tile map it's referring to.\r\n   The object is responsible for performing micro-level planning.\r\n   It fires events to an Actor object so that it can carry out \r\n   the corresponding actions (jumping or moving, etc).\r\n\r\n\r\nIs This Smarter than humans?\r\n----------------------------\r\n\r\nUnfortunately, no.  Due to computational limits, the current\r\nimplementation considers only a handful of ways of possible jumps at\r\neach position. Since it uses a rectangle as an approximation of jump\r\ntrajectory, it cannot emulate a complex manuever that humans could\r\ndo. Also, since it's on block-by-block basis, it cannot consider a\r\npossibility of barely-make-it kinds of jumps. These are mostly\r\ncomplexity problems, but in some cases there might be need to give up\r\nto find an optimal solution.\r\n\r\n\r\nTerms and Conditions\r\n--------------------\r\n\r\n(This is so-called MIT/X License)\r\n\r\nCopyright (c) 2013  Yusuke Shinyama \u003cyusuke at cs dot nyu dot edu\u003e\r\n\r\nPermission is hereby granted, free of charge, to any person\r\nobtaining a copy of this software and associated documentation\r\nfiles (the \"Software\"), to deal in the Software without\r\nrestriction, including without limitation the rights to use,\r\ncopy, modify, merge, publish, distribute, sublicense, and/or\r\nsell copies of the Software, and to permit persons to whom the\r\nSoftware is furnished to do so, subject to the following\r\nconditions:\r\n\r\nThe above copyright notice and this permission notice shall be\r\nincluded in all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY\r\nKIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\r\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\r\nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\r\nOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\r\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n","funding_links":[],"categories":["Utilities"],"sub_categories":["Geometry"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feuske%2Fplanpathplat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feuske%2Fplanpathplat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feuske%2Fplanpathplat/lists"}