{"id":26658274,"url":"https://github.com/ltbringer/november","last_synced_at":"2025-03-25T09:19:12.407Z","repository":{"id":41471859,"uuid":"509044424","full_name":"ltbringer/november","owner":"ltbringer","description":"An open world RPG fun project ","archived":false,"fork":false,"pushed_at":"2022-07-20T15:30:28.000Z","size":22425,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-03-03T00:07:33.457Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://ltbringer.github.io/november/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ltbringer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-06-30T11:02:25.000Z","updated_at":"2022-07-12T06:08:53.000Z","dependencies_parsed_at":"2022-07-18T08:49:19.969Z","dependency_job_id":null,"html_url":"https://github.com/ltbringer/november","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ltbringer%2Fnovember","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ltbringer%2Fnovember/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ltbringer%2Fnovember/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ltbringer%2Fnovember/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ltbringer","download_url":"https://codeload.github.com/ltbringer/november/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245431684,"owners_count":20614184,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":"2025-03-25T09:19:11.695Z","updated_at":"2025-03-25T09:19:12.385Z","avatar_url":"https://github.com/ltbringer.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# November\n\nI have loved Pokemon since a I was a 13 year old child. Charizard was my favorite Pokemon at the time.\nLimited access to TV and friends, my escape was this fantasy world where I could befriend these creatures.\nA world where dragons were as real as ghosts. The anime series could only feed me so much and in time I started looking.\nDiscovered the official pokemon.com website, the pokedex, events and what not but none of it available to my country.\nAt that age, I was used to it but I kept looking and I heard about a GBC game called pokemon crystal.\n\nI tried hard to find it, and all I got was a copy in Spanish. Nevertheless the 8-bit intro music still brings peace to me.\nI barely understood the dialog of the game but that didn't stop me from playing. The joy of getting my own pokemon (I picked Typhlosion),\nand running into the grass to battle a hoot hoot was the best thing ever for my 13 year old self. I departed from the series after Pokemon Black and White.\nLife got busy and childhood needed to rest. \n\nYears later, I still remember that game for its simplicity. Children my age had access to games that won't run on my computer, yet I wasn't settling.\nThe pixelated graphics, simple art style, no _seemingly_ real interactions but all that meant nothing in front of hours of exploring cities, defeating\nteam rocket, training pokemon and grinding till they would evolve to their final forms. It had no substitute. I tried to play the old games\nand realized I didn't like a few things after all. I didn't like the battle scene, I didn't like the lack of interaction with the environment.\n\n1. You could cycle but that's like walking 2-4x faster.\n2. You could using fishing rods but it was all about timing the \"A\" button.\n3. You could use surf and dive in water. Honestly diving was a refresher. Underwater caves and explorations in Pokemon Emerald were breathtaking.\n4. You could use various pokeballs to catch pokemon but arbitrary probability would lead to capture.\n5. The most exciting battle scene felt like pictures. No movement, No reaction to damage, while there was an attack animation it just felt like\n    a special effect translated from a point to another.\n6. Rare pokemon were limited to events.\n7. Trading required custom hardware. Although things have changed now. Its a smaller world with a wifi connection.\n\nAt my age, I think it is a good way to pay respect to the devs that gave me a hopeful childhood,\nby trying to extend the idea and see for myself if my expectations make sense for a role playing game.\n\n## Game Design\n\nWIP. \n\n- The Main Character (MC) can explore an open world map. I am starting with a static image but want to learn building dynamic maps.\n- There are hostile monsters that can attack the MC.\n- There are curious/friendly monsters that can join the MC in their journey.\n- Battling monsters generates gold (in-game currency).\n- The map can generate items that can be collected.\n- Living things have a healing factor (which can be reduced).\n\n## v1\n\n### 30 Jun, 2022 - 2 July, 2022\n\nThis was a humbling experience. I thought I could have pulled it off in one day but it took me over 2 days and 5 hours.\nI learned building tiled maps. There was a lot of struggle figuring out resolutions and I'll be honest, I have skimmed that part.\nRegarding the background image, there were a couple of things to worry about. \n\nThe world is made of a grid with 30 x 40 tiles. This was decision was taken on tiled map editor.\nAt that moment, I wasn't aware of the choices I am making but I thought I would figure out the maths later.\nLater on HTML5 land, I built the canvas and set the resolution of 1280 x 720. Things didn't look good:\n\n- Canvas tries to anti-alias images. Since I am already using pixel art I had to turn it off.\n- The image was not scaled to the resolution.\n\nHowever, I moved on and added the sprite for my main character and started integrating the tile-map for collisions.\nIt was this moment, when I started panicking. The collision tiles would not align. No, it wasn't because of offsets\nthe image seemed to belong to a completely different resolution than the collision tiles. To work out the correct resolution,\nI used the 30x40 rule for the world. Decided to use a 64px for single collider block (a square). Giving me the resolution\nof 1920 x 1440.\n\nDetecting collisions was still hard. The way the illusion of movement works is: everything except the player moves!\nI had a hard time understanding this but it made sense. This way you don't need to code up a virtual camera to follow \nthe player, saving a lot of code. I was stuck for a while having the MC touch a collider and never getting to move out of it.\nSo I tried a pre-emptive approach to prevent movement if the MC's movement speed would lead to a collision in the next frame.\n\nCollision is still not perfect. There are places (like a bridge) where the MC can't walk over since there is an invisible collider\nblock due to the ocean water right above. This isn't very intuitive and I may have to customize certain colliders to be more forgiving\nfor certain vectors. Since the impact is cosmetic I will not work on it for now.\n\nThe sprite animation took a while to smoothen. I had to study how [requestAnimationFrame](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) works. It calls your function approx every 16ms.\nIt may not do that if you switch a tab or are running an `\u003cIframe\u003e`. This gave me a hint to move the sprite face in the order of 10e-3.\nI think a reset to idle frame is a good touch and possibly simple.\n\nI also don't like the way foreground works. The foreground is a single image so items that are farther also cover the MC, giving the\ngame a very flat appearance. I think I need to have the foreground imported separately and row-wise. This way I can tell which\nrows should come before the MC but it seems very inefficient.\n\nHere's a demo.\n\n![Collision enabled movement](images/november_v1.gif)\n\n## v1\n\n### 2 July, 2022 - 18 July, 2022\n\n- Implemented a priority queue. This data structure is key before implementing A-Star.\n- Implemented A-star to let NPCs chase me around and kill.\n- Smoother animation for MC. (animates even on collision)\n- Added a health bar to the MC and NPC.\n- Gave the NPC as toxic cloud attack.\n- Gave the MC an attack (no animations).\n\nThere seems to be a lot of room to save compute. A lot of grid calculations loop\nbecause the map moves instead of characters. Since I am looking forward to move many NPCs around, it might be\na good benefit to move only the characters and cache the paths.\n\n![AStar at work](images/astarmini.gif)\n\nCredits to my resources:\n\n- [Sproutlands](https://cupnooble.itch.io/sprout-lands-asset-pack) from [itch.io](https://itch.io/). I have supported the creator by purchasing the premium edition.\n- This project draws inspiration from [Chris Courses YT video](https://www.youtube.com/watch?v=yP5DKzriqXA\u0026t). I have made a lot of different\n    design choices but want to credit the creator for the time they spent on the video. It helped me stay motivated and gave me a solid starting point.\n\n## Todos\n\n- [x] Render the map.\n- [x] Render the collision grid.\n- [x] Implement collision detection.\n- [x] Add a enemy npc sprite.\n- [x] Move the MC around the MAP.\n- [x] Move NPC using A-star.\n- [x] Animate MC's movements.\n- [x] Create attacks.\n- [ ] Create/Destroy interaction with tiles.\n- [ ] Animate MC's attacks.\n- [ ] ...\n- [ ] Build maps dynamically.\n- [ ] Build and Destroy ability for MC.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fltbringer%2Fnovember","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fltbringer%2Fnovember","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fltbringer%2Fnovember/lists"}