├── .editorconfig ├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── assets ├── audio │ ├── effects │ │ ├── LTTP_Agahnim_Charge.lite.ogg │ │ ├── LTTP_Agahnim_Dash.lite.ogg │ │ ├── LTTP_Agahnim_Fireball.lite.ogg │ │ ├── LTTP_Agahnim_Shock1.lite.ogg │ │ ├── LTTP_Agahnim_Shock2.lite.ogg │ │ ├── LTTP_Arrow_Hit.lite.ogg │ │ ├── LTTP_Arrow_Shoot.lite.ogg │ │ ├── LTTP_BallAndChain.lite.ogg │ │ ├── LTTP_BatGanon_Crash.lite.ogg │ │ ├── LTTP_Bee.lite.ogg │ │ ├── LTTP_Bee_Fade.lite.ogg │ │ ├── LTTP_Bomb_Blow.lite.ogg │ │ ├── LTTP_Bomb_Drop.lite.ogg │ │ ├── LTTP_BoneBurn.lite.ogg │ │ ├── LTTP_BookOfMudora.lite.ogg │ │ ├── LTTP_Boomerang.lite.ogg │ │ ├── LTTP_Boss_Fireball.lite.ogg │ │ ├── LTTP_Boss_Hit.lite.ogg │ │ ├── LTTP_Boss_Mouth.lite.ogg │ │ ├── LTTP_Boss_Sand1.lite.ogg │ │ ├── LTTP_Boss_Sand2.lite.ogg │ │ ├── LTTP_Boss_Tailwhip.lite.ogg │ │ ├── LTTP_Bounce.lite.ogg │ │ ├── LTTP_Cane.lite.ogg │ │ ├── LTTP_Cane_Magic.lite.ogg │ │ ├── LTTP_CannonBall.lite.ogg │ │ ├── LTTP_Chest.lite.ogg │ │ ├── LTTP_Chest_Appears.lite.ogg │ │ ├── LTTP_Cucco.lite.ogg │ │ ├── LTTP_Cucco_Fly.lite.ogg │ │ ├── LTTP_Cucco_Hit.lite.ogg │ │ ├── LTTP_Door.lite.ogg │ │ ├── LTTP_Door_Close.lite.ogg │ │ ├── LTTP_Door_Double.lite.ogg │ │ ├── LTTP_Door_Unlock.lite.ogg │ │ ├── LTTP_Dungeon_Open.lite.ogg │ │ ├── LTTP_Enemy_Chase.lite.ogg │ │ ├── LTTP_Enemy_Hit.lite.ogg │ │ ├── LTTP_Enemy_Kill.lite.ogg │ │ ├── LTTP_Enemy_Skitter.lite.ogg │ │ ├── LTTP_Error.lite.ogg │ │ ├── LTTP_Ether.lite.ogg │ │ ├── LTTP_FinalDoor1.lite.ogg │ │ ├── LTTP_FinalDoor2.lite.ogg │ │ ├── LTTP_FireRod.lite.ogg │ │ ├── LTTP_FloorTile1.lite.ogg │ │ ├── LTTP_FloorTile2.lite.ogg │ │ ├── LTTP_FloorTile3.lite.ogg │ │ ├── LTTP_FloorTile4.lite.ogg │ │ ├── LTTP_Flute.lite.ogg │ │ ├── LTTP_Flute_Extended.lite.ogg │ │ ├── LTTP_Get_Fairy.lite.ogg │ │ ├── LTTP_Get_HeartContainer.lite.ogg │ │ ├── LTTP_Get_HeartPiece.lite.ogg │ │ ├── LTTP_Get_HeartPiece_StereoL.lite.ogg │ │ ├── LTTP_Get_HeartPiece_StereoR.lite.ogg │ │ ├── LTTP_Get_Key.lite.ogg │ │ ├── LTTP_Get_Key_StereoL.lite.ogg │ │ ├── LTTP_Get_Key_StereoR.lite.ogg │ │ ├── LTTP_Grass_Cut.lite.ogg │ │ ├── LTTP_Grass_Walk.lite.ogg │ │ ├── LTTP_Hammer.lite.ogg │ │ ├── LTTP_Hammer_Post.lite.ogg │ │ ├── LTTP_Hookshot.lite.ogg │ │ ├── LTTP_IceRod.lite.ogg │ │ ├── LTTP_Item.lite.ogg │ │ ├── LTTP_ItemFanfare.lite.ogg │ │ ├── LTTP_ItemFanfare_Stereo.lite.ogg │ │ ├── LTTP_Lamp.lite.ogg │ │ ├── LTTP_Link_Dash.lite.ogg │ │ ├── LTTP_Link_Dying.lite.ogg │ │ ├── LTTP_Link_Fall.lite.ogg │ │ ├── LTTP_Link_Hurt.lite.ogg │ │ ├── LTTP_Link_Jump.lite.ogg │ │ ├── LTTP_Link_Land.lite.ogg │ │ ├── LTTP_Link_Pickup.lite.ogg │ │ ├── LTTP_Link_Push.lite.ogg │ │ ├── LTTP_Link_Shock.lite.ogg │ │ ├── LTTP_Link_Shock_Fast.lite.ogg │ │ ├── LTTP_Link_Throw.lite.ogg │ │ ├── LTTP_LowHealth.lite.ogg │ │ ├── LTTP_Magic.lite.ogg │ │ ├── LTTP_MagicCape_Off.lite.ogg │ │ ├── LTTP_MagicCape_On.lite.ogg │ │ ├── LTTP_MagicPowder.lite.ogg │ │ ├── LTTP_Map.lite.ogg │ │ ├── LTTP_Menu_Cursor.lite.ogg │ │ ├── LTTP_Menu_Erase.lite.ogg │ │ ├── LTTP_Menu_Select.lite.ogg │ │ ├── LTTP_Moldorm_Skitter.lite.ogg │ │ ├── LTTP_Mushroom.lite.ogg │ │ ├── LTTP_Net.lite.ogg │ │ ├── LTTP_Pause_Close.lite.ogg │ │ ├── LTTP_Pause_Open.lite.ogg │ │ ├── LTTP_Quake.lite.ogg │ │ ├── LTTP_Quake_Double.lite.ogg │ │ ├── LTTP_Quake_Double_Stereo.lite.ogg │ │ ├── LTTP_Quake_Stereo.lite.ogg │ │ ├── LTTP_Rain_In.lite.ogg │ │ ├── LTTP_Rain_InL.lite.ogg │ │ ├── LTTP_Rain_InR.lite.ogg │ │ ├── LTTP_Rain_Out.lite.ogg │ │ ├── LTTP_Rain_OutL.lite.ogg │ │ ├── LTTP_Rain_OutR.lite.ogg │ │ ├── LTTP_Rat.lite.ogg │ │ ├── LTTP_RefillHealth.lite.ogg │ │ ├── LTTP_Rupee1.lite.ogg │ │ ├── LTTP_Rupee2.lite.ogg │ │ ├── LTTP_SaveQuit.lite.ogg │ │ ├── LTTP_Secret.lite.ogg │ │ ├── LTTP_Sewer_Drain.lite.ogg │ │ ├── LTTP_Sewer_Drain_Begin.lite.ogg │ │ ├── LTTP_Sewer_Fill.lite.ogg │ │ ├── LTTP_Sewer_Fill_Begin.lite.ogg │ │ ├── LTTP_Shatter.lite.ogg │ │ ├── LTTP_Shield.lite.ogg │ │ ├── LTTP_Shovel.lite.ogg │ │ ├── LTTP_Stairs_Down.lite.ogg │ │ ├── LTTP_Stairs_FloorDown.lite.ogg │ │ ├── LTTP_Stairs_FloorUp.lite.ogg │ │ ├── LTTP_Stairs_Up.lite.ogg │ │ ├── LTTP_StalfosKnight_Crumble.lite.ogg │ │ ├── LTTP_SwampWater_Walk.lite.ogg │ │ ├── LTTP_Switch.lite.ogg │ │ ├── LTTP_Sword1.lite.ogg │ │ ├── LTTP_Sword2.lite.ogg │ │ ├── LTTP_Sword3.lite.ogg │ │ ├── LTTP_Sword4.lite.ogg │ │ ├── LTTP_Sword_Charge.lite.ogg │ │ ├── LTTP_Sword_Magic.lite.ogg │ │ ├── LTTP_Sword_Magic_Loop.lite.ogg │ │ ├── LTTP_Sword_Spin.lite.ogg │ │ ├── LTTP_Sword_SpinMagic.lite.ogg │ │ ├── LTTP_Sword_Tap.lite.ogg │ │ ├── LTTP_Text_Done.lite.ogg │ │ ├── LTTP_Text_Letter.lite.ogg │ │ ├── LTTP_TurtleRock_Transform1.lite.ogg │ │ ├── LTTP_TurtleRock_Transform2.lite.ogg │ │ ├── LTTP_TurtleRock_Transform3.lite.ogg │ │ ├── LTTP_Warp.lite.ogg │ │ ├── LTTP_Water_Item.lite.ogg │ │ ├── LTTP_Water_Land.lite.ogg │ │ ├── LTTP_Water_Splash.lite.ogg │ │ ├── LTTP_Water_Swim.lite.ogg │ │ ├── LTTP_Water_Walk.lite.ogg │ │ ├── LTTP_Wind.lite.ogg │ │ ├── LTTP_Wind_Mono.lite.ogg │ │ ├── LTTP_World_Warp.lite.ogg │ │ └── LTTP_Zora_Fireball.lite.ogg │ └── music │ │ ├── battle_with_ganon.lite.ogg │ │ ├── boss_clear_fanfare.lite.ogg │ │ ├── boss_~bgm~.lite.ogg │ │ ├── cave.lite.ogg │ │ ├── church.lite.ogg │ │ ├── crystal.lite.ogg │ │ ├── dark_mountain_forest.lite.ogg │ │ ├── dark_world.lite.ogg │ │ ├── dark_world_dungeon.lite.ogg │ │ ├── ending.lite.ogg │ │ ├── forest.lite.ogg │ │ ├── fortune-telling_house.lite.ogg │ │ ├── ganons_message.lite.ogg │ │ ├── guessing-game_house.lite.ogg │ │ ├── hyrule_castle.lite.ogg │ │ ├── kakariko_village.lite.ogg │ │ ├── master_sword_demo.lite.ogg │ │ ├── opening_demo.lite.ogg │ │ ├── overworld.lite.ogg │ │ ├── priest.lite.ogg │ │ ├── princess_zeldas_rescue.lite.ogg │ │ ├── sanctuary_dungeon.lite.ogg │ │ ├── select_screen.lite.ogg │ │ ├── the_goddess_appears.lite.ogg │ │ ├── the_priest_transforms_into_ganon.lite.ogg │ │ ├── the_soldiers_of_kakariko_village.lite.ogg │ │ ├── time_of_falling_rain.lite.ogg │ │ ├── title.lite.ogg │ │ ├── triforce_chamber.lite.ogg │ │ └── turned_into_a_rabbit%21.lite.ogg ├── favicon.ico ├── index.ejs ├── index.html ├── levels │ ├── cave_034 │ │ ├── cave_034-Tileset.png │ │ └── cave_034.json │ ├── darkworld │ │ ├── darkworld.json │ │ └── tiles │ │ │ └── darkworld-tileset.png │ ├── lightworld │ │ ├── lightworld.json │ │ └── tiles │ │ │ ├── lightworld-tileset.png │ │ │ ├── misc.png │ │ │ ├── misc_large.png │ │ │ └── woods.png │ ├── linkshouse │ │ ├── linkshouse.json │ │ └── tiles │ │ │ └── linkshouse-tileset.png │ ├── minimaps │ │ ├── dw_minimap.json │ │ ├── dw_minimap_tileset.png │ │ ├── lw_minimap.json │ │ └── lw_minimap_tileset.png │ └── shared_tiles │ │ ├── colliders.png │ │ ├── colliders.tsx │ │ ├── overworlditems.png │ │ ├── overworlditems.tsx │ │ ├── wall_torch.tsx │ │ └── wall_torch1.png ├── sprites │ ├── entities │ │ ├── enemies.json │ │ ├── enemies.png │ │ ├── link.json │ │ ├── link.png │ │ ├── misc.json │ │ └── misc.png │ ├── fonts │ │ ├── hud.json │ │ ├── hud.png │ │ ├── retofganon.json │ │ └── retofganon.png │ ├── misc │ │ ├── intro.json │ │ ├── intro.png │ │ ├── overworlditems.json │ │ ├── overworlditems.png │ │ ├── particles.json │ │ ├── particles.png │ │ ├── selectscreen.json │ │ └── selectscreen.png │ ├── overlays │ │ ├── overlays.json │ │ └── overlays.png │ └── ui │ │ ├── gui.json │ │ └── gui.png └── ui │ ├── loader.png │ ├── lore_bg1.png │ └── lore_bg2.png ├── gulpfile.js ├── less └── main.less ├── package.json ├── src ├── Game.ts ├── app.ts ├── data │ ├── Constants.ts │ ├── ItemDescriptors.ts │ ├── Keymap.ts │ ├── PlayerInventory.ts │ └── TiledMapData.ts ├── effects │ ├── Effects.ts │ ├── MapOverlay.ts │ └── ScreenFlash.ts ├── entities │ ├── Enemy.ts │ ├── Entity.ts │ ├── Player.ts │ ├── enemies │ │ └── Guard.ts │ ├── items │ │ └── WorldItem.ts │ └── misc │ │ ├── Flower.ts │ │ ├── Particle.ts │ │ ├── Smash.ts │ │ └── Torch.ts ├── fonts │ ├── Font.ts │ ├── Hud.ts │ └── ReturnOfGanon.ts ├── gui │ ├── Dialog.ts │ ├── Hud.ts │ ├── Inventory.ts │ └── items │ │ ├── EquiptedItem.ts │ │ ├── GuiItem.ts │ │ ├── InventoryCounter.ts │ │ ├── LifeMeter.ts │ │ └── MagicMeter.ts ├── levels │ ├── Cave034.ts │ ├── Darkworld.ts │ ├── Level.ts │ ├── Lightworld.ts │ └── LinksHouse.ts ├── math.ts ├── states │ ├── Boot.ts │ ├── GameState.ts │ ├── Intro.ts │ ├── MainMenu.ts │ ├── Play.ts │ └── Preloader.ts └── utility │ ├── Pool.ts │ ├── Save.ts │ ├── Storage.ts │ └── phaser-patches.ts ├── tsconfig.json ├── tslint.json ├── typings └── main.d.ts ├── vendor ├── build.sh ├── p2.js ├── phaser.js └── pixi.js └── webpack.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs. 2 | # More information at http://EditorConfig.org 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | indent_style = space 10 | indent_size = 4 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | [{package.json,bower.json,*.yml}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.gif filter=lfs diff=lfs merge=lfs -text 2 | *.jpg filter=lfs diff=lfs merge=lfs -text 3 | *.png filter=lfs diff=lfs merge=lfs -text 4 | *.ogg filter=lfs diff=lfs merge=lfs -text 5 | *.wav filter=lfs diff=lfs merge=lfs -text 6 | *.mp3 filter=lfs diff=lfs merge=lfs -text 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sublime text 2 files 2 | *.sublime* 3 | *.*~*.TMP 4 | 5 | # temp files 6 | .DS_Store 7 | Thumbs.db 8 | Desktop.ini 9 | npm-debug.log 10 | 11 | # vim swap files 12 | *.sw* 13 | 14 | # emacs temp files 15 | *~ 16 | \#*# 17 | 18 | # project ignores 19 | !.gitkeep 20 | *__temp 21 | .records 22 | node_modules/ 23 | public/ 24 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 4, 3 | "editor.insertSpaces": true, 4 | 5 | "search.excludeFolders": [ 6 | ".git", 7 | ".tscache", 8 | "node_modules", 9 | "public", 10 | "vendor" 11 | ], 12 | 13 | "typescript.tsdk": "./node_modules/typescript/lib" 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013-2016 Chad Engler 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Lttp 2 | 3 | This is a recreation of [Nintendo's The Legend of Zelda: A Link to the Past](http://www.nintendo.com/games/detail/5oMtHuB3aOHoawfC6brZ6myQYnE4flQ_). 4 | This is _not_ a port of the game, this is _not_ code conversion, this is _not_ the ROM running in an emulator. This is 5 | a complete, written from scratch, recreation of one of my favorite classic games using WebGL in the browser. While I 6 | will try my hardest to preserve the spirit of the game, and to come as close to the original as I can; expect slight 7 | differences in gameplay, mechanics, and graphics. 8 | 9 | This project is in no way endorsed by [Nintendo](http://www.nintendo.com/). Most images, logos, characters, dialog, 10 | plot, and other assets taken from the original Link to the Past are copyrights of Nintendo; I claim no ownership of 11 | any of the assets taken from the original game. 12 | 13 | This game is built with [Phaser](http://phaser.io). 14 | 15 | ### Building and running the game 16 | 17 | When the project gets more stable I will host a playable version on GitHub Pages, but for now you need to build manually. 18 | 19 | This project uses [node](https://nodejs.org/) for building and [git-lfs](https://git-lfs.github.com/) for managing 20 | binary files. You will need to install both to work on this project. 21 | 22 | After you have the dependencies above installed, clone this repository. If you already cloned this repository before 23 | installing git-lfs you can get the binary files by using `git lfs pull` after you have it installed properly. 24 | 25 | Once you have the repostiory cloned, you can install dependencies and run the development server: 26 | 27 | ``` 28 | npm install && npm start 29 | ``` 30 | 31 | ### Resources 32 | 33 | Below is a list of resources I used for game content. This including sprites, sounds, technical data, walkthroughs, mob 34 | information, and misc details of the game: 35 | 36 | * [Return of Ganon Font](http://www.zone38.net/font/#ganon) - For dialog and other text 37 | * [The Spriter's Resource](http://www.spriters-resource.com/snes/zeldalinkpast/index.html) - Used a couple sprites from here 38 | * [LTTP Maps](http://ian-albert.com/games/legend_of_zelda_a_link_to_the_past_maps/) - maps of all the dungeons 39 | * [SNES Maps](http://vgmaps.com/Atlas/SuperNES/index.htm#LegendOfZeldaALinkToThePast) - maps of all the dungeons 40 | * [Zelda Wiki](http://www.zeldawiki.org/The_Legend_of_Zelda:_A_Link_to_the_Past) - Great source of information on game content and mechanics 41 | * [Zelda Elements](http://www.zeldaelements.net/games/c/a_link_to_the_past/) - Another good wiki-like source 42 | * [nes-snes-sprites.com](http://www.nes-snes-sprites.com/LegendofZeldaTheALinktothePast.html) - Used for some character sprites 43 | 44 | ### Roadmap 45 | 46 | Below is a non-exhaustive TODO list for the project: 47 | 48 | - Signage 49 | - Lifting items 50 | - Fix drops 51 | - Add handling for gamepad axis sticks 52 | - Implement ERASE/COPY menu options in main menu 53 | - NPCs (generic npc loading from tmx) 54 | - Implement better level loading and manifest 55 | - Finish up ROG Font characters 56 | - Bosses and boss mechanics 57 | - First Dungeon (palace) 58 | - Intro dialog 59 | 60 | ### License and Legal 61 | 62 | This code-base is released under the [MIT License](http://opensource.org/licenses/MIT). 63 | 64 | All dependencies are released under their own respective licenses. 65 | 66 | Most images, logos, characters, dialog, plot, and other assets taken from the original The Legend of Zelda: A Link to the Past 67 | are copyrights of [Nintendo](http://www.nintendo.com/); I claim no ownership of any of the assets taken from the original game. 68 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Agahnim_Charge.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eebe0660678226df9c0cb31c712f60c3c078861f67d81b844bd36f423a04e15b 3 | size 10125 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Agahnim_Dash.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8ea6f96f05a82928bb38d4613bb0fee2041056a1081ce56fa7a5213a693826fa 3 | size 10925 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Agahnim_Fireball.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:31efa623c7b57068853775c1b466a21169f9ae0c12eb0ef372f3961372c4ff42 3 | size 6407 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Agahnim_Shock1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e0298705aec00b02b528d6836b71d81504d02a4c4ddc5f321b9b6661633de30f 3 | size 3971 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Agahnim_Shock2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2a1929b08b21d60d728a468b074b5e4a1a91b761ecbe3f0f9ab0558155292b8c 3 | size 3971 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Arrow_Hit.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2753e9d9134e983d48fb64ef0b92b7f08d13b99a3bf400e07895d16cf2e34773 3 | size 5292 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Arrow_Shoot.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4eafc369683267b34c4c688b919ab1e22fd35e17152fb374097a83df102bfb91 3 | size 4325 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_BallAndChain.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:96c6eb4ecd1855b34363ffba42e2a81964da8479a1efb581c317a459f661a457 3 | size 5884 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_BatGanon_Crash.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:743507509c5a8886e8e5e535223c4dd2650e5e95e27f7ff98ee8042e7d8eb10d 3 | size 11356 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Bee.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f2fec0e443fab5f058f3fd826536dcdb6a6ae2db577c2b3d6da2c9fcdd501faa 3 | size 6191 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Bee_Fade.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ab05246d6b324a3b60d8ea9651a765422cc1d5ea69a4184ec78aa241a8655b4d 3 | size 6341 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Bomb_Blow.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5e7c56e587986fa499ac29dd02d4e7e6516003aaddfeaea8f5b6bd42e69f8371 3 | size 7370 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Bomb_Drop.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:80bb0bebb33e2b5b4da3fc090fec210c123a0ec2c0915db58116affb9f341632 3 | size 4539 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_BoneBurn.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f7e4b583f4f27738c2ad623c2f9b192807d4955a2b617ee767cc4046f7dc4122 3 | size 4992 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_BookOfMudora.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:18eebf491e042107b838a171b10b51ec3ffe2d4ef9fb327306d7e6317432b9f5 3 | size 29853 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boomerang.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:77d1b48b6aa1575bf876963a20f7061d3e9ae49567c6d94e127a6c32cf4e660d 3 | size 6471 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boss_Fireball.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:832131804b54f20ab13d12d738d1c9c7d556e99e4911fec57802293cad19b666 3 | size 5417 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boss_Hit.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5414ab0454cf7385d28f38270f81fd6aae2ff75900c9489e0b78617983f1b9df 3 | size 5341 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boss_Mouth.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b63ec47c6d500326254940d6f66ddc34d8a11920f98fbc221885fcb52595a76 3 | size 5298 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boss_Sand1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f8bc58a8c763a8ebe520bde68c1b6eb79b28f7d91ff3376677ce3f8e3e5e9a5c 3 | size 5143 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boss_Sand2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca90ac344ee5b4ff60439b83db7020c9dd359936124146a9afad00bc7c83a221 3 | size 5135 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Boss_Tailwhip.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:10783b0ea5a78439a312cc16c4caefa157376fbede6da2bc3e8deb957ae9d5e3 3 | size 6109 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Bounce.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7f1b5e43b00009c956e86ed2cdadf00b3c2f8fb75729be867a57dedf003b646b 3 | size 5877 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Cane.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:474885b83db7fef091d147ace66897e04e8c5d54b960e0f62d3dd831c3e1e69b 3 | size 5350 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Cane_Magic.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ac5779e80d0b7e6b3d84e17e01f1ea937fe9038d973fb153bb44628530f862d6 3 | size 4744 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_CannonBall.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:777895b0ecb768395cc4b17ef7cc4dcf6a267a8bb8a1b1bd0502e0e8e5093ef9 3 | size 4942 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Chest.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:81037cf4e47da97b20685bdd33e21919a089a8121a7c4092472e7ca55ed5d76c 3 | size 4409 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Chest_Appears.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:349ff677d4d5e4bb694753b42a03d4a2b49c4aea5ac0497c481817422a9acc33 3 | size 8130 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Cucco.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4d522dcb088943c4f967cc051fb92d002d805594eae6fb17beb4f78f057b593a 3 | size 5000 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Cucco_Fly.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4f8fbe69c96f4056030ab61333f2f1a02c255d14f46b50c79c0f15919cd49b2c 3 | size 6654 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Cucco_Hit.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ff09052428dd0b31c6e04f8799a4e79ff2e352569e7277b3a88672e095a8b541 3 | size 4401 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Door.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c2406b379603acde4969da3c902fb9aaa5b1b8b9a086fd0b24b9fb911b37b1ad 3 | size 5015 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Door_Close.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dbd763a178bbc027e70af4a9ecb07b103ef5cc9748b0f7ef335ae4bcf3010342 3 | size 5086 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Door_Double.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f4797393ec1b2f18d944d4267053e9ba112ea501e5d1044269db38201e07b8bd 3 | size 5505 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Door_Unlock.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:49866f1a1787b10fe62b9e04f83f42b959111245670c3477720b2db618844a70 3 | size 4633 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Dungeon_Open.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fcab040043dd59c99ec26eabd0b00a528595926c7f4f71883c617357c0734159 3 | size 7392 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Enemy_Chase.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:abc7e13e0e5e5de6e895fd84e07b4f467593fc925284df2cfa9e8bb2053a99b5 3 | size 8704 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Enemy_Hit.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6cca13c8afb93a266d6d6cfc6000f674528abe21f4f923f83cbc89195293becd 3 | size 4418 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Enemy_Kill.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f5a4967bd890ae409ef566fef71988ffe5a780ea3df9c378ab3b8d3a8bf4e8a8 3 | size 5874 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Enemy_Skitter.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8b5adfb38e4bd4addfa4e9f47e4bff584392b3f05f715e1a88597005606a66f1 3 | size 6269 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Error.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:301c45df0ab38046dc6f35152951660932a7e2d9453d524a2a348e37fbd2c6dc 3 | size 6570 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Ether.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f60bcf8e8b62d5fc1886af315cef6e5af237dcbc8c99114e735d7550aa54a030 3 | size 5621 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FinalDoor1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cd9597331cac29d40970734199df315797f40130d127622fd8acc39984521f22 3 | size 5628 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FinalDoor2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:64b9b0171f1870065fd38bd8c57cc0f71cedc3e001bf503ab2c50b6270d94453 3 | size 5519 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FireRod.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:059acc5543b791f03c4fa7b07ab18954fded3a9a187f1e02efab3664065f5c8d 3 | size 6529 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FloorTile1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:93e2412ea6c71b3160a79baad0e978e191c508ed153467bd0250e2c0e713d0e0 3 | size 4470 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FloorTile2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6e4b7291b2d6237711f6b5e971e11dfe36df7f68aa8a81c0515ab5eef75b1a9c 3 | size 4407 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FloorTile3.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:59a46dadfe3abe7631c4bbaf0beedc60f36ed5b60e02537153aa63afb87e57b2 3 | size 4432 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_FloorTile4.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3e51af851df504a68f397acc7efa135933734c93fd9a44ef31389252a40d9864 3 | size 4448 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Flute.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:05e53d4043719ec759cab10c5d58796a2bebba9ef677e4bf064823b335bb8d5f 3 | size 14124 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Flute_Extended.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:60cd573fe795d9509d3d0f4ba68db08d7c9dfcb2a3b0773511b52265f46672b5 3 | size 54251 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_Fairy.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c127ce9549666405c9252e2c53ce9b593d732864ecb49828938e3e983fbd85cc 3 | size 5292 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_HeartContainer.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:09523429b0a849059dd515cabb07016584eb589264275a45e5df8d030dfedd24 3 | size 10982 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_HeartPiece.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1e0880299fd97389a659501c2c6366a2d6485f3c9b8bae91cfcf299c72b18f9f 3 | size 7839 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_HeartPiece_StereoL.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a97a52e4241035eebfd5d08b7258dec9552fe69002bf1964ee8ee44a91c15d1d 3 | size 7716 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_HeartPiece_StereoR.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b39350a237fddbad5198fe67bbf884a2498e167264b3965c6c63aa1926100d1 3 | size 7700 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_Key.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:92b5281631a0b1171c24552b1514f48391d7c2b8ce5febe5101ee349059bcea2 3 | size 7941 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_Key_StereoL.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f871e42a5fc0999f229398deeb3e49790e0c52b149f81690c8a44efe7416f96c 3 | size 7683 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Get_Key_StereoR.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:858b7c7b6a12227d875d7f7c9197b2925dd3f9fa84380f727ba175232cd11402 3 | size 7685 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Grass_Cut.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fbd8863786e4b552dfacb3a67fa60b9dfd18dd06539e3666b44d42d24fe823a7 3 | size 5849 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Grass_Walk.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0b9574ab44eed52fc1dd6d7d3bd425c889236355e77d01f0adfc2ab58e4972bd 3 | size 4181 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Hammer.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9475b35b9ca754c1fcfb5cb094b143fc4d34b7504f5a45ac75a1c98448f03088 3 | size 4167 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Hammer_Post.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f754c2cb1b4aedb2ff4cbf07c5c1cbcb6e6254e303973529de1232ae31b3ee88 3 | size 4121 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Hookshot.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7ed8857d76653657961179c418fd61ecad8c09a19a20901688cf0eb18e0831c4 3 | size 4373 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_IceRod.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:342e81abc3b23a9cea361f955a58d0da936447c8e9aafd19b53015e2de27229e 3 | size 7309 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Item.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:eee44eb1eadff78e571190d88467a1cb226b73bb71b38c581dc389d2c03f12f6 3 | size 4430 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_ItemFanfare.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1a7e57f9625191629e090cd7cd4d9bbe5fc83db3686db46cbe8e4b5e8c7f2cae 3 | size 9809 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_ItemFanfare_Stereo.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6d42c58429ae16fa32b12bfbd8f71db380e41242a03175c6e98da2daa6d4aea9 3 | size 9797 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Lamp.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:900f7ee0284bad235938bc74c027b933cc7829fbffa195eb998b5017cfbb48b1 3 | size 4366 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Dash.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:782850dab5fb8d80f16d3ece5f67881794f1256cb9b02e2318082b9aedc0f412 3 | size 4128 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Dying.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a6a2aa26ba6e65362675af10c0f7641731b44277d89b3ecc150967948957455a 3 | size 9054 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Fall.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:84d5072ff3c8d7f0e5892a95d97494ffc2b2a0fc77ef0a2879df4b6e589cce00 3 | size 7614 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Hurt.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:96dd4380b3fabc2d43550d895c97501199cb02d45a168056822efa273c25748c 3 | size 4156 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Jump.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6fe824bbe4bf35d1bf0190d441a74adcec16918cdc621a538c2ae6817cb74d61 3 | size 5163 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Land.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:414acb27e3a1d3d801995b4ddb1edc85538d8a1b53a11a85c28b70db81fc83ca 3 | size 4234 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Pickup.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:15a9c0a9659b5fb62048d067fdfc09f2bcd18912aca7b64898190856aa6e716e 3 | size 4816 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Push.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f84a82f310d6b7ceeb64b15298029970ae9b17aeec049410ce542a662034cbee 3 | size 6414 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Shock.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:71c233730dc98d99e416d3cabd009589b016a7b97cfe1e2cb50dbc5ce3892806 3 | size 5255 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Shock_Fast.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6ba6a94d6a7fb8b635b16ae7a17f2fdcea6de3bf863baf332cd60d5fe8ee299a 3 | size 4936 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Link_Throw.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ed35833f16cea0e0d94affb5b1aa5bd3c369cda761176e4e9d99076763cc1e1e 3 | size 4481 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_LowHealth.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:daec0c994e8bc8f9128a0743b2d2ebb2d0b4e4f1abbf7689c7444f4fbf31f318 3 | size 5166 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Magic.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:55a98d567e7912f74ab51043e2dab26a9be49a1318ae6c1f63ce22660e9f679d 3 | size 5055 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_MagicCape_Off.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f6ba28fb735b0d959e637456d909b583ffd1f7a2b924d330585c9855c7a6349e 3 | size 4847 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_MagicCape_On.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e443755c38705db8fad94797a3fd6b2070ac3b20047907bf3e6e49024ddb8443 3 | size 4804 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_MagicPowder.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c7d81a84129843ccc800ebb4ab8c1685806cc2821141bf49a8f7a4002d6008ee 3 | size 5934 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Map.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:154c4d81ba0cecaec0ea41c4c31a0024487abe4503a1eee232bffc9de3cb9bcf 3 | size 6715 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Menu_Cursor.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:33c0d692bf8923cafddb3e855b590f96a53b813b972d8aa6a082234fd7bb9ea8 3 | size 4512 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Menu_Erase.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2a5bb9fe792c9d4de3c46e7a144904c7e61ec17f5a6d62f270ff09cdda85165c 3 | size 15662 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Menu_Select.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9339d9732f47a4fb2bf8d43f344b7089b34984d0895109f8ab029a17bc9e247d 3 | size 5485 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Moldorm_Skitter.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1b2adbbf099359a05f473b5c7a880fe540585800a90258f2c1ad83eaa3e52f42 3 | size 4399 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Mushroom.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5b09e668f5585f1baeb271c2552c3741f14d8d7dbad997f74483b08bdddf327d 3 | size 7557 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Net.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:376d6020a3739785565e4b378c3ac5b9a2879bf7d4ba58896019978a1a749737 3 | size 5629 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Pause_Close.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d9c859e4a217d1814b6777b9e2253784139c887916ab618cbe9f350e6b481c2f 3 | size 5235 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Pause_Open.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:acc4719a82add7972d7ca9ecd88f4b5561272e33292d34ac65e7ff4f2b6810d7 3 | size 5214 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Quake.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:068192e8f84fa46850cdb2f898abba794d2d50730c5173e689b5797593038ce0 3 | size 10806 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Quake_Double.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e50ec3f11b29489127d45433a1403a7ef8e1e1ba61059ab904a65104a112e825 3 | size 10907 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Quake_Double_Stereo.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ecf377c67ffb41fb58f1ed197c010646d1f3f7da4d4c8516807488d0778829ef 3 | size 10704 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Quake_Stereo.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1f756d3736038c853b06f7d39fc67be37e7291171098b7f88a7a187b763ad71c 3 | size 10992 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rain_In.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3214cbab47a7e32977200b4ea32c990eb3cd191d5c95b1ac4708acfbcd077ed8 3 | size 25413 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rain_InL.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6a8c35036b39727cc679b9a5023cdd5365dff8fc870eeded534511a9e72e111d 3 | size 10876 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rain_InR.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:29089c7e67bd3e3fc4f13adbbdb0b521266cbe83025f495d44cbcb5bb498ef8a 3 | size 14485 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rain_Out.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:754b698617d167d6b6becba0f8948e78d3cb405944f2ce0671544eba843db202 3 | size 25318 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rain_OutL.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8ce22032935bceadb3a61cc53a9019bc1742a681444354fb9f64ad4ca52cb41f 3 | size 10834 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rain_OutR.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c09fbc951c39004c6ad7362fe355b4634c948968dbbb0e928f0a51efe5ee4648 3 | size 14503 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rat.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:58c47efdb50f036c3b3cf9e525e37523290dc2f99f77b83d298094a21a9f0c6c 3 | size 4933 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_RefillHealth.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7d637ab8f58ff7566186e21e89d1c77a72581f53e8f21bb0d4889bfb453f9804 3 | size 4258 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rupee1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b170b67cb300cb3039a042c60c234a2965004784647cf7f3a719fad8a1246aa4 3 | size 4920 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Rupee2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cef8066f5ebbfc08ed135e30e7128e8a7e6e1b644bf22bd7e7af1b22dbbc0057 3 | size 5406 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_SaveQuit.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3d142af75afd2fa710af8d48ab5ebea13697f00632e0848ea954da1fe0e6792f 3 | size 7048 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Secret.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f0de2748471906404799028a9232bb83ef5b1a2751aaad46266a564b54d7f7c6 3 | size 8901 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sewer_Drain.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:02a44df1f78d1da98434c23cf308adb22d2b264381082e4046ea5146c909c624 3 | size 16012 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sewer_Drain_Begin.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f7f2305288d6a0de0f41e7d3393576a513a206f0caf240c969fea3f410d6ca03 3 | size 7341 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sewer_Fill.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a579912fb535f28bea95140ab2b89049226ef6ce35239b9847cca88680d6865e 3 | size 17879 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sewer_Fill_Begin.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9f16fd97e3a19663dc016c4c75cdfcac22d80e62690e0fce9c7646ec14cb597c 3 | size 7381 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Shatter.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bc21d5b3e133443346f93452b79d2626e5ab0e7ce8963b6f3eaa914ce6dcbeac 3 | size 6119 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Shield.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a50498a766f7f163691d343eb29246be4eac0a0bd6813f7cfc11083d9e07bbcd 3 | size 4604 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Shovel.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e0cb198f1abd685e8b096f10e39476988763d1a472e8d5fdc48674fd5ad367c1 3 | size 5808 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Stairs_Down.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:15a2822671cdb31aa0d470d8009ca4ee5c87fae4614f55df20f630742f73d1e6 3 | size 8005 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Stairs_FloorDown.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6ca3b25b2f9767681fb9fe3e061a66881c28ac135e6d05d2294b2ce7a3fb7c50 3 | size 9735 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Stairs_FloorUp.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:71b4a2cb7f54990a06f7f090c1d1bdc8fe8164624b3de1f90b7e7a7ccf772556 3 | size 9689 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Stairs_Up.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:044e2f4f42bbbc35a5e3417a25e098c75670e0fcfff8ac9adb9327a454f01542 3 | size 7991 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_StalfosKnight_Crumble.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d1e46277414b6916bf3f0df7f9ceb207b21ed893f48266629e643ab75d302d15 3 | size 7626 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_SwampWater_Walk.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c5ac1729825f404cb6ec2bda6ea4037d9da2ab442c7d1b8b5bcdc101e4a8bcc8 3 | size 4421 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Switch.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:01641f9645d9335a12567c60cf99b0e9b5ffbacfaf30f5be16f7706b966f5993 3 | size 4632 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a34c97775fc37c95f3392b4b874801ee72d218db047d71546772d393af10a258 3 | size 4516 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5f93703dc2e497aa9a01c5335a4bef8dae92b19a36658e8db53650559d4ae533 3 | size 4436 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword3.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:60dd2da7ee64dd2e2c5d14a3fd4f5d072eb998864f29cd7b67c28690fa764515 3 | size 4699 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword4.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bf183170831aa04cc00301bafe728588bd0440ab1a35228af6839e3f5bdefd3b 3 | size 4846 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword_Charge.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9c8a6904e950d3a9cb884321c437a0dae49913d989b62641166e3184fbd9080d 3 | size 4966 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword_Magic.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8200ee3092bc8bc1578c1249dd52238c85441369c930250075ab63961e5a105c 3 | size 5697 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword_Magic_Loop.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aaf6eea88436bcd1997381a5365e6277bad9e6cc7ddd7cba10a1021a4bef2c43 3 | size 4787 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword_Spin.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c2173ca4babc9e45e982ede2a8c7d930b1fee00ea082ae71e3a2b4610141171f 3 | size 5164 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword_SpinMagic.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6c73e44e83605f3dd8ff8bd06d9c69c28c7cf458da9227e92076f32a32cf7b03 3 | size 4696 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Sword_Tap.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1f4acfb450e457f85c8a6ce1a615ca808e415f799810c43bfd5d9f0ad3c2c733 3 | size 4135 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Text_Done.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:160c980eecbcb03b3d2ae80c7f14aa086ace85ea1e5301e109e25f9393bfb19f 3 | size 4735 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Text_Letter.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3e36db06fd0716af1e19ab8f07b71fbcea30d8fb73445be6a237428d4bcab9f4 3 | size 4062 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_TurtleRock_Transform1.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:45ada471d2201f6cc07dba274b4d3f570428de0f75458a5c597ca5ad2c06d212 3 | size 5549 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_TurtleRock_Transform2.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:6311dc43bfdc22ad1aaa1dde85e1182bc47ad0c7ccdf39bd95f33cb39ff5cda2 3 | size 5562 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_TurtleRock_Transform3.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cf25261ee5b2e9a2ea8af4ae1d5da9bad62b9804bfb9730c441f4ddcab7e4860 3 | size 5607 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Warp.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:328b06320a5bad8000841b7390882ccbdc5938daa325f73f00e6c256dce89eb7 3 | size 12780 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Water_Item.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b7b50d5e3317021114b56c03b0dcd376a6d82be8a1b9c3591c93b377ed477fd2 3 | size 4363 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Water_Land.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:09cbacd706795c0ce3aa8dc3dd3b29c4e250bafce80a29a5865be981b008216f 3 | size 5002 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Water_Splash.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:673e7715d6c379edd849ee5316d8edcf2f6768fa4b4a2111ece23e38caf4e106 3 | size 6179 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Water_Swim.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0768b901f5285fbd1e7cce73da5e48eacc954b86916196ddb6caac562843bb5e 3 | size 4621 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Water_Walk.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a222c69a6dea40a482e015592684b40942b98f74d2735d5c072670b160f62608 3 | size 4531 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Wind.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:960539ef028d8a0ae79be4bc225d3b8e3a6dae0bb1eccc4eaaf2a004c266e185 3 | size 24797 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Wind_Mono.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:08d7fda19df0d7800693d87271ce95a320275af242929bc43f84f2405e47e6f3 3 | size 24732 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_World_Warp.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c1e7fe627f2a4c60f7e1d7e35fe5eb65b97a5d136db3d319bfaa6fee2d5a5bf4 3 | size 19733 4 | -------------------------------------------------------------------------------- /assets/audio/effects/LTTP_Zora_Fireball.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c7ab723f74b877b32da2f75c675b24e4e899993f51033c6b289fa3ab3358566e 3 | size 5449 4 | -------------------------------------------------------------------------------- /assets/audio/music/battle_with_ganon.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:227898662b9bbbf11f326e0b15b47a229865ea52a820a8b8c97da03be00ac9d0 3 | size 322418 4 | -------------------------------------------------------------------------------- /assets/audio/music/boss_clear_fanfare.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:30e7804e6e8ee7fb323f34d2b7d57b871f51232858d6572dd0b4d2dc1f65cc13 3 | size 58681 4 | -------------------------------------------------------------------------------- /assets/audio/music/boss_~bgm~.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:283e9d988ee071ae5c9a179b80fa68f294302e1c77c6aeac3bd9c968c2cf8f08 3 | size 152546 4 | -------------------------------------------------------------------------------- /assets/audio/music/cave.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5668c3535187d066d8bd12efc8942ee386f0e4e1d6cd4c88d1c74cfdb8ad815c 3 | size 250631 4 | -------------------------------------------------------------------------------- /assets/audio/music/church.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:737869aa64924c8d96ed699d4bd35b419ee2239b97769378d7f076491b3168d6 3 | size 387415 4 | -------------------------------------------------------------------------------- /assets/audio/music/crystal.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ab6087878b53f9a33453bf508a3628bb91e955ecd8b9e0895a2bf41f71bec89d 3 | size 269012 4 | -------------------------------------------------------------------------------- /assets/audio/music/dark_mountain_forest.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:12407253af3d5e3d9298d133bcacf7b2bd2c5a657c65bd4a4efa13edf939e1b9 3 | size 459014 4 | -------------------------------------------------------------------------------- /assets/audio/music/dark_world.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4409850819906513787ec1bb64b4b58d0a060d2fd9c9dc76eeb09f0987275e60 3 | size 585977 4 | -------------------------------------------------------------------------------- /assets/audio/music/dark_world_dungeon.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:efc5863e364dd5aaa325b1cc6b9e7f54fd133d35615e7f1f6541ba24e286c4e1 3 | size 425072 4 | -------------------------------------------------------------------------------- /assets/audio/music/ending.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3cdd3b1c5ad3e0d366200112fe00f241c0ab0795aed7eb1d2a603e6cdb0edf3a 3 | size 1895932 4 | -------------------------------------------------------------------------------- /assets/audio/music/forest.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c5cbda2fe0b895ff9fd19f371f83de04af13f8677ddf536c4d54c3c2c65ccb0b 3 | size 233337 4 | -------------------------------------------------------------------------------- /assets/audio/music/fortune-telling_house.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2929e2e3a7517bade5ef9c7d06274244214f87d4e31d65aa8e29a8cbdeeda9f3 3 | size 178041 4 | -------------------------------------------------------------------------------- /assets/audio/music/ganons_message.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4a13122d093d6729b2d151656d01b43fe161c4a2977f4ea550110847820e9ed4 3 | size 180997 4 | -------------------------------------------------------------------------------- /assets/audio/music/guessing-game_house.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4575969854ce449b0a0b82104ddb8536765da1ceae4caae0fd4a0669b9c01210 3 | size 217962 4 | -------------------------------------------------------------------------------- /assets/audio/music/hyrule_castle.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c8870dc27cfbaad5302d155a64fd17a077b822da93e854fe789dd04a41665696 3 | size 714346 4 | -------------------------------------------------------------------------------- /assets/audio/music/kakariko_village.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:40980ada9c4338f163d0c67444b62e6214553c85c29fd2b6c94bbad8aab3835e 3 | size 538862 4 | -------------------------------------------------------------------------------- /assets/audio/music/master_sword_demo.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d6cc976faafc47f7ceb3208ff8affd011611eaf6de5895f6698e941191818833 3 | size 64679 4 | -------------------------------------------------------------------------------- /assets/audio/music/opening_demo.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4329204268280e4eda475403384034f301d3edeea45b61534da767f366431cec 3 | size 501672 4 | -------------------------------------------------------------------------------- /assets/audio/music/overworld.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3dd68479db3e28e0fbe9cf54d2c06f1213ee578a666f036825f1131997e661e5 3 | size 277316 4 | -------------------------------------------------------------------------------- /assets/audio/music/priest.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ad6ce8cb38745841663b5a1994ef7ee8f4dff434deee512615828f17b5e01fd3 3 | size 402289 4 | -------------------------------------------------------------------------------- /assets/audio/music/princess_zeldas_rescue.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:1812b33d760d607b876e493d59c40b1669e691adfc35ed02abdaee3c5394c090 3 | size 381705 4 | -------------------------------------------------------------------------------- /assets/audio/music/sanctuary_dungeon.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8b6eba9c3fd277f9556540b18c789ae49ee098bbebbd3e03a09183d8da9381b9 3 | size 502071 4 | -------------------------------------------------------------------------------- /assets/audio/music/select_screen.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:21e2c0538d5edbfccecee392c6bf1c79dfa09e066ec873a024de712c7a0d242d 3 | size 224842 4 | -------------------------------------------------------------------------------- /assets/audio/music/the_goddess_appears.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0972c175c516427ae257a44de66f00e29a5c9943fd78ecf81cd42040011a4336 3 | size 228333 4 | -------------------------------------------------------------------------------- /assets/audio/music/the_priest_transforms_into_ganon.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b4ddb435e9a9b3247b7d3c3fb3ecd82e16f0dc8d78f807278b44b95e014002c 3 | size 34468 4 | -------------------------------------------------------------------------------- /assets/audio/music/the_soldiers_of_kakariko_village.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2131cfadf66a79299609a42a29bb93f267e5e3856a446706882846d8188fdee6 3 | size 180631 4 | -------------------------------------------------------------------------------- /assets/audio/music/time_of_falling_rain.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:5c39d76f08bda5934ee36bc4907134cc37cb5f52cf620a8a028b32a15c08878b 3 | size 287883 4 | -------------------------------------------------------------------------------- /assets/audio/music/title.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:744ae6eabbee2a5e7a6e2679638521542f8c2865b479e12ec55bfeb52b20ee55 3 | size 76372 4 | -------------------------------------------------------------------------------- /assets/audio/music/triforce_chamber.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fd40dd162a416da5d5a911a6474c99fd7720818e7c0984700efde56c011bfe1d 3 | size 390166 4 | -------------------------------------------------------------------------------- /assets/audio/music/turned_into_a_rabbit%21.lite.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:fc0a452025da7f3ceb4b77eb204b95b968876547be23c5557e3e77847246dbb5 3 | size 235326 4 | -------------------------------------------------------------------------------- /assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/englercj/lttp/e949b6b74532c4820c2271cee1ad65429a5d9df2/assets/favicon.ico -------------------------------------------------------------------------------- /assets/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%- htmlWebpackPlugin.options.title %> 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | lttp 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /assets/levels/cave_034/cave_034-Tileset.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a16715022145cdeedaeddfff178edc37c98ccbf4ec15751380ad9992f1b61390 3 | size 12868 4 | -------------------------------------------------------------------------------- /assets/levels/darkworld/tiles/darkworld-tileset.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:df5d2fef42676d39a45e3f3d3234154a1fed3466c9d4183cf3a5678403ad8d2c 3 | size 259128 4 | -------------------------------------------------------------------------------- /assets/levels/lightworld/tiles/lightworld-tileset.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3106c8706b063bea66bf8a5515fa3fffa89f105e7b31206c8992e1a51c9f7bf0 3 | size 257469 4 | -------------------------------------------------------------------------------- /assets/levels/lightworld/tiles/misc.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8766ec144a67bda262d225162a8a7675f4c0046f7fab06c350f7cddd60ba21b3 3 | size 6259 4 | -------------------------------------------------------------------------------- /assets/levels/lightworld/tiles/misc_large.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:07ca58c6360c1824616ed23408b1f00fe89231cbb3937e5bfed736cdcc62a6f4 3 | size 7094 4 | -------------------------------------------------------------------------------- /assets/levels/lightworld/tiles/woods.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:69f921a372c9bde860c7621f7165a5c62c9176ec606e1c68432391a471f4a61b 3 | size 3163 4 | -------------------------------------------------------------------------------- /assets/levels/linkshouse/tiles/linkshouse-tileset.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:00f7c74a013536bc57abcb8a6c6bcd91621967f031c81642a03f1047d0ef9b69 3 | size 9559 4 | -------------------------------------------------------------------------------- /assets/levels/minimaps/dw_minimap_tileset.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e5ac2a1e3694415b30c8f3b2342be4f512e7bdcffce4735f5a782626068570f8 3 | size 9675 4 | -------------------------------------------------------------------------------- /assets/levels/minimaps/lw_minimap_tileset.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d81c1a0841e5027b4f4108c813de87d189ca7bcf9413d80cdd6d4d226b105d0b 3 | size 9964 4 | -------------------------------------------------------------------------------- /assets/levels/shared_tiles/colliders.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:93793e5a4b3d2bc34f5771b6432dec909a8803fdc4bbb024e2b10f3c87edcc90 3 | size 2611 4 | -------------------------------------------------------------------------------- /assets/levels/shared_tiles/colliders.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /assets/levels/shared_tiles/overworlditems.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:54121fc32eb4fce7d91970d5d736f50e273e83bcc55216cc258e0511aa90fcd0 3 | size 11365 4 | -------------------------------------------------------------------------------- /assets/levels/shared_tiles/overworlditems.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /assets/levels/shared_tiles/wall_torch.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /assets/levels/shared_tiles/wall_torch1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8d8843a930bb3c76c68d4901eaa4aa4888f451d3ae6502c437bad40a90e16f63 3 | size 441 4 | -------------------------------------------------------------------------------- /assets/sprites/entities/enemies.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4d2f4e7485325c51e4113f3c429fd10ca3bce14a04233245da943d4ea10d9866 3 | size 20873 4 | -------------------------------------------------------------------------------- /assets/sprites/entities/link.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9e3153539f9003fadffeba9c2878c5208370f990b97b1ef16dfa975928a52fc8 3 | size 45139 4 | -------------------------------------------------------------------------------- /assets/sprites/entities/misc.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "flower/flower_1_1.png": 4 | { 5 | "frame": {"x":48,"y":48,"w":16,"h":16}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 9 | "sourceSize": {"w":16,"h":16} 10 | }, 11 | "flower/flower_1_2.png": 12 | { 13 | "frame": {"x":48,"y":32,"w":16,"h":16}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 17 | "sourceSize": {"w":16,"h":16} 18 | }, 19 | "flower/flower_1_3.png": 20 | { 21 | "frame": {"x":32,"y":48,"w":16,"h":16}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 25 | "sourceSize": {"w":16,"h":16} 26 | }, 27 | "flower/flower_2_1.png": 28 | { 29 | "frame": {"x":32,"y":32,"w":16,"h":16}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 33 | "sourceSize": {"w":16,"h":16} 34 | }, 35 | "flower/flower_2_2.png": 36 | { 37 | "frame": {"x":16,"y":48,"w":16,"h":16}, 38 | "rotated": false, 39 | "trimmed": false, 40 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 41 | "sourceSize": {"w":16,"h":16} 42 | }, 43 | "flower/flower_2_3.png": 44 | { 45 | "frame": {"x":16,"y":32,"w":16,"h":16}, 46 | "rotated": false, 47 | "trimmed": false, 48 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 49 | "sourceSize": {"w":16,"h":16} 50 | }, 51 | "torch/torch0.png": 52 | { 53 | "frame": {"x":0,"y":48,"w":16,"h":16}, 54 | "rotated": false, 55 | "trimmed": false, 56 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 57 | "sourceSize": {"w":16,"h":16} 58 | }, 59 | "torch/torch1.png": 60 | { 61 | "frame": {"x":0,"y":32,"w":16,"h":16}, 62 | "rotated": false, 63 | "trimmed": false, 64 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 65 | "sourceSize": {"w":16,"h":16} 66 | }, 67 | "torch/torch2.png": 68 | { 69 | "frame": {"x":48,"y":16,"w":16,"h":16}, 70 | "rotated": false, 71 | "trimmed": false, 72 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 73 | "sourceSize": {"w":16,"h":16} 74 | }, 75 | "torch/torch3.png": 76 | { 77 | "frame": {"x":32,"y":16,"w":16,"h":16}, 78 | "rotated": false, 79 | "trimmed": false, 80 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 81 | "sourceSize": {"w":16,"h":16} 82 | }, 83 | "torch/wall_torch1.png": 84 | { 85 | "frame": {"x":0,"y":16,"w":32,"h":16}, 86 | "rotated": false, 87 | "trimmed": false, 88 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":16}, 89 | "sourceSize": {"w":32,"h":16} 90 | }, 91 | "torch/wall_torch2.png": 92 | { 93 | "frame": {"x":32,"y":0,"w":32,"h":16}, 94 | "rotated": false, 95 | "trimmed": false, 96 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":16}, 97 | "sourceSize": {"w":32,"h":16} 98 | }, 99 | "torch/wall_torch3.png": 100 | { 101 | "frame": {"x":0,"y":0,"w":32,"h":16}, 102 | "rotated": false, 103 | "trimmed": false, 104 | "spriteSourceSize": {"x":0,"y":0,"w":32,"h":16}, 105 | "sourceSize": {"w":32,"h":16} 106 | }}, 107 | "meta": { 108 | "app": "http://www.codeandweb.com/texturepacker ", 109 | "version": "1.0", 110 | "image": "misc.png", 111 | "format": "RGBA8888", 112 | "size": {"w":64,"h":64}, 113 | "scale": "1", 114 | "smartupdate": "$TexturePacker:SmartUpdate:d1427816b9cd768e8ab8003669db0ab1:1/1$" 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /assets/sprites/entities/misc.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bbe17c91c4dc4207d965419e0f627b646c282d0510f8f277c7817e220587284a 3 | size 1687 4 | -------------------------------------------------------------------------------- /assets/sprites/fonts/hud.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "0.png": 4 | { 5 | "frame": {"x":14,"y":28,"w":14,"h":14}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 9 | "sourceSize": {"w":14,"h":14} 10 | }, 11 | "1.png": 12 | { 13 | "frame": {"x":14,"y":42,"w":12,"h":14}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":12,"h":14}, 17 | "sourceSize": {"w":12,"h":14} 18 | }, 19 | "2.png": 20 | { 21 | "frame": {"x":14,"y":14,"w":14,"h":14}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 25 | "sourceSize": {"w":14,"h":14} 26 | }, 27 | "3.png": 28 | { 29 | "frame": {"x":42,"y":0,"w":14,"h":14}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 33 | "sourceSize": {"w":14,"h":14} 34 | }, 35 | "4.png": 36 | { 37 | "frame": {"x":28,"y":0,"w":14,"h":14}, 38 | "rotated": false, 39 | "trimmed": false, 40 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 41 | "sourceSize": {"w":14,"h":14} 42 | }, 43 | "5.png": 44 | { 45 | "frame": {"x":14,"y":0,"w":14,"h":14}, 46 | "rotated": false, 47 | "trimmed": false, 48 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 49 | "sourceSize": {"w":14,"h":14} 50 | }, 51 | "6.png": 52 | { 53 | "frame": {"x":0,"y":42,"w":14,"h":14}, 54 | "rotated": false, 55 | "trimmed": false, 56 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 57 | "sourceSize": {"w":14,"h":14} 58 | }, 59 | "7.png": 60 | { 61 | "frame": {"x":0,"y":28,"w":14,"h":14}, 62 | "rotated": false, 63 | "trimmed": false, 64 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 65 | "sourceSize": {"w":14,"h":14} 66 | }, 67 | "8.png": 68 | { 69 | "frame": {"x":0,"y":14,"w":14,"h":14}, 70 | "rotated": false, 71 | "trimmed": false, 72 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 73 | "sourceSize": {"w":14,"h":14} 74 | }, 75 | "9.png": 76 | { 77 | "frame": {"x":0,"y":0,"w":14,"h":14}, 78 | "rotated": false, 79 | "trimmed": false, 80 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 81 | "sourceSize": {"w":14,"h":14} 82 | }}, 83 | "meta": { 84 | "app": "http://www.texturepacker.com", 85 | "version": "1.0", 86 | "image": "hud.png", 87 | "format": "RGBA8888", 88 | "size": {"w":64,"h":64}, 89 | "scale": "1", 90 | "smartupdate": "$TexturePacker:SmartUpdate:47025c98c8b10634b75172d4ed7e7edc$" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /assets/sprites/fonts/hud.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0eb5c67060c482d91922733a3fd4f90d9ba814ed6427ad9ed8eb104567b2ac73 3 | size 509 4 | -------------------------------------------------------------------------------- /assets/sprites/fonts/retofganon.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:28127ec33d4b70bae622eb63510d7cd4f1950ca12978fc01e42e28547eab2442 3 | size 2319 4 | -------------------------------------------------------------------------------- /assets/sprites/misc/intro.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0fa548ef26fb9ac7b4302161dfbaad16db3b0462a4a9dd828f2dec16d339e855 3 | size 176793 4 | -------------------------------------------------------------------------------- /assets/sprites/misc/overworlditems.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9c4458b758f606a6f9f40892ab578a257b89b1226606af7df146983166114314 3 | size 12519 4 | -------------------------------------------------------------------------------- /assets/sprites/misc/particles.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4d347e8570cc347e354147622223d81787d1685fa5f1ef9048e8547605385401 3 | size 10795 4 | -------------------------------------------------------------------------------- /assets/sprites/misc/selectscreen.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "fairy1.png": 4 | { 5 | "frame": {"x":36,"y":471,"w":16,"h":16}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 9 | "sourceSize": {"w":16,"h":16} 10 | }, 11 | "fairy2.png": 12 | { 13 | "frame": {"x":20,"y":492,"w":16,"h":16}, 14 | "rotated": false, 15 | "trimmed": false, 16 | "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, 17 | "sourceSize": {"w":16,"h":16} 18 | }, 19 | "heart-empty.png": 20 | { 21 | "frame": {"x":36,"y":487,"w":14,"h":14}, 22 | "rotated": false, 23 | "trimmed": false, 24 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 25 | "sourceSize": {"w":14,"h":14} 26 | }, 27 | "heart-full.png": 28 | { 29 | "frame": {"x":38,"y":448,"w":14,"h":14}, 30 | "rotated": false, 31 | "trimmed": false, 32 | "spriteSourceSize": {"x":0,"y":0,"w":14,"h":14}, 33 | "sourceSize": {"w":14,"h":14} 34 | }, 35 | "heart-half.png": 36 | { 37 | "frame": {"x":0,"y":500,"w":8,"h":8}, 38 | "rotated": false, 39 | "trimmed": true, 40 | "spriteSourceSize": {"x":2,"y":2,"w":8,"h":8}, 41 | "sourceSize": {"w":14,"h":14} 42 | }, 43 | "link1.png": 44 | { 45 | "frame": {"x":20,"y":471,"w":16,"h":21}, 46 | "rotated": false, 47 | "trimmed": true, 48 | "spriteSourceSize": {"x":1,"y":4,"w":16,"h":21}, 49 | "sourceSize": {"w":20,"h":27} 50 | }, 51 | "link2.png": 52 | { 53 | "frame": {"x":0,"y":475,"w":20,"h":25}, 54 | "rotated": false, 55 | "trimmed": true, 56 | "spriteSourceSize": {"x":0,"y":0,"w":20,"h":25}, 57 | "sourceSize": {"w":20,"h":27} 58 | }, 59 | "link3.png": 60 | { 61 | "frame": {"x":20,"y":448,"w":18,"h":23}, 62 | "rotated": false, 63 | "trimmed": true, 64 | "spriteSourceSize": {"x":0,"y":4,"w":18,"h":23}, 65 | "sourceSize": {"w":20,"h":27} 66 | }, 67 | "link4.png": 68 | { 69 | "frame": {"x":0,"y":448,"w":20,"h":27}, 70 | "rotated": false, 71 | "trimmed": false, 72 | "spriteSourceSize": {"x":0,"y":0,"w":20,"h":27}, 73 | "sourceSize": {"w":20,"h":27} 74 | }, 75 | "pointer.png": 76 | { 77 | "frame": {"x":8,"y":500,"w":8,"h":7}, 78 | "rotated": false, 79 | "trimmed": false, 80 | "spriteSourceSize": {"x":0,"y":0,"w":8,"h":7}, 81 | "sourceSize": {"w":8,"h":7} 82 | }, 83 | "register.png": 84 | { 85 | "frame": {"x":0,"y":224,"w":256,"h":224}, 86 | "rotated": false, 87 | "trimmed": false, 88 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":224}, 89 | "sourceSize": {"w":256,"h":224} 90 | }, 91 | "select.png": 92 | { 93 | "frame": {"x":0,"y":0,"w":256,"h":224}, 94 | "rotated": false, 95 | "trimmed": false, 96 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":224}, 97 | "sourceSize": {"w":256,"h":224} 98 | }}, 99 | "meta": { 100 | "app": "http://www.codeandweb.com/texturepacker ", 101 | "version": "1.0", 102 | "image": "selectscreen.png", 103 | "format": "RGBA8888", 104 | "size": {"w":256,"h":512}, 105 | "scale": "1", 106 | "smartupdate": "$TexturePacker:SmartUpdate:6faa2ef25867ced3e7c48ef9627dd3aa:1/1$" 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /assets/sprites/misc/selectscreen.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bb75d854cea24fa31b4cd316aed21dc0194c8729e54d7007ad638dfae78c8a74 3 | size 8661 4 | -------------------------------------------------------------------------------- /assets/sprites/overlays/overlays.json: -------------------------------------------------------------------------------- 1 | {"frames": { 2 | 3 | "fog.png": 4 | { 5 | "frame": {"x":2,"y":260,"w":256,"h":128}, 6 | "rotated": false, 7 | "trimmed": false, 8 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":128}, 9 | "sourceSize": {"w":256,"h":128}, 10 | "pivot": {"x":0.5,"y":0.5} 11 | }, 12 | "rain/rain1.png": 13 | { 14 | "frame": {"x":260,"y":2,"w":256,"h":223}, 15 | "rotated": false, 16 | "trimmed": false, 17 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":223}, 18 | "sourceSize": {"w":256,"h":223}, 19 | "pivot": {"x":0.5,"y":0.5} 20 | }, 21 | "rain/rain2.png": 22 | { 23 | "frame": {"x":518,"y":2,"w":256,"h":223}, 24 | "rotated": false, 25 | "trimmed": false, 26 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":223}, 27 | "sourceSize": {"w":256,"h":223}, 28 | "pivot": {"x":0.5,"y":0.5} 29 | }, 30 | "rain/rain3.png": 31 | { 32 | "frame": {"x":260,"y":227,"w":256,"h":223}, 33 | "rotated": false, 34 | "trimmed": false, 35 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":223}, 36 | "sourceSize": {"w":256,"h":223}, 37 | "pivot": {"x":0.5,"y":0.5} 38 | }, 39 | "rain/rain4.png": 40 | { 41 | "frame": {"x":518,"y":227,"w":256,"h":223}, 42 | "rotated": false, 43 | "trimmed": false, 44 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":223}, 45 | "sourceSize": {"w":256,"h":223}, 46 | "pivot": {"x":0.5,"y":0.5} 47 | }, 48 | "woods.png": 49 | { 50 | "frame": {"x":2,"y":2,"w":256,"h":256}, 51 | "rotated": false, 52 | "trimmed": false, 53 | "spriteSourceSize": {"x":0,"y":0,"w":256,"h":256}, 54 | "sourceSize": {"w":256,"h":256}, 55 | "pivot": {"x":0.5,"y":0.5} 56 | }}, 57 | "meta": { 58 | "app": "http://www.codeandweb.com/texturepacker", 59 | "version": "1.0", 60 | "image": "overlays.png", 61 | "format": "RGBA8888", 62 | "size": {"w":776,"h":452}, 63 | "scale": "1", 64 | "smartupdate": "$TexturePacker:SmartUpdate:54609803848834733048c51ef555406e:8d83f2d42c8f54f05ff3804aa047c01a:3e3fdb9952b3a9403ddef30418cea9dc$" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /assets/sprites/overlays/overlays.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:409663a7a9931e90045e5cbf97b2f7788068672b858d41f0b3c6eb5fcdba108c 3 | size 6954 4 | -------------------------------------------------------------------------------- /assets/sprites/ui/gui.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:05e567a3d04e8999ad5ca2ff2466e406dab0b808fa1b190fdbc880cfd52379f1 3 | size 10180 4 | -------------------------------------------------------------------------------- /assets/ui/loader.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:63367a9fd00377cb14da41ae5e9d9a73119c685a7e8dfc80baf4bc3d79f000f6 3 | size 3106 4 | -------------------------------------------------------------------------------- /assets/ui/lore_bg1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:81bdec5d8ad992e528b7e3b51ea891d1ef81e0dc214f88e35c6bc99acb77fb1f 3 | size 214 4 | -------------------------------------------------------------------------------- /assets/ui/lore_bg2.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:80af572cc9a7255d3924a313943bc3524eeedfbbfeefd69e0d9fe28fcd1ae7ed 3 | size 206 4 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | // TODO: Can I generate the tilemap pack file and inject it into 2 | // the webpack build somehow? That way it can use webpack for loading 3 | // resources and the copy task can go away. 4 | 5 | 'use strict'; 6 | 7 | const gulp = require('gulp'); 8 | const gutil = require('gulp-util'); 9 | const tslint = require('gulp-tslint'); 10 | const tiledPack = require('gulp-phaser-tiled-pack'); 11 | const del = require('del'); 12 | const runSeq = require('run-sequence'); 13 | const webpack = require('webpack'); 14 | const WebpackDevServer = require('webpack-dev-server'); 15 | 16 | const webpackConfig = require('./webpack.config.js'); 17 | 18 | const webpackDevConfig = Object.create(webpackConfig); 19 | webpackDevConfig.devtool = 'source-map'; 20 | webpackDevConfig.debug = true; 21 | 22 | const webpackDevServerConfig = Object.create(webpackConfig); 23 | webpackDevServerConfig.devtool = 'eval'; 24 | webpackDevServerConfig.debug = true; 25 | 26 | /** 27 | * default - Task to run when no task is specified. 28 | */ 29 | gulp.task('default', ['build']); 30 | 31 | /** 32 | * build - Builds the bundle and processes resources. 33 | */ 34 | gulp.task('build', function (done) { 35 | runSeq('pre-build', ['webpack:build'], done); 36 | }); 37 | 38 | /** 39 | * dev - Development build meant for rebuilding incrementally during development. 40 | */ 41 | gulp.task('dev', function (done) { 42 | runSeq('pre-build', ['watch', 'webpack:dev-server'], done); 43 | }); 44 | 45 | /** 46 | * watch - WAtches for file changes to the asset pack. 47 | */ 48 | gulp.task('watch', function () { 49 | return gulp.watch('./assets/levels/**/*.json', ['tilemap:pack', 'copy']); 50 | }); 51 | 52 | /** 53 | * clean - Cleans the output path. 54 | */ 55 | gulp.task('clean', function () { 56 | return del(webpackConfig.output.path); 57 | }); 58 | 59 | /** 60 | * pre-build - Run a couple tasks before the build starts. 61 | */ 62 | gulp.task('pre-build', ['lint'], function (done) { 63 | runSeq('clean', ['tilemap:pack', 'copy'], done); 64 | }); 65 | 66 | /** 67 | * lint - Runs a fine-toothed comb over the typescript to remove lint. 68 | */ 69 | gulp.task('lint', function () { 70 | return gulp.src(['./src/**/*.ts', './typings/**/*/.d.ts']) 71 | .pipe(tslint()) 72 | .pipe(tslint.report('verbose')); 73 | }); 74 | 75 | /** 76 | * copy - Copy some necessary source files to the output. 77 | */ 78 | gulp.task('copy', function () { 79 | return gulp.src('./assets/levels/**') 80 | .pipe(gulp.dest(webpackConfig.output.path + '/assets/levels')); 81 | }); 82 | 83 | /** 84 | * webpack:build - Builds the webpack bundle. 85 | */ 86 | gulp.task('webpack:build', function (done) { 87 | webpack(process.env.NODE_ENV === 'production' ? webpackConfig : webpackDevConfig, webpackCallback.bind(null, done)); 88 | }); 89 | 90 | /** 91 | * webpack:dev - Builds the webpack bundle, and starts a dev server. 92 | */ 93 | gulp.task('webpack:dev-server', function (done) { 94 | const port = process.env.PORT || 8000; 95 | 96 | new WebpackDevServer(webpack(webpackDevServerConfig), { 97 | contentBase: 'public/', 98 | stats: { colors: true } 99 | }).listen(port, 'localhost', function (err) { 100 | if (err) 101 | throw new gutil.PluginError("webpack-dev-server", err); 102 | 103 | // Server listening 104 | gutil.log('[webpack-dev-server]', `http://localhost:${port}/`); 105 | 106 | // keep the server alive or continue? 107 | // done(); 108 | }); 109 | }); 110 | 111 | /** 112 | * tilemap:pack - Builds a phaser resource pack that represents the tilemaps. 113 | */ 114 | gulp.task('tilemap:pack', function () { 115 | return gulp.src('./assets/levels/**/*.json') 116 | .pipe(tiledPack({ baseUrl: 'assets/levels' })) 117 | .pipe(gulp.dest(webpackConfig.output.path + '/' + webpackConfig.output.assetPath)); 118 | }); 119 | 120 | // helper for when webpack completes 121 | function webpackCallback(done, err, stats) { 122 | if (err) 123 | throw new gutil.PluginError('webpack', err); 124 | 125 | gutil.log('[webpack]', stats.toString({ colors: true })); 126 | 127 | done(); 128 | } 129 | -------------------------------------------------------------------------------- /less/main.less: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | padding: 0; 9 | 10 | background: #222 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAFVBMVEUqKiopKSkoKCgjIyMuLi4kJCQtLS0dJckpAAAAO0lEQVR42iXLAQoAUQhCQSvr/kfe910jHIikElsl5qVFa1iE5f0Pom/CNZdbNM6756lQ41NInMfuFPgAHVEAlGk4lvIAAAAASUVORK5CYII="); 11 | color: black; 12 | 13 | font-family: Verdana,sans-serif; 14 | } 15 | 16 | #game { 17 | width: 100%; 18 | height: 100%; 19 | 20 | -moz-user-select: none; 21 | -webkit-user-select: none; 22 | -ms-user-select: none; 23 | 24 | canvas { 25 | image-rendering: optimizeSpeed; /* Legal fallback */ 26 | 27 | image-rendering: -moz-crisp-edges; /* Firefox */ 28 | image-rendering: -o-crisp-edges; /* Opera */ 29 | image-rendering: -webkit-optimize-contrast; /* Safari */ 30 | 31 | image-rendering: optimize-contrast; /* CSS3 Proposed */ 32 | image-rendering: crisp-edges; /* CSS4 Proposed */ 33 | image-rendering: pixelated; /* CSS4 Proposed */ 34 | 35 | -ms-interpolation-mode: nearest-neighbor; /* IE8+ */ 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lttp", 3 | "version": "1.0.0", 4 | "longName": "The Legend of Zelda: A Link to the Past (WebGL Edition)", 5 | "description": "A recreation of LTTP in WebGL", 6 | "author": "Chad Engler ", 7 | "contributors": [], 8 | "homepage": "https://github.com/englercj/lttp", 9 | "bugs": "https://github.com/englercj/lttp/issues", 10 | "license": "MIT", 11 | "licenseUrl": "http://opensource.org/licenses/MIT", 12 | "scripts": { 13 | "build": "gulp clean && gulp build", 14 | "dev": "gulp clean && gulp dev", 15 | "start": "npm run dev" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/englercj/lttp.git" 20 | }, 21 | "dependencies": { 22 | "lz-string": "^1.4.4", 23 | "phaser": "^2.4.6", 24 | "phaser-debug": "git+https://github.com/englercj/phaser-debug.git#master", 25 | "phaser-tiled": "2.0.0" 26 | }, 27 | "devDependencies": { 28 | "css-loader": "^0.23.1", 29 | "del": "^2.2.0", 30 | "extract-text-webpack-plugin": "^1.0.1", 31 | "file-loader": "^0.8.5", 32 | "gulp": "^3.9.1", 33 | "gulp-phaser-tiled-pack": "^1.1.0", 34 | "gulp-tslint": "^4.3.3", 35 | "gulp-util": "^3.0.7", 36 | "html-webpack-plugin": "^2.9.0", 37 | "image-webpack-loader": "^1.6.3", 38 | "less": "^2.6.1", 39 | "less-loader": "^2.2.2", 40 | "run-sequence": "^1.1.5", 41 | "script-loader": "^0.6.1", 42 | "ts-loader": "^0.8.1", 43 | "tslint": "^3.5.0", 44 | "typescript": "^1.8.7", 45 | "webpack": "^1.12.14", 46 | "webpack-dev-server": "^1.14.1" 47 | }, 48 | "private": true 49 | } 50 | -------------------------------------------------------------------------------- /src/Game.ts: -------------------------------------------------------------------------------- 1 | import Player from './entities/Player'; 2 | import Save from './utility/Save'; 3 | import Effects from './effects/Effects'; 4 | import Constants from './data/Constants'; 5 | 6 | // states 7 | import BootState from './states/Boot'; 8 | import IntroState from './states/Intro'; 9 | import MainMenuState from './states/MainMenu'; 10 | import PlayState from './states/Play'; 11 | import PreloaderState from './states/Preloader'; 12 | 13 | // levels, todo: remove the need for a class per level 14 | // use a single class for Level and unload them as we go along. 15 | import Cave034 from './levels/Cave034'; 16 | import Darkworld from './levels/Darkworld'; 17 | import Lightworld from './levels/Lightworld'; 18 | import LinksHouse from './levels/LinksHouse'; 19 | 20 | import Debug = require('phaser-debug'); 21 | import Tiled = require('phaser-tiled'); 22 | 23 | export default class Game extends Phaser.Game { 24 | static timer: Phaser.Timer = null; 25 | 26 | player: Player = null; 27 | 28 | loadedSave: Save = null; 29 | 30 | effects: Effects = null; 31 | 32 | private _autosaveInterval: number; 33 | 34 | constructor() { 35 | super( 36 | Constants.GAME_WIDTH, 37 | Constants.GAME_HEIGHT, 38 | Phaser.AUTO, // renderer 39 | 'game', // DOM parent ID 40 | null, // default state obj 41 | false, // transparent 42 | false, // antialias 43 | { p2: true } // physics config 44 | ); 45 | 46 | this.state.add(Constants.STATES.BOOT, BootState, false); 47 | this.state.add(Constants.STATES.PRELOADER, PreloaderState, false); 48 | this.state.add(Constants.STATES.INTRO, IntroState, false); 49 | this.state.add(Constants.STATES.MAIN_MENU, MainMenuState, false); 50 | this.state.add(Constants.STATES.PLAY, PlayState, false); 51 | 52 | this.state.add(Constants.LEVELS.CAVE034, Cave034, false); 53 | this.state.add(Constants.LEVELS.DARKWORLD, Darkworld, false); 54 | this.state.add(Constants.LEVELS.LIGHTWORLD, Lightworld, false); 55 | this.state.add(Constants.LEVELS.LINKSHOUSE, LinksHouse, false); 56 | 57 | this.state.start('state_boot'); 58 | } 59 | 60 | boot() { 61 | super.boot(); 62 | 63 | this.renderer.renderSession.roundPixels = true; 64 | 65 | // Setup our scaling parameters, we want the largest the browser can fit, minimum of our size. 66 | this.scale.windowConstraints.bottom = 'layout'; 67 | 68 | console.log(this); 69 | 70 | this.scale.setMinMax( 71 | Constants.GAME_WIDTH, 72 | Constants.GAME_HEIGHT 73 | ); 74 | 75 | this.scale.pageAlignHorizontally = true; 76 | // this.scale.pageAlignVertically = true; 77 | 78 | this.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; 79 | 80 | this.scale.refresh(); 81 | 82 | // capture keyboard keys 83 | this.input.keyboard.addKeyCapture([ 84 | Phaser.Keyboard.SPACEBAR, 85 | Phaser.Keyboard.ENTER, 86 | Phaser.Keyboard.UP, 87 | Phaser.Keyboard.DOWN, 88 | Phaser.Keyboard.LEFT, 89 | Phaser.Keyboard.RIGHT, 90 | ]); 91 | 92 | // start polling for gamepad input 93 | this.input.gamepad.start(); 94 | 95 | this.add.plugin(new Debug(this, this.stage)); 96 | this.add.plugin(new Tiled(this, this.stage)); 97 | 98 | this.effects = this.add.plugin(new Effects(this)); 99 | 100 | this.sound.mute = true; 101 | } 102 | 103 | gamePaused(event: Object) { 104 | super.gamePaused(event); 105 | 106 | this.sound.pauseAll(); 107 | } 108 | 109 | gameResumed(event: Object) { 110 | super.gameResumed(event); 111 | 112 | this.sound.resumeAll(); 113 | } 114 | 115 | startAutosave() { 116 | clearInterval(this._autosaveInterval); 117 | 118 | this._autosaveInterval = setInterval(this.save.bind(this), Constants.GAME_SAVE_INTERVAL); 119 | } 120 | 121 | save(exit?: Phaser.Plugin.Tiled.ITiledObject, previousLayer?: Phaser.Plugin.Tiled.Objectlayer) { 122 | if (exit) { 123 | this.loadedSave.updateExit(exit); 124 | } 125 | 126 | if (previousLayer) { 127 | this.loadedSave.updateZoneData(previousLayer); 128 | } 129 | 130 | this.loadedSave.save(this.player); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | // import styles 2 | import '../less/main.less'; 3 | 4 | // import Phaser patches 5 | import './utility/phaser-patches'; 6 | 7 | // start game 8 | import Game from './Game'; 9 | 10 | window.onload = () => { 11 | const game = new Game(); 12 | 13 | (window).game = game; 14 | }; 15 | -------------------------------------------------------------------------------- /src/data/Constants.ts: -------------------------------------------------------------------------------- 1 | export const enum ENTITY_TYPE { 2 | // player/npc entities 3 | PLAYER, 4 | ENEMY, 5 | FRIENDLY, 6 | NEUTRAL 7 | } 8 | 9 | export default class Constants { 10 | static DEBUG: boolean = false; 11 | 12 | /* tslint:disable:typedef */ 13 | static WORLD_ITEMS = { 14 | HEART: 'heart', 15 | MAGIC: 'magic', 16 | ARROWS: 'arrows', 17 | BOMBS: 'bombs', 18 | RUPEES: 'rupees', 19 | }; 20 | 21 | static MAP_OBJECTS = { 22 | CHEST: 'chest', 23 | SIGN: 'sign', 24 | ROCK: 'rock', 25 | GRASS: 'grass', 26 | POT: 'pot', 27 | MINE: 'mine', 28 | }; 29 | 30 | static STATES = { 31 | BOOT: 'state_boot', 32 | PRELOADER: 'state_preloader', 33 | INTRO: 'state_intro', 34 | MAIN_MENU: 'state_mainmenu', 35 | PLAY: 'state_play', 36 | }; 37 | 38 | static LEVELS = { 39 | CAVE034: 'level_case034', 40 | DARKWORLD: 'level_darkworld', 41 | LIGHTWORLD: 'level_lightworld', 42 | LINKSHOUSE: 'level_linkshouse', 43 | }; 44 | 45 | static COLORS = { 46 | WHITE: [255, 255, 255, 1], 47 | BLACK: [ 0, 0, 0, 1], 48 | RED: [255, 0, 0, 1], 49 | GREEN: [ 0, 255, 0, 1], 50 | BLUE: [ 0, 0, 255, 1], 51 | }; 52 | /* tslint:enable:typedef */ 53 | 54 | // deminsions of the screen 55 | static GAME_WIDTH: number = 256; 56 | static GAME_HEIGHT: number = 224; 57 | static GAME_TEXT_SCALE: number = 1.5; 58 | static GAME_SAVE_INTERVAL: number = 10000; 59 | 60 | // cone within hit detector to check for interactions 61 | static PLAYER_ATTACK_CONE: number = 0.5; 62 | static PLAYER_USE_CONE: number = 0.4; 63 | 64 | // radius of hit detector 65 | static PLAYER_ATTACK_SENSOR_RADIUS: number = 18; 66 | 67 | // distance to throw an item 68 | static PLAYER_THROW_DISTANCE_X: number = 75; 69 | static PLAYER_THROW_DISTANCE_Y: number = 50; 70 | 71 | // how long to run into something before an action takes place (blocked/jump down) 72 | static PLAYER_BLOCKED_WAIT_TIME: number = 500; 73 | 74 | // time it takes to execute a jump animation (in seconds) 75 | static PLAYER_JUMP_TIME: number = 0.5; 76 | static PLAYER_JUMP_DISTANCE: number = 50; 77 | 78 | // time it takes for the inventory menu to drop down (in seconds) 79 | static PLAYER_INVENTORY_DROP_TIME: number = 0.5; 80 | 81 | // volume for sounds 82 | static AUDIO_EFFECT_VOLUME: number = 0.80; 83 | static AUDIO_MUSIC_VOLUME: number = 0.20; 84 | 85 | // tilemap pack location 86 | static ASSET_TILEMAP_PACKS_URL: string = 'assets/tilemap-assets.json'; 87 | static ASSET_TILEMAP_PACKS_KEY: string = 'pack_tilemap_asssets'; 88 | 89 | // input data 90 | static INPUT_GAMEPAD_AXIS_THRESHOLD: number = 0.25; 91 | 92 | // some effect constants 93 | static EFFECT_INTRO_FLASH_ALPHA: number = 0.6; 94 | static EFFECT_INTRO_FLASH_LENGTH: number = 15; 95 | 96 | static EFFECT_ZONE_TRANSITION_TIME: number = 250; 97 | static EFFECT_ZONE_TRANSITION_SPACE: number = 20; 98 | 99 | static EFFECT_MAP_TRANSITION_TIME: number = 500; 100 | 101 | static EFFECT_OVERLAY_SCROLL_TIME: number = 100; 102 | static EFFECT_OVERLAY_SCROLL_FACTOR: number = 0.5; 103 | 104 | // direction vectors 105 | static VECTOR_ZERO: Phaser.Point = new Phaser.Point(0, -1); 106 | static VECTOR_UP: Phaser.Point = new Phaser.Point(0, -1); 107 | static VECTOR_DOWN: Phaser.Point = new Phaser.Point(0, 1); 108 | static VECTOR_LEFT: Phaser.Point = new Phaser.Point(-1, 0); 109 | static VECTOR_RIGHT: Phaser.Point = new Phaser.Point(1, 0); 110 | 111 | static DIRECTION_STRING_MAP: string[] = [ 112 | 'none', 113 | 'left', 114 | 'right', 115 | 'up', 116 | 'down', 117 | ]; 118 | 119 | static DIRECTION_VECTOR_MAP: Phaser.Point[] = [ 120 | Constants.VECTOR_ZERO, 121 | Constants.VECTOR_LEFT, 122 | Constants.VECTOR_RIGHT, 123 | Constants.VECTOR_UP, 124 | Constants.VECTOR_DOWN, 125 | ]; 126 | } 127 | -------------------------------------------------------------------------------- /src/data/ItemDescriptors.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | 3 | export type IconCallback = (game: Game) => string; 4 | 5 | export interface IParticleDescriptor { 6 | path: string; 7 | ext: string; 8 | type: string; 9 | num: number; 10 | framerate: number; 11 | loop: boolean; 12 | spacing: number; 13 | hitArea: Phaser.Rectangle; 14 | } 15 | 16 | export interface IItemDescriptor { 17 | name: string; 18 | icon: (string | IconCallback); 19 | position: number[]; 20 | grid?: number[]; 21 | cost?: number; 22 | particle?: IParticleDescriptor; 23 | } 24 | 25 | export const itemDescriptors: TTable = { 26 | // Special items 27 | sword: { name: 'sword', icon: 'items/sword%d.png', position: [180, 160] }, 28 | shield: { name: 'shield', icon: 'items/shield%d.png', position: [200, 160] }, 29 | armor: { name: 'armor', icon: 'items/armor%d.png', position: [220, 160] }, 30 | boot: { name: 'boot', icon: 'items/boot.png', position: [32, 190] }, 31 | gloves: { name: 'gloves', icon: 'items/gloves%d.png', position: [64, 190] }, 32 | flippers: { name: 'flippers', icon: 'items/flippers.png', position: [96, 190] }, 33 | pearl: { name: 'pearl', icon: 'items/pearl.png', position: [128, 190] }, 34 | heart: { name: 'heart', icon: 'items/heart%d.png', position: [200, 190] }, 35 | txtLiftNum: { name: 'txtLiftNum', icon: 'text/%d.png', position: [67, 161] }, 36 | txtRun: { name: 'txtRun', icon: 'text/run.png', position: [81, 176] }, 37 | txtSwim: { name: 'txtSwim', icon: 'text/swim.png', position: [121, 176] }, 38 | 39 | // equiptable items 40 | boomerang: { name: 'boomerang', icon: 'items/boomerang%d.png', position: [56, 32], grid: [1, 0] }, 41 | hookshot: { name: 'hookshot', icon: 'items/hookshot.png', position: [80, 32], grid: [2, 0] }, 42 | bombs: { name: 'bombs', icon: 'items/bomb.png', position: [104, 32], grid: [3, 0] }, 43 | mushroom: { name: 'mushroom', icon: 'items/mushroom.png', position: [128, 32], grid: [4, 0] }, 44 | powder: { name: 'powder', icon: 'items/magic_powder.png', position: [128, 32], grid: [4, 0] }, 45 | firerod: { name: 'firerod', icon: 'items/firerod.png', position: [32, 56], grid: [0, 1] }, 46 | icerod: { name: 'icerod', icon: 'items/icerod.png', position: [56, 56], grid: [1, 1] }, 47 | bombos: { name: 'bombos', icon: 'items/bombos.png', position: [80, 56], grid: [2, 1] }, 48 | ether: { name: 'ether', icon: 'items/ether.png', position: [104, 56], grid: [3, 1] }, 49 | quake: { name: 'quake', icon: 'items/quake.png', position: [128, 56], grid: [4, 1] }, 50 | hammer: { name: 'hammer', icon: 'items/hammer.png', position: [56, 80], grid: [1, 2] }, 51 | shovel: { name: 'shovel', icon: 'items/shovel.png', position: [80, 80], grid: [2, 2] }, 52 | flute: { name: 'flute', icon: 'items/flute.png', position: [80, 80], grid: [2, 2] }, 53 | net: { name: 'net', icon: 'items/net.png', position: [104, 80], grid: [3, 2] }, 54 | book: { name: 'book', icon: 'items/book_of_mudora.png', position: [128, 80], grid: [4, 2] }, 55 | bottle: { name: 'bottle', icon: 'items/bottle_empty.png', position: [32, 104], grid: [0, 3] }, 56 | somaria: { name: 'somaria', icon: 'items/cane_of_somaria.png', position: [56, 104], grid: [1, 3] }, 57 | byrna: { name: 'byrna', icon: 'items/cane_of_byrna.png', position: [80, 104], grid: [2, 3] }, 58 | cape: { name: 'cape', icon: 'items/magic_cape.png', position: [104, 104], grid: [3, 3] }, 59 | mirror: { name: 'mirror', icon: 'items/magic_mirror.png', position: [128, 104], grid: [4, 3] }, 60 | 61 | bow: { 62 | name: 'bow', 63 | icon: function (game: Game) { 64 | if (game.player.inventory.silverArrows && game.player.inventory.arrows) { 65 | return 'items/bow_and_silver_arrow.png'; 66 | } 67 | else if (game.player.inventory.arrows) { 68 | return 'items/bow_and_arrow.png'; 69 | } 70 | else { 71 | return 'items/bow.png'; 72 | } 73 | }, 74 | position: [32, 32], 75 | grid: [0, 0], 76 | }, 77 | 78 | lantern: { 79 | name: 'lantern', 80 | icon: 'items/lantern.png', 81 | position: [32, 80], 82 | grid: [0, 2], 83 | cost: 0.5, 84 | particle: { 85 | path: 'fire/fire', 86 | ext: '.png', 87 | type: 'fire', 88 | num: 3, 89 | framerate: 9, 90 | loop: false, 91 | spacing: 2, 92 | hitArea: new Phaser.Rectangle(0, 8, 8, 8), 93 | }, 94 | }, 95 | }; 96 | -------------------------------------------------------------------------------- /src/data/Keymap.ts: -------------------------------------------------------------------------------- 1 | export interface IKeymap { 2 | keyboard: IKeys; 3 | gamepad: IKeys; 4 | } 5 | 6 | export interface IKeys { 7 | up: number; 8 | down: number; 9 | left: number; 10 | right: number; 11 | 12 | use: number; 13 | useItem: number; 14 | attack: number; 15 | 16 | menuSave: number; 17 | menuMap: number; 18 | menuInv: number; 19 | } 20 | -------------------------------------------------------------------------------- /src/data/PlayerInventory.ts: -------------------------------------------------------------------------------- 1 | export default class PlayerInventory { 2 | [key: string]: number; 3 | 4 | // upgradable items 5 | armor: number = 0; 6 | sword: number = 0; 7 | shield: number = 0; 8 | gloves: number = 0; 9 | silverArrows: number = 0; 10 | 11 | // normal inventory items 12 | boomerang: number = 0; 13 | bow: number = 0; 14 | byrna: number = 0; 15 | somaria: number = 0; 16 | mushroom: number = 0; 17 | firerod: number = 0; 18 | flute: number = 0; 19 | hammer: number = 0; 20 | hookshot: number = 0; 21 | icerod: number = 0; 22 | lantern: number = 0; 23 | cape: number = 0; 24 | mirror: number = 0; 25 | powder: number = 0; 26 | net: number = 0; 27 | shovel: number = 0; 28 | 29 | // keys 30 | bigKey: number = 0; 31 | keys: number = 0; 32 | 33 | // medallions 34 | bombos: number = 0; 35 | ether: number = 0; 36 | quake: number = 0; 37 | 38 | // expendibles 39 | arrows: number = 0; 40 | bombs: number = 0; 41 | rupees: number = 0; 42 | 43 | // passives 44 | flippers: number = 0; 45 | boot: number = 0; 46 | mudora: number = 0; 47 | pearl: number = 0; 48 | heartPieces: number = 0; 49 | 50 | // victory tokens 51 | crystals: number = 0; 52 | pendants: number = 0; 53 | } 54 | -------------------------------------------------------------------------------- /src/data/TiledMapData.ts: -------------------------------------------------------------------------------- 1 | export interface ITiledMapData { 2 | width: number; 3 | height: number; 4 | 5 | tilewidth: number; 6 | tileheight: number; 7 | 8 | version: number; 9 | 10 | orientation: string; // TODO: make enum 11 | 12 | layers: ITiledLayerData[]; 13 | tilesets: ITiledTilesetData[]; 14 | 15 | properties: TTable; 16 | } 17 | 18 | export interface ITiledLayerData { 19 | data: number[]; 20 | 21 | width: number; 22 | height: number; 23 | 24 | x: number; 25 | y: number; 26 | 27 | name: string; 28 | 29 | type: string; // TODO: make enum 30 | 31 | opacity: number; 32 | visible: boolean; 33 | 34 | properties: TTable; 35 | } 36 | 37 | export interface ITiledTilesetData { 38 | firstgid: number; 39 | 40 | name: string; 41 | 42 | image: string; 43 | imagewidth: number; 44 | imageheight: number; 45 | 46 | margin: number; 47 | spacing: number; 48 | 49 | tilewidth: number; 50 | tileheight: number; 51 | 52 | properties: TTable; 53 | } 54 | -------------------------------------------------------------------------------- /src/effects/Effects.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import ScreenFlash from './ScreenFlash'; 3 | import Constants from '../data/Constants'; 4 | 5 | interface IOverScale { 6 | object: Phaser.Sprite; 7 | cache: Phaser.Point; 8 | scale: number; 9 | } 10 | 11 | export default class Effects extends Phaser.Plugin { 12 | game: Game; 13 | 14 | private _boundsCache: Phaser.Rectangle; 15 | 16 | private _shakeWorldTime: number = 20; 17 | private _shakeWorldMax: number = 20; 18 | 19 | private _overScales: IOverScale[] = []; 20 | 21 | private _screenFlashPool: ScreenFlash[] = []; 22 | 23 | constructor(game: Game) { 24 | super(game, null); 25 | 26 | this._boundsCache = Phaser.Utils.extend(false, {}, game.world.bounds); 27 | } 28 | 29 | /** 30 | * Begins the screen shake effect. 31 | * 32 | * @param [duration=20] {number} The duration of the screen shake 33 | * @param [strength=20] {number} The strength of the screen shake 34 | */ 35 | shakeScreen(duration: number, strength: number) { 36 | this._shakeWorldTime = duration || 20; 37 | this._shakeWorldMax = strength || 20; 38 | 39 | this.game.world.setBounds( 40 | this._boundsCache.x - this._shakeWorldMax, 41 | this._boundsCache.y - this._shakeWorldMax, 42 | this._boundsCache.width + this._shakeWorldMax, 43 | this._boundsCache.height + this._shakeWorldMax 44 | ); 45 | } 46 | 47 | /** 48 | * Flashes a color to the screen, then fades away. 49 | * 50 | * @param color - The color to use for the flash. 51 | * @param maxAlpha - The max alpha to flash to. 52 | * @param duration - The duration of the flash. 53 | */ 54 | flashScreen(color: TColorRGBA = Constants.COLORS.WHITE, duration?: number, maxAlpha: number = 0, easing?: any) { 55 | let obj = this._screenFlashPool.pop() || this._createScreenFlashForPool(); 56 | 57 | obj.color = color; 58 | obj.alpha = maxAlpha; 59 | obj.flash(0, duration, easing); 60 | 61 | return obj; 62 | } 63 | 64 | /** 65 | * Fades the screen to a color. 66 | * 67 | * @param color - The color to use for the flash. 68 | * @param maxAlpha - The max alpha to flash to. 69 | * @param duration - The duration of the flash. 70 | */ 71 | fadeScreen(color: TColorRGBA = Constants.COLORS.WHITE, duration?: number, maxAlpha: number = 1, easing?: any) { 72 | let obj = this._screenFlashPool.pop() || this._createScreenFlashForPool(); 73 | 74 | obj.color = color; 75 | obj.alpha = 0; 76 | obj.flash(maxAlpha, duration, easing); 77 | 78 | return obj; 79 | } 80 | 81 | /** 82 | * Creates the over scale effect on the given object. 83 | * 84 | * @param object - The object to over scale. 85 | * @param scale - The scale amount to overscale by. 86 | * @param initialScale - The initial scale of the object. 87 | * 88 | */ 89 | overScale(object: Phaser.Sprite, scale: number = 1.5, initialScale?: Phaser.Point) { 90 | initialScale = initialScale || object.scale.clone(); 91 | 92 | this._overScales.push({ 93 | object: object, 94 | cache: initialScale, 95 | scale: scale, 96 | }); 97 | } 98 | 99 | /** 100 | * Creates the jelly effect on the given object 101 | * 102 | * @param object - The object to gelatinize. 103 | * @param strength - The strength of the effect. 104 | * @param delay - The delay of the snap-back tween. 50ms are automaticallly added to whatever the delay amount is. 105 | * @param initialScale - The initial scale of the object. 106 | */ 107 | jelly(object: Phaser.Sprite, strength: number = 0.2, delay: number = 0, initialScale?: Phaser.Point) { 108 | initialScale = initialScale || object.scale.clone(); 109 | 110 | this.game.add.tween(object.scale) 111 | .to({ x: initialScale.x + (initialScale.x * strength) }, 50, Phaser.Easing.Quadratic.InOut, true, delay) 112 | .to({ x: initialScale.x }, 600, Phaser.Easing.Elastic.Out, true) 113 | .start(); 114 | 115 | this.game.add.tween(object.scale) 116 | .to({ y: initialScale.y + (initialScale.y * strength)}, 50, Phaser.Easing.Quadratic.InOut, true, delay + 50) 117 | .to({ y: initialScale.y }, 600, Phaser.Easing.Elastic.Out, true) 118 | .start(); 119 | } 120 | 121 | /** 122 | * Creates the mouse stretch effect on the given object 123 | * 124 | * @param object - The object to mouse stretch. 125 | * @param strength - The strength of the effect. 126 | * @param initialScale - The initial scale of the object. 127 | */ 128 | mouseStretch(object: Phaser.Sprite, strength: number = 0.5, initialScale?: Phaser.Point) { 129 | initialScale = initialScale || object.scale.clone(); 130 | 131 | object.scale.x = initialScale.x + (Math.abs(object.x - this.game.input.activePointer.x) / 100) * strength; 132 | object.scale.y = initialScale.y + (initialScale.y * strength) - (object.scale.x * strength); 133 | } 134 | 135 | /** 136 | * Runs the core update function and causes screen shake and overscaling effects to occur 137 | * if they are queued to do so. 138 | */ 139 | update() { 140 | // screen shake 141 | if (this._shakeWorldTime > 0) { 142 | const magnitude = (this._shakeWorldTime / this._shakeWorldMax) * this._shakeWorldMax; 143 | const x = this.game.rnd.integerInRange(-magnitude, magnitude); 144 | const y = this.game.rnd.integerInRange(-magnitude, magnitude); 145 | 146 | this.game.camera.x = x; 147 | this.game.camera.y = y; 148 | 149 | this._shakeWorldTime--; 150 | 151 | if (this._shakeWorldTime <= 0) { 152 | this.game.world.setBounds(this._boundsCache.x, this._boundsCache.x, this._boundsCache.width, this._boundsCache.height); 153 | } 154 | } 155 | 156 | // over scales 157 | for (let i = this._overScales.length - 1; i >= 0; --i) { 158 | let scaleObj = this._overScales[i]; 159 | 160 | if (scaleObj.scale > 0.01) { 161 | scaleObj.object.scale.x = scaleObj.scale * scaleObj.cache.x; 162 | scaleObj.object.scale.y = scaleObj.scale * scaleObj.cache.y; 163 | scaleObj.scale -= this.game.time.elapsed * scaleObj.scale * 0.35; 164 | } 165 | else { 166 | scaleObj.object.scale.x = scaleObj.cache.x; 167 | scaleObj.object.scale.y = scaleObj.cache.y; 168 | 169 | this._overScales.splice(i, 1); 170 | } 171 | } 172 | } 173 | 174 | private _createScreenFlashForPool(): ScreenFlash { 175 | let obj = new ScreenFlash(this.game); 176 | 177 | obj.onComplete.add(this._onFlashComplete, this); 178 | 179 | return obj; 180 | } 181 | 182 | private _onFlashComplete(obj: ScreenFlash) { 183 | this._screenFlashPool.push(obj); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /src/effects/MapOverlay.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import Constants from '../data/Constants'; 3 | 4 | export default class MapOverlay extends Phaser.Group { 5 | game: Game; 6 | 7 | key: Phaser.BitmapData; 8 | 9 | onComplete: Phaser.Signal; 10 | 11 | private _darkenerBmd: Phaser.BitmapData; 12 | private _darkener: Phaser.Image; 13 | private _animator: Phaser.TileSprite; 14 | 15 | private _activeEffect: string; 16 | 17 | private _cachedCameraPos: Phaser.Point; 18 | 19 | constructor(game: Game) { 20 | super(game, null, 'map overlay'); 21 | 22 | this.fixedToCamera = true; 23 | 24 | this._darkenerBmd = game.add.bitmapData(game.width, game.height); 25 | this._darkenerBmd.fill.apply(this._darkenerBmd, Constants.COLORS.BLACK); 26 | 27 | this._darkener = this._darkenerBmd.addToWorld(); 28 | this._darkener.alpha = 0.5; 29 | this._darkener.name = 'darkener'; 30 | 31 | this.add(this._darkener); 32 | 33 | this._animator = game.add.tileSprite(0, 0, game.width, game.height, 'sprite_overlays', null, this); 34 | this._animator.alpha = 0.8; 35 | this._animator.name = 'animator'; 36 | this.add(this._animator); 37 | 38 | this._cachedCameraPos = new Phaser.Point(this.game.camera.view.x, this.game.camera.view.y); 39 | 40 | // add rain animation 41 | this._animator.animations.add('rain', [ 42 | 'rain/rain1.png', 43 | 'rain/rain2.png', 44 | 'rain/rain3.png', 45 | 'rain/rain4.png', 46 | ], 18, true); 47 | 48 | // this.deactivate(); 49 | } 50 | 51 | activate(anim: string) { 52 | // this.deactivate(); 53 | 54 | this.visible = true; 55 | 56 | this._activeEffect = anim; 57 | 58 | switch (anim) { 59 | case 'rain': 60 | this._animator.animations.play('rain'); 61 | this._animator.visible = true; 62 | this._darkener.visible = true; 63 | } 64 | } 65 | 66 | deactivate() { 67 | this._animator.animations.stop(); 68 | this._animator.visible = false; 69 | 70 | this._darkener.visible = false; 71 | 72 | this.visible = false; 73 | } 74 | 75 | update() { 76 | if (this.game.camera.view.x !== this._cachedCameraPos.x) { 77 | const diff = this.game.camera.view.x - this._cachedCameraPos.x; 78 | 79 | this._cachedCameraPos.x = this.game.camera.view.x; 80 | 81 | this._animator.tilePosition.x -= diff * Constants.EFFECT_OVERLAY_SCROLL_FACTOR; 82 | } 83 | 84 | if (this.game.camera.view.y !== this._cachedCameraPos.y) { 85 | const diff = this.game.camera.view.y - this._cachedCameraPos.y; 86 | 87 | this._cachedCameraPos.y = this.game.camera.view.y; 88 | 89 | this._animator.tilePosition.y -= diff * Constants.EFFECT_OVERLAY_SCROLL_FACTOR; 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/effects/ScreenFlash.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import Constants from '../data/Constants'; 3 | 4 | export default class ScreenFlash extends Phaser.BitmapData { 5 | game: Game; 6 | 7 | onComplete: Phaser.Signal; 8 | 9 | private _worldObject: Phaser.Image; 10 | 11 | constructor(game: Game, color?: TColorRGBA) { 12 | super(game, '', game.width, game.height); 13 | 14 | this._worldObject = this.addToWorld(); 15 | this._worldObject.alpha = 0; 16 | 17 | this.onComplete = new Phaser.Signal(); 18 | 19 | this.color = color || Constants.COLORS.WHITE; 20 | } 21 | 22 | flash(maxAlpha: number = 1, duration: number = 100, easing: any = Phaser.Easing.Linear.None): ScreenFlash { 23 | this.game.add.tween(this._worldObject) 24 | .to({ alpha: maxAlpha }, duration, easing) 25 | .start() 26 | .onComplete.addOnce(() => { 27 | this._worldObject.alpha = 0; 28 | this.onComplete.dispatch(this); 29 | }, this); 30 | 31 | return this; 32 | } 33 | 34 | set color(c: TColorRGBA) { 35 | this.fill(c[0], c[1], c[2], c[3]); 36 | } 37 | 38 | set alpha(v: number) { 39 | this._worldObject.alpha = v; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/entities/Enemy.ts: -------------------------------------------------------------------------------- 1 | import Entity from './Entity'; 2 | import { ENTITY_TYPE } from '../data/Constants'; 3 | 4 | export default class Enemy extends Entity { 5 | entityType: ENTITY_TYPE = ENTITY_TYPE.ENEMY; 6 | } 7 | -------------------------------------------------------------------------------- /src/entities/Entity.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import Level from '../levels/Level'; 3 | import { default as Constants, ENTITY_TYPE } from '../data/Constants'; 4 | 5 | export default class Entity extends Phaser.Sprite { 6 | game: Game; 7 | 8 | // is this sprite able to move? 9 | locked: boolean = false; 10 | 11 | // maximum health of this entity 12 | maxHealth: number = 3; 13 | 14 | // current health of this entity 15 | health: number = 3; 16 | 17 | // moveSpeed the entity moves at 18 | moveSpeed: number = 80; 19 | 20 | // current direction of movement 21 | movement: Phaser.Point = new Phaser.Point(); 22 | 23 | // the amount of damage this entity deals normally 24 | attackDamage: number = 1; 25 | 26 | // state of movement of this entity 27 | moving: number[] = [0, 0, 0, 0, 0]; 28 | 29 | // the direction the entity is facing 30 | facing: number = Phaser.DOWN; 31 | 32 | // a few dirty flags 33 | moveDirty: boolean = false; 34 | textureDirty: boolean = false; 35 | 36 | // type of this entity 37 | entityType: ENTITY_TYPE = ENTITY_TYPE.NEUTRAL; 38 | 39 | frames: Phaser.FrameData; 40 | 41 | properties: any; 42 | 43 | constructor(game: Game, key: any, frame?: any) { 44 | super(game, 0, 0, key, frame); 45 | 46 | // TODO: collision groups 47 | // if (this.body) { 48 | // this.body.collides(game.collisionGroups.ground); 49 | // } 50 | } 51 | 52 | heal(amount: number) { 53 | if (this.alive) { 54 | this.health += amount; 55 | } 56 | 57 | this.health = this.health > this.maxHealth ? this.maxHealth : this.health; 58 | 59 | return this; 60 | } 61 | 62 | lock(): Entity { 63 | this.body.setZeroVelocity(); 64 | 65 | this.locked = true; 66 | 67 | return this; 68 | } 69 | 70 | unlock(): Entity { 71 | this.body.velocity.x = this.movement.x; 72 | this.body.velocity.y = this.movement.y; 73 | 74 | this.locked = false; 75 | this.textureDirty = true; 76 | 77 | return this; 78 | } 79 | 80 | setup(level: Level): Entity { 81 | level.physics.enable(this, Phaser.Physics.P2JS); 82 | 83 | this.body.setZeroDamping(); 84 | this.body.fixedRotation = true; 85 | 86 | this.body.debug = Constants.DEBUG; 87 | 88 | level.physics.p2.addBody(this.body); 89 | 90 | return this; 91 | } 92 | 93 | getFacingString(): string { 94 | return Constants.DIRECTION_STRING_MAP[this.facing]; 95 | } 96 | 97 | getFacingVector(): Phaser.Point { 98 | return Constants.DIRECTION_VECTOR_MAP[this.facing]; 99 | } 100 | 101 | evalFacingDirection(): number { 102 | if (this.moving[Phaser.UP]) { 103 | this.facing = Phaser.UP; 104 | } 105 | else if (this.moving[Phaser.DOWN]) { 106 | this.facing = Phaser.DOWN; 107 | } 108 | else if (this.moving[Phaser.LEFT]) { 109 | this.facing = Phaser.LEFT; 110 | } 111 | else if (this.moving[Phaser.RIGHT]) { 112 | this.facing = Phaser.RIGHT; 113 | } 114 | 115 | return this.facing; 116 | } 117 | 118 | _addDirectionalFrames(type: string, num: number, frameRate: number = 60, loop: boolean = false) { 119 | if (type.indexOf('%s') === -1) { 120 | type += '_%s'; 121 | } 122 | 123 | this._addFrames([ 124 | type.replace(/%s/g, 'left'), 125 | type.replace(/%s/g, 'right'), 126 | type.replace(/%s/g, 'down'), 127 | type.replace(/%s/g, 'up'), 128 | ], num, frameRate, loop); 129 | } 130 | 131 | _addFrames(types: string[], num: number, frameRate: number = 60, loop: boolean = false) { 132 | for (let t = 0, tl = types.length; t < tl; ++t) { 133 | const frames: string[] = []; 134 | let type = types[t]; 135 | const name = type.replace(/.+\/|\.png|_%./g, ''); 136 | 137 | if (type.indexOf('%d') === -1) { 138 | type += '_%d'; 139 | } 140 | 141 | for (let f = 1; f <= num; ++f) { 142 | frames.push(type.replace(/%d/g, f.toString()) + '.png'); 143 | } 144 | 145 | this.animations.add(name, frames, frameRate, loop); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/entities/enemies/Guard.ts: -------------------------------------------------------------------------------- 1 | // TODO: Finish up guard entity 2 | import Enemy from '../Enemy'; 3 | 4 | export default class Guard extends Enemy { 5 | /* 6 | var Guard = function(type) { 7 | Enemy.call(this, lttp.game.cache.getTextures('sprite_enemies'), 0.2); 8 | 9 | this.name = type; 10 | 11 | this._addAnimations(type); 12 | }; 13 | 14 | gf.inherit(Guard, Enemy, { 15 | _addAnimations: function(type) { 16 | var prefix = 'guards/guard_' + type; 17 | 18 | switch(type) { 19 | case 'small': 20 | this._addDirectionalFrames(prefix + '/walk', 2, 0.2, true); 21 | this._addDirectionalFrames(prefix + '/walk_%s_look', 2, 0.2, true); 22 | break; 23 | case 'green': 24 | case 'blue': 25 | this._addDirectionalFrames(prefix + '/walk', 4, 0.2, true); 26 | this._addDirectionalFrames(prefix + '/walk_%s_look', 2, 0.2, true); 27 | break; 28 | case 'block': 29 | this.addAnimation('up', this.spritesheet[prefix + '/up.png'].frames[0]); 30 | this.addAnimation('down', this.spritesheet[prefix + '/down.png'].frames[0]); 31 | this.addAnimation('left', this.spritesheet[prefix + '/left.png'].frames[0]); 32 | this.addAnimation('right', this.spritesheet[prefix + '/right.png'].frames[0]); 33 | break; 34 | } 35 | } 36 | }); 37 | */ 38 | } 39 | -------------------------------------------------------------------------------- /src/entities/items/WorldItem.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Entity from '../Entity'; 3 | import Constants from '../../data/Constants'; 4 | 5 | export default class WorldItem extends Entity { 6 | itemSound: Phaser.Sound; 7 | rupeesSound1: Phaser.Sound; 8 | rupeesSound2: Phaser.Sound; 9 | 10 | frameKeys: TTable; 11 | 12 | itemType: string; 13 | 14 | value: number; 15 | 16 | constructor(game: Game) { 17 | super(game, 'sprite_worlditems'); 18 | 19 | this.frames = game.cache.getFrameData('sprite_worlditems'); 20 | 21 | this.body.data.shapes[0].sensor = true; 22 | 23 | this.itemSound = game.add.sound('effect_item', Constants.AUDIO_EFFECT_VOLUME); 24 | this.rupeesSound1 = game.add.sound('effect_rupee1', Constants.AUDIO_EFFECT_VOLUME); 25 | this.rupeesSound2 = game.add.sound('effect_rupee2', Constants.AUDIO_EFFECT_VOLUME); 26 | 27 | this.frameKeys = { 28 | heart: 'hearts/heart.png', 29 | bombs: 'inventory/bombs_%d.png', 30 | arrows: 'inventory/arrows_%d.png', 31 | magic: 'magic/magic_%d.png', 32 | rupees: 'rupees_%d', 33 | }; 34 | 35 | this.itemType = null; 36 | this.value = 0; 37 | 38 | let a = [1, 5, 20]; 39 | 40 | for (let i = 0; i < a.length; ++i) { 41 | let n = a[i]; 42 | this.animations.add('rupees_' + n, [ 43 | 'inventory/rupees_' + n + '_1.png', 44 | 'inventory/rupees_' + n + '_2.png', 45 | 'inventory/rupees_' + n + '_3.png', 46 | ], 6, true); 47 | } 48 | 49 | this.anchor.set(0, 1); 50 | 51 | } 52 | 53 | boot(item: any, forceLoot: string = '') { 54 | const loot = forceLoot || item.properties.loot; 55 | const type = loot.split('_')[0]; 56 | const value = parseInt(loot.split('_')[1], 10) || 1; 57 | 58 | let frame = this.frameKeys[type] || 'items/' + loot + '.png'; 59 | 60 | if (value) { 61 | frame = frame.replace('%d', value.toString()); 62 | } 63 | 64 | this.itemType = type; 65 | this.value = value; 66 | 67 | if (type === 'rupees') { 68 | this.animations.play(frame); 69 | } 70 | else { 71 | this.animations.stop(); 72 | this.setFrame(this.frames.getFrameByName(frame)); 73 | } 74 | 75 | this.position.x = item.position.x; // + (item.width / 2); 76 | this.position.y = item.position.y; // - (item.height / 2); 77 | 78 | this.visible = true; 79 | 80 | // smallness 81 | // this.hitArea = new gf.Rectangle(4, 4, 8, 8); 82 | 83 | // if(psys) 84 | // this.enablePhysics(psys); 85 | } 86 | 87 | pickup() { 88 | this.visible = false; 89 | // this.disablePhysics(); 90 | 91 | if (this.itemType === 'rupees') { 92 | this.rupeesSound1.play(); 93 | 94 | Game.timer.add(100, function () { 95 | this.rupeesSound2.play(); 96 | }, this); 97 | } 98 | else { 99 | this.itemSound.play(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/entities/misc/Flower.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Entity from '../Entity'; 3 | 4 | export default class Flower extends Entity { 5 | constructor(game: Game) { 6 | super(game, 'sprite_misc', false); 7 | 8 | this.animations.add('flower_1', [ 9 | 'flower/flower_1_3.png', 10 | 'flower/flower_1_1.png', 11 | 'flower/flower_1_2.png', 12 | ], 6, true); 13 | 14 | this.animations.add('flower_2', [ 15 | 'flower/flower_2_3.png', 16 | 'flower/flower_2_1.png', 17 | 'flower/flower_2_2.png', 18 | ], 6, true); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/entities/misc/Particle.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Entity from '../Entity'; 3 | import { IItemDescriptor } from '../../data/ItemDescriptors'; 4 | 5 | export default class Particle extends Entity { 6 | particleType: string; 7 | 8 | constructor(game: Game) { 9 | super(game, 'sprite_particles'); 10 | 11 | this.body.data.shapes[0].sensor = true; 12 | 13 | this.particleType = ''; 14 | 15 | this.anchor.set(0, 1); 16 | 17 | this.events.onAnimationComplete.add(this.expire, this); 18 | } 19 | 20 | boot(item: IItemDescriptor, phys: boolean = false) { 21 | const cfg = item.particle; 22 | 23 | this.visible = true; 24 | // this.hitArea = cfg.hitArea || new Rectangle(0, 8, 8, 8); 25 | 26 | if (!this.animations.getAnimation(item.name)) { 27 | const frames: string[] = []; 28 | 29 | for (let i = 0; i < cfg.num; ++i) { 30 | frames.push(cfg.path + (i + 1) + cfg.ext); 31 | } 32 | 33 | this.animations.add(item.name, frames, cfg.framerate, cfg.loop); 34 | } 35 | 36 | // set type 37 | this.name = item.name; 38 | this.particleType = cfg.type; 39 | 40 | // play animation for this item 41 | this.animations.play(item.name); 42 | // this.enablePhysics(phys); 43 | 44 | // set position 45 | const player = this.game.player; 46 | const space = cfg.spacing; 47 | 48 | switch (player.facing) { 49 | case Phaser.UP: 50 | this.x = player.x + (player.width / 2) - (this.width / 2); 51 | this.y = player.y - space - player.height; 52 | break; 53 | 54 | case Phaser.DOWN: 55 | this.x = player.x + (player.width / 2) - (this.width / 2); 56 | this.y = player.y + space + this.height; 57 | break; 58 | 59 | case Phaser.LEFT: 60 | this.x = player.x - space - this.width; 61 | this.y = player.y - 3; 62 | break; 63 | 64 | case Phaser.RIGHT: 65 | this.x = player.x + space + player.width; 66 | this.y = player.y - 3; 67 | break; 68 | 69 | } 70 | 71 | // if there is a velocity set it 72 | // if (cfg.velocity) { 73 | // this.velocity = cfg.velocity.clone(); 74 | // this.setVelocity(this.velocity); 75 | 76 | // if(cfg.velocityTimer) { 77 | // var cb; 78 | // if(cfg.velocityReverse) { 79 | // cb = this.reverse; 80 | // } else { 81 | // cb = this.expire; 82 | // } 83 | 84 | // this.velto = setTimeout(cb.bind(this), cfg.velocityTimer) 85 | // } 86 | // } 87 | } 88 | 89 | expire() { 90 | // clearTimeout(this.velto); 91 | this.animations.stop(); 92 | this.visible = false; 93 | // this.disablePhysics(); 94 | } 95 | 96 | reverse() { 97 | // clearTimeout(this.velto); 98 | // this.velocity.x = -this.velocity.x; 99 | // this.velocity.y = -this.velocity.y; 100 | 101 | // this.setVelocity(this.velocity); 102 | } 103 | 104 | // private _collide(obj, vec, colShape, myShape) { 105 | // //fire particle 106 | // if(this.type === 'fire') { 107 | // if(obj.lite) { 108 | // obj.lite(); 109 | // } 110 | // } 111 | 112 | // //firerod hitting wall 113 | // if(this.name === 'firerod') { 114 | // if(obj.type === C.ENTITY.TILE) { 115 | // this.expire(); 116 | // } 117 | // } 118 | // //boomerang hitting stuff 119 | // else if(this.name === 'boomerang') { 120 | // switch(obj.type) { 121 | // //reverse the velocity back to the player 122 | // case C.ENTITY.TILE: 123 | // this.reverse(); 124 | // break; 125 | 126 | // //expire (player caught it) 127 | // case C.ENTITY.PLAYER: 128 | // this.expire(); 129 | // break; 130 | // } 131 | // } 132 | // } 133 | } 134 | -------------------------------------------------------------------------------- /src/entities/misc/Smash.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Entity from '../Entity'; 3 | import Constants from '../../data/Constants'; 4 | 5 | export default class Smash extends Entity { 6 | grassSound: Phaser.Sound; 7 | smashSound: Phaser.Sound; 8 | 9 | constructor(game: Game) { 10 | super(game, 'sprite_particles', false); 11 | 12 | this.grassSound = game.add.sound('effect_grass_cut', Constants.AUDIO_EFFECT_VOLUME); 13 | this.smashSound = game.add.sound('effect_smash', Constants.AUDIO_EFFECT_VOLUME); 14 | 15 | this.events.onAnimationComplete.add(this._done, this); 16 | this.events.onAnimationStart.add(this._start, this); 17 | 18 | this._addAnimations(); 19 | } 20 | 21 | private _addAnimations() { 22 | this._addSlices('pot', 0, 0, 0, 7); 23 | this._addSlices('grass', 0, 8, 1, 5); 24 | this._addSlices('grass_pink', 1, 6, 2, 3); 25 | this._addSlices('rock', 2, 4, 3, 1); 26 | this._addSlices('grass_white', 3, 2, 3, 9); 27 | this._addSlices('grass_brown', 4, 0, 4, 7); 28 | this._addSlices('grass_dark', 4, 8, 5, 6); 29 | } 30 | 31 | private _addSlices(name: string, sx: number, sy: number, tx: number, ty: number) { 32 | const frames: string[] = []; 33 | 34 | while (sx !== tx || sy !== ty) { 35 | frames.push('slice_' + sx + '_' + sy + '.png'); 36 | 37 | ++sy; 38 | 39 | if (sy > 9) { 40 | sx++; 41 | sy = 0; 42 | } 43 | } 44 | 45 | this.animations.add(name, frames, 12); 46 | } 47 | 48 | private _start(animation: Phaser.Animation) { 49 | if (animation.name.indexOf('grass') !== -1) { 50 | this.grassSound.play(); 51 | } 52 | else { 53 | this.smashSound.play(); 54 | } 55 | } 56 | 57 | private _done(animation: Phaser.Animation) { 58 | this.visible = false; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/entities/misc/Torch.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Entity from '../Entity'; 3 | 4 | export default class Torch extends Entity { 5 | light: number = 0.25; 6 | fuelTime: number = 5000; 7 | 8 | constructor(game: Game) { 9 | super(game, 'sprite_misc', false); 10 | 11 | this.animations.add('torch', [ 12 | 'torch/torch0.png', 13 | ]); 14 | 15 | this.animations.add('torch_lit', [ 16 | 'torch/torch1.png', 17 | 'torch/torch2.png', 18 | 'torch/torch3.png', 19 | ], 0.09, true); 20 | 21 | this.animations.add('wall_torch', [ 22 | 'torch/wall_torch1.png', 23 | 'torch/wall_torch2.png', 24 | 'torch/wall_torch3.png', 25 | ], 0.09, true); 26 | } 27 | 28 | lite() { 29 | this.animations.play('torch_lit'); 30 | Game.timer.add(this.fuelTime, this.extinguish, this); 31 | 32 | // light up dat world 33 | // lttp.play.world.findLayer('darkness').alpha -= this.light; 34 | } 35 | 36 | extinguish() { 37 | this.animations.stop('torch'); 38 | 39 | // darken dat world 40 | // lttp.play.world.findLayer('darkness').alpha += this.light; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/fonts/Font.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | 3 | export interface IBitmapFontJson { 4 | font: { 5 | info: { 6 | _face: string; 7 | _size: number; 8 | }; 9 | 10 | common: { 11 | _lineHeight: number; 12 | }; 13 | 14 | chars: { 15 | char: IBitmapFontCharacterJson[] 16 | } 17 | }; 18 | 19 | } 20 | 21 | export interface IBitmapFontCharacterJson { 22 | _id: number; 23 | _x: number; 24 | _y: number; 25 | _width: number; 26 | _height: number; 27 | _xoffset: number; 28 | _yoffset: number; 29 | _xadvance: number; 30 | } 31 | 32 | export default class Font extends Phaser.BitmapText { 33 | static cachedFonts: TTable = {}; 34 | 35 | game: Game; 36 | 37 | monospace: number; 38 | 39 | constructor(game: Game, font: string, x: number = 0, y: number = 0, text: string = '', monospace: number = 0, size: number = 32) { 40 | super(game, x, y, font, text, size); 41 | this.monospace = monospace; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/fonts/Hud.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import { default as Font, IBitmapFontJson } from './Font'; 3 | 4 | export default class Hud extends Font { 5 | constructor(game: Game, x: number, y: number, text: string = '', monospace: number = 0, size: number = 16) { 6 | super(game, prepareFontData(game, monospace), x, y, text, monospace, size); 7 | } 8 | } 9 | 10 | function prepareFontData(game: Game, monospace: number = 0): string { 11 | const key = 'sprite_hud_font'; 12 | const fontName = 'HudFont' + (monospace ? 'Mono' + monospace.toString() : ''); 13 | 14 | if (Font.cachedFonts[fontName]) { return fontName; } 15 | 16 | const fontData: IBitmapFontJson = { 17 | font: { 18 | info: { 19 | _face: fontName, 20 | _size: 16, 21 | }, 22 | common: { 23 | _lineHeight: 16, 24 | }, 25 | chars: { 26 | char: [], 27 | }, 28 | }, 29 | }; 30 | 31 | const frames = game.cache.getFrameData(key); 32 | const letters = '0123456789'; 33 | 34 | for (let i = 0; i < letters.length; ++i) { 35 | let letter = letters.charAt(i); 36 | let code = letter.charCodeAt(0); 37 | let frame = frames.getFrameByName(letter + '.png'); 38 | 39 | if (!frame) { continue; } 40 | 41 | let rect = frame.getRect(); 42 | 43 | fontData.font.chars.char.push({ 44 | _id: code, 45 | _x: rect.x, 46 | _y: rect.y, 47 | _width: rect.width, 48 | _height: rect.height, 49 | _xoffset: 0, 50 | _yoffset: 0, 51 | _xadvance: monospace || frame.width, 52 | }); 53 | } 54 | 55 | const baseTexture = game.cache.getBaseTexture(key); 56 | 57 | game.cache.addBitmapFont(fontName, null, baseTexture.source, fontData, 'json', 0, 0); 58 | 59 | Font.cachedFonts[fontName] = true; 60 | 61 | return fontName; 62 | } 63 | -------------------------------------------------------------------------------- /src/fonts/ReturnOfGanon.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import { default as Font, IBitmapFontJson } from './Font'; 3 | 4 | export default class ReturnOfGanon extends Font { 5 | // You may notice that the "size" param default is 16, not 32 like when we create the font in "prepareFontData" 6 | // this is because we actually want the font to be half-size when used. 7 | constructor(game: Game, x: number = 0, y: number = 0, text: string = '', monospace: number = 0, size: number = 16) { 8 | super(game, prepareFontData(game, monospace), x, y, text, monospace, size); 9 | } 10 | } 11 | 12 | function prepareFontData(game: Game, monospace: number = 0): string { 13 | const key = 'sprite_rog_font'; 14 | const fontName = 'ReturnOfGanon' + (monospace ? 'Mono' + monospace.toString() : ''); 15 | 16 | if (Font.cachedFonts[fontName]) { return fontName; } 17 | 18 | const fontData: IBitmapFontJson = { 19 | font: { 20 | info: { 21 | _face: fontName, 22 | _size: 32, 23 | }, 24 | common: { 25 | _lineHeight: 32, 26 | }, 27 | chars: { 28 | char: [], 29 | }, 30 | }, 31 | }; 32 | 33 | const frames = game.cache.getFrameData(key); 34 | const letters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ:;\',-!.?<>() '; 35 | const spaceFrame = new Phaser.Frame(0, 0, 0, 0, 0, 'spacer'); 36 | 37 | // special characters use names in the file names 38 | let map: any = { 39 | // TODO: Colon, semicolon, pipe, mudora symbols, heart symbols 40 | ':': 'colon', 41 | ';': 'semicolon', 42 | 43 | "'": 'comma', 44 | ',': 'comma', 45 | '-': 'dash', 46 | '!': 'exclamation', 47 | '.': 'period', 48 | '?': 'question', 49 | '<': 'arrow-left', 50 | '>': 'arrow-right', 51 | '(': 'open-parenthesis', 52 | ')': 'close-parenthesis', 53 | }; 54 | 55 | // lowercase alpha characters are named "_x" where "x" is the character 56 | 'abcdefghijklmnopqrstuvwxyz'.split('').forEach((c: string) => { 57 | map[c] = '_' + c; 58 | }); 59 | 60 | // these characters are offset a bit 61 | 'acegjmnopqrsuvwxyz<>'.split('').forEach((c: string) => { 62 | map[c] = { 63 | yOffset: 6, 64 | name: map[c], 65 | }; 66 | }); 67 | 68 | ','.split('').forEach((c: string) => { 69 | map[c] = { 70 | yOffset: 18, 71 | name: map[c], 72 | }; 73 | }); 74 | 75 | // quote is offset upwards 76 | map["'"] = { 77 | yOffset: -16, 78 | name: map["'"], 79 | }; 80 | 81 | // period has a small offset as well 82 | map['.'] = { 83 | yOffset: 18, 84 | name: 'period', 85 | }; 86 | 87 | // space should advance the cursor 88 | map[' '] = { 89 | xAdvance: 7, 90 | name: ' ', 91 | }; 92 | 93 | // add characters 94 | for (let i = 0; i < letters.length; ++i) { 95 | let letter = letters.charAt(i); 96 | let code = letter.charCodeAt(0); 97 | let val = map[letter] || letter; 98 | let frame = frames.getFrameByName((val.name || val) + '.png'); 99 | 100 | if (code === 32) { 101 | frame = spaceFrame; 102 | } 103 | 104 | if (!frame) { continue; } 105 | 106 | let rect = frame.getRect(); 107 | 108 | fontData.font.chars.char.push({ 109 | _id: code, 110 | _x: rect.x, 111 | _y: rect.y, 112 | _width: rect.width, 113 | _height: rect.height, 114 | _xoffset: val.xOffset || 0, 115 | _yoffset: val.yOffset || 0, 116 | _xadvance: monospace || val.xAdvance || frame.width, 117 | }); 118 | } 119 | 120 | const baseTexture = game.cache.getBaseTexture(key); 121 | 122 | game.cache.addBitmapFont(fontName, null, baseTexture.source, fontData, 'json', 0, 0); 123 | 124 | return fontName; 125 | } 126 | -------------------------------------------------------------------------------- /src/gui/Dialog.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import Constants from '../data/Constants'; 3 | import ReturnOfGanon from '../fonts/ReturnOfGanon'; 4 | 5 | const rgxNewlines = /\n/g; 6 | 7 | export default class Dialog extends Phaser.Group { 8 | game: Game; 9 | 10 | openSound: Phaser.Sound; 11 | letterSound: Phaser.Sound; 12 | 13 | frameSprite: Phaser.Sprite; 14 | 15 | font: ReturnOfGanon; 16 | 17 | text: string = ''; 18 | queue: string[] = []; 19 | range: number[] = [0, 1]; // start pos, length 20 | 21 | fastSpeed: number = 15; 22 | typeSpeed: number = 60; 23 | speed: number = 60; 24 | 25 | speedCooldown: number = 250; 26 | 27 | padding: number = 5; 28 | 29 | typing: boolean = false; 30 | 31 | autoAdvance: boolean; 32 | 33 | buffer: Phaser.RenderTexture; 34 | bufferSprite: Phaser.Sprite; 35 | bufferScroll: Phaser.Point; 36 | 37 | onTypingComplete: Phaser.Signal; 38 | 39 | constructor(game: Game, parent?: any, showFrame: boolean = true, autoAdvance: boolean = false) { 40 | super(game, parent, 'dialog'); 41 | 42 | this.autoAdvance = autoAdvance; 43 | 44 | // load sound 45 | this.openSound = this.game.add.audio('effect_pause_close', Constants.AUDIO_EFFECT_VOLUME); 46 | this.letterSound = this.game.add.audio('effect_text_letter', Constants.AUDIO_EFFECT_VOLUME); 47 | 48 | // setup visibility 49 | // this.position.set(102, 438); 50 | this.visible = false; 51 | 52 | // add background 53 | this.frameSprite = this.game.add.sprite(0, 0, 'sprite_gui', 'dialog.png', this); 54 | this.frameSprite.name = 'frame'; 55 | this.frameSprite.visible = showFrame; 56 | 57 | // add font 58 | this.font = new ReturnOfGanon(game, 8, 8); 59 | this.font.name = 'text'; 60 | this.add(this.font); 61 | 62 | // initialize the render buffer 63 | this.buffer = game.add.renderTexture(game.width, game.height); 64 | this.bufferScroll = new Phaser.Point(); 65 | this.bufferSprite = game.add.sprite(0, 0, this.buffer, null, this); 66 | this.bufferSprite.name = 'buffer'; 67 | this.bufferSprite.position.set(this.font.position.x, this.font.position.y); 68 | 69 | this.onTypingComplete = new Phaser.Signal(); 70 | } 71 | 72 | show(text: (string|string[]), speed?: number, insertNewlines: boolean = true, playSound: boolean = true) { 73 | this.visible = true; 74 | 75 | this.range[0] = 0; 76 | this.range[1] = 1; 77 | 78 | this.speed = speed || this.typeSpeed; 79 | this.text = ''; 80 | this.font.text = ''; 81 | 82 | if (playSound) { 83 | this.openSound.play(); 84 | } 85 | 86 | if (Array.isArray(text)) { 87 | for (let i = 0; i < text.length; ++i) { 88 | this.append(text[i], insertNewlines); 89 | } 90 | } 91 | else { 92 | this.append(text, insertNewlines); 93 | } 94 | 95 | return this; 96 | } 97 | 98 | hide() { 99 | this.visible = false; 100 | 101 | return this; 102 | } 103 | 104 | append(text: string, insertNewlines: boolean = true) { 105 | let newText = insertNewlines ? this._insertNewlines(text) : text; 106 | 107 | if (newText.charAt(newText.length - 1) !== '\n') { 108 | newText += '\n'; 109 | } 110 | 111 | if (!this.typing) { 112 | this.text += newText; 113 | this._type(); 114 | } 115 | else { 116 | this.queue.push(newText); 117 | } 118 | 119 | return this; 120 | } 121 | 122 | advance() { 123 | if (this.typing) { 124 | this.speedUp(); 125 | } 126 | else if (this.queue.length) { 127 | this.append(this.queue.pop()); 128 | } 129 | } 130 | 131 | speedUp() { 132 | this.speed = this.fastSpeed; 133 | 134 | Game.timer.add(this.speedCooldown, () => { this.speed = this.typeSpeed; }, this); 135 | 136 | return this; 137 | } 138 | 139 | // TODO: This needs to be cleaned up quite a bit 140 | private _type() { 141 | const newlines = this.font.text.match(rgxNewlines); 142 | 143 | if ((this.range[0] + this.range[1]) > this.text.length) { 144 | this.typing = false; 145 | 146 | this.font.visible = true; 147 | this.buffer.renderXY(this.font, this.bufferScroll.x, this.bufferScroll.y, true); 148 | this.bufferSprite.visible = true; 149 | this.font.visible = false; 150 | 151 | if (!this.queue.length) { 152 | this.onTypingComplete.dispatch(); 153 | } 154 | else if (this.autoAdvance) { 155 | this.append(this.queue.pop()); 156 | } 157 | } 158 | else if (newlines && newlines.length && newlines.length === 3) { 159 | this.typing = true; 160 | 161 | this.font.visible = true; 162 | this.buffer.renderXY(this.font, this.bufferScroll.x, this.bufferScroll.y, true); 163 | this.bufferSprite.visible = true; 164 | this.font.visible = false; 165 | 166 | this.bufferScroll.y--; 167 | 168 | if (this.bufferScroll.y > -this.font.fontSize) { 169 | Game.timer.add(this.fastSpeed, this._type, this); 170 | } 171 | else { 172 | const newStart = this.text.indexOf('\n', this.range[0]); 173 | 174 | this.range[1] = this.range[1] - (newStart - this.range[0]) - 1; 175 | this.range[0] = newStart + 1; 176 | 177 | this.font.text = this.text.substr(this.range[0], this.range[1] - 1); 178 | 179 | this.bufferScroll.y = 0; 180 | 181 | Game.timer.add(this.speed, this._type, this); 182 | } 183 | } 184 | else { 185 | this.typing = true; 186 | 187 | this.font.visible = true; 188 | this.bufferSprite.visible = false; 189 | 190 | this.font.text = this.text.substr(this.range[0], this.range[1]); 191 | 192 | this.range[1]++; 193 | 194 | Game.timer.add(this.speed, this._type, this); 195 | } 196 | } 197 | 198 | private _getPreviousSpace(str: string, i: number) { 199 | let sub = 0; 200 | 201 | do { 202 | if (str[i - sub] === ' ') { 203 | return i - sub; 204 | } 205 | 206 | sub++; 207 | } while ((i + sub) < str.length || (i - sub) > 0); 208 | } 209 | 210 | private _insertNewlines(text: string) { 211 | let i = 30; 212 | while (text[i]) { 213 | const sp = this._getPreviousSpace(text, i); 214 | text = [text.slice(0, sp), text.slice(sp + 1)].join('\n'); 215 | i += 30; 216 | } 217 | 218 | return text; 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /src/gui/Hud.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import Player from '../entities/Player'; 3 | 4 | import MagicMeter from './items/MagicMeter'; 5 | import EquiptedItem from './items/EquiptedItem'; 6 | import InventoryCounter from './items/InventoryCounter'; 7 | import LifeMeter from './items/LifeMeter'; 8 | 9 | export default class Hud extends Phaser.Group { 10 | game: Game; 11 | 12 | items: any; 13 | 14 | constructor(game: Game, parent?: any) { 15 | super(game, parent, 'HUD'); 16 | 17 | this.items = { 18 | magic: new MagicMeter(game, this, 20, 18, 1), 19 | equipted: new EquiptedItem(game, this, 38, 20, ''), 20 | rupees: new InventoryCounter(game, this, 68, 15, 'rupees', 0), 21 | bombs: new InventoryCounter(game, this, 98, 15, 'bombs', 0), 22 | arrows: new InventoryCounter(game, this, 123, 15, 'arrows', 0), 23 | life: new LifeMeter(game, this, 160, 18, 3), 24 | }; 25 | } 26 | 27 | updateValues(link: Player) { 28 | this.items.magic.setValue(link.magic / link.maxMagic); 29 | 30 | this.items.equipted.setValue(link.equipted); 31 | this.items.rupees.setValue(link.inventory.rupees); 32 | this.items.bombs.setValue(link.inventory.bombs); 33 | this.items.arrows.setValue(link.inventory.arrows); 34 | 35 | this.items.life.max = link.maxHealth; 36 | this.items.life.setValue(link.health); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/gui/Inventory.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import ReturnOfGanon from '../fonts/ReturnOfGanon'; 3 | import { itemDescriptors, IItemDescriptor, IconCallback } from '../data/ItemDescriptors'; 4 | import Constants from '../data/Constants'; 5 | import GameState from '../states/GameState'; 6 | 7 | class InventoryItemSprite extends Phaser.Sprite { 8 | game: Game; 9 | item: IItemDescriptor; 10 | _frame: Phaser.Frame; 11 | } 12 | 13 | export default class Inventory extends Phaser.Group { 14 | game: Game; 15 | 16 | private openSound: Phaser.Sound; 17 | 18 | private empty: boolean; 19 | 20 | private frames: Phaser.FrameData; 21 | 22 | private grid: InventoryItemSprite[][][]; 23 | 24 | private items: TTable; 25 | 26 | private selected: InventoryItemSprite; 27 | private selector: Phaser.Sprite; 28 | 29 | private activeItem: Phaser.Sprite; 30 | private activeText: ReturnOfGanon; 31 | 32 | private isSliding: boolean; 33 | 34 | private _temp: Phaser.Point; 35 | 36 | constructor(game: Game, parent?: any) { 37 | super(game, parent, 'inventory'); 38 | 39 | this.openSound = game.add.sound('effect_pause_close', Constants.AUDIO_EFFECT_VOLUME); 40 | 41 | this.grid = []; 42 | this.empty = false; 43 | this.isSliding = false; 44 | 45 | this.frames = game.cache.getFrameData('sprite_gui'); 46 | 47 | this.position.y = -Constants.GAME_HEIGHT; 48 | this.visible = false; 49 | 50 | this._temp = new Phaser.Point(); 51 | 52 | this._setup(); 53 | 54 | (this.game.state.getCurrentState()).onInputDown.add(this._onInputDown, this); 55 | (this.game.state.getCurrentState()).onInputUp.add(this._onInputUp, this); 56 | } 57 | 58 | destroy(destroyChildren?: boolean) { 59 | super.destroy(destroyChildren); 60 | 61 | (this.game.state.getCurrentState()).onInputDown.removeAll(this); 62 | (this.game.state.getCurrentState()).onInputUp.removeAll(this); 63 | } 64 | 65 | updateValues() { 66 | const wasEmpty = this.empty; 67 | 68 | for (let i in this.items) { 69 | if (!this.items.hasOwnProperty(i)) { continue; } 70 | 71 | const sprite = this.items[i]; 72 | const item = sprite.item; 73 | 74 | if (!item) { continue; } 75 | 76 | const name: string = item.name; 77 | const val: number = this.game.player.inventory[name]; 78 | let ico: string; 79 | 80 | // set the texture and visibility 81 | if (val || (val === 0 && (name === 'armor' || name === 'crystal'))) { 82 | // some items have other sprites that should be enabled as well 83 | if (name === 'flippers') { 84 | this.items['txtSwim'].visible = true; 85 | } 86 | else if (name === 'boot') { 87 | this.items['txtRun'].visible = true; 88 | } 89 | 90 | // run icon function if there is one 91 | if (typeof item.icon === 'function') { 92 | ico = (item.icon)(this.game); 93 | } 94 | else { 95 | ico = (item.icon).replace('%d', val.toString()); 96 | } 97 | 98 | // enable item and set texture 99 | sprite.setFrame(this.frames.getFrameByName(ico)); 100 | sprite.visible = true; 101 | 102 | if (item.grid) { 103 | this.empty = false; 104 | } 105 | } 106 | else { 107 | sprite.visible = false; 108 | } 109 | } 110 | 111 | // always show lift power 112 | this.items['txtLiftNum'].visible = true; 113 | this.items['txtLiftNum'].setFrame(this.frames.getFrameByName( 114 | (this.items['txtLiftNum'].item.icon).replace('%d', (this.game.player.inventory.gloves + 1).toString()) 115 | )); 116 | 117 | // first item added 118 | if (wasEmpty && !this.empty) { 119 | // setup to scan right to the first item and select it 120 | // this.selected.x = -1; 121 | // this.selected.y = 0; 122 | // this.onMove('right', { down: true }); 123 | // this.onMove('right', { down: false }); 124 | 125 | // make sure it is equipted 126 | // TODO: hud updates?? 127 | // this.game.player.equipted = this.grid[this.selected.x][this.selected.y][0].item.name; 128 | // lttp.play.hud.updateValues(link); 129 | } 130 | 131 | this._moveSelector(); 132 | } 133 | 134 | open(cb?: Function) { 135 | if (this.isSliding) { return; } 136 | 137 | this.isSliding = true; 138 | this.visible = true; 139 | this.openSound.play(); 140 | 141 | this.game.add.tween(this) 142 | .to({ y: 0 }, Constants.PLAYER_INVENTORY_DROP_TIME) 143 | .start() 144 | .onComplete.addOnce(function () { 145 | this.isSliding = false; 146 | if (cb) { cb(); } 147 | }, this); 148 | } 149 | 150 | close(cb: Function) { 151 | if (this.isSliding) { return; } 152 | 153 | this.isSliding = true; 154 | 155 | this.game.add.tween(this) 156 | .to({ y: -Constants.GAME_HEIGHT }, Constants.PLAYER_INVENTORY_DROP_TIME) 157 | .start() 158 | .onComplete.addOnce(function () { 159 | this.visible = false; 160 | this.isSliding = false; 161 | if (cb) { cb(); } 162 | }, this); 163 | } 164 | 165 | move(dir: number) { 166 | if (this.empty) { return; } 167 | 168 | let next: Phaser.Point; 169 | 170 | switch (dir) { 171 | case Phaser.UP: 172 | next = this._findNext(0, -1); break; 173 | case Phaser.DOWN: 174 | next = this._findNext(0, 1); break; 175 | case Phaser.LEFT: 176 | next = this._findNext(-1, 0); break; 177 | case Phaser.RIGHT: 178 | next = this._findNext(1, 0); break; 179 | } 180 | 181 | if (next) { 182 | this.selected = this.grid[next.x][next.y][0]; 183 | 184 | this._moveSelector(); 185 | } 186 | } 187 | 188 | private _setup() { 189 | // add background 190 | this.game.add.sprite(0, 0, 'sprite_gui', 'inventory.png', this); 191 | 192 | // add item sprites 193 | for (let i in itemDescriptors) { 194 | if (!itemDescriptors.hasOwnProperty(i)) { continue; } 195 | 196 | const item = itemDescriptors[i]; 197 | const ico = typeof item.icon === 'function' ? (item.icon)(this.game) : (item.icon); 198 | 199 | ico.replace('%d', '1'); 200 | 201 | let sprite = new InventoryItemSprite(this.game, item.position[0], item.position[1], 'sprite_gui', ico); 202 | sprite.item = item; 203 | 204 | this.add(sprite); 205 | 206 | if (item.grid) { 207 | this._addToGrid(sprite, item.grid); 208 | } 209 | 210 | this.items[item.name] = sprite; 211 | } 212 | 213 | this.selector = this.game.add.sprite(0, 0, 'sprite_gui', 'selector.png', this); 214 | this.selector.visible = false; 215 | 216 | this.activeItem = this.game.add.sprite(200, 25, 'sprite_gui', 'items/lantern.png', this); 217 | this.activeItem.visible = false; 218 | 219 | this.activeText = new ReturnOfGanon(this.game, 175, 55); 220 | this.activeText.visible = false; 221 | this.add(this.activeText); 222 | } 223 | 224 | private _addToGrid(sprite: InventoryItemSprite, pos: number[]) { 225 | if (!this.grid[pos[0]]) { 226 | this.grid[pos[0]] = []; 227 | } 228 | 229 | if (!this.grid[pos[0]][pos[1]]) { 230 | this.grid[pos[0]][pos[1]] = []; 231 | } 232 | 233 | this.grid[pos[0]][pos[1]].push(sprite); 234 | } 235 | 236 | private _moveSelector() { 237 | const sprite = this.selected; 238 | 239 | this.selector.position.x = sprite.position.x - 5; 240 | this.selector.position.y = sprite.position.y - 5; 241 | 242 | this.activeItem.setFrame(sprite._frame); 243 | this.activeText.text = sprite.item.name; 244 | 245 | if (sprite.visible) { 246 | this.selector.visible = true; 247 | this.activeItem.visible = true; 248 | this.activeText.visible = true; 249 | } 250 | } 251 | 252 | private _findNext(stepX: number, stepY: number) { 253 | const pos = this._temp.set(this.selected.item.grid[0], this.selected.item.grid[1]); 254 | const maxX = this.grid.length - 1; 255 | const maxY = this.grid[0].length - 1; 256 | let found = false; 257 | 258 | while (!found) { 259 | pos.x += stepX; 260 | pos.y += stepY; 261 | 262 | this._wrapGrid(pos, maxX, maxY); 263 | 264 | const val = this.grid[pos.x][pos.y]; 265 | for (let i = val.length - 1; i > -1; --i) { 266 | found = found || val[i].visible; 267 | } 268 | } 269 | 270 | return pos; 271 | } 272 | 273 | private _wrapGrid(pos: Phaser.Point, maxX: number, maxY: number) { 274 | // wrap X 275 | if (pos.x < 0) { 276 | pos.y--; 277 | pos.x = maxX; 278 | // left of first slot, goto last 279 | if (pos.y < 0) { 280 | pos.y = maxY; 281 | } 282 | } 283 | else if (pos.x > maxX) { 284 | pos.y++; 285 | pos.x = 0; 286 | // right of last slot, goto first 287 | if (pos.y > maxY) { 288 | pos.y = 0; 289 | } 290 | } 291 | 292 | // wrap Y 293 | if (pos.y < 0) { 294 | pos.x--; 295 | pos.y = maxY; 296 | // up off first slot, goto last 297 | if (pos.x < 0) { 298 | pos.x = maxX; 299 | } 300 | } 301 | else if (pos.y > maxY) { 302 | pos.x++; 303 | pos.y = 0; 304 | // down off last slot, goto first 305 | if (pos.x > maxX) { 306 | pos.x = 0; 307 | } 308 | } 309 | } 310 | 311 | private _onInputDown(key: number, value: number, event: any) { 312 | switch (key) { 313 | // UP 314 | case Phaser.Keyboard.UP: 315 | case Phaser.Keyboard.W: 316 | case Phaser.Gamepad.XBOX360_DPAD_UP: 317 | this.move(Phaser.UP); 318 | break; 319 | 320 | // DOWN 321 | case Phaser.Keyboard.DOWN: 322 | case Phaser.Keyboard.S: 323 | case Phaser.Gamepad.XBOX360_DPAD_DOWN: 324 | this.move(Phaser.DOWN); 325 | break; 326 | 327 | // LEFT 328 | case Phaser.Keyboard.LEFT: 329 | case Phaser.Keyboard.A: 330 | case Phaser.Gamepad.XBOX360_DPAD_LEFT: 331 | this.move(Phaser.LEFT); 332 | break; 333 | 334 | // RIGHT 335 | case Phaser.Keyboard.RIGHT: 336 | case Phaser.Keyboard.D: 337 | case Phaser.Gamepad.XBOX360_DPAD_RIGHT: 338 | this.move(Phaser.RIGHT); 339 | break; 340 | 341 | // AXIS UP/DOWN 342 | case Phaser.Gamepad.XBOX360_STICK_LEFT_Y: 343 | this.move(value > 0 ? Phaser.DOWN : Phaser.UP); 344 | break; 345 | 346 | // AXIS LEFT/RIGHT 347 | case Phaser.Gamepad.XBOX360_STICK_LEFT_X: 348 | this.move(value > 0 ? Phaser.RIGHT : Phaser.LEFT); 349 | break; 350 | } 351 | } 352 | 353 | private _onInputUp(key: number, value: number, event: any) { 354 | // TODO: Implementation needed? 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /src/gui/items/EquiptedItem.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Hud from '../Hud'; 3 | import GuiItem from './GuiItem'; 4 | 5 | export default class EquiptedItem extends GuiItem { 6 | frameSprite: Phaser.Sprite; 7 | itemSprite: Phaser.Sprite; 8 | 9 | frames: Phaser.FrameData; 10 | 11 | constructor(game: Game, parent: Hud, x: number, y: number, value: string = '') { 12 | super(game, parent, x, y, 'equipted', value); 13 | 14 | this.frames = game.cache.getFrameData('sprite_gui'); 15 | 16 | this.frameSprite = game.add.sprite(0, 0, 'sprite_gui', 'hud/item-frame.png', this); 17 | this.itemSprite = game.add.sprite(6, 0, 'sprite_gui', 'items/lantern.png', this); 18 | 19 | this.itemSprite.visible = false; 20 | // this.itemSprite.scale.set(2); 21 | 22 | this.setValue(value); 23 | } 24 | 25 | setValue(val: any) { 26 | super.setValue(val); 27 | 28 | const tx = this.frames.getFrameByName('items/' + val + '.png'); 29 | 30 | if (!tx) { 31 | this.itemSprite.visible = false; 32 | } 33 | else { 34 | this.itemSprite.visible = true; 35 | this.itemSprite.setFrame(tx); 36 | } 37 | 38 | return this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/gui/items/GuiItem.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import Hud from '../Hud'; 3 | 4 | export default class GuiItem extends Phaser.Group { 5 | game: Game; 6 | 7 | value: any; 8 | 9 | constructor(game: Game, parent: Hud, x: number, y: number, name: string, value: any = 0) { 10 | super(game, parent, name); 11 | 12 | this.value = value; 13 | 14 | this.position.set(x, y); 15 | } 16 | 17 | setValue(val: any) { 18 | this.value = val; 19 | 20 | return this; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/gui/items/InventoryCounter.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import HudFont from '../../fonts/Hud'; 3 | import GuiItem from './GuiItem'; 4 | import Hud from '../Hud'; 5 | 6 | export default class InventoryCounter extends GuiItem { 7 | icon: Phaser.Sprite; 8 | 9 | font: HudFont; 10 | 11 | constructor(game: Game, parent: Hud, x: number, y: number, name: string, value: number = 0) { 12 | super(game, parent, x, y, name, value); 13 | 14 | this.icon = game.add.sprite(0, 0, 'sprite_gui', 'hud/indicator-' + this.name + '.png', this); 15 | 16 | if (name === 'rupees') { 17 | this.icon.position.x += 8; 18 | } 19 | else if (name === 'bombs') { 20 | this.icon.position.x += 4; 21 | } 22 | 23 | this.font = new HudFont(game, 0, 10, '', 16, 8); 24 | this.add(this.font); 25 | 26 | this.setValue(value); 27 | } 28 | 29 | setValue(val: any) { 30 | const l = this.name === 'rupees' ? 3 : 2; 31 | val = val.toString(); 32 | 33 | while (val.length < l) { 34 | val = '0' + val; 35 | } 36 | 37 | super.setValue(val); 38 | 39 | this.font.text = val; 40 | 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/gui/items/LifeMeter.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import GuiItem from './GuiItem'; 3 | import Hud from '../Hud'; 4 | 5 | export default class LifeMeter extends GuiItem { 6 | max: number; 7 | 8 | dash1: Phaser.Sprite; 9 | dash2: Phaser.Sprite; 10 | life: Phaser.Sprite; 11 | 12 | hearts: Phaser.Sprite[]; 13 | 14 | frames: Phaser.FrameData; 15 | 16 | constructor(game: Game, parent: Hud, x: number, y: number, value: number = 0) { 17 | super(game, parent, x, y, 'life', value); 18 | 19 | this.dash1 = game.add.sprite(18, 0, 'sprite_gui', 'hud/life-dash.png', this); 20 | this.dash2 = game.add.sprite(56, 0, 'sprite_gui', 'hud/life-dash.png', this); 21 | this.life = game.add.sprite(36, -2, 'sprite_gui', 'text/life.png', this); 22 | 23 | this.frames = game.cache.getFrameData('sprite_gui'); 24 | 25 | this.hearts = []; 26 | 27 | this.setValue(value); 28 | } 29 | 30 | setValue(val: any) { 31 | super.setValue(val); 32 | 33 | for (let i = 0, il = this.hearts.length; i < il; ++i) { 34 | this.hearts[i].visible = false; 35 | } 36 | 37 | let x = 0; 38 | let y = 7; 39 | const size = 8; 40 | const perRow = 10; 41 | let done = 0; 42 | 43 | for (let hp = val; hp > 0; --hp) { 44 | let off = 0; 45 | let frame: Phaser.Frame; 46 | 47 | // handle partial heart 48 | if (hp < 1) { 49 | frame = this.frames.getFrameByName('hud/heart-half.png'); 50 | off = 2; 51 | } 52 | else { 53 | frame = this.frames.getFrameByName('hud/heart-full.png'); 54 | } 55 | 56 | this.enableHeartSprite(done, frame, x, y + off); 57 | 58 | if ((x / size) >= (perRow - 1)) { 59 | x = 0; 60 | y += size; 61 | } 62 | else { 63 | x += size; 64 | } 65 | 66 | done++; 67 | } 68 | 69 | for (done; done < this.max; ++done) { 70 | this.enableHeartSprite(done, this.frames.getFrameByName('hud/heart-empty.png'), x, y); 71 | 72 | if ((x / size) >= (perRow - 1)) { 73 | x = 0; 74 | y += size; 75 | } 76 | else { 77 | x += size; 78 | } 79 | } 80 | 81 | return this; 82 | } 83 | 84 | enableHeartSprite(idx: number, frame: Phaser.Frame, x: number, y: number) { 85 | const spr = this.hearts[idx] || (this.hearts[idx] = this.game.add.sprite(0, 0, 'sprite_gui', null, this)); 86 | 87 | spr.setFrame(frame); 88 | spr.position.set(x, y); 89 | spr.visible = true; 90 | 91 | return spr; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/gui/items/MagicMeter.ts: -------------------------------------------------------------------------------- 1 | import Game from '../../Game'; 2 | import GuiItem from './GuiItem'; 3 | import Hud from '../Hud'; 4 | 5 | export default class MagicMeter extends GuiItem { 6 | background: Phaser.Sprite; 7 | valueSprite: Phaser.Sprite; 8 | 9 | maxHeight: number; 10 | 11 | constructor(game: Game, parent: Hud, x: number, y: number, value: number = 0) { 12 | super(game, parent, x, y, 'magic', value); 13 | 14 | this.background = game.add.sprite(0, 0, 'sprite_gui', 'hud/magic_meter.png', this); 15 | this.valueSprite = game.add.sprite(3, 0, 'sprite_gui', 'hud/magic_meter_value.png', this); 16 | 17 | this.maxHeight = this.valueSprite.height; 18 | 19 | this.setValue(value); 20 | } 21 | 22 | setValue(val: any) { 23 | super.setValue(val); 24 | 25 | this.valueSprite.height = this.maxHeight * val; 26 | this.valueSprite.position.y = (this.maxHeight - this.valueSprite.height) + (4 * this.valueSprite.scale.y); 27 | 28 | return this; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/levels/Cave034.ts: -------------------------------------------------------------------------------- 1 | import Level from './Level'; 2 | 3 | export default class Cave034 extends Level { 4 | levelKey: string = 'cave_034'; 5 | } 6 | -------------------------------------------------------------------------------- /src/levels/Darkworld.ts: -------------------------------------------------------------------------------- 1 | import Level from './Level'; 2 | 3 | export default class Darkworld extends Level { 4 | levelKey: string = 'darkworld'; 5 | 6 | preload() { 7 | super.preload(); 8 | 9 | // Music 10 | this.load.audio('music_darkworld', [ 11 | require('../../assets/audio/music/dark_world.lite.ogg'), 12 | ]); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/levels/Lightworld.ts: -------------------------------------------------------------------------------- 1 | import Level from './Level'; 2 | 3 | export default class Lightworld extends Level { 4 | levelKey: string = 'lightworld'; 5 | 6 | preload() { 7 | super.preload(); 8 | 9 | // Music 10 | this.load.audio('music_lightworld', [ 11 | require('../../assets/audio/music/overworld.lite.ogg'), 12 | ]); 13 | 14 | this.load.audio('music_village', [ 15 | require('../../assets/audio/music/kakariko_village.lite.ogg'), 16 | ]); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/levels/LinksHouse.ts: -------------------------------------------------------------------------------- 1 | import Level from './Level'; 2 | 3 | export default class LinksHouse extends Level { 4 | levelKey: string = 'linkshouse'; 5 | 6 | preload() { 7 | super.preload(); 8 | 9 | this.load.audio('music_village', [ 10 | require('../../assets/audio/music/kakariko_village.lite.ogg'), 11 | ]); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/math.ts: -------------------------------------------------------------------------------- 1 | import Entity from './entities/Entity'; 2 | 3 | const coneVec = new Phaser.Point(0, 0); 4 | 5 | export default { 6 | isInViewCone(viewer: Entity, obj: Entity, coneSize: number) { 7 | coneVec.set( 8 | // size offset compensates for anchor (0, 1) that tiled objects have 9 | (obj.x + (obj.width / 2)) - viewer.x, 10 | (obj.y - (obj.height / 2)) - viewer.y 11 | ); 12 | 13 | coneVec.normalize(); 14 | 15 | // check if 'e' is withing a conic area in the direction we face 16 | switch (viewer.facing) { 17 | case Phaser.UP: 18 | return (coneVec.y < 0 && coneVec.x > -coneSize && coneVec.x < coneSize); 19 | case Phaser.DOWN: 20 | return (coneVec.y > 0 && coneVec.x > -coneSize && coneVec.x < coneSize); 21 | case Phaser.LEFT: 22 | return (coneVec.x < 0 && coneVec.y > -coneSize && coneVec.y < coneSize); 23 | case Phaser.RIGHT: 24 | return (coneVec.x > 0 && coneVec.y > -coneSize && coneVec.y < coneSize); 25 | } 26 | }, 27 | }; 28 | -------------------------------------------------------------------------------- /src/states/Boot.ts: -------------------------------------------------------------------------------- 1 | import GameState from './GameState'; 2 | 3 | export default class Boot extends GameState { 4 | preload(): void { 5 | super.preload(); 6 | 7 | this.load.image('image_preloader', require('../../assets/ui/loader.png')); 8 | this.load.atlas( 9 | 'sprite_rog_font', 10 | require('../../assets/sprites/fonts/retofganon.png'), 11 | require('../../assets/sprites/fonts/retofganon.json'), 12 | null, 13 | Phaser.Loader.TEXTURE_ATLAS_JSON_HASH 14 | ); 15 | } 16 | 17 | create(): void { 18 | super.create(); 19 | 20 | // don't specifically need multitouch, so turn it off. 21 | this.input.maxPointers = 1; 22 | 23 | this.game.state.start('state_preloader'); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/states/GameState.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | import Constants from '../data/Constants'; 3 | 4 | interface IGamepadAxisState { 5 | axis: number; // the axis index 6 | value: number; // the value of the axis 7 | } 8 | 9 | export default class GameState extends Phaser.State { 10 | game: Game; 11 | 12 | onInputDown: Phaser.Signal; 13 | onInputUp: Phaser.Signal; 14 | 15 | constructor() { 16 | super(); 17 | 18 | // create signals 19 | this.onInputDown = new Phaser.Signal(); 20 | this.onInputUp = new Phaser.Signal(); 21 | } 22 | 23 | create() { 24 | // add callbacks for keyboard/gamepad data 25 | this.input.keyboard.addCallbacks(this, this.onKeyboardDown, this.onKeyboardUp); 26 | this.input.gamepad.addCallbacks(this, { 27 | onDown: this.onGamepadDown, 28 | onUp: this.onGamepadUp, 29 | onAxis: this.onGamepadAxis, 30 | }); 31 | 32 | // destroy old timer 33 | if (Game.timer) { 34 | Game.timer.destroy(); 35 | } 36 | 37 | // start the static game timer 38 | Game.timer = this.time.create(false); 39 | Game.timer.start(); 40 | } 41 | 42 | shutdown() { 43 | this.onInputDown.removeAll(); 44 | this.onInputUp.removeAll(); 45 | this.sound.stopAll(); 46 | } 47 | 48 | onKeyboardDown(event: KeyboardEvent) { 49 | this.onInputDown.dispatch(event.keyCode, 1, event); 50 | } 51 | 52 | onKeyboardUp(event: KeyboardEvent) { 53 | this.onInputUp.dispatch(event.keyCode, 1, event); 54 | } 55 | 56 | onGamepadDown(button: number, value: number) { 57 | this.onInputDown.dispatch(button, value, event); 58 | } 59 | 60 | onGamepadUp(button: number, value: number) { 61 | this.onInputUp.dispatch(button, value, event); 62 | } 63 | 64 | onGamepadAxis(pad: Phaser.SinglePad, index: number, value: number) { 65 | // if we pass the threshold send a "down" signal 66 | if (value > Constants.INPUT_GAMEPAD_AXIS_THRESHOLD 67 | || value < -Constants.INPUT_GAMEPAD_AXIS_THRESHOLD 68 | ) { 69 | this.onInputDown.dispatch(index, value, null); 70 | } 71 | // otherwise send an "up" signal 72 | else { 73 | this.onInputUp.dispatch(index, value, null); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/states/Play.ts: -------------------------------------------------------------------------------- 1 | import GameState from './GameState'; 2 | import Player from '../entities/Player'; 3 | 4 | export default class Play extends GameState { 5 | preload() { 6 | super.preload(); 7 | 8 | this.load.image('image_preloader', require('../../assets/ui/loader.png')); 9 | this.load.atlas( 10 | 'sprite_rog_font', 11 | require('../../assets/sprites/fonts/retofganon.png'), 12 | require('../../assets/sprites/fonts/retofganon.json'), 13 | null, 14 | Phaser.Loader.TEXTURE_ATLAS_JSON_HASH 15 | ); 16 | } 17 | 18 | create() { 19 | super.create(); 20 | 21 | this.game.player = new Player(this.game); 22 | 23 | // load the save data into the player 24 | this.game.loadedSave.copyTo(this.game.player); 25 | 26 | // startup the autosave interval 27 | this.game.startAutosave(); 28 | 29 | // todo load active level from save file 30 | this.game.state.start('level_' + this.game.loadedSave.lastUsedExit.name); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/states/Preloader.ts: -------------------------------------------------------------------------------- 1 | import GameState from './GameState'; 2 | import Constants from '../data/Constants'; 3 | 4 | export default class Preloader extends GameState { 5 | preloadBar: Phaser.Sprite; 6 | 7 | preload() { 8 | super.preload(); 9 | 10 | // Set-up our preloader sprite 11 | this.preloadBar = this.add.sprite(200, 250, 'image_preloader'); 12 | this.load.setPreloadSprite(this.preloadBar); 13 | 14 | // LOAD EM UP! 15 | 16 | // Images 17 | this.load.image('image_lore_bg1', require('../../assets/ui/lore_bg1.png')); 18 | this.load.image('image_lore_bg2', require('../../assets/ui/lore_bg2.png')); 19 | 20 | /* tslint:disable:max-line-length */ 21 | 22 | // Misc Sprites Atlases 23 | this.load.atlas('sprite_intro', require('../../assets/sprites/misc/intro.png'), require('../../assets/sprites/misc/intro.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 24 | this.load.atlas('sprite_select', require('../../assets/sprites/misc/selectscreen.png'), require('../../assets/sprites/misc/selectscreen.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 25 | this.load.atlas('sprite_particles', require('../../assets/sprites/misc/particles.png'), require('../../assets/sprites/misc/particles.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 26 | this.load.atlas('sprite_link', require('../../assets/sprites/entities/link.png'), require('../../assets/sprites/entities/link.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 27 | this.load.atlas('sprite_misc', require('../../assets/sprites/entities/misc.png'), require('../../assets/sprites/entities/misc.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 28 | this.load.atlas('sprite_enemies', require('../../assets/sprites/entities/enemies.png'), require('../../assets/sprites/entities/enemies.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 29 | this.load.atlas('sprite_worlditems', require('../../assets/sprites/misc/overworlditems.png'), require('../../assets/sprites/misc/overworlditems.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 30 | this.load.atlas('sprite_overlays', require('../../assets/sprites/overlays/overlays.png'), require('../../assets/sprites/overlays/overlays.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 31 | 32 | // HUD Sprite Atlases 33 | this.load.atlas('sprite_gui', require('../../assets/sprites/ui/gui.png'), require('../../assets/sprites/ui/gui.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 34 | this.load.atlas('sprite_hud_font', require('../../assets/sprites/fonts/hud.png'), require('../../assets/sprites/fonts/hud.json'), null, Phaser.Loader.TEXTURE_ATLAS_JSON_HASH); 35 | 36 | // Asset packs for tilemaps 37 | this.load.json(Constants.ASSET_TILEMAP_PACKS_KEY, Constants.ASSET_TILEMAP_PACKS_URL); 38 | 39 | // Minimaps 40 | this.load.tilemap('map_minimap_lightworld', require('../../assets/levels/minimaps/lw_minimap.json'), null, Phaser.Tilemap.TILED_JSON); 41 | this.load.tilemap('map_minimap_darkworld', require('../../assets/levels/minimaps/dw_minimap.json'), null, Phaser.Tilemap.TILED_JSON); 42 | 43 | /* tslint:enable:max-line-length */ 44 | 45 | // Music 46 | this.load.audio('music_title', [ 47 | require('../../assets/audio/music/title.lite.ogg'), 48 | ]); 49 | 50 | this.load.audio('music_lore', [ 51 | require('../../assets/audio/music/opening_demo.lite.ogg'), 52 | ]); 53 | 54 | this.load.audio('music_select', [ 55 | require('../../assets/audio/music/select_screen.lite.ogg'), 56 | ]); 57 | 58 | // Sound Effects 59 | this.load.audio('effect_text_done', [ 60 | require('../../assets/audio/effects/LTTP_Text_Done.lite.ogg'), 61 | ]); 62 | 63 | this.load.audio('effect_text_letter', [ 64 | require('../../assets/audio/effects/LTTP_Text_Letter.lite.ogg'), 65 | ]); 66 | 67 | this.load.audio('effect_grass_cut', [ 68 | require('../../assets/audio/effects/LTTP_Grass_Cut.lite.ogg'), 69 | ]); 70 | 71 | this.load.audio('effect_lift', [ 72 | require('../../assets/audio/effects/LTTP_Link_Pickup.lite.ogg'), 73 | ]); 74 | 75 | this.load.audio('effect_throw', [ 76 | require('../../assets/audio/effects/LTTP_Link_Throw.lite.ogg'), 77 | ]); 78 | 79 | this.load.audio('effect_smash', [ 80 | require('../../assets/audio/effects/LTTP_Shatter.lite.ogg'), 81 | ]); 82 | 83 | this.load.audio('effect_sword1', [ 84 | require('../../assets/audio/effects/LTTP_Sword1.lite.ogg'), 85 | ]); 86 | 87 | this.load.audio('effect_sword2', [ 88 | require('../../assets/audio/effects/LTTP_Sword1.lite.ogg'), 89 | ]); 90 | 91 | this.load.audio('effect_menu_select', [ 92 | require('../../assets/audio/effects/LTTP_Menu_Select.lite.ogg'), 93 | ]); 94 | 95 | this.load.audio('effect_menu_select_cursor', [ 96 | require('../../assets/audio/effects/LTTP_Menu_Cursor.lite.ogg'), 97 | ]); 98 | 99 | this.load.audio('effect_menu_select_erase', [ 100 | require('../../assets/audio/effects/LTTP_Menu_Erase.lite.ogg'), 101 | ]); 102 | 103 | this.load.audio('effect_error', [ 104 | require('../../assets/audio/effects/LTTP_Error.lite.ogg'), 105 | ]); 106 | 107 | this.load.audio('effect_lowhp', [ 108 | require('../../assets/audio/effects/LTTP_LowHealth.lite.ogg'), 109 | ]); 110 | 111 | this.load.audio('effect_pause_close', [ 112 | require('../../assets/audio/effects/LTTP_Pause_Close.lite.ogg'), 113 | ]); 114 | 115 | this.load.audio('effect_fall', [ 116 | require('../../assets/audio/effects/LTTP_Link_Jump.lite.ogg'), 117 | ]); 118 | 119 | // Item effects 120 | this.load.audio('effect_chest', [ 121 | require('../../assets/audio/effects/LTTP_Chest.lite.ogg'), 122 | ]); 123 | 124 | this.load.audio('effect_chest_appear', [ 125 | require('../../assets/audio/effects/LTTP_Chest_Appears.lite.ogg'), 126 | ]); 127 | 128 | this.load.audio('effect_item', [ 129 | require('../../assets/audio/effects/LTTP_Item.lite.ogg'), 130 | ]); 131 | 132 | this.load.audio('effect_item_fanfaire', [ 133 | require('../../assets/audio/effects/LTTP_ItemFanfare_Stereo.lite.ogg'), 134 | ]); 135 | 136 | this.load.audio('effect_rupee1', [ 137 | require('../../assets/audio/effects/LTTP_Rupee1.lite.ogg'), 138 | ]); 139 | 140 | this.load.audio('effect_rupee2', [ 141 | require('../../assets/audio/effects/LTTP_Rupee2.lite.ogg'), 142 | ]); 143 | } 144 | 145 | create() { 146 | super.create(); 147 | 148 | this.add.tween(this.preloadBar).to({ alpha: 0 }, 1000, Phaser.Easing.Linear.None, true) 149 | .onComplete 150 | .add(this.startIntro, this); 151 | } 152 | 153 | startIntro() { 154 | this.game.state.start('state_intro'); 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/utility/Pool.ts: -------------------------------------------------------------------------------- 1 | import Game from '../Game'; 2 | 3 | interface IConstructable { 4 | new(...args: any[]): T; 5 | prototype: T; 6 | } 7 | 8 | export default class Pool { 9 | game: Game; 10 | group: Phaser.Group; 11 | 12 | private _ctor: IConstructable; 13 | private _pool: T[] = []; 14 | 15 | constructor(game: Game, ctor: IConstructable, group: Phaser.Group = null) { 16 | this.game = game; 17 | this.group = group; 18 | 19 | this._ctor = ctor; 20 | } 21 | 22 | // main methods 23 | alloc(forceNew: boolean = false, ...args: any[]): T { 24 | let obj: T; 25 | 26 | if (!forceNew) { 27 | obj = this._pool.pop(); 28 | } 29 | 30 | if (!obj) { 31 | args.unshift(this.game); 32 | obj = this._construct(args); 33 | 34 | if (this.group) { 35 | this.group.add(obj); 36 | } 37 | } 38 | 39 | return obj; 40 | } 41 | 42 | free(obj: T): Pool { 43 | this._pool.push(obj); 44 | 45 | return this; 46 | } 47 | 48 | // less common helpers 49 | preallocate(num: number): Pool { 50 | for (let i = 0; i < num; ++i) { 51 | this.free(this.alloc(true)); 52 | } 53 | 54 | return this; 55 | } 56 | 57 | clear(): Pool { 58 | this._pool.length = 0; 59 | return this; 60 | } 61 | 62 | remove(obj: T): T { 63 | const idx = this._pool.indexOf(obj); 64 | 65 | if (idx !== -1) { 66 | this._pool.splice(idx, 1); 67 | } 68 | 69 | return obj; 70 | } 71 | 72 | private _construct(args: any[]): T { 73 | switch (args.length) { 74 | case 0: 75 | return new this._ctor(); 76 | case 1: 77 | return new this._ctor(args[0]); 78 | case 2: 79 | return new this._ctor(args[0], args[1]); 80 | case 3: 81 | return new this._ctor(args[0], args[1], args[2]); 82 | case 4: 83 | return new this._ctor(args[0], args[1], args[2], args[3]); 84 | case 5: 85 | return new this._ctor(args[0], args[1], args[2], args[3], args[4]); 86 | case 6: 87 | return new this._ctor(args[0], args[1], args[2], args[3], args[4], args[5]); 88 | default: 89 | const ctor = this._ctor; 90 | function PoolObjectCtor(): void { 91 | return ctor.apply(this, args); 92 | } 93 | PoolObjectCtor.prototype = ctor.prototype; 94 | 95 | return new (PoolObjectCtor)(); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/utility/Save.ts: -------------------------------------------------------------------------------- 1 | import Storage from './Storage'; 2 | import Player from '../entities/Player'; 3 | import PlayerInventory from '../data/PlayerInventory'; 4 | import { IItemDescriptor } from '../data/ItemDescriptors'; 5 | 6 | export default class Save { 7 | private static VERSION: number = 1; 8 | 9 | // player data 10 | inventory: PlayerInventory = new PlayerInventory(); 11 | equipted: IItemDescriptor = null; 12 | 13 | health: number = 3; 14 | maxHealth: number = 3; 15 | 16 | magic: number = 0; 17 | maxMagic: number = 10; 18 | 19 | // save slot info 20 | slot: number; 21 | name: string; 22 | 23 | // other save data 24 | mapData: any = {}; 25 | 26 | lastUsedExit: any = { 27 | name: 'linkshouse', 28 | properties: { loc: [125, 140] }, 29 | }; 30 | 31 | saveFileExists: boolean = false; 32 | 33 | private _cacheKey: string; 34 | 35 | constructor(slot: number, name?: string) { 36 | this._cacheKey = this._key(slot); 37 | this.slot = slot; 38 | this.name = name; 39 | } 40 | 41 | save(player?: Player): Save { 42 | // load the player data into this save object 43 | this.loadFrom(player); 44 | 45 | this.saveFileExists = true; 46 | 47 | Storage.save(this._cacheKey, this); 48 | 49 | return this; 50 | } 51 | 52 | load(): Save { 53 | const data = Storage.load(this._cacheKey); 54 | 55 | if (data) { 56 | this.loadFrom(data); 57 | this.saveFileExists = true; 58 | } 59 | 60 | return this; 61 | } 62 | 63 | remove() { 64 | Storage.remove(this._cacheKey); 65 | 66 | this.saveFileExists = false; 67 | } 68 | 69 | updateZoneData(layer: Phaser.Plugin.Tiled.Objectlayer) { 70 | const mapData = this.mapData[layer.map.name] || { zones: {} }; 71 | const zoneData = mapData.zones[layer.name] || { objects: [] }; 72 | 73 | zoneData.objects.length = 0; 74 | 75 | // TODO: Using the object index means if the map changes (adding a missing object, for example) 76 | // then the indexes change and saved data is invalid. Instead there should be a keying system. 77 | // Potentially hashing some data about the object to generate a unique key? 78 | 79 | for (let i = 0, il = layer.objects.length; i < il; ++i) { 80 | zoneData.objects.push({ 81 | properties: { 82 | loot: layer.objects[i].properties.loot, 83 | }, 84 | }); 85 | } 86 | 87 | mapData.zones[layer.name] = zoneData; 88 | this.mapData[layer.map.name] = mapData; 89 | } 90 | 91 | updateExit(exit: Phaser.Plugin.Tiled.ITiledObject) { 92 | this.lastUsedExit = exit; 93 | } 94 | 95 | copyTo(player: Player) { 96 | player.name = this.name; 97 | 98 | player.inventory = this.inventory; 99 | player.equipted = this.equipted; 100 | 101 | player.health = this.health; 102 | player.maxHealth = this.maxHealth; 103 | 104 | player.magic = this.magic; 105 | player.maxMagic = this.maxMagic; 106 | } 107 | 108 | private loadFrom(data: (Player|Save)) { 109 | if (!data) { 110 | return; 111 | } 112 | 113 | this.name = data.name; 114 | 115 | this.inventory = data.inventory; 116 | this.equipted = data.equipted; 117 | 118 | this.health = data.health; 119 | this.maxHealth = data.maxHealth; 120 | 121 | this.magic = data.magic; 122 | this.maxMagic = data.maxMagic; 123 | 124 | if (!(data instanceof Player)) { 125 | this.mapData = (data).mapData; 126 | this.lastUsedExit = (data).lastUsedExit; 127 | } 128 | } 129 | 130 | private _key(slot: number = this.slot, version: number = Save.VERSION) { 131 | return 'save:' + version + ':' + slot; 132 | } 133 | 134 | // TODO: Migrations from old to new versions of saves. This way when people patch 135 | // it should automatically upgrade their saves and they shouldn't loase any data. 136 | } 137 | -------------------------------------------------------------------------------- /src/utility/Storage.ts: -------------------------------------------------------------------------------- 1 | import lzstring = require('lz-string'); 2 | 3 | export default { 4 | save(key: string, value: any) { 5 | localStorage.setItem(key, lzstring.compressToUTF16(JSON.stringify(value))); 6 | }, 7 | 8 | load(key: string) { 9 | const val: string = localStorage.getItem(key); 10 | 11 | try { 12 | return JSON.parse(lzstring.decompressFromUTF16(val)); 13 | } 14 | catch (e) { 15 | return val; 16 | } 17 | }, 18 | 19 | remove(key: string) { 20 | localStorage.removeItem(key); 21 | }, 22 | }; 23 | -------------------------------------------------------------------------------- /src/utility/phaser-patches.ts: -------------------------------------------------------------------------------- 1 | // I want to manage the camera bounds manually, remove all the code that will mess with it. 2 | Phaser.Camera.prototype.setBoundsToWorld = function () { /* do nothing */ }; 3 | Phaser.World.prototype.setBounds = function (x: number, y: number, width: number, height: number) { 4 | this._definedSize = true; 5 | this._width = width; 6 | this._height = height; 7 | 8 | this.bounds.setTo(x, y, width, height); 9 | 10 | this.x = x; 11 | this.y = y; 12 | 13 | this.game.physics.setBoundsToWorld(); 14 | }; 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "declaration": false, 7 | "noImplicitAny": true, 8 | "removeComments": true, 9 | "sourceMap": true 10 | }, 11 | "exclude": [ 12 | "assets", 13 | "less", 14 | "node_modules", 15 | "public", 16 | "vendor" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "align": [true, 4 | "parameters", 5 | "statements" 6 | ], 7 | "ban": false, 8 | "class-name": true, 9 | "comment-format": [true, "check-space"], 10 | "curly": true, 11 | "eofline": true, 12 | "forin": true, 13 | "indent": [true, "spaces"], 14 | "interface-name": true, 15 | "jsdoc-format": true, 16 | "label-position": true, 17 | "label-undefined": true, 18 | "max-line-length": [true, 140], 19 | "member-access": false, 20 | "member-ordering": [true, 21 | "public-before-private", 22 | "static-before-instance", 23 | "variables-before-functions" 24 | ], 25 | "no-any": false, 26 | "no-arg": true, 27 | "no-bitwise": false, 28 | "no-conditional-assignment": true, 29 | "no-consecutive-blank-lines": true, 30 | "no-console": [true, 31 | "debug", 32 | "info", 33 | "time", 34 | "timeEnd", 35 | "trace" 36 | ], 37 | "no-construct": true, 38 | "no-constructor-vars": true, 39 | "no-debugger": true, 40 | "no-duplicate-key": true, 41 | "no-duplicate-variable": true, 42 | "no-empty": true, 43 | "no-eval": true, 44 | "no-inferrable-types": false, 45 | "no-internal-module": true, 46 | "no-null-keyword": false, 47 | "no-require-imports": false, 48 | "no-shadowed-variable": true, 49 | "no-string-literal": false, 50 | "no-switch-case-fall-through": true, 51 | "no-trailing-whitespace": true, 52 | "no-unreachable": true, 53 | "no-unused-expression": true, 54 | "no-unused-variable": true, 55 | "no-use-before-declare": true, 56 | "no-var-keyword": true, 57 | "no-var-requires": true, 58 | "object-literal-sort-keys": false, 59 | "one-line": [true, 60 | "check-open-brace", 61 | "check-whitespace" 62 | ], 63 | "quotemark": [true, "single", "avoid-escape"], 64 | "radix": true, 65 | "semicolon": [true, "always"], 66 | "switch-default": false, 67 | "trailing-comma": [true, { 68 | "singleline": "never", 69 | "multiline": "always" 70 | }], 71 | "triple-equals": [true, "allow-null-check"], 72 | "typedef": [true, 73 | "parameter", 74 | "arrow-parameter", 75 | "member-variable-declaration" 76 | ], 77 | "typedef-whitespace": [true, { 78 | "call-signature": "nospace", 79 | "index-signature": "nospace", 80 | "parameter": "nospace", 81 | "property-declaration": "nospace", 82 | "variable-declaration": "nospace" 83 | }], 84 | "use-strict": [true, "check-module"], 85 | "variable-name": [true, 86 | "check-format", 87 | "allow-leading-underscore", 88 | "ban-keywords" 89 | ], 90 | "whitespace": [true, 91 | "check-branch", 92 | "check-decl", 93 | "check-operator", 94 | "check-module", 95 | "check-separator", 96 | "check-type" 97 | ] 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /typings/main.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | /* tslint:disable:no-internal-module */ 6 | declare module p2 { 7 | export interface IBodyEx { 8 | parent: Phaser.Physics.P2.Body; 9 | } 10 | 11 | export interface ISpringEx { 12 | parent: Phaser.Physics.P2.Spring; 13 | } 14 | } 15 | /* tslint:enable:no-internal-module */ 16 | 17 | // declare stub phaser-debug 18 | declare module 'phaser-debug' { 19 | export = class Debug extends Phaser.Plugin { 20 | constructor(game: Phaser.Game, parent: PIXI.DisplayObject); 21 | } 22 | } 23 | 24 | // declare stub phaser-tiled 25 | declare module 'phaser-tiled' { 26 | export = class Tiled extends Phaser.Plugin { 27 | constructor(game: Phaser.Game, parent: PIXI.DisplayObject); 28 | } 29 | } 30 | 31 | // declare lz-string 32 | declare module 'lz-string' { 33 | export = LZString; 34 | } 35 | 36 | // stub require so TS will shut up 37 | declare var require: (file: string) => any; 38 | 39 | // global types 40 | declare type TCallback = () => R; 41 | declare type TPoint = (PIXI.Point|Phaser.Point|Phaser.Physics.P2.InversePointProxy); 42 | 43 | declare type TTable = { [index: string]: V }; 44 | declare type TArrayTable = { [index: number]: V }; 45 | 46 | declare type TColorRGBA = number[]; 47 | -------------------------------------------------------------------------------- /vendor/build.sh: -------------------------------------------------------------------------------- 1 | # This is the build command used for the custom phaser build: 2 | grunt custom --exclude retrofont,rope,net,debug,flexgrid,arcade,ninja,particles,creature,video --split true 3 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin'); 7 | const NoErrorsPlugin = require('webpack/lib/NoErrorsPlugin'); 8 | 9 | const ASSET_PATH = 'assets'; 10 | const VENDOR_PATH = path.join(__dirname, '/vendor'); 11 | 12 | const phaser = path.join(VENDOR_PATH, 'phaser.js'); 13 | const pixi = path.join(VENDOR_PATH, 'pixi.js'); 14 | const p2 = path.join(VENDOR_PATH, 'p2.js'); 15 | const phaserDebug = path.join(__dirname, 'node_modules', 'phaser-debug', 'dist', 'phaser-debug.js'); 16 | 17 | module.exports = { 18 | cache: true, 19 | progress: true, 20 | recordsPath: path.join(__dirname, '.records'), 21 | entry: { 22 | app: './src/app.ts', 23 | vendor: ['pixi.js', 'p2', 'phaser', 'phaser-tiled', 'phaser-debug', 'lz-string'] 24 | }, 25 | output: { 26 | path: path.join(__dirname, 'public'), 27 | publicPath: '/', 28 | assetPath: ASSET_PATH, 29 | filename: `${ASSET_PATH}/[chunkhash].js`, 30 | chunkFilename: `${ASSET_PATH}/[id].[chunkhash].js` 31 | }, 32 | resolve: { 33 | extensions: ['', '.ts', '.js'], 34 | alias: { 35 | 'pixi.js': pixi, 36 | 'p2': p2, 37 | 'phaser': phaser, 38 | 'phaser-debug': phaserDebug, 39 | } 40 | }, 41 | module: { 42 | loaders: [ 43 | { 44 | test: /\.ts$/, 45 | loader: 'ts-loader' 46 | }, 47 | { 48 | test: /(pixi|phaser|p2).js/, 49 | loader: 'script' 50 | }, 51 | { 52 | test: /\.(png|jpe?g|svg|gif|ttf|woff2?|eot|ogg|mp3|wav|json)(\?v=[0-9]\.[0-9]\.[0-9])?$/i, 53 | loaders: [ 54 | `file?name=${ASSET_PATH}/[hash].[ext]`, 55 | 'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false' 56 | ] 57 | }, 58 | { 59 | test: /\.less$/, 60 | loader: ExtractTextPlugin.extract( 61 | // activate source maps via loader query 62 | 'css?sourceMap!less?sourceMap', 63 | { allChunks: true } 64 | ) 65 | } 66 | ] 67 | }, 68 | plugins: [ 69 | // don't emit output when there are errors 70 | // new NoErrorsPlugin(), 71 | 72 | // extract inline css into separate 'styles.css' 73 | new ExtractTextPlugin(`${ASSET_PATH}/[hash].css`), 74 | 75 | // extract shared dependencies to a central bundle 76 | new CommonsChunkPlugin({ 77 | name: 'vendor', 78 | 79 | // (with more entries, this ensures that no other module 80 | // goes into the vendor chunk) 81 | minChunks: Infinity 82 | }), 83 | 84 | // create app html 85 | new HtmlWebpackPlugin({ 86 | filename: 'index.html', 87 | template: './assets/index.ejs', 88 | title: 'LTTP', 89 | chunks: ['vendor', 'app'], 90 | cache: true 91 | }) 92 | ] 93 | }; 94 | --------------------------------------------------------------------------------