{"id":15101195,"url":"https://github.com/js13kgames/mirror-delivery","last_synced_at":"2025-10-08T08:32:11.295Z","repository":{"id":82385850,"uuid":"543929392","full_name":"js13kGames/mirror-delivery","owner":"js13kGames","description":"Mirror Delivery - a js13kGames 2013 competition entry by @4lbertoC.","archived":false,"fork":true,"pushed_at":"2013-09-07T08:45:59.000Z","size":7108,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-02T07:41:51.512Z","etag":null,"topics":["2013","bad-luck","competition","desktop","game","html5","javascript","js13k","js13kgames","js13kgames2013","mobile","optimization","touch"],"latest_commit_sha":null,"homepage":"https://js13kgames.com/entries/mirror-delivery","language":null,"has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"4lbertoC/mirrordelivery","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/js13kGames.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-10-01T07:14:10.000Z","updated_at":"2023-02-22T19:54:04.000Z","dependencies_parsed_at":"2023-02-28T10:01:35.605Z","dependency_job_id":null,"html_url":"https://github.com/js13kGames/mirror-delivery","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js13kGames%2Fmirror-delivery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js13kGames%2Fmirror-delivery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js13kGames%2Fmirror-delivery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js13kGames%2Fmirror-delivery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/js13kGames","download_url":"https://codeload.github.com/js13kGames/mirror-delivery/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235700110,"owners_count":19031668,"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":["2013","bad-luck","competition","desktop","game","html5","javascript","js13k","js13kgames","js13kgames2013","mobile","optimization","touch"],"created_at":"2024-09-25T18:09:24.520Z","updated_at":"2025-10-08T08:32:05.712Z","avatar_url":"https://github.com/js13kGames.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"MIRROR DELIVERY\n===============\n#### A 13kB game by Alberto Congiu for [js13kgames 2013](http://js13kgames.com/)\n\n#### [Play](http://albertocongiu.com/mirrordelivery)\n\n### DESCRIPTION\n\nMirror Delivery is a competitive HTML5 game for 2 players. They use the\nsame machine, but different controls (keyboard vs mouse on desktop or\nseparate button groups on a touch enabled device)\n\n*Player 1* interprets **Luke**, a delivery boy who has to deliver some crates full of mirrors to an old lady (from now on called \"Granny\").\n\n*Player 2* plays the **Crow**, an animal that enjoys annoying the delivery boys\nthat pass nearby. Unfortunately for him, Granny hates crows. Her shotgun is\nready to knock down any bird whose feather color is darker than #1f261c.\n\n\n\n### TESTED BROWSERS\n\n- Chrome 29 (Windows 7, Windows 8 on a Tablet PC, Mac OS X, Android 4)\n- Firefox 23\n- Opera 16\n- Safari 6 (Mac OS X, iOS 6)\n- IE 10\n\n\n\n### MECHANICS\n\n#### Luke\n\n\u003e ###### Breaking a mirror brings seven years of bad luck, and you have to deliver a crate full of them (forewarned is forearmed).\n  \nLuke can grab crates and carry them across the level. If he falls from too\nhigh, the crate breaks. Each crate have a number on it that indicates its\nweight. The heavier the crate, the slower Luke is when carrying it and the\nlower is the height from which it breaks if he falls.\nCrates break also if Luke is hit by animals.\nLuke can buy up to three candies from the dispensers, and use them to have\na speed boost for five seconds. When he eats a candy, crumbs are left on the\nground.\nGranny doesn't tolerate delays, so Luke has a limited time to deliver all\nthe crates.\n\n#### Crow\n\n\u003e ###### Crows are strong, but killing a bird is generally not advisable.\n\nThe Crow likes to shoot on the head of Luke to make his crate fall and break.\nIt can ready up to three shots, by eating from the food stock in his nest(s).\nIf he finds some delicious candy crumbs left on the ground, it can eat them and\ninstantly have five shots.\nThe Crow has to be careful because he is not the only hunter. The Granny hates\nhim and her shotgun is a real danger. She is very slow at aiming, but doesn't\nmiss a shot. To avoid to attract attention, the Crow can hide inside its nest.\nIt also has to be careful not to fly over roofs or too near to Luke, as he can\nreach it too!\nWhen the Crow is hit, it loses all his shots, and it's stunned for five seconds,\nin which he can move but cannot eat or shoot.\n\n#### Black Cat\n\n\u003e ###### Black cats. Do I need to say anything else?\n\nIf Luke breaks too many crates or the Crow is stunned too many times, a Black\nCat will appear. It will start jumping around, and it will hit any of the\nplayers that touch it.\nMoreover, Granny gets scared by the Cat's presence, and she gets faster at\naiming as the time passes.\n\n### CONTROLS\n\n#### Player 1 (Luke, the delivery boy)\n\n  Desktop  |  Mobile   |  Action\n:-----------|------------:|:------------:\nArrows  |  Arrows   |  Move and jump, climb ladders\n\t Spacebar |     I     |  Grab/release crates, buy candies from dispensers\n\t     E    |     E     |  Eat candy\n\t    Esc   |     X     |  Quit level\n\n#### Player 2 (The Crow)\n\n  Desktop  |  Mobile   |  Action\n:-----------|------------:|:------------:\n\t  Mouse   | Analog Pad |  Move and jump, climb ladders\n\t Left btn |     S     |  Shoot\n\tRight btn |     A     |  Eat from the nest or the candy crumbs\n\n#### Edit Mode\n\n  Desktop  |  Mobile   |  Action\n:-----------|------------:|:------------:\n\t  Mouse   | Analog Pad |  Move cursor\n\t\u003c- -\u003e arrows| \u003c- -\u003e arrows|  Select element to draw\n\t Left btn |     S     |  Draw\n\t          |     A     |  Toggle auto-draw when moving\n\t     C    |     C     |  Change the number and value of the crates\n\t     T    |     T     |  Change the time limit\n\t     N    |     N     |  Change the name of the level\n\t    Esc   |     X     |  Quit editing\n\n#### Menu\n\n  Desktop  |  Mobile   |  Action\n:-----------|------------:|:------------:\n\t\u003c- -\u003e arrows| \u003c- -\u003e arrows|  Select the level\n\t     E    |     E     |  Edit the level (or create a new one from base level)\n\t     I    |     I     |  Imports a level by entering its JSON\n\t     J    |     A     |  Export the current level in JSON format\n\t     D    |     S     |  Delete current level\n\n\n\n### PROJECT STRUCTURE\n\nI decided to sacrifice cleanliness and OO structure to have instead more features\non the game.\nThere are no classes, but instead a lot of function definitions.\nSince the algorithm used by zip compression tends to optimize repetitive chunks\nof data, some of the functions are not refactored in order to gain some (preciousss) bytes.\nThis has the disadvantage that the unpacked code is bigger, and the game slower to\nload. And, obviously, it's a lot more painful to read and understand (sorry).\n\nOn the final phases, I was going up and down the limit of 13312 bytes (in a range\nof ~10bytes!), and sometimes cutting away pieces of code had the result of having\na bigger final package.\n\n#### Libraries\nThe only external library that I use is [jsfx](https://github.com/egonelbre/jsfx) to dynamically create sounds.\nI have modified and optimized it for advanced minification.\n\n#### Minification\nTo minify the code I use [Closure Compiler](https://developers.google.com/closure/compiler/)\n\nI use externs for [jsfx](https://github.com/egonelbre/jsfx), otherwise the Compiler would complain that it doesn't\nfind some symbols.\n\n#### Graphics\nI used TexturePacker to create the texture atlas, then I modified and imported\nthe JSON map to include only the data that I need, plus adding information about\nanimation frames.\n\nTo draw mirrored images, like Luke going left, I create during initialization\na new canvas in which I draw the mirrored map, and then use this map with also\nmirrored coordinates.\n\nThe game is tile-based, but the map is drawn only once on level load on a dedicated\ncanvas, to improve performance on mobile devices.\n\n#### Audio\nI use [jsfx](https://github.com/egonelbre/jsfx) library to do all the audio in the game. The single sounds are generated\nat runtime, including the music notes.\n\n#### Level Editor\nEach level of the game can be edited and shared by exporting and importing their JSON.\nCusotm Levels are persisted to the local storage.\n\n#### Server\nI made a test with some server APIs to push your custom Levels on the cloud and\nshare them by appending a hash to the URL, but storing data on files is\nproblematic on some service providers, and using databases requires heavy\nlibraries.\nI dropped this feature and now I just show the JSON inside a prompt dialog.\n\n#### Compatibility\nOn touch enabled devices, I show an overlay with the buttons to control both\nLuke and the Crow. This works as long as the device has multitouch support.\n\n#### Code sections\nThe code is divided into:\n\n- Constants\n- Helper functions (cross-browser issues, device detection)\n- Variables\n- Game mechanics functions\n- Game loop functions\n\nEach section is organized into smaller parts, each relative to a specific\ncomponent of the game (graphics, audio, input, etc...)\n\n#### Game loop\nThe game loop uses requestAnimationFrame, and is divided in the three phases of\ninput processing, state update and rendering. You can find it at the bottom of the\nfile. The entry point to the entire code is the function start() that is called\ninside the onload callback of the image file.\n\n#### Build\nTo build the package, just run `build.sh`","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs13kgames%2Fmirror-delivery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjs13kgames%2Fmirror-delivery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs13kgames%2Fmirror-delivery/lists"}