├── README.md ├── fonts ├── russoone │ ├── OFL.txt │ └── RussoOne-Regular.ttf └── vt323 │ ├── SIL Open Font License.txt │ └── VT323-Regular.ttf ├── main.lua ├── maps ├── LICENSE.txt ├── _template1.tmx ├── _template2.tmx ├── _template3.tmx ├── _template4.tmx ├── blank.lua ├── blank.tmx ├── blank2.lua ├── blank2.tmx ├── rm1.lua ├── rm1.tmx ├── rm10.lua ├── rm10.tmx ├── rm11.lua ├── rm11.tmx ├── rm12.lua ├── rm12.tmx ├── rm13.lua ├── rm13.tmx ├── rm14.lua ├── rm14.tmx ├── rm15.lua ├── rm15.tmx ├── rm16.lua ├── rm16.tmx ├── rm17.lua ├── rm17.tmx ├── rm18.lua ├── rm18.tmx ├── rm19.lua ├── rm19.tmx ├── rm2.lua ├── rm2.tmx ├── rm20.lua ├── rm20.tmx ├── rm21.lua ├── rm21.tmx ├── rm22.lua ├── rm22.tmx ├── rm23.lua ├── rm23.tmx ├── rm24.lua ├── rm24.tmx ├── rm25.lua ├── rm25.tmx ├── rm26.lua ├── rm26.tmx ├── rm27.lua ├── rm27.tmx ├── rm28.lua ├── rm28.tmx ├── rm3.lua ├── rm3.tmx ├── rm4.lua ├── rm4.tmx ├── rm5.lua ├── rm5.tmx ├── rm6.lua ├── rm6.tmx ├── rm7.lua ├── rm7.tmx ├── rm8.lua ├── rm8.tmx ├── rm9.lua ├── rm9.tmx ├── rmBoss.lua ├── rmBoss.tmx ├── rmBossAfter.lua ├── rmBossAfter.tmx ├── rmCredits.lua ├── rmCredits.tmx ├── rmIntro.lua ├── rmIntro.tmx ├── rmMainMenu.lua ├── rmMainMenu.tmx └── tilesheets │ ├── 3by3_1.png │ ├── darkCorners_sheet.png │ ├── sheet1.png │ └── sheet2.png ├── music ├── LICENSE.txt ├── boss.ogg ├── cavern.ogg ├── danger.ogg ├── ending.ogg ├── intro.ogg └── menu.ogg ├── sounds ├── LICENSE.txt ├── blip.wav ├── enemies │ ├── bossDie.wav │ ├── bossDie_old.wav │ ├── bossExplode.wav │ ├── bossLaser.wav │ ├── enemyHurt.wav │ ├── enemyHurt_2.wav │ ├── helloBoss.wav │ ├── spikes.wav │ ├── starfish-old1.wav │ └── starfish.wav ├── itemGet.wav ├── laser.wav ├── player │ ├── bombShot.wav │ ├── explosion.wav │ ├── explosion2.wav │ ├── laser1.wav │ ├── laser2.wav │ ├── laser3.wav │ ├── playerHurt.wav │ ├── spear.wav │ └── splash.wav └── ui │ ├── click.wav │ └── text.wav ├── source ├── LICENSE.txt ├── draw.lua ├── enemies │ ├── bat.lua │ ├── boss.lua │ ├── egg.lua │ ├── enemy.lua │ ├── enemyProj.lua │ ├── eye.lua │ ├── fish.lua │ ├── spike.lua │ └── spikeProj.lua ├── environment │ ├── blast.lua │ ├── breakable.lua │ ├── explosion.lua │ ├── fire.lua │ ├── particle.lua │ ├── trail.lua │ ├── vine.lua │ └── water.lua ├── global │ ├── collision_classes.lua │ ├── gameState.lua │ ├── saveGame.lua │ ├── saveUtil.lua │ ├── shake.lua │ ├── soundManager.lua │ └── utilities.lua ├── levels │ ├── background.lua │ ├── destroyAll.lua │ ├── drawWalls.lua │ ├── intro.lua │ └── map_loader.lua ├── libraries │ ├── Tserial.lua │ ├── anim8.lua │ ├── flux.lua │ ├── hump │ │ ├── camera.lua │ │ └── vector.lua │ ├── slam.lua │ ├── sti │ │ ├── graphics.lua │ │ ├── init.lua │ │ ├── plugins │ │ │ ├── box2d.lua │ │ │ └── bump.lua │ │ └── utils.lua │ └── windfield │ │ ├── init.lua │ │ └── mlib │ │ ├── Changes.txt │ │ ├── LICENSE.md │ │ ├── README.md │ │ └── mlib.lua ├── pickup.lua ├── player.lua ├── startup │ ├── loadFonts.lua │ ├── loadSounds.lua │ ├── loadSprites.lua │ ├── main_require.lua │ └── startup.lua ├── text │ ├── credits.lua │ ├── damage.lua │ ├── messages.lua │ ├── scrollText.lua │ ├── textBox.lua │ └── tutorial.lua ├── ui │ ├── blackScreen.lua │ ├── cam.lua │ ├── flash.lua │ └── mainMenu.lua ├── update.lua └── weapon.lua └── sprites ├── LICENSE.txt ├── enemies ├── bigBossEye.png ├── bossBody.png ├── egg.png ├── evilBubble.png ├── flyerBody.png ├── flyerEye.png ├── flyerWing1.png ├── flyerWing2.png ├── spikeBody.png ├── spikeProj.png └── starfish.png ├── environment ├── bg.png ├── breakParticle.png ├── crack.png ├── cracks │ ├── crack1.png │ ├── crack2.png │ └── crack3.png ├── rockySurface.png ├── rockySurface2.png ├── rockySurface_white.png ├── sinkingWall.png ├── vine.png ├── wall.png ├── wall2.png ├── wall_old.png └── waterSheet.png ├── fire ├── fire_1.png ├── fire_2.png ├── fire_3.png ├── fire_4.png └── fire_5.png ├── items ├── aquaPack.png ├── blaster.png ├── healthPickup.png ├── itemPickup.png ├── pickup_back.png ├── rocketLauncher.png └── spearGun.png ├── newPlayer ├── aquapack.png ├── arm.png ├── armBlaster.png ├── armRocket.png ├── armSpear.png ├── armSpearLoaded.png ├── backArm.png ├── backArm_old.png ├── body.png ├── helmet.png ├── jetpack.png ├── newPlayer.png └── spear.png ├── newPlayer2 ├── arm.png ├── armBlaster.png ├── armRocket.png ├── armSpear.png ├── armSpearLoaded.png ├── backArm.png ├── body.png └── helmet.png ├── player ├── aquapack.png ├── armSpear.png ├── arm_blaster.png ├── arm_blaster2.png ├── arm_empty.png ├── body.png ├── bomb.png ├── helmet.png ├── jetpack.png ├── rocketLauncher.png ├── rocketLauncherAlt.png └── spear.png └── ui ├── github.png └── sound.png /README.md: -------------------------------------------------------------------------------- 1 | # Cavern 2 | 3 | A 2D adventure game made with Lua and LÖVE 4 | 5 | ## About this project 6 | 7 | Cavern is an open-source game written in Lua utilizing the game framework [LÖVE](https://love2d.org/). This game was created to provide LÖVE developers with a fully completed project to refer to when creating their own games. 8 | 9 | ## Running the game 10 | 11 | Download or clone this repo, and then run the project with LÖVE, which can be downloaded [here](https://love2d.org/). The game will only work properly with versions 11.0 or later. The easiest way to run a project with LÖVE is to drag the project folder onto a LÖVE application shortcut. 12 | 13 | ## License 14 | 15 | Each folder for this project (maps, music, sounds, source, and sprites) contains its own LICENSE.txt file. All code (found in 16 | the "source" directory) is under the MIT license, meaning you can use the code for any purpose without restriction. The assets 17 | (maps, music, sounds, and sprites) are under the BY-NC-ND 4.0 license, which requires attribution, denies use for commercial 18 | projects, and prevents modification of those assets. 19 | 20 | Simply put, you can use the code however you want, but the assets (art, music, etc.) have restrictions in place. The 21 | project is set up like this to prevent people from downloading the full game and selling it as their own. At the same time, 22 | developers can still use the code in their own projects. 23 | -------------------------------------------------------------------------------- /fonts/russoone/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2012, Jovanny Lemonad (jovanny.ru), with Reserved Font Name "Russo" 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /fonts/russoone/RussoOne-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/fonts/russoone/RussoOne-Regular.ttf -------------------------------------------------------------------------------- /fonts/vt323/SIL Open Font License.txt: -------------------------------------------------------------------------------- 1 | Copyright 2011, The VT323 Project Authors (peter.hull@oikoi.com) 2 | 3 | 4 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 5 | This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL 6 | 7 | ----------------------------------------------------------- 8 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 9 | ----------------------------------------------------------- 10 | 11 | PREAMBLE 12 | The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. 13 | 14 | The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. 15 | 16 | DEFINITIONS 17 | "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. 18 | 19 | "Reserved Font Name" refers to any names specified as such after the copyright statement(s). 20 | 21 | "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). 22 | 23 | "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. 24 | 25 | "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. 26 | 27 | PERMISSION & CONDITIONS 28 | Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 29 | 30 | 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 31 | 32 | 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 33 | 34 | 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 35 | 36 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 37 | 38 | 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 39 | 40 | TERMINATION 41 | This license becomes null and void if any of the above conditions are not met. 42 | 43 | DISCLAIMER 44 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /fonts/vt323/VT323-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/fonts/vt323/VT323-Regular.ttf -------------------------------------------------------------------------------- /main.lua: -------------------------------------------------------------------------------- 1 | function love.load() 2 | 3 | -- This function configures game window and performs additional setup 4 | require("source/startup/startup") 5 | startup() 6 | 7 | -- Debug value, comment out for final game 8 | debug = 0 9 | debug2 = 0 10 | 11 | -- Temporary, used for drawing Explosion radius before particles 12 | expX = 0 13 | expY = 0 14 | 15 | -- Temporary, used to determine if physics will be drawn 16 | drawPhysics = false 17 | 18 | end 19 | 20 | function love.update(dt) 21 | 22 | if gameState.state == 1 then 23 | -- Handles most updating for the game 24 | local updateGameplay = require("source/update") 25 | updateGameplay(dt) 26 | end 27 | 28 | scroll:update(dt) 29 | textBox:update(dt) 30 | 31 | end 32 | 33 | function love.draw() 34 | 35 | cam:attach() 36 | 37 | -- Handles most drawing for the game 38 | local drawGameplay = require("source/draw") 39 | drawGameplay() 40 | 41 | -- Draw the colliders for all physics objects 42 | -- Commented out for final game, used for debugging 43 | if drawPhysics then 44 | love.graphics.setLineWidth(2) 45 | world:draw(150) 46 | gravWorld:draw(150) 47 | end 48 | 49 | cam:detach() 50 | 51 | menuDraw() 52 | 53 | textBox:draw() 54 | intro:drawInterrupt() 55 | 56 | saveUtil:drawMessage() 57 | 58 | blackScreen:draw() 59 | flash:draw() 60 | 61 | --[[ 62 | love.graphics.setColor(1, 1, 1, 1) 63 | love.graphics.print(debug, 0, 100) 64 | love.graphics.print(debug2, 0, 120) 65 | ]] 66 | 67 | end 68 | 69 | function love.mousepressed( x, y, button, istouch ) 70 | 71 | -- Interrupts the intro text 72 | intro:interrupt() 73 | 74 | -- Checks for button clicks on the main menu 75 | if button == 1 and gameState.room == "rmMainMenu" then 76 | buttons:click() 77 | end 78 | 79 | end 80 | 81 | function love.keypressed(key, scancode, isrepeat) 82 | 83 | -- Interrupts the intro text 84 | intro:interrupt() 85 | 86 | if key == "space" then 87 | player:swapWeapon() 88 | end 89 | 90 | if key == "backspace" then 91 | if drawPhysics then 92 | drawPhysics = false 93 | else 94 | drawPhysics = true 95 | end 96 | end 97 | 98 | end 99 | 100 | function love.wheelmoved(x, y) 101 | 102 | -- Change weapons 103 | if y < 0 then 104 | player:swapWeapon() 105 | elseif y > 0 then 106 | player:swapWeapon(true) 107 | end 108 | 109 | end 110 | -------------------------------------------------------------------------------- /maps/LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/maps/LICENSE.txt -------------------------------------------------------------------------------- /maps/_template1.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /maps/_template3.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /maps/_template4.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /maps/rm12.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm13.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm17.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm20.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm22.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm23.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm24.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm4.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm5.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm7.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rm9.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rmBoss.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rmBossAfter.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAA== 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 | -------------------------------------------------------------------------------- /maps/rmIntro.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /maps/rmMainMenu.tmx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /maps/tilesheets/3by3_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/maps/tilesheets/3by3_1.png -------------------------------------------------------------------------------- /maps/tilesheets/darkCorners_sheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/maps/tilesheets/darkCorners_sheet.png -------------------------------------------------------------------------------- /maps/tilesheets/sheet1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/maps/tilesheets/sheet1.png -------------------------------------------------------------------------------- /maps/tilesheets/sheet2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/maps/tilesheets/sheet2.png -------------------------------------------------------------------------------- /music/LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/LICENSE.txt -------------------------------------------------------------------------------- /music/boss.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/boss.ogg -------------------------------------------------------------------------------- /music/cavern.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/cavern.ogg -------------------------------------------------------------------------------- /music/danger.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/danger.ogg -------------------------------------------------------------------------------- /music/ending.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/ending.ogg -------------------------------------------------------------------------------- /music/intro.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/intro.ogg -------------------------------------------------------------------------------- /music/menu.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/music/menu.ogg -------------------------------------------------------------------------------- /sounds/LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/LICENSE.txt -------------------------------------------------------------------------------- /sounds/blip.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/blip.wav -------------------------------------------------------------------------------- /sounds/enemies/bossDie.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/bossDie.wav -------------------------------------------------------------------------------- /sounds/enemies/bossDie_old.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/bossDie_old.wav -------------------------------------------------------------------------------- /sounds/enemies/bossExplode.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/bossExplode.wav -------------------------------------------------------------------------------- /sounds/enemies/bossLaser.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/bossLaser.wav -------------------------------------------------------------------------------- /sounds/enemies/enemyHurt.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/enemyHurt.wav -------------------------------------------------------------------------------- /sounds/enemies/enemyHurt_2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/enemyHurt_2.wav -------------------------------------------------------------------------------- /sounds/enemies/helloBoss.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/helloBoss.wav -------------------------------------------------------------------------------- /sounds/enemies/spikes.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/spikes.wav -------------------------------------------------------------------------------- /sounds/enemies/starfish-old1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/starfish-old1.wav -------------------------------------------------------------------------------- /sounds/enemies/starfish.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/enemies/starfish.wav -------------------------------------------------------------------------------- /sounds/itemGet.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/itemGet.wav -------------------------------------------------------------------------------- /sounds/laser.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/laser.wav -------------------------------------------------------------------------------- /sounds/player/bombShot.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/bombShot.wav -------------------------------------------------------------------------------- /sounds/player/explosion.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/explosion.wav -------------------------------------------------------------------------------- /sounds/player/explosion2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/explosion2.wav -------------------------------------------------------------------------------- /sounds/player/laser1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/laser1.wav -------------------------------------------------------------------------------- /sounds/player/laser2.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/laser2.wav -------------------------------------------------------------------------------- /sounds/player/laser3.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/laser3.wav -------------------------------------------------------------------------------- /sounds/player/playerHurt.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/playerHurt.wav -------------------------------------------------------------------------------- /sounds/player/spear.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/spear.wav -------------------------------------------------------------------------------- /sounds/player/splash.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/player/splash.wav -------------------------------------------------------------------------------- /sounds/ui/click.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/ui/click.wav -------------------------------------------------------------------------------- /sounds/ui/text.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sounds/ui/text.wav -------------------------------------------------------------------------------- /source/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2018 Kyle Schaub 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /source/draw.lua: -------------------------------------------------------------------------------- 1 | local function drawGameplay() 2 | love.graphics.setLineWidth(2) 3 | 4 | -- Draw the background (drawn before anything else) 5 | background:draw() 6 | 7 | -- Draw the credits (only in rmCredits) 8 | credits:draw() 9 | 10 | -- draw all weapons 11 | weapons:draw() 12 | 13 | -- Draw the player 14 | player:draw() 15 | 16 | -- Draw spike projectiles 17 | spikes:draw() 18 | 19 | -- Draw enemy projectiles 20 | enemyProjectiles:draw() 21 | 22 | -- Draw eggs from the final boss 23 | eggs:draw() 24 | 25 | -- draw all enemies (except final boss) 26 | enemies:draw(false) 27 | 28 | -- draw final boss (boss must appear over other enemies) 29 | enemies:draw(true) 30 | 31 | -- Draw trails 32 | trails:draw() 33 | 34 | -- Draw vines 35 | vines:draw() 36 | 37 | -- Draw water and ripples after everything else to give underwater objects 38 | -- a blue tint (since the drawing is translucent) 39 | ripples:draw() 40 | 41 | -- Draws all walls (including breakable ones) 42 | local drawWalls = require("source/levels/drawWalls") 43 | drawWalls() 44 | 45 | love.graphics.setColor(1, 1, 1, 1) 46 | mapdata.map:drawLayer(mapdata.map.layers["Main_Tiles"]) 47 | 48 | particles:draw() 49 | fires:draw() 50 | blasts:draw() 51 | damages:draw() 52 | pickups:draw() 53 | 54 | -- Draw the player's healthbar 55 | player:drawHealth() 56 | 57 | -- Draw the tutorial text (when applicable) 58 | tutorial:draw() 59 | 60 | if gameState.room == "rmBoss" then 61 | 62 | -- find the boss object 63 | for _,e in ipairs(enemies) do 64 | if e.type == "boss" then 65 | e:bossBar() 66 | end 67 | end 68 | 69 | end 70 | 71 | end 72 | 73 | return drawGameplay 74 | -------------------------------------------------------------------------------- /source/enemies/bat.lua: -------------------------------------------------------------------------------- 1 | local function batInit(enemy, x, y, arg) 2 | 3 | -- Initialize physics 4 | enemy.physics = world:newBSGRectangleCollider(x, y, 92, 92, 25) 5 | enemy.physics:setCollisionClass('Enemy') 6 | enemy.physics:setLinearDamping(2) 7 | enemy.physics:setFixedRotation(true) 8 | -- We need this to access the table itself given the physics 9 | enemy.physics.parent = enemy 10 | 11 | -- Properties 12 | enemy.health = 12 13 | enemy.hitPower = 5 14 | enemy.moveForce = 17000 15 | enemy.maxSpeed = 800 16 | enemy.barY = 62 17 | 18 | -- Sprite info 19 | enemy.sprite = sprites.enemies.flyerBody 20 | enemy.wingSprite = sprites.enemies.flyerWing1 21 | enemy.spriteTimerBase = 0.001 22 | enemy.spriteTimer = enemy.spriteTimerBase 23 | 24 | enemy.eye = spawnEye(x, y, 0, 1, sprites.enemies.flyerEye) 25 | 26 | -- Final boss can spawn these, and they shoot down 27 | -- if arg is true 28 | if arg then 29 | enemy.physics:applyLinearImpulse(0, 20000) 30 | end 31 | 32 | function enemy:update(dt) 33 | 34 | if self:inSight() then 35 | local speed = speedFromVelocity( self.physics:getLinearVelocity() ) 36 | if speed < self.maxSpeed then 37 | local ex, ey = self.physics:getPosition() 38 | local dir = toPlayerVector(ex, ey) 39 | dir = dir * self.moveForce 40 | self.physics:applyForce(dir:unpack()) 41 | end 42 | end 43 | 44 | -- Update the animation; alternate between the two frames 45 | self.spriteTimer = updateTimer(self.spriteTimer, dt) 46 | if self.spriteTimer == 0 then 47 | if self.wingSprite == sprites.enemies.flyerWing1 then 48 | self.wingSprite = sprites.enemies.flyerWing2 49 | else 50 | self.wingSprite = sprites.enemies.flyerWing1 51 | end 52 | self.spriteTimer = self.spriteTimerBase 53 | end 54 | 55 | -- Update the eye of the flyer 56 | -- Not to be confused with the Eye of the Tiger 57 | local ex, ey = self.physics:getPosition() 58 | local dir = toPlayerVector(ex, ey) 59 | local offX, offY = (dir * 16):unpack() 60 | self.eye:update(dt, ex + offX, ey + offY, toPlayerRotate(ex, ey)) 61 | end 62 | 63 | function enemy:draw() 64 | local sprW = self.wingSprite:getWidth() 65 | local sprH = self.wingSprite:getHeight() 66 | local sprX, sprY = self.physics.body:getPosition() 67 | 68 | local wingOffset = -24 69 | if self.wingSprite == sprites.enemies.flyerWing2 then 70 | wingOffset = wingOffset + 5 71 | end 72 | 73 | -- Draw the wings first 74 | love.graphics.setColor(1, 1, 1, 0.314) 75 | love.graphics.draw(self.wingSprite, sprX, sprY + wingOffset, nil, 1, 1, sprW/2, sprH/2) 76 | 77 | -- Draw the body of the flyer (rotates towards player) 78 | sprW = self.sprite:getWidth() 79 | sprH = self.sprite:getHeight() 80 | love.graphics.setColor(1, 1, 1, 1) 81 | love.graphics.draw(self.sprite, sprX, sprY, toPlayerRotate(sprX, sprY), 1, 1, sprW/2, sprH/2) 82 | end 83 | 84 | return enemy 85 | 86 | end 87 | 88 | return batInit 89 | -------------------------------------------------------------------------------- /source/enemies/egg.lua: -------------------------------------------------------------------------------- 1 | -- Eggs that the final boss drops 2 | eggs = {} 3 | 4 | function eggs:spawn(x) 5 | 6 | local egg = {} 7 | egg.width = 100 8 | egg.height = 100 9 | 10 | egg.power = 7 -- damage taken by player when colliding 11 | 12 | egg.physics = gravWorld:newBSGRectangleCollider(x, 200, egg.width, egg.height, 10) 13 | egg.physics:setFixedRotation(true) 14 | egg.physics:setCollisionClass('Particle') 15 | 16 | table.insert(eggs, egg) 17 | 18 | end 19 | 20 | function eggs:update(dt) 21 | 22 | for i=#eggs,1,-1 do 23 | 24 | local ex, ey = eggs[i].physics:getPosition() 25 | local width = eggs[i].width 26 | local dmg = eggs[i].power 27 | 28 | -- Check collision with player 29 | -- Note: since eggs are in a different physics world 30 | -- than the player, this is handled differently than 31 | -- most other collisions in the game 32 | 33 | if distToPlayer(ex, ey) < width then 34 | player:hurt(dmg) 35 | end 36 | 37 | -- Crash into the ground 38 | 39 | if ey > 1280 then 40 | 41 | -- Egg has hit the ground, hatch 42 | spawnEnemy(ex-(width/2), 1280, "bat") 43 | 44 | eggs[i].physics:destroy() 45 | table.remove(eggs, i) 46 | 47 | end 48 | end 49 | 50 | end 51 | 52 | function eggs:draw() 53 | 54 | for _,e in ipairs(self) do 55 | local ex, ey = e.physics:getPosition() 56 | local spr = sprites.enemies.egg 57 | love.graphics.draw(spr, ex, ey, nil, 1, 1, spr:getWidth()/2, spr:getHeight()/2) 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /source/enemies/enemyProj.lua: -------------------------------------------------------------------------------- 1 | -- projectiles launched by enemies (does not include spikes) 2 | enemyProjectiles = {} 3 | 4 | function spawnEnemyProj(x, y, dir, type) 5 | 6 | local enProj = {} 7 | enProj.dir = dir 8 | enProj.dead = false 9 | enProj.power = 6 10 | enProj.id = math.random() 11 | enProj.rad = 10 12 | enProj.sprite = nil 13 | enProj.impulse = 2000 14 | 15 | if type == "fish" then 16 | enProj.rad = 19 17 | enProj.power = 6 18 | enProj.sprite = sprites.enemies.evilBubble 19 | enProj.impulse = 2500 20 | soundManager:play("starfish") 21 | end 22 | 23 | if type == "bossLaser" then 24 | enProj.rad = 10 25 | enProj.power = 7 26 | enProj.sprite = nil 27 | enProj.impulse = 3000 28 | -- This projectile has a trail, which is spawned here 29 | spawnTrail(enProj.id, 12, 16, {1, 0, 0, 0.706}) 30 | 31 | soundManager:play("bossLaser") 32 | 33 | -- Offset the starting location of the laser 34 | -- so it appears in the eye's pupil 35 | local offsetVec = enProj.dir * 100 36 | local wx, wy = offsetVec:unpack() 37 | x = x + wx 38 | y = y + wy 39 | end 40 | 41 | enProj.physics = world:newCircleCollider(x, y, enProj.rad) 42 | enProj.physics:setCollisionClass('E_Weapon') 43 | enProj.dir = enProj.dir:normalized() 44 | 45 | enProj.physics:applyLinearImpulse((enProj.dir * enProj.impulse):unpack()) 46 | 47 | function enProj:update(dt) 48 | 49 | -- Hurt player on contact 50 | if self.physics:enter('Player') then 51 | player:hurt(self.power) 52 | self.dead = true 53 | end 54 | 55 | if self.physics:enter('Wall') or self.physics:enter('Breakable') 56 | or self.physics:enter('Transition') then 57 | self.dead = true 58 | end 59 | 60 | end 61 | 62 | table.insert(enemyProjectiles, enProj) 63 | 64 | end 65 | 66 | function enemyProjectiles:update(dt) 67 | 68 | for i,s in ipairs(self) do 69 | s:update(dt) 70 | end 71 | 72 | -- Iterate through all enemyProjectiles in reverse to remove dead ones 73 | -- Update trails before removal 74 | for i=#enemyProjectiles,1,-1 do 75 | 76 | local proj = enemyProjectiles[i] 77 | 78 | -- Updates the projectile's trail (if it has one) 79 | if proj.dead ~= true then 80 | for _,t in ipairs(trails) do 81 | if t.id == proj.id then 82 | t:update(dt, proj) 83 | end 84 | end 85 | end 86 | 87 | if proj.dead then 88 | proj.physics:destroy() 89 | table.remove(enemyProjectiles, i) 90 | end 91 | 92 | end 93 | 94 | end 95 | 96 | function enemyProjectiles:draw() 97 | 98 | love.graphics.setColor(1, 1, 1, 1) 99 | 100 | for i,p in ipairs(self) do 101 | 102 | if p.sprite ~= nil then 103 | local sprX, sprY = p.physics:getPosition() 104 | local sprW = p.sprite:getWidth() 105 | local sprH = p.sprite:getHeight() 106 | love.graphics.draw(p.sprite, sprX, sprY, nil, 1, 1, sprW/2, sprH/2) 107 | end 108 | 109 | end 110 | 111 | end 112 | -------------------------------------------------------------------------------- /source/enemies/eye.lua: -------------------------------------------------------------------------------- 1 | eyes = {} 2 | 3 | function spawnEye(x, y, rot, scale, spr, args) 4 | 5 | local eye = {} 6 | eye.x = x 7 | eye.y = y 8 | eye.rot = rot 9 | eye.scale = scale 10 | eye.spr = spr 11 | eye.id = id 12 | eye.args = args 13 | 14 | eye.dead = false 15 | 16 | function eye:update(dt, x, y, rot) 17 | 18 | eye.x = x 19 | eye.y = y 20 | 21 | -- Only look at the player if the player is alive 22 | if player.health > 0 then 23 | eye.rot = rot 24 | end 25 | 26 | end 27 | 28 | function eye:draw() 29 | 30 | love.graphics.setColor(1, 1, 1, 1) 31 | love.graphics.draw(self.spr, self.x, self.y, self.rot, self.scale, self.scale, self.spr:getWidth()/2, self.spr:getHeight()/2) 32 | 33 | end 34 | 35 | return eye 36 | --table.insert(eyes, eye) 37 | 38 | end 39 | -------------------------------------------------------------------------------- /source/enemies/fish.lua: -------------------------------------------------------------------------------- 1 | local function fishInit(enemy, x, y, arg) 2 | 3 | -- Initialize physics 4 | enemy.physics = world:newBSGRectangleCollider(x, y, 106, 106, 26) 5 | enemy.physics:setCollisionClass('Enemy') 6 | enemy.physics:setLinearDamping(2) 7 | enemy.physics:setFixedRotation(true) 8 | -- We need this to access the table itself given the physics 9 | enemy.physics.parent = enemy 10 | 11 | -- Properties 12 | enemy.health = 18 13 | enemy.hitPower = 6 14 | enemy.moveForce = 5000 15 | enemy.maxSpeed = 500 16 | enemy.barY = 80 17 | 18 | enemy.sprite = sprites.enemies.starfish 19 | enemy.rotate = 0 20 | enemy.slowRotSpeed = math.pi/160 21 | enemy.fastRotSpeed = math.pi/10 22 | enemy.rotSpeed = enemy.slowRotSpeed 23 | enemy.rotTween = nil 24 | enemy.timeBetweenShots = 0.8 25 | 26 | enemy.stateTimer = 0 27 | enemy.state = 0 28 | 29 | enemy.eye = spawnEye(x, y, 0, 1, sprites.enemies.flyerEye) 30 | 31 | function enemy:update(dt) 32 | 33 | self.stateTimer = updateTimer(self.stateTimer, dt) 34 | 35 | -- State 0: idle 36 | if self.state == 0 and self:inSight() then 37 | self.state = 1 38 | self.stateTimer = self.timeBetweenShots 39 | self.timeBetweenShots = 1.5 40 | end 41 | 42 | -- State 1: chasing player, start shooting process after timer is up 43 | if self.state == 1 then 44 | 45 | if self.stateTimer <= 0 then 46 | self.state = 1.5 47 | local tweenTo = self.fastRotSpeed 48 | self.rotTween = flux.to(self, 0.5, {rotSpeed = tweenTo}):ease("sineinout") 49 | end 50 | 51 | local speed = speedFromVelocity( self.physics:getLinearVelocity() ) 52 | local ex, ey = self.physics:getPosition() 53 | if speed < self.maxSpeed then 54 | local dir = toPlayerVector(ex, ey) 55 | dir = dir * self.moveForce 56 | self.physics:applyForce(dir:unpack()) 57 | end 58 | 59 | end 60 | 61 | -- State 1.5: After first tween is done, shoot and slow down rotSpeed 62 | local ex, ey = self.physics:getPosition() 63 | if self.state == 1.5 and self.rotSpeed == self.fastRotSpeed then 64 | self.state = 2 65 | local tweenTo = self.slowRotSpeed 66 | self.rotTween = flux.to(self, 0.5, {rotSpeed = tweenTo}):ease("cubicout") 67 | 68 | -- Shoot bullet 69 | spawnEnemyProj(ex, ey, toPlayerVector(ex, ey), "fish") 70 | end 71 | 72 | -- State 2: After shooting, slowing down 73 | if self.state == 2 and self.rotSpeed == self.slowRotSpeed then 74 | self.state = 0 75 | end 76 | 77 | self.rotate = self.rotate + self.rotSpeed 78 | 79 | self.eye:update(dt, ex, ey, toPlayerRotate(ex, ey)) 80 | 81 | end 82 | 83 | function enemy:draw() 84 | local sprX, sprY = self.physics.body:getPosition() 85 | 86 | -- Draw the body 87 | sprW = self.sprite:getWidth() 88 | sprH = self.sprite:getHeight() 89 | love.graphics.setColor(1, 1, 1, 1) 90 | love.graphics.draw(self.sprite, sprX, sprY, self.rotate, 1, 1, sprW/2, sprH/2+6) 91 | end 92 | 93 | return enemy 94 | 95 | end 96 | 97 | return fishInit 98 | -------------------------------------------------------------------------------- /source/enemies/spikeProj.lua: -------------------------------------------------------------------------------- 1 | -- spikes launched by "spike" enemies 2 | spikes = {} 3 | 4 | function spawnSpike(x, y, num, id, groundDir) 5 | 6 | local spike = {} 7 | spike.dir = vector.new(-1, 0) 8 | spike.dead = false 9 | spike.power = 6 10 | spike.id = id 11 | spike.sprite = sprites.enemies.spikeProj 12 | 13 | -- Originally planned to have spikes pause before launching 14 | -- Since this is no longer needed, just keep this timer at -1 15 | -- so they immediately launch 16 | spike.launchTimer = -1 17 | 18 | -- Assign dir (vector) 19 | if num == 1 then -- left 20 | spike.dir = vector.new(-1, 0) 21 | elseif num == 2 then -- up-left 22 | spike.dir = vector.new(-1, -1) 23 | elseif num == 3 then -- up 24 | spike.dir = vector.new(0, -1) 25 | elseif num == 4 then -- up-right 26 | spike.dir = vector.new(1, -1) 27 | elseif num == 5 then -- right 28 | spike.dir = vector.new(1, 0) 29 | end 30 | 31 | -- Rotate dir based on host's groundDir value 32 | if groundDir == "left" then 33 | spike.dir:rotateInplace(math.pi / 2) -- rotate by 90 degrees 34 | elseif groundDir == "up" then 35 | spike.dir:rotateInplace(math.pi) -- rotate by 180 degrees 36 | elseif groundDir == "right" then 37 | spike.dir:rotateInplace(math.pi / -2) -- rotate by -90 degrees 38 | end 39 | 40 | spike.dir:normalizeInplace() 41 | spike.dir = spike.dir * 64 -- radius of spike enemies 42 | 43 | local tempX, tempY = spike.dir:unpack() 44 | x = x + tempX 45 | y = y + tempY 46 | 47 | spike.physics = world:newCircleCollider(x, y, 16) 48 | spike.physics:setCollisionClass('E_Weapon') 49 | spike.dir = spike.dir:normalized() 50 | 51 | function spike:update(dt) 52 | 53 | --self.launchTimer = updateTimer(self.launchTimer, dt) 54 | if self.launchTimer < 0 then 55 | self.physics:applyLinearImpulse((self.dir * 1500):unpack()) 56 | self.launchTimer = 0 57 | 58 | -- self.id is used to destroy spikes that haven't launched yet 59 | -- since this spike has launched, make the id invalid 60 | self.id = -1 61 | end 62 | 63 | -- Hurt player on contact 64 | if self.physics:enter('Player') then 65 | player:hurt(self.power) 66 | self.dead = true 67 | end 68 | 69 | if self.physics:enter('Wall') or self.physics:enter('Breakable') 70 | or self.physics:enter('Transition') then 71 | self.dead = true 72 | end 73 | 74 | end 75 | 76 | table.insert(spikes, spike) 77 | 78 | end 79 | 80 | function spikes:update(dt) 81 | 82 | for i,s in ipairs(self) do 83 | s:update(dt) 84 | end 85 | 86 | -- Iterate through all spikes in reverse to remove dead ones 87 | for i=#spikes,1,-1 do 88 | if spikes[i].dead then 89 | spikes[i].physics:destroy() 90 | table.remove(spikes, i) 91 | end 92 | end 93 | 94 | end 95 | 96 | function spikes:draw() 97 | 98 | love.graphics.setColor(1, 1, 1, 1) 99 | 100 | for i,s in ipairs(self) do 101 | local sprX, sprY = s.physics:getPosition() 102 | local sprW = s.sprite:getWidth() 103 | local sprH = s.sprite:getHeight() 104 | 105 | local vx, vy = s.dir:unpack() 106 | local rotate = math.atan2(vy, vx) 107 | 108 | love.graphics.draw(s.sprite, sprX, sprY, rotate, 1, 1, sprW/2, sprH/2) 109 | end 110 | 111 | end 112 | -------------------------------------------------------------------------------- /source/environment/blast.lua: -------------------------------------------------------------------------------- 1 | blasts = {} 2 | 3 | function spawnBlast(x, y, size, color, time, rev) 4 | blast = {} 5 | blast.x = x 6 | blast.y = y 7 | blast.color = color 8 | blast.radius = 1 9 | blast.max_radius = size 10 | blast.time = time 11 | blast.timer = time + 1 12 | blast.rev = rev or false 13 | blast.dead = false 14 | blast.maxAlpha = 0.706 15 | blast.alpha = blast.maxAlpha 16 | blast.state = 0 17 | 18 | -- If the blast should happen in reverse 19 | if rev then 20 | blast.radius = size 21 | blast.max_radius = 1 22 | blast.maxAlpha = 0.2 23 | blast.alpha = 0 24 | blast.revTimer = size/2 25 | end 26 | 27 | function blast:update(dt, i) 28 | self.timer = updateTimer(self.timer, dt) 29 | 30 | if self.timer == 0 then 31 | self.dead = true 32 | end 33 | 34 | local max = self.max_radius 35 | local maxAlph = self.maxAlpha 36 | 37 | if self.state == 0 then 38 | 39 | flux.to(self, self.time, { radius = max }) 40 | 41 | if self.rev == false then 42 | -- Normal blast, fades out 43 | flux.to(self, self.time, { alpha = 0 }) 44 | else 45 | -- Reverse blast, fade in, then out 46 | flux.to(self, self.time/4, { alpha = maxAlph }) 47 | end 48 | 49 | self.state = 1 50 | end 51 | 52 | if self.rev and self.alpha == maxAlph then 53 | flux.to(self, self.time/2, { alpha = 0 }) 54 | end 55 | 56 | end 57 | 58 | table.insert(blasts, blast) 59 | 60 | end 61 | 62 | function blasts:update(dt) 63 | for i,w in ipairs(blasts) do 64 | w:update(dt, i) 65 | end 66 | 67 | local i = table.getn(blasts) 68 | while i > 0 do 69 | if blasts[i].dead == true then 70 | table.remove(blasts, i) 71 | end 72 | i = i - 1 73 | end 74 | end 75 | 76 | function blasts:draw() 77 | for _,e in ipairs(blasts) do 78 | local r, g, b = unpack(e.color) 79 | love.graphics.setColor(r, g, b, e.alpha) 80 | love.graphics.circle("fill", e.x, e.y, e.radius, math.ceil(e.radius/2)) 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /source/environment/breakable.lua: -------------------------------------------------------------------------------- 1 | -- Blocks that can be blown up by the rocket luancher 2 | breakables = {} 3 | 4 | function spawnBreakable(x, y) 5 | 6 | local newBreak = {} 7 | newBreak.breakable = true 8 | newBreak.dead = false 9 | 10 | newBreak.x = x 11 | newBreak.y = y 12 | newBreak.width = 256 13 | newBreak.height = 256 14 | 15 | newBreak.physics = world:newRectangleCollider(x, y, newBreak.width, newBreak.height) 16 | newBreak.physics.parent = newBreak 17 | newBreak.physics:setCollisionClass('Wall') 18 | newBreak.physics:setType('static') 19 | 20 | -- These variables are needed for drawing the rocky surface 21 | newBreak.up = true 22 | newBreak.down = true 23 | newBreak.left = true 24 | newBreak.right = true 25 | 26 | math.randomseed(table.getn(breakables)) 27 | newBreak.crackRot = math.random() * 3.14 28 | 29 | table.insert(breakables, newBreak) 30 | 31 | end 32 | 33 | -- spawns all particles for when a wall is blown up 34 | function breakParticles(x, y) 35 | 36 | spawnParticle(x, y, "break", vector(-2500, -4500)) 37 | spawnParticle(x, y, "break", vector(2500, -4500)) 38 | spawnParticle(x, y, "break", vector(-4500, -2500)) 39 | spawnParticle(x, y, "break", vector(4500, -2500)) 40 | 41 | end 42 | 43 | function breakables:update(dt) 44 | 45 | -- Iterate through all breakables in reverse to remove dead ones 46 | for i=#breakables,1,-1 do 47 | if breakables[i].dead then 48 | 49 | local bx, by = breakables[i].physics:getPosition() 50 | breakParticles(bx, by) 51 | 52 | breakables[i].physics:destroy() 53 | table.remove(breakables, i) 54 | 55 | end 56 | end 57 | 58 | end 59 | -------------------------------------------------------------------------------- /source/environment/explosion.lua: -------------------------------------------------------------------------------- 1 | function explode(x, y) 2 | 3 | soundManager:play("explosion") 4 | 5 | local radius = 315 6 | 7 | -- Spawn the particles for the explosion 8 | local scl = 12 9 | local spd = 240 10 | local life = 0.8 11 | for inc=1, 7 do 12 | spd = spd * 0.8 13 | life = life * 1.1 14 | if inc == 7 then 15 | spd = 32 -- This is so the middle particles stay more centralized 16 | end 17 | fires:spawnFire(x, y, life, vector(1, 1), scl, nil, spd) 18 | fires:spawnFire(x, y, life, vector(1, 0), scl, nil, spd) 19 | fires:spawnFire(x, y, life, vector(1, -1), scl, nil, spd) 20 | fires:spawnFire(x, y, life, vector(0, 1), scl, nil, spd) 21 | fires:spawnFire(x, y, life, vector(-1, -1), scl, nil, spd) 22 | fires:spawnFire(x, y, life, vector(-1, 0), scl, nil, spd) 23 | fires:spawnFire(x, y, life, vector(-1, 1), scl, nil, spd) 24 | fires:spawnFire(x, y, life, vector(0, -1), scl, nil, spd) 25 | end 26 | 27 | -- finds all enemies in the blast radius 28 | local ens = world:queryCircleArea(x, y, radius, {'Enemy'}) 29 | for i,e in ipairs(ens) do 30 | if e.parent.type ~= "fish" then 31 | e.parent:damage(25) 32 | end 33 | end 34 | 35 | -- finds all breakable walls in the blast radius 36 | local br = world:queryCircleArea(x, y, radius, {'Wall'}) 37 | for i,b in ipairs(br) do 38 | if b.parent ~= nil and b.parent.breakable then 39 | b.parent.dead = true 40 | end 41 | end 42 | 43 | shake:start(0.01, 12, 0.005, 0.25) 44 | 45 | expX = x 46 | expY = y 47 | 48 | end 49 | -------------------------------------------------------------------------------- /source/environment/fire.lua: -------------------------------------------------------------------------------- 1 | -- This "fires" table contains every particle of fire currently in the game 2 | -- The illusion of fire is made by spawning many small blob-shaped sprites 3 | -- that move, change color, and fade away 4 | fires = {} 5 | 6 | function fires:spawnFire(x, y, life, dir, scale, off, speed, smoke, start_alpha) 7 | 8 | -- p is a single fire particle 9 | local p = {} 10 | p.width = 32 11 | p.height = 32 12 | 13 | p.x = x - p.width/2 14 | p.y = y - p.height/2 15 | 16 | p.speed = speed or 60 17 | p.smoke = smoke or false 18 | p.spr_rot = math.random(-3, 2) + math.random() -- 0 to pi radians 19 | 20 | -- sets a random blob sprite for the fire particle 21 | local spriteint = math.random(1, 5) 22 | p.sprite = nil 23 | if spriteint == 1 then 24 | p.sprite = sprites.fire.f1 25 | elseif spriteint == 2 then 26 | p.sprite = sprites.fire.f2 27 | elseif spriteint == 3 then 28 | p.sprite = sprites.fire.f3 29 | elseif spriteint == 4 then 30 | p.sprite = sprites.fire.f4 31 | elseif spriteint == 5 then 32 | p.sprite = sprites.fire.f5 33 | end 34 | 35 | p.dead = false -- if the particle should be destroyed 36 | p.max_life = life -- time the particle is visible 37 | p.life = p.max_life -- current timer counting down 38 | p.scale = scale -- size of the particle 39 | p.front = front or false -- used for draw order (drawn sooner or later) 40 | p.direction = dir or vector(0, -1) -- direction the particle will move 41 | 42 | if dir ~= nil then 43 | -- set the direction of the particle 44 | p.direction = dir:normalized() 45 | 46 | -- This section uses the offset parameter to move the starting position 47 | -- of the particle slightly, based on the direction the particle moves. 48 | -- For example, if the direction was straight up, the particle would be 49 | -- offset randomly to the left or right. 50 | local o = off or 15 51 | local offset = math.random(-1 * o, o) 52 | local randrot = math.random(-3, 2) + math.random() 53 | local perp_vec = p.direction:rotated(randrot) * offset 54 | local ox, oy = perp_vec:unpack() 55 | p.x, p.y = p.x + ox, p.y + oy 56 | end 57 | 58 | -- Gives the particle a bit of random movement by slightly changing its 59 | -- direction. Multi is used to ensure there is an equal amount of clockwise 60 | -- rotation to counterclockwise. 61 | local multi = -1 62 | if table.getn(fires) % 2 == 0 then 63 | multi = 1 64 | end 65 | p.direction:rotateInplace(multi * math.random()/4) 66 | p.direction = p.direction * 3 67 | 68 | p.start_alpha = start_alpha or 0.188 69 | p.alpha = start_alpha or 0.188 70 | --p.scale = 2 71 | p.color = {1, 1, 1} 72 | if p.smoke == true then 73 | p.color = {0.471, 0.471, 0.471} 74 | end 75 | 76 | function p:update(dt) 77 | self.life = updateTimer(self.life, dt) 78 | --if self.life > (self.max_life/6)*5 then 79 | --p.color = {1, 1, 1} 80 | if self.life > (self.max_life/6)*5 then 81 | self.color = {1, 0.988, 0.757} 82 | elseif self.life > (self.max_life/6)*4 then 83 | self.color = {1, 0.788, 0.302} 84 | elseif self.life > (self.max_life/6)*2 then 85 | self.color = {1, 0.635, 0.176} 86 | elseif self.life > (self.max_life/6) then 87 | self.color = {1, 0.569, 0.098} 88 | else 89 | self.color = {1, 1, 1} 90 | end 91 | 92 | -- tints the fire to be smoke 93 | if self.smoke == true then 94 | self.color = {0.471, 0.471, 0.471} 95 | end 96 | 97 | if p.start_alpha == 0.188 then 98 | if self.life > 0.75 then 99 | self.alpha = p.start_alpha 100 | else 101 | self.alpha = self.life/4 102 | end 103 | else 104 | if self.life > 0.75 then 105 | self.alpha = p.start_alpha 106 | else 107 | self.alpha = self.life/9.75 108 | end 109 | end 110 | 111 | local dx, dy = self.direction:unpack() 112 | self.x = self.x + (dx * self.speed * dt) 113 | self.y = self.y + (dy * self.speed * dt) 114 | if self.alpha < 0.001 then 115 | self.dead = true 116 | end 117 | end 118 | 119 | table.insert(fires, p) 120 | end 121 | 122 | function fires:update(dt) do 123 | 124 | for i,f in ipairs(fires) do 125 | f:update(dt) 126 | end 127 | 128 | -- Iterate through all fires in reverse to remove dead ones 129 | for i=#fires,1,-1 do 130 | if fires[i].dead then 131 | table.remove(fires, i) 132 | end 133 | end 134 | 135 | end 136 | 137 | function fires:draw() 138 | 139 | for i,f in ipairs(fires) do 140 | love.graphics.setColor(f.color[1], f.color[2], f.color[3], f.alpha) 141 | love.graphics.draw(f.sprite, f.x+f.width/2, f.y+f.height/2, f.spr_rot, f.scale or 1, f.scale or 1, f.sprite:getWidth()/2, f.sprite:getHeight()/2) 142 | end 143 | 144 | end 145 | end 146 | -------------------------------------------------------------------------------- /source/environment/trail.lua: -------------------------------------------------------------------------------- 1 | trails = {} 2 | 3 | function spawnTrail(id, max, width, color) 4 | trail = {} 5 | trail.id = id -- used to tell which object to follow 6 | trail.max = max -- length of the trail 7 | trail.width = width -- width of the trail 8 | trail.color = color -- color of the trail 9 | 10 | trail.points = {} 11 | trail.dead = false 12 | trail.updated = false 13 | 14 | trail.arc = {} 15 | trail.poly = {} 16 | trail.triangles = {} 17 | 18 | function trail:update(dt, wep) 19 | 20 | self.updated = true 21 | self.arc = {} 22 | 23 | local t = {} 24 | t.x = wep.physics.body:getX() 25 | t.y = wep.physics.body:getY() 26 | t.dir = nil 27 | 28 | if wep.moving == false then 29 | t.dir = wep.direct:normalized() 30 | else 31 | local vx, vy = wep.physics.body:getLinearVelocity() 32 | t.dir = vector(vx, vy):normalized() 33 | end 34 | 35 | table.insert(self.points, t) 36 | end 37 | 38 | table.insert(trails, trail) 39 | 40 | end 41 | 42 | function trails:update(dt) 43 | 44 | for _,t in ipairs(trails) do 45 | t.updated = false 46 | end 47 | 48 | local i = table.getn(trails) 49 | while i > 0 do 50 | if trails[i].dead == true then 51 | table.remove(trails, i) 52 | end 53 | i = i - 1 54 | end 55 | 56 | end 57 | 58 | -- Call this AFTER weapons get updated 59 | -- This function handles what happens to the trail after the weapon is destroyed 60 | function trails:fadeOut(dt) 61 | for _,t in ipairs(trails) do 62 | if t.updated == false then 63 | t.max = t.max - 1 64 | --create_poly(t) 65 | if t.max < 2 then 66 | t.dead = true 67 | end 68 | end 69 | end 70 | end 71 | 72 | function trails:draw() 73 | for _,t in ipairs(trails) do 74 | if table.getn(t.points) > 1 then 75 | local firstpt = table.getn(t.points) - t.max 76 | if firstpt < 1 then 77 | firstpt = 1 78 | end 79 | love.graphics.setColor(unpack(t.color)) 80 | love.graphics.setLineWidth(t.width) 81 | love.graphics.line(t.points[firstpt].x, t.points[firstpt].y, t.points[table.getn(t.points)].x, t.points[table.getn(t.points)].y) 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /source/environment/vine.lua: -------------------------------------------------------------------------------- 1 | -- These are vines that the player shoots, and they sink into the ground 2 | vines = {} 3 | 4 | function spawnVine(x, y) 5 | 6 | local vine = world:newRectangleCollider(x + 32, y + 16, 64, 640) 7 | vine:setCollisionClass('Wall') 8 | vine:setType('static') 9 | 10 | vine.trueX = vine:getX() 11 | vine.trueY = vine:getY() 12 | 13 | vine.sinkTimer = 0 14 | vine.speed = 320 15 | vine.offset = 0 16 | vine.offsetTween = nil 17 | 18 | function vine:update(dt) 19 | 20 | self.sinkTimer = updateTimer(self.sinkTimer, dt) 21 | if self.sinkTimer > 0 then 22 | self.trueY = self.trueY + self.speed * dt 23 | end 24 | 25 | if self:enter('P_Weapon') then 26 | local wep = self:getEnterCollisionData('P_Weapon') 27 | if wep.collider.parent.type == 1 then 28 | self.sinkTimer = 0.35 29 | self.speed = 320 30 | else 31 | self.sinkTimer = 0.8 32 | self.speed = 640 33 | end 34 | end 35 | 36 | if self.offset == 0 then 37 | self.offset = 1 38 | self.offsetTween = flux.to(self, 4, {offset = 32}):ease("quadinout") 39 | elseif self.offset == 32 then 40 | self.offsetTween = flux.to(self, 4, {offset = 0}):ease("quadinout") 41 | end 42 | 43 | self:setPosition(self.trueX, self.trueY + self.offset) 44 | 45 | end 46 | 47 | table.insert(vines, vine) 48 | 49 | end 50 | 51 | function vines:update(dt) 52 | 53 | for i,v in ipairs(self) do 54 | v:update(dt) 55 | end 56 | 57 | end 58 | 59 | function vines:draw() 60 | 61 | for i,v in ipairs(self) do 62 | love.graphics.setColor(1, 1, 1, 1) 63 | local vx, vy = v:getPosition() 64 | love.graphics.draw(sprites.environment.vine, vx-32, vy-320) 65 | end 66 | 67 | end 68 | -------------------------------------------------------------------------------- /source/environment/water.lua: -------------------------------------------------------------------------------- 1 | -- Ripple objects are small ripple animations on top of all bodies of water 2 | ripples = {} 3 | 4 | -- Spritesheet that ripples use 5 | ripples.spr = sprites.environment.waterSheet 6 | 7 | -- This is the grid that all ripple objects use for animations 8 | local w = ripples.spr:getWidth() 9 | local h = ripples.spr:getHeight() 10 | ripples.grid = anim8.newGrid(64, 64, w, h) 11 | 12 | function spawnRipple(x, y) 13 | 14 | local ripple = {} 15 | ripple.x = x 16 | ripple.y = y 17 | 18 | ripple.animation = anim8.newAnimation(ripples.grid('1-20', 1), 0.1) 19 | ripple.animation:gotoFrame(math.random(1, 20)) 20 | 21 | table.insert(ripples, ripple) 22 | 23 | end 24 | 25 | -- Updates the anim8 animation for all ripple objects 26 | function ripples:update(dt) 27 | 28 | for i,r in ipairs(self) do 29 | r.animation:update(dt) 30 | end 31 | 32 | end 33 | 34 | -- Draws the anim8 animation for all ripple objects 35 | function ripples:draw() 36 | 37 | love.graphics.setColor(0.388, 0.502, 0.541, 0.471) 38 | 39 | for i,r in ipairs(self) do 40 | r.animation:draw(self.spr, r.x, r.y) 41 | end 42 | 43 | for i,w in ipairs(mapdata.water) do 44 | love.graphics.rectangle("fill", w.x, w.y, w.width, w.height) 45 | end 46 | 47 | end 48 | 49 | function ripples:destroy() 50 | 51 | for i=#ripples,1,-1 do 52 | table.remove(ripples, i) 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /source/global/collision_classes.lua: -------------------------------------------------------------------------------- 1 | -- Collision Classes used with windfield (see the libraries) 2 | function getCollisionClasses() 3 | world:addCollisionClass('Ignore', {ignores = {'Ignore'}}) 4 | world:addCollisionClass('Water', {ignores = {'Ignore'}}) 5 | world:addCollisionClass('Ripple', {ignores = {'Ignore', 'Water'}}) 6 | world:addCollisionClass('Pickup', {ignores = {'Ignore'}}) 7 | world:addCollisionClass('Player', {ignores = {'Ignore', 'Water', 'Ripple'}}) 8 | world:addCollisionClass('Enemy', {ignores = {'Ignore', 'Pickup', 'Water'}}) 9 | world:addCollisionClass('P_Weapon', {ignores = {'Ignore', 'Player', 'Pickup', 'Ripple', 'Water'}}) 10 | world:addCollisionClass('E_Weapon', {ignores = {'Ignore', 'Enemy', 'Pickup', 'Ripple', 'Water', 'P_Weapon', 'E_Weapon'}}) 11 | world:addCollisionClass('Wall', {ignores = {'Ignore', 'Wall'}}) 12 | world:addCollisionClass('Breakable', {ignores = {'Ignore', 'Wall'}}) 13 | world:addCollisionClass('Transition', {ignores = {'Ignore'}}) 14 | 15 | gravWorld:addCollisionClass('Particle', {ignores = {'Particle'}}) 16 | end 17 | -------------------------------------------------------------------------------- /source/global/gameState.lua: -------------------------------------------------------------------------------- 1 | -- Stores global information about the player's progress 2 | gameState = {} 3 | gameState.player = {} 4 | gameState.pickups = {} 5 | 6 | function gameStateInit() 7 | 8 | -- Number of times the game has been saved. 9 | -- Used to prevent certain save blocks from spawning 10 | gameState.saveCount = 0 11 | 12 | -- State stores if update functions should occur 13 | gameState.state = 1 14 | 15 | -- Stores the current room 16 | gameState.room = "rm1" 17 | 18 | -- Player information 19 | gameState.player.x = 0 20 | gameState.player.y = 0 21 | gameState.player.maxHealth = 20 22 | gameState.player.weapon = 0 23 | 24 | -- Which pickups have been obtained 25 | gameState.pickups.blaster = false 26 | gameState.pickups.rocket = false 27 | gameState.pickups.harpoon = false 28 | gameState.pickups.aquaPack = false 29 | gameState.pickups.health1 = false 30 | gameState.pickups.health2 = false 31 | 32 | -- Changes to false after the tutorial text disappears 33 | gameState.tutorial = true 34 | 35 | end 36 | -------------------------------------------------------------------------------- /source/global/saveGame.lua: -------------------------------------------------------------------------------- 1 | function saveGame() 2 | gameState.saveCount = gameState.saveCount + 1 3 | gameState.player.x = player.physics:getX() 4 | gameState.player.y = player.physics:getY() 5 | gameState.player.weapon = player.weapon 6 | local temp = Tserial.pack(gameState) 7 | love.filesystem.write("savefile.txt", temp) 8 | saveUtil:startMessage() 9 | saveUtil:destroySave() 10 | 11 | -- Restore the player's health when the game saves 12 | player.health = gameState.player.maxHealth 13 | end 14 | 15 | function loadGame() 16 | if love.filesystem.getInfo("savefile.txt") ~= nil then 17 | local temp = love.filesystem.read("savefile.txt") 18 | gameState = Tserial.unpack(temp, true) 19 | end 20 | 21 | player.physics:setPosition(gameState.player.x, gameState.player.y) 22 | player.health = gameState.player.maxHealth 23 | player.weapon = gameState.player.weapon 24 | player.state = 1 25 | changeToMap(gameState.room) 26 | 27 | if gameState.room ~= "rm27" then 28 | soundManager:startMusic("cavern") 29 | end 30 | 31 | blackScreen:fadeIn(1) 32 | end 33 | -------------------------------------------------------------------------------- /source/global/saveUtil.lua: -------------------------------------------------------------------------------- 1 | -- Throughout the game, there are invisible save blocks. 2 | -- When the player hits one of these, the game saves. 3 | -- saveUtil stores these blocks and handles the save message. 4 | saveUtil = {} 5 | 6 | -- Block starts offscreen so the player can't hit it. 7 | saveUtil.saveBlock = {} 8 | saveUtil.saveBlock.x = -1000 9 | 10 | -- Info for the "Saving..." message 11 | saveUtil.message = {} 12 | saveUtil.message.state = 0 13 | saveUtil.message.stateTimer = 0 14 | saveUtil.message.text = "Saving..." 15 | saveUtil.message.alpha = 0 16 | 17 | -- Spawn a save block 18 | function saveUtil:spawnSave(x, num) 19 | 20 | -- Do not spawn this block if its value is greater 21 | -- than the number of saves. This prevents blocks 22 | -- that have been used already from spawning again. 23 | if num < gameState.saveCount then 24 | return 25 | end 26 | 27 | saveUtil.saveBlock.x = x 28 | 29 | end 30 | 31 | function saveUtil:destroySave() 32 | -- Move the block offscreen so the player can't hit it 33 | saveUtil.saveBlock.x = -1000 34 | end 35 | 36 | -- Start the "Saving..." message 37 | function saveUtil:startMessage() 38 | saveUtil.message.state = 1 39 | end 40 | 41 | function saveUtil:update(dt) 42 | 43 | -- Collision with player 44 | local px = player.physics:getX() 45 | if math.abs(saveUtil.saveBlock.x - px) < 128 then 46 | saveGame() 47 | end 48 | 49 | saveUtil.message.stateTimer = updateTimer(saveUtil.message.stateTimer, dt) 50 | 51 | -- State 1: Message fades in 52 | if saveUtil.message.state == 1 then 53 | 54 | saveUtil.message.alpha = saveUtil.message.alpha + (dt*1.5) 55 | 56 | if saveUtil.message.alpha >= 1 then 57 | 58 | saveUtil.message.alpha = 1 59 | saveUtil.message.state = 2 60 | saveUtil.message.stateTimer = 1 61 | 62 | end 63 | 64 | end 65 | 66 | -- State 2: Message is fully visible 67 | if saveUtil.message.state == 2 and saveUtil.message.stateTimer == 0 then 68 | saveUtil.message.state = 3 69 | end 70 | 71 | -- State 3: Message fades away 72 | if saveUtil.message.state == 3 then 73 | 74 | saveUtil.message.alpha = saveUtil.message.alpha - dt 75 | 76 | if saveUtil.message.alpha <= 0 then 77 | saveUtil.message.alpha = 0 78 | saveUtil.message.state = 0 79 | end 80 | 81 | end 82 | 83 | end 84 | 85 | function saveUtil:drawMessage() 86 | 87 | -- The message is only visible at states 1 and 2 88 | -- Also, only show the message if the player is in control 89 | if saveUtil.message.state > 0 and player.state == 1 then 90 | 91 | love.graphics.setColor(1, 1, 1, saveUtil.message.alpha) 92 | love.graphics.setFont(fonts.menu.button) 93 | love.graphics.print(saveUtil.message.text, 12 * scale, 4 * scale) 94 | 95 | end 96 | 97 | end 98 | -------------------------------------------------------------------------------- /source/global/shake.lua: -------------------------------------------------------------------------------- 1 | -- This file handles all things related to screenshake 2 | 3 | shake = {} 4 | 5 | shake.time = 0 -- Timer keeping track of shake duration 6 | shake.fade = true -- Whether or not the shake intensity fades out 7 | shake.fadeSpeed = 10 -- How fast the fade is 8 | shake.intensity = 6 -- Intensity of the shake (in pixels) 9 | shake.speed = 2 -- Duration between camera movements (in seconds) 10 | shake.speedTimer = 2 -- Counts down from speed in real time to change shake dir 11 | shake.dir = 1 -- Tracks if the camera will shift left or right 12 | 13 | function shake:start(t, i, s, f, f_speed) 14 | shake.time = t 15 | shake.intensity = i 16 | shake.speed = s 17 | shake.speedTimer = s 18 | shake.fade = f or true 19 | shake.fadeSpeed = f_speed or 10 20 | 21 | shake.count = 0 22 | shake.dir = 1 23 | end 24 | 25 | function shake:stop() 26 | shake.time = t 27 | shake.intensity = i 28 | shake.speed = s 29 | shake.fade = f or true 30 | shake.fadeSpeed = f_speed or 10 31 | end 32 | 33 | -- be sure to call after cam:update() 34 | function shake:update(dt) 35 | 36 | shake.time = updateTimer(shake.time, dt) 37 | 38 | if shake.time > 0 or (shake.fade and shake.intensity > 0) then 39 | 40 | -- offsets the camera based on the shake's intensity and direction 41 | cam:lookAt(cam.x + (shake.intensity * shake.dir), cam.y) 42 | 43 | if shake.speedTimer <= 0 then 44 | -- When the timer hits zero, change the direction of the camera offset 45 | shake.dir = shake.dir * -1 46 | shake.speedTimer = shake.speed 47 | else 48 | shake.speedTimer = updateTimer(shake.speedTimer, dt) 49 | end 50 | 51 | -- After shake time is up, start fading the intensity 52 | if shake.time <= 0 and shake.fade and shake.intensity > 0 then 53 | shake.intensity = shake.intensity - (dt * shake.fadeSpeed) 54 | end 55 | 56 | else 57 | cam:lookAt(cam.x, cam.y) 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /source/global/soundManager.lua: -------------------------------------------------------------------------------- 1 | -- This table is used to play sounds and music. 2 | -- Use this table's functions so that it can check 3 | -- whether or not the sound file should actually 4 | -- be played (it checks if sound is turned off). 5 | 6 | soundManager = {} 7 | soundManager.music = sounds.music.cavern -- replace with menu music 8 | soundManager.volume = 1 -- volume of the music 9 | soundManager.fading = false -- volume will fade down if true 10 | 11 | -- Used for the rooms leading up to the boss 12 | soundManager.danger = false 13 | 14 | -- Used to tell if the ending music has started 15 | soundManager.ending = false 16 | 17 | -- Use for Sound Effects 18 | function soundManager:play(snd) 19 | 20 | if soundOn then 21 | sounds[snd]:play() 22 | end 23 | 24 | end 25 | 26 | function soundManager:startMusic(song) 27 | 28 | if song ~= nil then 29 | self.music = sounds.music[song] 30 | end 31 | 32 | if soundOn then 33 | self.fading = false 34 | self.volume = 1 35 | self.music:setVolume(self.volume) 36 | 37 | if song ~= "ending" and song ~= "intro" then 38 | self.music:setLooping(true) 39 | else 40 | self.music:setLooping(false) 41 | end 42 | 43 | love.audio.play(self.music) 44 | end 45 | 46 | self.danger = false 47 | 48 | end 49 | 50 | function soundManager:musicFade() 51 | self.fading = true 52 | end 53 | 54 | function soundManager:update(dt) 55 | if self.fading then 56 | self.volume = self.volume - dt -- will take 1 second to fade out 57 | if self.volume < 0 then 58 | self.volume = 0 59 | self.fading = false 60 | love.audio.stop(self.music) 61 | end 62 | self.music:setVolume(self.volume) 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /source/global/utilities.lua: -------------------------------------------------------------------------------- 1 | -- Distance formula 2 | function distance(x1, y1, x2, y2) 3 | return math.sqrt((y2 - y1)^2 + (x2 - x1)^2) 4 | end 5 | 6 | -- Speed given X and Y velocity values 7 | function speedFromVelocity(vx, vy) 8 | return math.sqrt(vx * vx + vy * vy) 9 | end 10 | 11 | -- Returns a normalized HUMP vector towards the player from (mx, my) 12 | -- If no parameters are given, it's assumed to be the mouse's position 13 | function toPlayerVector(mx, my) 14 | local px, py = player.physics:getPosition() 15 | local reverse = true 16 | if mx == nil and my == nil then 17 | mx, my = cam:mousePosition() 18 | mx = mx 19 | my = my 20 | reverse = false 21 | end 22 | 23 | if reverse then 24 | return vector.new(px-mx, py-my):normalized() 25 | else 26 | return vector.new(mx-px, my-py):normalized() 27 | end 28 | end 29 | 30 | function toMouseVector(px, py) 31 | local mx, my = cam:mousePosition() 32 | return vector.new(mx-px, my-py):normalized() 33 | end 34 | 35 | -- Gets radians needed to rotate towards the player 36 | function toPlayerRotate(mx, my) 37 | local dir = toPlayerVector(mx, my) 38 | local vx, vy = dir:normalized():unpack() 39 | return math.atan2(vy, vx) 40 | end 41 | 42 | -- Update timer variables 43 | function updateTimer(v, dt) 44 | if v > 0 then 45 | v = v - dt 46 | elseif v < 0 then 47 | v = 0 48 | end 49 | 50 | return v 51 | end 52 | 53 | -- Distance between object and player 54 | function distToPlayer(mx, my) 55 | local px, py = player.physics:getPosition() 56 | return distance(px, py, mx, my) 57 | end 58 | -------------------------------------------------------------------------------- /source/levels/background.lua: -------------------------------------------------------------------------------- 1 | -- Stores all data about the background 2 | background = {} 3 | background.x = 0 4 | background.y = 0 5 | background.img = sprites.environment.bg 6 | background.tileSize = 512 7 | 8 | -- PARALLAX 9 | 10 | -- Relative position of the background compared to the camera 11 | background.relX = 0 12 | background.relY = 0 13 | 14 | -- Stores the position of the camera in the previous frame 15 | background.oldCamX = 0 16 | background.oldCamY = 0 17 | 18 | -- Used to help with tracking the change in background position 19 | background.diffBufferX = 0 20 | background.diffBufferY = 0 21 | 22 | -- Number of pixels the camera has to move before the background moves 23 | background.speed = 2 24 | 25 | -- calculate parallax positioning 26 | function background:update(dt) 27 | 28 | local camX, camY = cam:position() 29 | local diffX = camX - background.oldCamX 30 | local diffY = camY - background.oldCamY 31 | 32 | -- Background position always at (-768, -768) relative to camera position 33 | background.x = camX - 1920 34 | background.y = camY - 1536 35 | 36 | background.relX = background.relX - (diffX / background.speed) 37 | background.relY = background.relY - (diffY / background.speed) 38 | 39 | if background.relX < -1 * background.tileSize then 40 | background.relX = background.relX + background.tileSize 41 | end 42 | 43 | if background.relX > background.tileSize then 44 | background.relX = background.relY - background.tileSize 45 | end 46 | 47 | if background.relY < -1 * background.tileSize then 48 | background.relY = background.relY + background.tileSize 49 | end 50 | 51 | if background.relY > background.tileSize then 52 | background.relY = background.relY - background.tileSize 53 | end 54 | 55 | background.oldCamX = camX 56 | background.oldCamY = camY 57 | 58 | end 59 | 60 | function background:reset() 61 | 62 | background.relX = 0 63 | background.relY = 0 64 | background.diffBufferX = 0 65 | background.diffBufferY = 0 66 | 67 | local camX, camY = cam:position() 68 | background.x = camX - 1920 69 | background.y = camY - 1536 70 | 71 | background.oldCamX = camX 72 | background.oldCamY = camY 73 | 74 | end 75 | 76 | function background:draw() 77 | 78 | love.graphics.setColor(1, 1, 1, 1) 79 | 80 | if mapdata.map == maps.rmIntro then 81 | love.graphics.setColor(0, 0, 0, 1) 82 | end 83 | 84 | local imgW = self.img:getWidth() 85 | local imgH = self.img:getHeight() 86 | 87 | for i = 0, 8 do -- number of tiles to cover the width of the camera 88 | for j = 0, 6 do -- number of tiles to cover the height of the camera 89 | love.graphics.draw(self.img, background.x + background.relX + (i * imgW), 90 | background.y + background.relY + (j * imgH)) 91 | end 92 | end 93 | 94 | end 95 | -------------------------------------------------------------------------------- /source/levels/destroyAll.lua: -------------------------------------------------------------------------------- 1 | -- This function is called when a new map is loaded. 2 | -- Before the objects in the new map are created, the objects from the old map 3 | -- need to be deleted. 4 | 5 | local function destroyAll() 6 | 7 | -- Destroy all walls that were spawned for the previous map 8 | for i, w in ipairs(mapdata.walls) do 9 | w:destroy() 10 | mapdata.walls[i] = nil 11 | end 12 | 13 | -- Destroy all vines that were spawned for the previous map 14 | for i, v in ipairs(vines) do 15 | v:destroy() 16 | vines[i] = nil 17 | end 18 | 19 | -- Destroy all spikes that were spawned for the previous map 20 | for i, s in ipairs(spikes) do 21 | s.dead = true 22 | end 23 | 24 | -- Destroy all walls that were spawned for the previous map 25 | for i, w in ipairs(mapdata.water) do 26 | if w.ripplePhysics ~= nil then 27 | w.ripplePhysics:destroy() 28 | end 29 | w:destroy() 30 | mapdata.water[i] = nil 31 | end 32 | 33 | -- Destroys all water ripples 34 | ripples:destroy() 35 | 36 | -- Destroy all transition objects from the previous map 37 | for i, t in ipairs(mapdata.transitions) do 38 | t:destroy() 39 | mapdata.transitions[i] = nil 40 | end 41 | 42 | -- Destroy all breakable objects from the previous map 43 | for i, b in ipairs(breakables) do 44 | b.physics:destroy() 45 | breakables[i] = nil 46 | end 47 | 48 | -- Destroy all pickup objects from the previous map 49 | for i, p in ipairs(pickups) do 50 | p.physics:destroy() 51 | pickups[i] = nil 52 | end 53 | 54 | -- Destroy all enemies from the previous map 55 | for i, e in ipairs(enemies) do 56 | e.physics:destroy() 57 | enemies[i] = nil 58 | end 59 | 60 | -- Iterate through all weapons in reverse to remove dead weapons from table 61 | for i=#weapons,1,-1 do 62 | weapons[i].physics:destroy() 63 | table.remove(weapons, i) 64 | end 65 | 66 | for i=#fires,1,-1 do 67 | table.remove(fires, i) 68 | end 69 | 70 | -- Move the saveBlock offscreen so the player can't hit 71 | saveUtil.saveBlock.x = -1000 72 | 73 | end 74 | 75 | return destroyAll 76 | -------------------------------------------------------------------------------- /source/levels/drawWalls.lua: -------------------------------------------------------------------------------- 1 | local function drawWalls() 2 | 3 | -- This function, given a wall object, will draw the rocks for it 4 | local function singleWallRocks(wall) 5 | 6 | if wall.dontDraw then 7 | return 8 | end 9 | 10 | -- Draw rocks on the surface of all walls 11 | -- Make every wall have direction values to tell which sides need rocks 12 | local surface = sprites.environment.rockySurface 13 | local offY = surface:getHeight() 14 | if wall.up then 15 | for itr=0, (wall.width/128)-1 do 16 | love.graphics.draw(surface, wall.x + (itr * 128), wall.y - offY) 17 | end 18 | end 19 | if wall.down then 20 | for itr=0, (wall.width/128)-1 do 21 | love.graphics.draw(surface, wall.x + (itr * 128), wall.y + wall.height + offY, nil, nil, -1) 22 | end 23 | end 24 | if wall.right then 25 | for itr=0, (wall.height/128)-1 do 26 | love.graphics.draw(surface, wall.x + wall.width + offY, wall.y + (itr * 128), math.pi/2) 27 | end 28 | end 29 | if wall.left then 30 | for itr=0, (wall.height/128)-1 do 31 | love.graphics.draw(surface, wall.x - offY, wall.y + (itr * 128), math.pi/2, nil, -1) 32 | end 33 | end 34 | 35 | end 36 | 37 | -- Draw the ground 38 | love.graphics.setColor(1, 1, 1, 1) 39 | 40 | for i,w in ipairs(mapdata.walls) do 41 | singleWallRocks(w) 42 | end 43 | 44 | for i,b in ipairs(breakables) do 45 | singleWallRocks(b) 46 | end 47 | 48 | for i,w in ipairs(mapdata.walls) do 49 | 50 | if w.dontDraw == false then 51 | 52 | -- Draw the full rectangle for each wall 53 | --love.graphics.rectangle("fill", w.x, w.y, w.width, w.height) 54 | 55 | --[[ 56 | love.graphics.setColor(1, 1, 1, 1) 57 | 58 | local spr = sprites.environment.wall 59 | 60 | for itrX=0, (w.width/128)-1 do 61 | for itrY = 0, (w.height/128)-1 do 62 | love.graphics.draw(spr, w.x + (itrX * 128), w.y + (itrY * 128)) 63 | end 64 | end 65 | 66 | ]] 67 | 68 | -- Note: this is done in a different for loop than the one above because 69 | -- the ground color needs to be drawn after all the surface rocks have been 70 | -- drawn. This is because some walls extend into the ground, so some walls 71 | -- are drawing rocky surfaces underground. These underground surfaces 72 | -- should not be seen, so these rectangles will cover those surfaces. 73 | 74 | end 75 | 76 | end 77 | 78 | for i,b in ipairs(breakables) do 79 | 80 | love.graphics.setColor(1, 1, 1, 1) 81 | 82 | local spr = sprites.environment.wall 83 | 84 | for itrX=0, 1 do 85 | for itrY = 0, 1 do 86 | love.graphics.draw(spr, b.x + (itrX * 128), b.y + (itrY * 128)) 87 | end 88 | end 89 | 90 | love.graphics.setColor(0, 0, 0, 1) 91 | love.graphics.draw(sprites.environment.crack, b.x + 128, b.y + 128, b.crackRot, 1, 1, 90, 90) 92 | 93 | end 94 | end 95 | 96 | return drawWalls 97 | -------------------------------------------------------------------------------- /source/levels/intro.lua: -------------------------------------------------------------------------------- 1 | -- Handles everything during the intro sequence 2 | -- Also calls loadGame when pressing "Continue" 3 | intro = {} 4 | intro.state = 0 5 | intro.timer = 0 6 | intro.skipMessage = false 7 | 8 | function intro:update(dt) 9 | 10 | if gameState.room ~= "rmIntro" then 11 | return 12 | end 13 | 14 | self.timer = updateTimer(self.timer, dt) 15 | 16 | if self.state == 1 and self.timer == 0 then 17 | 18 | textBox:start("intro") 19 | self.state = 2 20 | self.timer = 1 21 | 22 | end 23 | 24 | if self.state == 2 and self.timer == 0 then 25 | 26 | if scroll.text == "" then 27 | self.state = 2.5 28 | self.timer = 1.25 29 | end 30 | 31 | end 32 | 33 | if self.state == 2.5 and self.timer == 0 then 34 | 35 | soundManager:startMusic("intro") 36 | self.state = 3 37 | self.timer = 1.7 38 | 39 | end 40 | 41 | if self.state == 3 and self.timer == 0 then 42 | 43 | self.state = 4 44 | blackScreen:fadeIn(8) 45 | player.physics:setPosition(512, 260) 46 | player.state = -10 47 | changeToMap("rm1") 48 | 49 | end 50 | 51 | -- Load the saved game (if it exists 52 | if self.state == 100 and self.timer == 0 then 53 | 54 | -- Reset the state 55 | self.state = 0 56 | 57 | if love.filesystem.getInfo("savefile.txt") == nil then 58 | 59 | -- No save file exists, return to the main menu 60 | changeToMap("rmMainMenu") 61 | textBox:start("failedLoad") 62 | 63 | else 64 | 65 | -- Load the game 66 | loadGame() 67 | 68 | end 69 | 70 | end 71 | 72 | end 73 | 74 | function intro:interrupt() 75 | 76 | if gameState.room ~= "rmIntro" then 77 | return 78 | end 79 | 80 | if self.skipMessage then 81 | scroll.text = "" 82 | scroll.messageObj = nil 83 | scroll.charTimer = 0 84 | self.state = 2 85 | self.timer = 0 86 | self.skipMessage = false 87 | else 88 | self.skipMessage = true 89 | end 90 | 91 | end 92 | 93 | function intro:drawInterrupt() 94 | 95 | if self.skipMessage and textBox.active and scroll.text ~= scroll.fullMessage then 96 | local w = gameWidth * scale 97 | local h = gameHeight * scale 98 | love.graphics.setColor(1, 1, 1, 1) 99 | love.graphics.setFont(fonts.menu.intro) 100 | love.graphics.print("Skip?", w - 96 * scale, h - 52 * scale) 101 | end 102 | 103 | end 104 | -------------------------------------------------------------------------------- /source/libraries/Tserial.lua: -------------------------------------------------------------------------------- 1 | --- Tserial v1.5, a simple table serializer which turns tables into Lua script 2 | -- @author Taehl (SelfMadeSpirit@gmail.com) 3 | Tserial = {} 4 | TSerial = Tserial -- for backwards-compatibility 5 | 6 | --- Serializes a table into a string, in form of Lua script. 7 | -- @param t table to be serialized (may not contain any circular reference) 8 | -- @param drop if true, unserializable types will be silently dropped instead of raising errors 9 | -- if drop is a function, it will be called to serialize unsupported types 10 | -- if drop is a table, it will be used as a serialization table (where {[value] = serial}) 11 | -- @param indent if true, output "human readable" mode with newlines and indentation (for debug) 12 | -- @return string recreating given table 13 | function Tserial.pack(t, drop, indent) 14 | assert(type(t) == "table", "Can only Tserial.pack tables.") 15 | local s, empty, indent = "{"..(indent and "\n" or ""), true, indent and math.max(type(indent)=="number" and indent or 0,0) 16 | local function proc(k,v, omitKey) -- encode a key/value pair 17 | empty = nil -- helps ensure empty tables return as "{}" 18 | local tk, tv, skip = type(k), type(v) 19 | if type(drop)=="table" and drop[k] then k = "["..drop[k].."]" 20 | elseif tk == "boolean" then k = k and "[true]" or "[false]" 21 | elseif tk == "string" then local f = string.format("%q",k) if f ~= '"'..k..'"' then k = '['..f..']' end 22 | elseif tk == "number" then k = "["..k.."]" 23 | elseif tk == "table" then k = "["..Tserial.pack(k, drop, indent and indent+1).."]" 24 | elseif type(drop) == "function" then k = "["..string.format("%q",drop(k)).."]" 25 | elseif drop then skip = true 26 | else error("Attempted to Tserial.pack a table with an invalid key: "..tostring(k)) 27 | end 28 | if type(drop)=="table" and drop[v] then v = drop[v] 29 | elseif tv == "boolean" then v = v and "true" or "false" 30 | elseif tv == "string" then v = string.format("%q", v) 31 | elseif tv == "number" then -- no change needed 32 | elseif tv == "table" then v = Tserial.pack(v, drop, indent and indent+1) 33 | elseif type(drop) == "function" then v = string.format("%q",drop(v)) 34 | elseif drop then skip = true 35 | else error("Attempted to Tserial.pack a table with an invalid value: "..tostring(v)) 36 | end 37 | if not skip then return string.rep("\t",indent or 0)..(omitKey and "" or k.."=")..v..","..(indent and "\n" or "") end 38 | return "" 39 | end 40 | local l=-1 repeat l=l+1 until rawget(t,l+1)==nil -- #t "can" lie! 41 | for i=1,l do s = s..proc(i, t[i], true) end -- use ordered values when possible for better string 42 | for k, v in pairs(t) do if not (type(k)=="number" and k<=l) then s = s..proc(k, v) end end 43 | if not empty then s = string.sub(s,1,string.len(s)-1) end 44 | if indent then s = string.sub(s,1,string.len(s)-1).."\n" end 45 | return s..string.rep("\t",(indent or 1)-1).."}" 46 | end 47 | 48 | --- Loads a table into memory from a string (like those output by Tserial.pack) 49 | -- @param s a string of Lua defining a table, such as "{2,4,8,ex='ample'}" 50 | -- @param safe if true, all extraneous parts of the string will be removed, leaving only a table (prevents running anomalous code when unpacking untrusted strings). Will also cause malformed tables to quietly return nil and an error message, instead of throwing an error (so your program can't be crashed with a bad string) 51 | -- @return a table recreated from the given string. 52 | function Tserial.unpack(s, safe) 53 | if safe then s = string.match(s, "(%b{})") end 54 | assert(type(s) == "string", "Can only Tserial.unpack strings.") 55 | local f, result = loadstring("Tserial.table="..s) 56 | if not safe then assert(f,result) elseif not f then return nil, result end 57 | result = f() 58 | local t = Tserial.table 59 | Tserial.table = nil 60 | return t, result 61 | end -------------------------------------------------------------------------------- /source/libraries/sti/graphics.lua: -------------------------------------------------------------------------------- 1 | local lg = love.graphics 2 | local graphics = { isCreated = lg and true or false } 3 | 4 | function graphics.newSpriteBatch(...) 5 | if graphics.isCreated then 6 | return lg.newSpriteBatch(...) 7 | end 8 | end 9 | 10 | function graphics.newCanvas(...) 11 | if graphics.isCreated then 12 | return lg.newCanvas(...) 13 | end 14 | end 15 | 16 | function graphics.newImage(...) 17 | if graphics.isCreated then 18 | return lg.newImage(...) 19 | end 20 | end 21 | 22 | function graphics.newQuad(...) 23 | if graphics.isCreated then 24 | return lg.newQuad(...) 25 | end 26 | end 27 | 28 | function graphics.getCanvas(...) 29 | if graphics.isCreated then 30 | return lg.getCanvas(...) 31 | end 32 | end 33 | 34 | function graphics.setCanvas(...) 35 | if graphics.isCreated then 36 | return lg.setCanvas(...) 37 | end 38 | end 39 | 40 | function graphics.clear(...) 41 | if graphics.isCreated then 42 | return lg.clear(...) 43 | end 44 | end 45 | 46 | function graphics.push(...) 47 | if graphics.isCreated then 48 | return lg.push(...) 49 | end 50 | end 51 | 52 | function graphics.origin(...) 53 | if graphics.isCreated then 54 | return lg.origin(...) 55 | end 56 | end 57 | 58 | function graphics.scale(...) 59 | if graphics.isCreated then 60 | return lg.scale(...) 61 | end 62 | end 63 | 64 | function graphics.translate(...) 65 | if graphics.isCreated then 66 | return lg.translate(...) 67 | end 68 | end 69 | 70 | function graphics.pop(...) 71 | if graphics.isCreated then 72 | return lg.pop(...) 73 | end 74 | end 75 | 76 | function graphics.draw(...) 77 | if graphics.isCreated then 78 | return lg.draw(...) 79 | end 80 | end 81 | 82 | function graphics.rectangle(...) 83 | if graphics.isCreated then 84 | return lg.rectangle(...) 85 | end 86 | end 87 | 88 | function graphics.getColor(...) 89 | if graphics.isCreated then 90 | return lg.getColor(...) 91 | end 92 | end 93 | 94 | function graphics.setColor(...) 95 | if graphics.isCreated then 96 | return lg.setColor(...) 97 | end 98 | end 99 | 100 | function graphics.line(...) 101 | if graphics.isCreated then 102 | return lg.line(...) 103 | end 104 | end 105 | 106 | function graphics.polygon(...) 107 | if graphics.isCreated then 108 | return lg.polygon(...) 109 | end 110 | end 111 | 112 | function graphics.getWidth() 113 | if graphics.isCreated then 114 | return lg.getWidth() 115 | end 116 | return 0 117 | end 118 | 119 | function graphics.getHeight() 120 | if graphics.isCreated then 121 | return lg.getHeight() 122 | end 123 | return 0 124 | end 125 | 126 | return graphics -------------------------------------------------------------------------------- /source/libraries/windfield/mlib/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Davis Claiborne 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgement in the product documentation would be 14 | appreciated but is not required. 15 | 2. Altered source versions must be plainly marked as such, and must not be 16 | misrepresented as being the original software. 17 | 3. This notice may not be removed or altered from any source distribution. 18 | -------------------------------------------------------------------------------- /source/pickup.lua: -------------------------------------------------------------------------------- 1 | -- Stores all pickups in the map 2 | pickups = {} 3 | 4 | -- Spawns a pickup, name is used to identify the type of pickup 5 | function spawnPickup(name, x, y) 6 | 7 | -- If we already collected the pickup, don't spawn it 8 | if gameState.pickups[name] then 9 | return nil 10 | end 11 | 12 | local pickup = {} 13 | pickup.name = name 14 | pickup.dead = false 15 | pickup.float = true 16 | pickup.radius = 40 17 | pickup.timer = 0.1 18 | pickup.scale = 0.16 19 | 20 | -- used for floating 21 | pickup.state = 0 22 | pickup.tween = nil 23 | pickup.startY = y 24 | pickup.y = y 25 | 26 | pickup.physics = world:newCircleCollider(x, y, pickup.radius) 27 | 28 | pickup.sprite = sprites.pickups.item 29 | 30 | if name == "blaster" then 31 | pickup.sprite = sprites.pickups.blaster 32 | elseif name == "rocket" then 33 | pickup.sprite = sprites.pickups.rocketLauncher 34 | pickup.scale = 0.2 35 | elseif name == "harpoon" then 36 | pickup.sprite = sprites.pickups.spearGun 37 | elseif name == "aquaPack" then 38 | pickup.sprite = sprites.pickups.aquaPack 39 | pickup.scale = 0.21 40 | elseif name == "health1" or name == "health2" then 41 | pickup.sprite = sprites.pickups.health 42 | end 43 | 44 | -- Set the pickup's collision class 45 | pickup.physics:setCollisionClass('Pickup') 46 | 47 | -- Needed so we can reference the pickup table given its physics 48 | pickup.physics.parent = pickup 49 | 50 | table.insert(pickups, pickup) 51 | 52 | end 53 | 54 | -- Update all pickups currently in the map 55 | function pickups:update(dt) 56 | 57 | for i, p in ipairs(pickups) do 58 | 59 | -- float functionality goes here 60 | if p.state == 0 then 61 | local destY = p.y + 20 62 | p.tween = flux.to(p, 2.5, {y = destY}):ease("quadinout") 63 | p.state = 1 64 | elseif p.state == 1 then 65 | if p.y == p.startY + 20 then 66 | local destY = p.y - 40 67 | p.tween = flux.to(p, 2.5, {y = destY}):ease("quadinout") 68 | p.state = 2 69 | end 70 | elseif p.state == 2 then 71 | if p.y == p.startY - 20 then 72 | local destY = p.y + 40 73 | p.tween = flux.to(p, 2.5, {y = destY}):ease("quadinout") 74 | p.state = 1 75 | end 76 | end 77 | 78 | p.physics:setY(p.y) 79 | 80 | -- colliding with the player 81 | if p.physics:enter('Player') then 82 | -- sets the appropriate pickup value 83 | gameState.pickups[p.name] = true 84 | p.physics:destroy() 85 | p.dead = true 86 | soundManager:play("itemGet") 87 | 88 | if p.name == "blaster" then 89 | player.weapon = 1 90 | textBox:start("blaster") 91 | elseif p.name == "rocket" then 92 | player.weapon = 2 93 | textBox:start("rocket") 94 | elseif p.name == "harpoon" then 95 | player.weapon = 3 96 | textBox:start("harpoon") 97 | elseif p.name == "aquaPack" then 98 | textBox:start("aquaPack") 99 | elseif p.name == "health1" or p.name == "health2" then 100 | gameState.player.maxHealth = gameState.player.maxHealth + 5 101 | player.health = gameState.player.maxHealth 102 | textBox:start("health") 103 | end 104 | end 105 | 106 | p.timer = updateTimer(p.timer, dt) 107 | 108 | --[[ 109 | 110 | -- Spawn a sparkle 111 | if p.timer == 0 then 112 | 113 | local px, py = p.physics:getPosition() 114 | 115 | -- Seed the randomness with the pickup's Y position 116 | -- (since it is constantly moving) 117 | math.randomseed(py) 118 | 119 | local moveVector = vector(10, 0) 120 | moveVector:rotateInplace(math.random(0, 2 * math.pi)) 121 | spawnParticle(px, py, "pickupSparkle", moveVector) 122 | p.timer = 0.2 123 | 124 | end 125 | 126 | ]] 127 | 128 | end 129 | 130 | -- Iterate through all pickups in reverse to remove dead pickups from table 131 | for i=#pickups,1,-1 do 132 | if pickups[i].dead then 133 | table.remove(pickups, i) 134 | end 135 | end 136 | 137 | end 138 | 139 | -- Draw all pickups 140 | function pickups:draw() 141 | for _,p in ipairs(self) do 142 | local px, py = p.physics:getPosition() 143 | love.graphics.setColor(1, 1, 1, 1) 144 | 145 | -- Background sprite 146 | local bg = sprites.pickups.pickup_back 147 | love.graphics.draw(bg, px, py, nil, 1, 1, bg:getWidth()/2, bg:getHeight()/2) 148 | 149 | -- Actual pickup sprite 150 | love.graphics.draw(p.sprite, px, py, nil, p.scale, nil, p.sprite:getWidth()/2, p.sprite:getHeight()/2) 151 | end 152 | end 153 | -------------------------------------------------------------------------------- /source/startup/loadFonts.lua: -------------------------------------------------------------------------------- 1 | fonts = {} 2 | 3 | -- fonts.pickup = love.graphics.newFont(34 * scale) 4 | fonts.pickup = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 42 * scale) 5 | fonts.damage = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 42) 6 | fonts.boss = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 52 * scale) 7 | 8 | -- Fonts used during the credits 9 | fonts.credits = {} 10 | fonts.credits.word = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 48) 11 | fonts.credits.title = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 118) 12 | fonts.credits.me = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 56) 13 | 14 | -- Fonts used for the Main Menu and Intro 15 | fonts.menu = {} 16 | fonts.menu.title = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 146 * scale) 17 | fonts.menu.button = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 48 * scale) 18 | fonts.menu.message = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 32 * scale) 19 | fonts.menu.intro = love.graphics.newFont("fonts/vt323/VT323-Regular.ttf", 42 * scale) 20 | 21 | -- Misc fonts 22 | fonts.misc = {} 23 | fonts.misc.save = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 36 * scale) 24 | fonts.misc.tutorial = love.graphics.newFont("fonts/russoone/RussoOne-Regular.ttf", 49) 25 | -------------------------------------------------------------------------------- /source/startup/loadSounds.lua: -------------------------------------------------------------------------------- 1 | sounds = {} 2 | 3 | sounds.itemGet = love.audio.newSource("sounds/itemGet.wav", "static") 4 | sounds.playerHurt = love.audio.newSource("sounds/player/playerHurt.wav", "static") 5 | sounds.splash = love.audio.newSource("sounds/player/splash.wav", "static") 6 | 7 | -- There are multiple laser sound effects, was originally planning to have 8 | -- it randomly play one, but I decided I like laser2.wav the best. 9 | sounds.laser = love.audio.newSource("sounds/player/laser2.wav", "static") 10 | sounds.spear = love.audio.newSource("sounds/player/spear.wav", "static") 11 | --sounds.laser = love.audio.newSource({"sounds/player/laser1.wav", "sounds/player/laser2.wav", "sounds/player/laser3.wav"}, "static") 12 | sounds.bombShot = love.audio.newSource("sounds/player/bombShot.wav", "static") 13 | sounds.explosion = love.audio.newSource("sounds/player/explosion.wav", "static") 14 | 15 | sounds.enemyHurt = love.audio.newSource("sounds/enemies/enemyHurt.wav", "static") 16 | sounds.spikes = love.audio.newSource("sounds/enemies/spikes.wav", "static") 17 | sounds.starfish = love.audio.newSource("sounds/enemies/starfish.wav", "static") 18 | sounds.helloBoss = love.audio.newSource("sounds/enemies/helloBoss.wav", "static") 19 | sounds.bossLaser = love.audio.newSource("sounds/enemies/bossLaser.wav", "static") 20 | sounds.bossDie = love.audio.newSource("sounds/enemies/bossDie.wav", "static") 21 | sounds.bossExplode = love.audio.newSource("sounds/enemies/bossExplode.wav", "static") 22 | 23 | sounds.text = love.audio.newSource("sounds/ui/text.wav", "static") 24 | sounds.click = love.audio.newSource("sounds/ui/click.wav", "static") 25 | 26 | sounds.blip = love.audio.newSource("sounds/blip.wav", "static") 27 | 28 | 29 | -- Music 30 | sounds.music = {} 31 | sounds.music.menu = love.audio.newSource("music/menu.ogg", "stream") 32 | sounds.music.cavern = love.audio.newSource("music/cavern.ogg", "stream") 33 | sounds.music.boss = love.audio.newSource("music/boss.ogg", "stream") 34 | sounds.music.danger = love.audio.newSource("music/danger.ogg", "stream") 35 | sounds.music.ending = love.audio.newSource("music/ending.ogg", "stream") 36 | 37 | -- Intro music is static since it is more time-dependent than other songs 38 | sounds.music.intro = love.audio.newSource("music/intro.ogg", "static") 39 | -------------------------------------------------------------------------------- /source/startup/loadSprites.lua: -------------------------------------------------------------------------------- 1 | sprites = {} 2 | 3 | -- Images for drawing the player 4 | sprites.player = {} 5 | sprites.player.helmet = love.graphics.newImage('sprites/newPlayer2/helmet.png') 6 | sprites.player.body = love.graphics.newImage('sprites/newPlayer2/body.png') 7 | sprites.player.armEmpty = love.graphics.newImage('sprites/newPlayer2/arm.png') 8 | sprites.player.backArm = love.graphics.newImage('sprites/newPlayer2/backArm.png') 9 | sprites.player.armBlaster = love.graphics.newImage('sprites/newPlayer2/armBlaster.png') 10 | sprites.player.armRocket = love.graphics.newImage('sprites/newPlayer2/armRocket.png') 11 | sprites.player.armSpear = love.graphics.newImage('sprites/newPlayer2/armSpear.png') 12 | sprites.player.armSpearLoaded = love.graphics.newImage('sprites/newPlayer2/armSpearLoaded.png') 13 | sprites.player.spear = love.graphics.newImage('sprites/newPlayer/spear.png') 14 | sprites.player.bomb = love.graphics.newImage('sprites/player/bomb.png') 15 | sprites.player.jetpack = love.graphics.newImage('sprites/newPlayer/jetpack.png') 16 | sprites.player.aquaPack = love.graphics.newImage('sprites/newPlayer/aquapack.png') 17 | 18 | sprites.player.newPlayer = love.graphics.newImage('sprites/newPlayer/newPlayer.png') 19 | 20 | -- Images for everything relating to the environment and levels 21 | sprites.environment = {} 22 | sprites.environment.bg = love.graphics.newImage('sprites/environment/bg.png') 23 | sprites.environment.wall = love.graphics.newImage('sprites/environment/wall.png') 24 | sprites.environment.waterSheet = love.graphics.newImage('sprites/environment/waterSheet.png') 25 | sprites.environment.rockySurface = love.graphics.newImage('sprites/environment/rockySurface.png') 26 | sprites.environment.crack = love.graphics.newImage('sprites/environment/crack.png') 27 | sprites.environment.breakParticle = love.graphics.newImage('sprites/environment/breakParticle.png') 28 | sprites.environment.vine = love.graphics.newImage('sprites/environment/vine.png') 29 | 30 | -- Images for enemies 31 | sprites.enemies = {} 32 | sprites.enemies.flyerBody = love.graphics.newImage('sprites/enemies/flyerBody.png') 33 | sprites.enemies.flyerEye = love.graphics.newImage('sprites/enemies/flyerEye.png') 34 | sprites.enemies.flyerWing1 = love.graphics.newImage('sprites/enemies/flyerWing1.png') 35 | sprites.enemies.flyerWing2 = love.graphics.newImage('sprites/enemies/flyerWing2.png') 36 | sprites.enemies.spikeBody = love.graphics.newImage('sprites/enemies/spikeBody.png') 37 | sprites.enemies.spikeProj = love.graphics.newImage('sprites/enemies/spikeProj.png') 38 | sprites.enemies.starfish = love.graphics.newImage('sprites/enemies/starfish.png') 39 | sprites.enemies.evilBubble = love.graphics.newImage('sprites/enemies/evilBubble.png') 40 | sprites.enemies.bossBody = love.graphics.newImage('sprites/enemies/bossBody.png') 41 | sprites.enemies.bigBossEye = love.graphics.newImage('sprites/enemies/bigBossEye.png') 42 | sprites.enemies.egg = love.graphics.newImage('sprites/enemies/egg.png') 43 | 44 | -- Images for items 45 | sprites.pickups = {} 46 | sprites.pickups.health = love.graphics.newImage('sprites/items/healthPickup.png') 47 | sprites.pickups.item = love.graphics.newImage('sprites/items/itemPickup.png') 48 | sprites.pickups.pickup_back = love.graphics.newImage('sprites/items/pickup_back.png') 49 | sprites.pickups.blaster = love.graphics.newImage('sprites/items/blaster.png') 50 | sprites.pickups.rocketLauncher = love.graphics.newImage('sprites/items/rocketLauncher.png') 51 | sprites.pickups.spearGun = love.graphics.newImage('sprites/items/spearGun.png') 52 | sprites.pickups.aquaPack = love.graphics.newImage('sprites/items/aquaPack.png') 53 | 54 | -- Individual blob shapes for drawing fire 55 | sprites.fire = {} 56 | sprites.fire.f1 = love.graphics.newImage('sprites/fire/fire_1.png') 57 | sprites.fire.f2 = love.graphics.newImage('sprites/fire/fire_2.png') 58 | sprites.fire.f3 = love.graphics.newImage('sprites/fire/fire_3.png') 59 | sprites.fire.f4 = love.graphics.newImage('sprites/fire/fire_4.png') 60 | sprites.fire.f5 = love.graphics.newImage('sprites/fire/fire_5.png') 61 | 62 | -- Images for UI 63 | sprites.ui = {} 64 | sprites.ui.sound = love.graphics.newImage('sprites/ui/sound.png') 65 | sprites.ui.github = love.graphics.newImage('sprites/ui/github.png') 66 | -------------------------------------------------------------------------------- /source/startup/main_require.lua: -------------------------------------------------------------------------------- 1 | function getGlobals() 2 | require("source/libraries/slam") 3 | require("source/startup/loadFonts") 4 | require("source/startup/loadSprites") 5 | require("source/startup/loadSounds") 6 | 7 | require("source/libraries/Tserial") 8 | 9 | require("source/global/utilities") 10 | require("source/global/collision_classes") 11 | require("source/global/gameState") 12 | gameStateInit() 13 | 14 | require("source/global/saveGame") 15 | require("source/global/saveUtil") 16 | require("source/global/soundManager") 17 | getCollisionClasses() 18 | 19 | Camera = require("source/libraries/hump/camera") 20 | vector = require("source/libraries/hump/vector") 21 | flux = require("source/libraries/flux") 22 | anim8 = require("source/libraries/anim8") 23 | 24 | require("source/player") 25 | require("source/weapon") 26 | require("source/pickup") 27 | require("source/enemies/enemy") 28 | require("source/enemies/spikeProj") 29 | require("source/enemies/enemyProj") 30 | require("source/enemies/eye") 31 | require("source/enemies/egg") 32 | 33 | require("source/environment/particle") 34 | require("source/environment/explosion") 35 | require("source/environment/breakable") 36 | require("source/environment/water") 37 | require("source/environment/vine") 38 | require("source/environment/fire") 39 | require("source/environment/trail") 40 | require("source/environment/blast") 41 | 42 | require("source/global/shake") 43 | 44 | require("source/text/messages") 45 | require("source/text/scrollText") 46 | require("source/text/textBox") 47 | require("source/text/damage") 48 | require("source/text/credits") 49 | require("source/text/tutorial") 50 | 51 | require("source/ui/cam") 52 | require("source/ui/blackScreen") 53 | require("source/ui/flash") 54 | require("source/ui/mainMenu") 55 | 56 | require("source/levels/intro") 57 | require("source/levels/background") 58 | 59 | sti = require("source/libraries/sti") 60 | require("source/levels/map_loader") 61 | loadMaps() 62 | end 63 | -------------------------------------------------------------------------------- /source/startup/startup.lua: -------------------------------------------------------------------------------- 1 | function startup() 2 | 3 | -- GAME WINDOW CONFIGURATION 4 | 5 | -- Window title 6 | love.window.setTitle("CAVERN") 7 | 8 | -- Window icon 9 | local icon = love.image.newImageData('sprites/newPlayer2/helmet.png') 10 | love.window.setIcon(icon) 11 | 12 | -- Game resolution 13 | gameWidth = 1152 14 | gameHeight = 768 15 | 16 | scale = 1 -- adjusts game window to screen size 17 | offset = 0.8 -- window size relative to scale 18 | 19 | local screen_width, screen_height = love.window.getDesktopDimensions() 20 | local w_scale = screen_width / gameWidth 21 | local h_scale = screen_height / gameHeight 22 | 23 | -- scale set to be the lesser of w_scale and h_scale 24 | -- this way, the game window will not ever exceed screen size 25 | if w_scale < h_scale then 26 | scale = w_scale 27 | else 28 | scale = h_scale 29 | end 30 | 31 | scale = scale * offset 32 | 33 | love.window.setMode(gameWidth * scale, gameHeight * scale, {fullscreen = false, 34 | fullscreentype = "desktop", resizable = false, borderless = false, 35 | vsync = true}) 36 | 37 | 38 | -- GAME SETUP 39 | 40 | -- Physics setup 41 | -- Windfield is a library that makes LOVE's physics easier to work with 42 | -- https://github.com/SSYGEN/windfield 43 | local wf = require("source/libraries/windfield") 44 | world = wf.newWorld(0, 0, true) -- No gravity, bodies can sleep 45 | gravWorld = wf.newWorld(0, 1000, true) 46 | 47 | -- Global sound variable, game starts with it on 48 | soundOn = true 49 | 50 | -- Requires all global source files 51 | require("source/startup/main_require") 52 | getGlobals() 53 | 54 | -- Sets first map of the game 55 | changeToMap("rmMainMenu") 56 | 57 | -- Start the music! 58 | soundManager:startMusic("menu") 59 | end 60 | 61 | -- This function resets all values after the game is completed 62 | function reinit() 63 | gameStateInit() 64 | player.weapon = 0 65 | player.health = gameState.player.maxHealth 66 | end 67 | -------------------------------------------------------------------------------- /source/text/credits.lua: -------------------------------------------------------------------------------- 1 | -- This table contains words that will be displayed 2 | -- in the credits room 3 | credits = {} 4 | credits.bottom = 12752 5 | 6 | -- Words follow this format: 7 | -- { Word Text, X position, Y position, Font } 8 | 9 | -- By default, font will be fonts.credits.word unless 10 | -- specified otherwise 11 | 12 | -- X position doesn't use a position value, but it has 13 | -- 3 options: "center", "left", or "right". Items in 14 | -- the credits will either be centered, or put into a 15 | -- left and right column. 16 | 17 | -- Y position is the number of pixels from the bottom 18 | -- Example: if Y position was 100, text would be 19 | -- displayed at credits.bottom - 100 20 | 21 | table.insert(credits, {"CAVERN", "center", 2304, fonts.credits.title}) 22 | table.insert(credits, {"Created by Kyle Schaub", "center", 4608, fonts.credits.me}) 23 | table.insert(credits, {"All code, art, and music is available on GitHub.", "center", 6912}) 24 | table.insert(credits, {"This is an open-source Love2D project.", "center", 7040}) 25 | table.insert(credits, {"All of my supportive students on Udemy", "center", 9344}) 26 | table.insert(credits, {"Everyone who helped with testing and reporting bugs", "center", 9472}) 27 | table.insert(credits, {"Special Thanks to:", "center", 9600}) 28 | table.insert(credits, {"Thank you for playing!", "center", 11892, fonts.credits.me}) 29 | 30 | function credits:draw() 31 | 32 | -- Only draw if we are in rmCredits 33 | if gameState.room == "rmCredits" then 34 | for _,w in ipairs(self) do 35 | 36 | if w[4] == nil then 37 | love.graphics.setFont(fonts.credits.word) 38 | else 39 | love.graphics.setFont(w[4]) 40 | end 41 | 42 | love.graphics.setColor(1, 1, 1, 1) 43 | 44 | local text = w[1] 45 | local x = 384 46 | local y = credits.bottom - w[3] 47 | local width = 1792 48 | 49 | if w[2] ~= "center" then 50 | width = width / 2 51 | end 52 | 53 | if w[2] == "right" then 54 | x = 1280 55 | end 56 | 57 | love.graphics.printf(text, x, y, width, "center") 58 | 59 | end 60 | end 61 | 62 | end 63 | -------------------------------------------------------------------------------- /source/text/damage.lua: -------------------------------------------------------------------------------- 1 | -- When an enemy takes damage, it'll display the damage amount 2 | damages = {} 3 | 4 | function damages:spawnDamage(x, y, val, who) 5 | 6 | local damage = {} 7 | 8 | -- starting position of the damage text 9 | damage.x = x - 40 10 | if val < 10 then 11 | damage.x = damage.x + 11 12 | end 13 | damage.y = y - 24 14 | 15 | -- Information for the bouncing tween used to animate the text 16 | damage.start_y = damage.y 17 | damage.val = val * -1 18 | damage.jump_tween_x = nil 19 | damage.jump_tween_y = nil 20 | damage.alpha_tween = nil 21 | damage.alpha = 255 22 | damage.dead = false 23 | 24 | -- Random value determining how far left or right the text will bounce 25 | damage.rx = math.random(-100, 100) 26 | 27 | function damage:update() 28 | 29 | local function on_fade_complete() 30 | self.jump_tween_x = nil 31 | self.jump_tween_y = nil 32 | self.alpha_tween = nil 33 | self.dead = true 34 | end 35 | 36 | local function on_y_complete() 37 | local sy = self.start_y 38 | self.jump_tween_y = flux.to(self, 0.5, {y = sy}):ease("quadin") 39 | self.alpha_tween = flux.to(self, 0.5, {alpha = 0}):oncomplete(on_fade_complete):ease("cubicout") 40 | end 41 | 42 | if self.jump_tween_x == nil then 43 | local rx = self.x + self.rx 44 | self.jump_tween_x = flux.to(self, 1, {x = rx}) 45 | end 46 | if self.jump_tween_y == nil then 47 | self.jump_tween_y = flux.to(self, 0.5, {y = y - 176}):oncomplete(on_y_complete):ease("quadout") 48 | end 49 | end 50 | 51 | table.insert(damages, damage) 52 | 53 | end 54 | 55 | function damages:update(dt) 56 | 57 | for i,d in ipairs(self) do 58 | d:update(dt) 59 | end 60 | 61 | -- Iterate through all damages in reverse to remove dead ones from table 62 | for i=#damages,1,-1 do 63 | if damages[i].dead then 64 | table.remove(damages, i) 65 | end 66 | end 67 | 68 | end 69 | 70 | function damages:draw() 71 | for _,d in ipairs(damages) do 72 | love.graphics.setColor(1, 0.196, 0.196, d.alpha/255) 73 | love.graphics.setFont(fonts.damage) 74 | love.graphics.print(d.val, d.x, d.y) 75 | love.graphics.setColor(1, 1, 1, 1) 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /source/text/messages.lua: -------------------------------------------------------------------------------- 1 | -- All messages that get displayed in a scroll 2 | 3 | messages = {} 4 | 5 | messages.blaster = { 6 | "You got the blaster!", 7 | "Use the mouse to aim, and\n to shoot!" 8 | } 9 | messages.blaster.img = sprites.pickups.blaster 10 | 11 | messages.rocket = { 12 | "You got the Rocket Launcher!", 13 | " to launch a missile\nthat explodes upon impact,\ndealing massive damage.", 14 | "Press the or scroll\nthe mouse wheel to switch\nyour equipped weapon." 15 | } 16 | messages.rocket.img = sprites.pickups.rocketLauncher 17 | 18 | messages.harpoon = { 19 | "You got the Spear Gun!", 20 | " to shoot a spear,\neven while underwater.", 21 | } 22 | messages.harpoon.img = sprites.pickups.spearGun 23 | 24 | messages.aquaPack = { 25 | "You got the Aqua Pack!", 26 | "Your suit is now capable of\ngoing underwater.", 27 | } 28 | messages.aquaPack.img = sprites.pickups.aquaPack 29 | 30 | messages.health = { 31 | "You got a Health Upgrade!", 32 | "Your health has been restored,\nand your maximum health has\nincreased by 5.", 33 | } 34 | messages.health.img = sprites.pickups.health 35 | 36 | messages.failedLoad = { 37 | "No save file found.", 38 | } 39 | 40 | messages.intro = { 41 | "1-31-2056 \n" 42 | .. "St. Louis, Missouri, United States of America @\n\n" 43 | .. "Asteroid \"433 Eros\" has crashed into Earth approximately \n30 miles " 44 | .. "southwest of the city.@The impact has uncovered the\nentrance to a series" 45 | .. " of unexplored caves deep underground. @\n\n" 46 | .. "It was discovered in the year 2053 that Eros was home to a\nnew form of " 47 | .. "life.@Movement has been detected beneath the\nsurface of the impact site," 48 | .. " indicating that these alien\nlifeforms have migrated into the caves." 49 | .. " @\n\n" 50 | .. "We are sending an expert in to investigate." 51 | 52 | } 53 | 54 | messages.tutorial = { 55 | "Use to move.\nUse the mouse to look around.", 56 | } 57 | -------------------------------------------------------------------------------- /source/text/scrollText.lua: -------------------------------------------------------------------------------- 1 | -- Scroll handles all text that shows text letter-by-letter 2 | 3 | scroll = {} 4 | 5 | scroll.text = "" -- Text currently on screen 6 | scroll.fullMessage = "" -- Full message that will be displayed 7 | scroll.messageObj = nil -- Message object pulled from messages.lua 8 | scroll.charTimer = 0 -- Timer until next letter is displayed 9 | scroll.textSpeed = 0.025 -- Display a new character every ____ seconds 10 | scroll.messageNum = 1 -- Which string from the message object 11 | scroll.charNum = 0 -- Which character of the full message we're on 12 | 13 | function scroll:showMessage(m) 14 | 15 | -- Sets the first set of text for the message 16 | self.fullMessage = messages[m][1] 17 | self.text = "" 18 | 19 | self.messageNum = 1 20 | self.charNum = 0 21 | self.messageObj = messages[m] 22 | 23 | -- The messages table contains other tables, each containing a set of strings 24 | -- which will be displayed in order to the text window. 25 | 26 | end 27 | 28 | function scroll:update(dt) 29 | 30 | if self.messageObj ~= nil then 31 | while self.messageNum <= #self.messageObj do 32 | 33 | if self.fullMessage == "" then 34 | self.fullMessage = self.messageObj[self.messageNum] 35 | end 36 | 37 | if self.charNum < string.len(self.fullMessage) then 38 | self.charTimer = updateTimer(self.charTimer, dt) 39 | if self.charTimer == 0 then 40 | self.charNum = self.charNum + 1 41 | self.text = string.sub(self.fullMessage, 1, self.charNum) 42 | 43 | self.charTimer = self.textSpeed 44 | 45 | -- an "@" represents a spot to wait longer to display the next letter 46 | -- Wait 30 times longer than normal, and replace the @ with a space 47 | -- If the current letter is a comma, wait only slightly longer 48 | local nextLetter = string.sub(self.fullMessage, self.charNum+1, self.charNum+1) 49 | local curLetter = string.sub(self.fullMessage, self.charNum, self.charNum) 50 | if nextLetter == "@" then 51 | 52 | -- Wait longer 53 | self.charTimer = self.textSpeed * 30 54 | 55 | -- replace the @ with a space 56 | self.fullMessage = string.sub(self.fullMessage, 1, self.charNum) .. 57 | " " .. string.sub(self.fullMessage, self.charNum+2, 58 | string.len(self.fullMessage)) 59 | 60 | end 61 | if curLetter == "," then 62 | self.charTimer = self.textSpeed * 15 63 | end 64 | 65 | -- The "string.sub" will get the latest character. 66 | -- The "string.byte" will convert that character into an integer 67 | -- that represents its ASCII equivalent 68 | -- All ASCII characters greater than 32 (visible characters) will 69 | -- play the text sound effect 70 | if string.byte( string.sub(self.text, self.charNum, self.charNum) ) > 32 then 71 | soundManager:play("text") 72 | end 73 | 74 | end 75 | else 76 | if love.keyboard.isDown("space","return", 'w', 'a', 's', 'd') or love.mouse.isDown(1,2) then 77 | self.text = "" 78 | self.fullMessage = "" 79 | self.charNum = 0 80 | self.messageNum = self.messageNum + 1 81 | end 82 | end 83 | 84 | return 85 | end 86 | 87 | self.messageObj = nil 88 | 89 | end 90 | 91 | end 92 | -------------------------------------------------------------------------------- /source/text/textBox.lua: -------------------------------------------------------------------------------- 1 | -- Controls overall display of scrollText messages 2 | 3 | textBox = {} 4 | 5 | textBox.active = false 6 | 7 | -- Box position and dimensions 8 | textBox.x = 100 9 | textBox.y = 100 10 | textBox.width = gameWidth - 200 11 | textBox.height = 400 12 | 13 | -- Where the text will be drawn within the box 14 | textBox.textX = textBox.x + 100 15 | textBox.textY = textBox.y + 100 16 | 17 | -- Misc textBox settings 18 | textBox.font = fonts.pickup 19 | textBox.visible = true 20 | 21 | 22 | function textBox:start(m) 23 | 24 | textBox.active = true 25 | 26 | -- Freezes everything (mostly) 27 | gameState.state = 0 28 | 29 | if m == "blaster" or m == "rocket" or m == "harpoon" 30 | or m == "aquaPack" or m == "health" then 31 | textBox:init("pickup") 32 | end 33 | 34 | if m == "failedLoad" or m == "tutorial" then 35 | textBox:init("failedLoad") 36 | end 37 | 38 | if m == "tutorial" then 39 | textBox:init("tutorial") 40 | end 41 | 42 | if m == "intro" then 43 | textBox:init("intro") 44 | end 45 | 46 | scroll:showMessage(m) 47 | 48 | end 49 | 50 | 51 | function textBox:update(dt) 52 | 53 | if self.active and scroll.messageObj == nil then 54 | self.active = false 55 | gameState.state = 1 56 | end 57 | 58 | end 59 | 60 | 61 | function textBox:draw() 62 | 63 | if self.active then 64 | 65 | -- Draw black background 66 | love.graphics.setColor(0, 0, 0, 1) 67 | love.graphics.rectangle("fill", self.x * scale, self.y * scale, 68 | self.width * scale, self.height * scale) 69 | 70 | -- Draw the border of the box 71 | if self.visible then 72 | love.graphics.setColor(1, 1, 1, 1) 73 | love.graphics.setLineWidth(22 * scale) 74 | love.graphics.rectangle("line", self.x * scale, self.y * scale, 75 | self.width * scale, self.height * scale) 76 | end 77 | 78 | -- Draw text 79 | love.graphics.setColor(1, 1, 1, 1) 80 | love.graphics.setFont(self.font) 81 | love.graphics.print(scroll.text, self.textX * scale, self.textY * scale) 82 | 83 | -- Draw image 84 | if scroll.messageObj ~= nil and scroll.messageObj.img ~= nil then 85 | local spr = scroll.messageObj.img 86 | local w = spr:getWidth() 87 | local h = spr:getHeight() 88 | love.graphics.draw(spr, self.x * scale + (self.width * scale / 2), 89 | -92 * scale + (self.width * scale / 2), nil, scale/4, nil, 90 | w/2, h/2) 91 | end 92 | 93 | end 94 | 95 | end 96 | 97 | 98 | function textBox:init(type) 99 | 100 | if type == "pickup" then 101 | textBox.x = 180 102 | textBox.y = 180 103 | textBox.width = gameWidth - 360 104 | textBox.height = 410 105 | textBox.textX = textBox.x + 40 106 | textBox.textY = textBox.y + 226 107 | textBox.font = fonts.pickup 108 | textBox.visible = true 109 | end 110 | 111 | if type == "failedLoad" then 112 | textBox.x = 180 113 | textBox.y = 265 114 | textBox.width = gameWidth - 360 115 | textBox.height = 170 116 | textBox.textX = textBox.x + 40 117 | textBox.textY = textBox.y + 60 118 | textBox.font = fonts.pickup 119 | textBox.visible = true 120 | end 121 | 122 | if type == "tutorial" then 123 | textBox.x = 180 124 | textBox.y = 60 125 | textBox.width = gameWidth - 360 126 | textBox.height = 189 127 | textBox.textX = textBox.x + 40 128 | textBox.textY = textBox.y + 44 129 | textBox.font = fonts.pickup 130 | textBox.visible = true 131 | end 132 | 133 | if type == "intro" then 134 | textBox.x = -100 135 | textBox.y = -100 136 | textBox.width = gameWidth * scale + 200 137 | textBox.height = gameHeight * scale + 200 138 | textBox.textX = 58 139 | textBox.textY = 104 140 | textBox.font = fonts.menu.intro 141 | textBox.visible = false 142 | end 143 | 144 | end 145 | -------------------------------------------------------------------------------- /source/text/tutorial.lua: -------------------------------------------------------------------------------- 1 | -- This table controls the text that displays the controls 2 | tutorial = {} 3 | tutorial.active = false -- turns to true when the text should appear 4 | tutorial.alpha = 0 -- transparency of the text 5 | tutorial.speed = 2 -- number of seconds to appear/disappear 6 | 7 | function tutorial:update(dt) 8 | 9 | -- Don't do anything if the tutorial has already finished 10 | if gameState.tutorial == false then 11 | return 12 | end 13 | 14 | if self.active and self.alpha < 1 then 15 | self.alpha = self.alpha + (dt / self.speed) 16 | end 17 | 18 | if self.alpha > 1 then 19 | self.alpha = 1 20 | end 21 | 22 | if self.active == false and self.alpha > 0 then 23 | self.alpha = self.alpha - (dt / self.speed) 24 | end 25 | 26 | if self.active == false and self.alpha < 0 then 27 | self.alpha = 0 28 | gameState.tutorial = false 29 | end 30 | 31 | end 32 | 33 | function tutorial:draw() 34 | 35 | -- Don't draw anything if the tutorial has already finished 36 | if gameState.tutorial == false then 37 | return 38 | end 39 | 40 | local x = 768 41 | local y = 320 42 | local sectionW = 896 43 | love.graphics.setColor(1, 1, 1, self.alpha) 44 | love.graphics.setFont(fonts.misc.tutorial) 45 | love.graphics.printf("Use the arrow keys\nor to move", x, y, sectionW, "center") 46 | love.graphics.printf("Point with the mouse\nto look around", x, y + 224, sectionW, "center") 47 | 48 | end 49 | 50 | function tutorial:start() 51 | 52 | self.active = true 53 | self.alpha = 0.001 54 | 55 | end 56 | -------------------------------------------------------------------------------- /source/ui/blackScreen.lua: -------------------------------------------------------------------------------- 1 | -- blackScreen is used for fading to black and adding darkness to the screen 2 | 3 | blackScreen = {} 4 | blackScreen.state = 0 -- 0 is stable, 1 is getting dark, -1 is getting lighter 5 | blackScreen.alpha = 0 6 | blackScreen.time = 1 -- time in seconds for the blackScreen fade/unfade 7 | 8 | -- blackScreen is also used for making the screen turn red when drowning 9 | blackScreen.red = false 10 | blackScreen.fullRedAlpha = 0.25 11 | 12 | function blackScreen:update(dt) 13 | 14 | if self.state ~= 0 then 15 | self.alpha = self.alpha + (self.state / self.time * dt) 16 | end 17 | 18 | if self.alpha < 0 then 19 | self.alpha = 0 20 | self.state = 0 21 | self.red = false 22 | end 23 | 24 | if self.alpha > 1 then 25 | self.alpha = 1 26 | self.state = 0 27 | end 28 | 29 | if self.red and self.alpha > self.fullRedAlpha then 30 | self.alpha = self.fullRedAlpha 31 | self.state = 0 32 | end 33 | 34 | end 35 | 36 | function blackScreen:draw() 37 | 38 | local red = 0 39 | if self.red then 40 | red = 1 41 | end 42 | love.graphics.setColor(red, 0, 0, self.alpha) 43 | love.graphics.rectangle("fill", -20, -20, (gameWidth + 40) * scale, (gameHeight + 40) * scale) 44 | 45 | end 46 | 47 | function blackScreen:fadeIn(t) 48 | 49 | self.alpha = 1 50 | self.state = -1 51 | self.time = t or 1 52 | self.red = false 53 | 54 | end 55 | 56 | function blackScreen:fadeOut(t) 57 | 58 | self.alpha = 0 59 | self.state = 1 60 | self.time = t or 1 61 | self.red = false 62 | 63 | end 64 | 65 | function blackScreen:setRed() 66 | 67 | self.alpha = 0 68 | self.state = 1 69 | self.time = 1 70 | self.red = true 71 | 72 | end 73 | 74 | function blackScreen:removeRed() 75 | 76 | self.state = -1 77 | self.time = 1 78 | self.red = true 79 | 80 | end 81 | -------------------------------------------------------------------------------- /source/ui/cam.lua: -------------------------------------------------------------------------------- 1 | -- 0.5 * scale zooms the camera out. Start at player's position 2 | cam = Camera(player.physics:getX(), player.physics:getY(), 0.5*scale) 3 | cam.x = 0 4 | cam.y = 0 5 | 6 | function cam:update(dt) 7 | 8 | -- player has died, don't update the camera 9 | if player.state < 0 then 10 | return 11 | end 12 | 13 | local lookX = player.physics:getX() 14 | local lookY = player.physics:getY() 15 | 16 | -- Camera can't pan outside the room 17 | if mapdata.room ~= nil then 18 | 19 | -- Normally you would divide gameWidth by 2, but you don't here because 20 | -- the camera is zoomed out, so gameWidth/Height is "doubled" 21 | 22 | local leftBound = mapdata.room.x + gameWidth 23 | if lookX < leftBound then 24 | lookX = leftBound 25 | end 26 | 27 | local rightBound = mapdata.room.x + mapdata.room.width - gameWidth 28 | if lookX > rightBound then 29 | lookX = rightBound 30 | end 31 | 32 | local upperBound = mapdata.room.y + gameHeight 33 | if lookY < upperBound then 34 | lookY = upperBound 35 | end 36 | 37 | local lowerBound = mapdata.room.y + mapdata.room.height - gameHeight 38 | if lookY > lowerBound then 39 | lookY = lowerBound 40 | end 41 | 42 | end 43 | 44 | cam:lookAt(lookX, lookY) 45 | 46 | -- cam.x and cam.y keep track of where the camera is located 47 | -- the lookAt value may be moved if a screenshake is happening, so these 48 | -- values know where the camera should be, regardless of lookAt 49 | cam.x = lookX 50 | cam.y = lookY 51 | end 52 | -------------------------------------------------------------------------------- /source/ui/flash.lua: -------------------------------------------------------------------------------- 1 | -- Flashes cause the screen to go white 2 | -- Similar to blackScreen, but needs to be its own class 3 | 4 | flash = {} 5 | flash.state = 0 -- 0 is stable, 1 is getting dark, -1 is getting lighter 6 | flash.alpha = 0 7 | flash.time = 1 -- time in seconds for the flash fade/unfade 8 | 9 | -- if this is true, the white screen fades in and immediately out 10 | flash.flashing = false 11 | 12 | function flash:update(dt) 13 | 14 | if self.state ~= 0 then 15 | self.alpha = self.alpha + (self.state / self.time * dt) 16 | end 17 | 18 | if self.alpha < 0 then 19 | self.alpha = 0 20 | self.state = 0 21 | self.flashing = false 22 | end 23 | 24 | if self.alpha > 1 then 25 | self.alpha = 1 26 | self.state = 0 27 | 28 | if self.flashing then 29 | self.state = -1 30 | end 31 | end 32 | 33 | end 34 | 35 | function flash:draw() 36 | 37 | love.graphics.setColor(1, 1, 1, self.alpha) 38 | love.graphics.rectangle("fill", -20, -20, (gameWidth + 40) * scale, (gameHeight + 40) * scale) 39 | 40 | end 41 | 42 | function flash:fadeIn(t) 43 | 44 | self.alpha = 1 45 | self.state = -1 46 | self.time = t or 1 47 | 48 | end 49 | 50 | function flash:fadeOut(t) 51 | 52 | self.alpha = 0 53 | self.state = 1 54 | self.time = t or 1 55 | 56 | end 57 | 58 | function flash:flash(t) 59 | 60 | self.flashing = true 61 | flash:fadeOut(t) 62 | 63 | end 64 | -------------------------------------------------------------------------------- /source/ui/mainMenu.lua: -------------------------------------------------------------------------------- 1 | -- Stores all clickable buttons on the main menu 2 | -- By index: X, Y, Width, Height, Message 3 | buttons = {} 4 | buttons[1] = {376, 380, 360, 72, "New Game"} 5 | buttons[2] = {376, 476, 360, 72, "Continue"} 6 | 7 | -- Dimensions and offset for the small corner buttons (sound and GitHub) 8 | local smSize = 72 9 | local smOffset = 14 10 | 11 | -- Place buttons 3 and 4 in the left and right corners respectively 12 | buttons[3] = {smOffset, gameHeight - smSize - smOffset, smSize, smSize, ".sound"} 13 | buttons[4] = {gameWidth - smSize - smOffset, gameHeight - smSize - smOffset, smSize, smSize, ".github"} 14 | 15 | -- This value stores the message displayed at the bottom of the menu 16 | buttons.message = "" 17 | 18 | -- This function draws everything on the Main Menu 19 | function menuDraw() 20 | 21 | if gameState.room == "rmMainMenu" then 22 | 23 | love.graphics.setFont(fonts.menu.title) 24 | love.graphics.setColor(1, 1, 1, 1) 25 | love.graphics.printf("CAVERN", 0, 140 * scale, gameWidth * scale, "center") 26 | 27 | -- Start message off as nothing, will be updated if hovering over a button 28 | buttons.message = "" 29 | 30 | for _,b in ipairs(buttons) do 31 | 32 | -- Get attributes stored for the current button 33 | local bX = b[1] * scale; 34 | local bY = b[2] * scale; 35 | local bW = b[3] * scale; 36 | local bH = b[4] * scale; 37 | local bText = b[5]; 38 | 39 | if buttons:mouseCheck(b) then -- if the mouse is over the button... 40 | 41 | -- Button border 42 | -- love.graphics.setColor(0.384, 0.604, 0.475) -- enemy color 43 | love.graphics.setColor(1, 1, 1) -- white 44 | love.graphics.setLineWidth(6) 45 | love.graphics.rectangle("line", bX, bY, bW, bH) 46 | 47 | -- Update the button message at the bottom of the screen 48 | if bText == "New Game" then 49 | buttons.message = "Start a new game - erases old save file" 50 | elseif bText == "Continue" then 51 | buttons.message = "Continue from where you left off" 52 | elseif bText == ".sound" then 53 | buttons.message = "Turn music and sound effects on or off" 54 | elseif bText == ".github" then 55 | buttons.message = "View the code on GitHub" 56 | end 57 | 58 | end 59 | 60 | love.graphics.setColor(1, 1, 1, 1) 61 | love.graphics.setFont(fonts.menu.button) 62 | 63 | if bText == ".sound" then 64 | if not soundOn then 65 | love.graphics.setColor(0.35, 0.35, 0.35, 0.5) 66 | end 67 | love.graphics.draw(sprites.ui.sound, bX + 15 * scale, bY + 9 * scale, 0, scale, scale) 68 | elseif bText == ".github" then 69 | love.graphics.draw(sprites.ui.github, bX + 9 * scale, bY + 8 * scale, 0, scale, scale) 70 | else 71 | love.graphics.printf(bText, bX, bY + 8 * scale, bW, "center") 72 | end 73 | 74 | end 75 | 76 | end 77 | 78 | love.graphics.setColor(1, 1, 1, 1) 79 | love.graphics.setFont(fonts.menu.message) 80 | love.graphics.printf(buttons.message, 0, love.graphics.getHeight() - 80, love.graphics.getWidth(), "center") 81 | 82 | end 83 | 84 | -- Check if the mouse is inside the passed button 85 | function buttons:mouseCheck(b) 86 | 87 | -- Get mouse coordinates 88 | local mx, my = love.mouse.getPosition() 89 | 90 | -- Get attributes stored for the passed button 91 | local bX = b[1] * scale; 92 | local bY = b[2] * scale; 93 | local bW = b[3] * scale; 94 | local bH = b[4] * scale; 95 | 96 | -- Compare coordinates to see if mouse is inside button 97 | if mx > bX and mx < bX+bW and my > bY and my < bY+bH then 98 | return true 99 | end 100 | 101 | return false 102 | 103 | end 104 | 105 | -- Called whenever the left mouse button is clicked 106 | -- Checks if it clicked on a button, and does what that 107 | -- button needs to do 108 | function buttons:click() 109 | 110 | for i,b in ipairs(self) do 111 | 112 | -- If the mouse is on the current button... 113 | if buttons:mouseCheck(b) then 114 | 115 | -- The button has been clicked 116 | 117 | if i == 1 then -- New Game button 118 | 119 | -- This is the state for new game sequence 120 | intro.state = 1 121 | intro.timer = 1 122 | buttons.message = "" 123 | soundManager:musicFade() 124 | changeToMap("rmIntro") 125 | 126 | elseif i == 2 then -- Continue button 127 | 128 | -- This is the state for intro's load sequence 129 | intro.state = 100 130 | intro.timer = 1.5 131 | buttons.message = "" 132 | soundManager:musicFade() 133 | changeToMap("rmIntro") 134 | 135 | elseif i == 3 then -- Sound button 136 | 137 | -- Toggle sound to be on/off 138 | soundOn = not soundOn 139 | if soundOn then 140 | soundManager:startMusic("menu") 141 | else 142 | soundManager:musicFade() 143 | end 144 | 145 | elseif i == 4 then -- GitHub button 146 | 147 | -- Open the GitHub page for this game! 148 | love.system.openURL("https://github.com/kyleschaub/cavern") 149 | 150 | end 151 | 152 | soundManager:play("click") 153 | 154 | end 155 | 156 | end 157 | 158 | end 159 | -------------------------------------------------------------------------------- /source/update.lua: -------------------------------------------------------------------------------- 1 | local function updateGameplay(dt) 2 | 3 | -- Update the main physics world 4 | world:update(dt) 5 | 6 | -- Update the gravity physics world 7 | gravWorld:update(dt) 8 | 9 | -- Update trail table (must be done before weapons are updated) 10 | trails:update(dt) 11 | 12 | -- Update the player 13 | player:update(dt) 14 | 15 | -- Update all weapons 16 | weapons:update(dt) 17 | 18 | -- Update all enemies 19 | enemies:update(dt) 20 | 21 | -- Update all pickup objects in the current map 22 | pickups:update(dt) 23 | 24 | -- Update the saveUtil (for the saveMessage) 25 | saveUtil:update(dt) 26 | 27 | -- Update camera 28 | cam:update(dt) 29 | 30 | -- Update background (for parallax) 31 | background:update(dt) 32 | 33 | -- Update the screen-shake (called right after cam:update) 34 | shake:update(dt) 35 | 36 | -- Update damage text 37 | damages:update(dt) 38 | 39 | -- Update all particles 40 | particles:update(dt) 41 | 42 | -- Update all blasts 43 | blasts:update(dt) 44 | 45 | -- Update water ripple animations 46 | ripples:update(dt) 47 | 48 | -- Update projectiles shot by spike enemies 49 | spikes:update(dt) 50 | 51 | -- Update enemy projectiles 52 | enemyProjectiles:update(dt) 53 | 54 | -- Update eggs from the final boss 55 | eggs:update(dt) 56 | 57 | -- Update the vines that come up from the ground 58 | vines:update(dt) 59 | 60 | -- Update fire particles 61 | fires:update(dt) 62 | 63 | -- Update tweens 64 | flux.update(dt) 65 | 66 | -- Update to remove dead breakable walls 67 | breakables:update(dt) 68 | 69 | -- Update the blackScreen 70 | blackScreen:update(dt) 71 | 72 | -- Update the Sound Manager 73 | soundManager:update(dt) 74 | 75 | -- Update the flash 76 | flash:update(dt) 77 | 78 | -- Handle trail fade-away (when its weapon is destroyed) 79 | trails:fadeOut(dt) 80 | 81 | -- Update the tutorial 82 | tutorial:update(dt) 83 | 84 | -- Update the intro sequence (if necessary) 85 | intro:update(dt) 86 | 87 | end 88 | 89 | return updateGameplay 90 | -------------------------------------------------------------------------------- /sprites/LICENSE.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/LICENSE.txt -------------------------------------------------------------------------------- /sprites/enemies/bigBossEye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/bigBossEye.png -------------------------------------------------------------------------------- /sprites/enemies/bossBody.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/bossBody.png -------------------------------------------------------------------------------- /sprites/enemies/egg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/egg.png -------------------------------------------------------------------------------- /sprites/enemies/evilBubble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/evilBubble.png -------------------------------------------------------------------------------- /sprites/enemies/flyerBody.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/flyerBody.png -------------------------------------------------------------------------------- /sprites/enemies/flyerEye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/flyerEye.png -------------------------------------------------------------------------------- /sprites/enemies/flyerWing1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/flyerWing1.png -------------------------------------------------------------------------------- /sprites/enemies/flyerWing2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/flyerWing2.png -------------------------------------------------------------------------------- /sprites/enemies/spikeBody.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/spikeBody.png -------------------------------------------------------------------------------- /sprites/enemies/spikeProj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/spikeProj.png -------------------------------------------------------------------------------- /sprites/enemies/starfish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/enemies/starfish.png -------------------------------------------------------------------------------- /sprites/environment/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/bg.png -------------------------------------------------------------------------------- /sprites/environment/breakParticle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/breakParticle.png -------------------------------------------------------------------------------- /sprites/environment/crack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/crack.png -------------------------------------------------------------------------------- /sprites/environment/cracks/crack1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/cracks/crack1.png -------------------------------------------------------------------------------- /sprites/environment/cracks/crack2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/cracks/crack2.png -------------------------------------------------------------------------------- /sprites/environment/cracks/crack3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/cracks/crack3.png -------------------------------------------------------------------------------- /sprites/environment/rockySurface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/rockySurface.png -------------------------------------------------------------------------------- /sprites/environment/rockySurface2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/rockySurface2.png -------------------------------------------------------------------------------- /sprites/environment/rockySurface_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/rockySurface_white.png -------------------------------------------------------------------------------- /sprites/environment/sinkingWall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/sinkingWall.png -------------------------------------------------------------------------------- /sprites/environment/vine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/vine.png -------------------------------------------------------------------------------- /sprites/environment/wall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/wall.png -------------------------------------------------------------------------------- /sprites/environment/wall2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/wall2.png -------------------------------------------------------------------------------- /sprites/environment/wall_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/wall_old.png -------------------------------------------------------------------------------- /sprites/environment/waterSheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/environment/waterSheet.png -------------------------------------------------------------------------------- /sprites/fire/fire_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/fire/fire_1.png -------------------------------------------------------------------------------- /sprites/fire/fire_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/fire/fire_2.png -------------------------------------------------------------------------------- /sprites/fire/fire_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/fire/fire_3.png -------------------------------------------------------------------------------- /sprites/fire/fire_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/fire/fire_4.png -------------------------------------------------------------------------------- /sprites/fire/fire_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/fire/fire_5.png -------------------------------------------------------------------------------- /sprites/items/aquaPack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/aquaPack.png -------------------------------------------------------------------------------- /sprites/items/blaster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/blaster.png -------------------------------------------------------------------------------- /sprites/items/healthPickup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/healthPickup.png -------------------------------------------------------------------------------- /sprites/items/itemPickup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/itemPickup.png -------------------------------------------------------------------------------- /sprites/items/pickup_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/pickup_back.png -------------------------------------------------------------------------------- /sprites/items/rocketLauncher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/rocketLauncher.png -------------------------------------------------------------------------------- /sprites/items/spearGun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/items/spearGun.png -------------------------------------------------------------------------------- /sprites/newPlayer/aquapack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/aquapack.png -------------------------------------------------------------------------------- /sprites/newPlayer/arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/arm.png -------------------------------------------------------------------------------- /sprites/newPlayer/armBlaster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/armBlaster.png -------------------------------------------------------------------------------- /sprites/newPlayer/armRocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/armRocket.png -------------------------------------------------------------------------------- /sprites/newPlayer/armSpear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/armSpear.png -------------------------------------------------------------------------------- /sprites/newPlayer/armSpearLoaded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/armSpearLoaded.png -------------------------------------------------------------------------------- /sprites/newPlayer/backArm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/backArm.png -------------------------------------------------------------------------------- /sprites/newPlayer/backArm_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/backArm_old.png -------------------------------------------------------------------------------- /sprites/newPlayer/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/body.png -------------------------------------------------------------------------------- /sprites/newPlayer/helmet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/helmet.png -------------------------------------------------------------------------------- /sprites/newPlayer/jetpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/jetpack.png -------------------------------------------------------------------------------- /sprites/newPlayer/newPlayer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/newPlayer.png -------------------------------------------------------------------------------- /sprites/newPlayer/spear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer/spear.png -------------------------------------------------------------------------------- /sprites/newPlayer2/arm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/arm.png -------------------------------------------------------------------------------- /sprites/newPlayer2/armBlaster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/armBlaster.png -------------------------------------------------------------------------------- /sprites/newPlayer2/armRocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/armRocket.png -------------------------------------------------------------------------------- /sprites/newPlayer2/armSpear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/armSpear.png -------------------------------------------------------------------------------- /sprites/newPlayer2/armSpearLoaded.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/armSpearLoaded.png -------------------------------------------------------------------------------- /sprites/newPlayer2/backArm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/backArm.png -------------------------------------------------------------------------------- /sprites/newPlayer2/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/body.png -------------------------------------------------------------------------------- /sprites/newPlayer2/helmet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/newPlayer2/helmet.png -------------------------------------------------------------------------------- /sprites/player/aquapack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/aquapack.png -------------------------------------------------------------------------------- /sprites/player/armSpear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/armSpear.png -------------------------------------------------------------------------------- /sprites/player/arm_blaster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/arm_blaster.png -------------------------------------------------------------------------------- /sprites/player/arm_blaster2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/arm_blaster2.png -------------------------------------------------------------------------------- /sprites/player/arm_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/arm_empty.png -------------------------------------------------------------------------------- /sprites/player/body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/body.png -------------------------------------------------------------------------------- /sprites/player/bomb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/bomb.png -------------------------------------------------------------------------------- /sprites/player/helmet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/helmet.png -------------------------------------------------------------------------------- /sprites/player/jetpack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/jetpack.png -------------------------------------------------------------------------------- /sprites/player/rocketLauncher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/rocketLauncher.png -------------------------------------------------------------------------------- /sprites/player/rocketLauncherAlt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/rocketLauncherAlt.png -------------------------------------------------------------------------------- /sprites/player/spear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/player/spear.png -------------------------------------------------------------------------------- /sprites/ui/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/ui/github.png -------------------------------------------------------------------------------- /sprites/ui/sound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/challacade/cavern/0d190d6099dfdf47d871d74790d41fae414024f6/sprites/ui/sound.png --------------------------------------------------------------------------------