Grog-Knight

some game in C++
Log | Files | Refs | Submodules | README | LICENSE | git clone https://git.ne02ptzero.me/git/Grog-Knight

commit de74fdc839dc66e4780f17b2f167ecaf380279b8
parent c7e814ff655ee8e5f93b984f628aa539cd6061b7
Author: Louis Solofrizzo <louis@ne02ptzero.me>
Date:   Wed,  1 Jul 2015 19:19:27 +0200

Merge pull request #18 from Ne02ptzero/build

All good
Diffstat:
MAngel/Infrastructure/World.cpp | 161++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
MAngel/Infrastructure/World.h | 352++++++++++++++++++++++++++++++++++++++++---------------------------------------
MAngel/Input/Input.cpp | 10++++------
MAngel/Input/InputManager.cpp | 11+++++++++++
MAngel/Input/InputManager.h | 5+++--
MAngel/Libraries/Box2D-2.2.1/Box2D/Collision/Shapes/b2ChainShape.h | 4++--
MAngel/Libraries/glfw-3.0.3/deps/GL/glext.h | 9+++++++--
MAngel/Messaging/Switchboard.cpp | 26++++++++++++++++++++++++--
MAngel/Messaging/Switchboard.h | 4+++-
AConfig/Bindings.json | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
AConfig/Settings.json | 11+++++++++++
MConfig/input_bindings.ini | 59+++++++++++++++++++++++++++++------------------------------
MMACOSX/Makefile | 57++++++++++++++++++++++++++++++---------------------------
MMakefile | 49++++++++++++++++++++++++++-----------------------
MMaps/MapCastle_3.json | 7+++----
AResources/Elements/Archer.json | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MResources/Elements/Armors/ChestArmor.json | 2+-
MResources/Elements/Armors/Robes.json | 6+++---
DResources/Elements/Hero.json | 107-------------------------------------------------------------------------------
MResources/Elements/Rings/NiceRing.json | 2+-
MResources/Elements/Rings/SmallRing.json | 2+-
AResources/Elements/Warrior.json | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MResources/Elements/Weapons/Bow.json | 5+++--
MResources/Elements/Weapons/Sword.json | 5+++--
AResources/Fonts/Market_Deco.ttf | 0
AResources/HUD/bag_empty.png | 0
AResources/HUD/bag_unavailable.png | 0
AResources/HUD/bg1.png | 0
AResources/HUD/bg2.png | 0
AResources/HUD/bg3.png | 0
AResources/HUD/gold.png | 0
AResources/HUD/normal_stuff.png | 0
AResources/HUD/perso_bg.png | 0
AResources/HUD/perso_pin.png | 0
AResources/HUD/spell_bg.png | 0
AResources/HUD/spells_bg.png | 0
AResources/HUD/tooltip_stuff_bg.png | 0
AResources/HUD/weapon_stuff.png | 0
AResources/Images/Blast/blast_000.png | 0
AResources/Images/Blast/blast_001.png | 0
AResources/Images/HUD/cible.png | 0
AResources/Images/HUD/selecItem.png | 0
AResources/Images/Hero/hero_074.png | 0
AResources/Images/Hero/hero_075.png | 0
AResources/Images/Hero/hero_076.png | 0
AResources/Images/Hero/hero_077.png | 0
AResources/Images/Hero/hero_078.png | 0
AResources/Images/Hero/hero_079.png | 0
AResources/Images/Hero/hero_080.png | 0
AResources/Images/Hero/hero_081.png | 0
AResources/Images/Hero/hero_082.png | 0
AResources/Images/Hero/hero_083.png | 0
AResources/Images/Hero/hero_084.png | 0
AResources/Images/Hero/hero_085.png | 0
AResources/Images/Hero/hero_086.png | 0
AResources/Images/Hero/hero_087.png | 0
MSources/inc/Characters.hpp | 41++++++++++++++++++++++++++++++++++++++++-
MSources/inc/Elements.hpp | 4++--
MSources/inc/Enemy.hpp | 2+-
MSources/inc/Equipment.hpp | 1+
MSources/inc/Game.hpp | 7+++++++
ASources/inc/HUDTargeting.hpp | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
MSources/inc/HUDWindow.hpp | 9++++++++-
MSources/inc/Hero.hpp | 3++-
MSources/inc/Inventory.hpp | 2++
MSources/inc/Loot.hpp | 1+
MSources/inc/Menu.hpp | 46+++++++++++++++++++++++++++++++++++++++++++++-
MSources/inc/Projectile.hpp | 3+++
ASources/inc/Quit.hpp | 43+++++++++++++++++++++++++++++++++++++++++++
ASources/inc/SpecialMoves.hpp | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MSources/inc/Tooltip.hpp | 13+++++++------
MSources/inc/Weapon.hpp | 7+++----
MSources/inc/main.hpp | 2+-
ASources/src/.#PassivePattern.cpp | 2++
ASources/src/.#Pattern.cpp | 2++
MSources/src/Armor.cpp | 15+++++++++++++--
MSources/src/Characters.cpp | 547++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
MSources/src/Consumable.cpp | 4++++
MSources/src/ContactFilter.cpp | 30+++++++++++++++---------------
MSources/src/Elements.cpp | 3+--
MSources/src/Enemy.cpp | 60+++++++++++++++++++++++++++++++++---------------------------
MSources/src/Equipment.cpp | 15++++++++++++---
MSources/src/Game.cpp | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
ASources/src/HUDTargeting.cpp | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MSources/src/HUDWindow.cpp | 215++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
MSources/src/Hero.cpp | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
MSources/src/Inventory.cpp | 38+++++++++++++++++++++++++++-----------
MSources/src/Loot.cpp | 24+++++++++++++++++-------
MSources/src/Map.cpp | 4+++-
MSources/src/Menu.cpp | 579++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
MSources/src/Object.cpp | 3+++
MSources/src/Projectile.cpp | 10+++++++---
ASources/src/Quit.cpp | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MSources/src/Ring.cpp | 6++++++
ASources/src/SpecialMoves.cpp | 217+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MSources/src/Tooltip.cpp | 62+++++++++++++++++++++++++++++++++++++++++++++++++-------------
MSources/src/Weapon.cpp | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
MSources/src/main.cpp | 7+++++--
98 files changed, 3056 insertions(+), 828 deletions(-)

diff --git a/Angel/Infrastructure/World.cpp b/Angel/Infrastructure/World.cpp @@ -1,29 +1,29 @@ ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2008-2014, Shane Liesegang // All rights reserved. -// -// Redistribution and use in source and binary forms, with or without +// +// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright +// +// * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. -// * Neither the name of the copyright holder nor the names of any -// contributors may be used to endorse or promote products derived from +// * Neither the name of the copyright holder nor the names of any +// contributors may be used to endorse or promote products derived from // this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. ////////////////////////////////////////////////////////////////////////////// @@ -56,6 +56,7 @@ #include <comdef.h> #endif #include <algorithm> +# include <sys/time.h> World* World::s_World = NULL; @@ -75,8 +76,13 @@ World::World() _gameManager = NULL; _elementsLocked = false; _highResScreen = false; - + _processingDeferredAdds = false; + + _physicsStep = 5; + _graphicsStep = 10; + _lastPhysics = 0; + _lastGraphics = 0; } World& World::GetInstance() @@ -113,7 +119,7 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri { return false; } - + _running = true; // Windows DLL locations @@ -155,12 +161,12 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri _chdir(bitsPath.c_str()); } #endif - + // General windowing initialization #if !ANGEL_MOBILE glfwInit(); #endif - + #if defined(__APPLE__) // Set up paths correctly in the .app bundle #if !ANGEL_MOBILE @@ -203,7 +209,7 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri chdir("Angel"); // the iPhone doesn't like having a "Resources" directory in the root of the .app bundle #endif #endif - + //Start scripting LuaScriptingModule::Prep(); @@ -214,7 +220,7 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri windowHeight = thePrefs.OverrideInt("WindowSettings", "height", windowHeight); windowWidth = thePrefs.OverrideInt("WindowSettings", "width", windowWidth); windowName = thePrefs.OverrideString("WindowSettings", "name", windowName); - + //Windowing system setup #if !ANGEL_MOBILE if (antiAliasing) @@ -226,7 +232,7 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri { _antiAliased = false; } - + GLFWmonitor* openOn = NULL; // windowed if (fullScreen) { @@ -240,17 +246,17 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri { glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); } - + _mainWindow = glfwCreateWindow(windowWidth, windowHeight, windowName.c_str(), openOn, NULL); glfwMakeContextCurrent(_mainWindow); - + int fbw, fbh; glfwGetFramebufferSize(_mainWindow, &fbw, &fbh); if (fbw == windowWidth * 2) { SetHighResolutionScreen(true); } - + #if defined(WIN32) glfwSwapInterval(0); // because double-buffering and Windows don't get along apparently #else @@ -264,14 +270,14 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri glfwSetScrollCallback(_mainWindow, MouseWheel); glfwSetWindowCloseCallback(_mainWindow, windowClosed); _prevTime = glfwGetTime(); - + Camera::ResizeCallback(_mainWindow, fbw, fbh); #else struct timeval tv; gettimeofday(&tv, NULL); _currTime = _startTime = tv.tv_sec + (double) tv.tv_usec / 1000000.0; #endif - + //OpenGL state setup #if !ANGEL_MOBILE glClearDepth(1.0f); @@ -297,10 +303,10 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri //Get textures going InitializeTextureLoading(); - + //Subscribe to camera changes theSwitchboard.SubscribeTo(this, "CameraChange"); - + //initialize singletons #if !ANGEL_MOBILE theInput; @@ -316,7 +322,7 @@ bool World::Initialize(unsigned int windowWidth, unsigned int windowHeight, Stri RegisterFont("Resources/Fonts/Inconsolata.otf", 24, "Console"); RegisterFont("Resources/Fonts/Inconsolata.otf", 18, "ConsoleSmall"); #endif - + LuaScriptingModule::Initialize(); return _initialized = true; @@ -388,7 +394,7 @@ bool World::SetupPhysics(const Vector2& gravity, const Vector2& maxVertex, const _physicsWorld = new b2World(gravityVector); _physicsWorld->SetContactListener(this); - + return _physicsSetUp = _physicsRunning = true; } @@ -399,10 +405,10 @@ void World::Destroy() theInput.Destroy(); #endif theSound.Shutdown(); - + FinalizeTextureLoading(); LuaScriptingModule::Finalize(); - + theUI.Shutdown(); if (_gameManager != NULL) @@ -437,7 +443,7 @@ void World::StartGame() glfwPollEvents(); #endif } - + #if !ANGEL_MOBILE glfwDestroyWindow(_mainWindow); glfwTerminate(); @@ -474,7 +480,7 @@ float World::CalculateNewDT() // SJML - We're now using the iOS GLKit to handle the timing of the update // functions, so there's no need to compare against time of day anymore. // This code is being left here (commented) in case we decide to someday - // port to other mobile platforms, stop using GLKit, etc. + // port to other mobile platforms, stop using GLKit, etc. // struct timeval tv; // gettimeofday(&tv, NULL); // _currTime = tv.tv_sec + (double) tv.tv_usec / 1000000.0 - _startTime; @@ -484,7 +490,7 @@ float World::CalculateNewDT() #endif _dt = MathUtil::Clamp((_currTime - _prevTime), 0.0f, MAX_TIMESTEP); _prevTime = _currTime; - return _dt; + return _dt; } void World::Simulate(bool simRunning) @@ -506,45 +512,47 @@ void World::Simulate(bool simRunning) _gameManager->Update(frame_dt); } + theSwitchboard.SendAllMessages(); if (simRunning) { - // Deliver any messages that have been queued from the last frame. - theSwitchboard.SendAllMessages(); + // Deliver any messages that have been queued from the last frame. RunPhysics(frame_dt); - + //Flag that the _elements array is locked so we don't try to add any // new actors during the update. _elementsLocked = true; UpdateRenderables(frame_dt); CleanupRenderables(); - _elementsLocked = false; + _elementsLocked = false; // Now that we're done updating the list, allow any deferred Adds to be processed. ProcessDeferredAdds(); ProcessDeferredLayerChanges(); ProcessDeferredRemoves(); - + theSwitchboard.Update(frame_dt); // Updated: 2015/05/12 15:36:50 by noich ### ########.fr // //if there are any system updates that still need to be run, put them here - } - + }/* else {*/ + //theSwitchboard.SendPauseMessages(); + /*}*/ + //making this the last update so we can accurately lock on position for rendering theCamera.Update(frame_dt); } void World::RunPhysics(float frame_dt) { - if (!_physicsSetUp || !_physicsRunning) + if (!_physicsSetUp || !_physicsRunning) return; _currentTouches.clear(); - + // fixed time step const float physicsDT = 1.0f/60.f; - + float total_step = _physicsRemainderDT + frame_dt; while (total_step >= physicsDT) { @@ -578,13 +586,13 @@ void World::SendCollisionNotifications(b2Contact* contact, bool beginning) { messageStart = "CollisionEndWith"; } - + PhysicsActor* pa1 /*= new PhysicsActor()*/; PhysicsActor* pa2 /*= new PhysicsActor()*/; pa1 = (PhysicsActor*)contact->GetFixtureA()->GetBody()->GetUserData(); pa2 = (PhysicsActor*)contact->GetFixtureB()->GetBody()->GetUserData(); - + if (pa1 != NULL) { String pa1Message = messageStart + pa1->GetName(); @@ -598,7 +606,7 @@ void World::SendCollisionNotifications(b2Contact* contact, bool beginning) _currentTouches[pa1].insert(pa2); } } - + if (pa2 != NULL) { String pa2Message = messageStart + pa2->GetName(); @@ -615,7 +623,6 @@ void World::SendCollisionNotifications(b2Contact* contact, bool beginning) /* MODIFIED CODE BY Louis */ if (pa1 && pa2) { - std::cout << "CALL " << pa1->getId() << ", " << pa2->getId() << std::endl; Game::callCallbacks(pa1->getId(), pa2->getId()); StringSet::iterator a = pa1->GetTags().begin(); StringSet::iterator b = pa2->GetTags().begin(); @@ -650,11 +657,31 @@ void World::EndContact(b2Contact* contact) void World::TickAndRender() { - Tick(); - Game::checkHeroPosition(); - Game::destroyAllBodies(); - Render(); - Game::showText(); + static int _physicsFPS = 0; + static int _graphicsFPS = 0; + static unsigned long long _lastFPS = 0; + + gettimeofday(&(this->_tp), NULL); + unsigned long long ms = this->_tp.tv_sec * 1000 + this->_tp.tv_usec / 1000; + if (ms > this->_lastPhysics + this->_physicsStep) { + this->_lastPhysics = ms; + Tick(); + Game::checkHeroPosition(); + Game::destroyAllBodies(); + _physicsFPS++; + } + // if (ms > this->_lastGraphics + this->_graphicsStep) { + // this->_lastGraphics = ms; + Render(); + Game::showText(); + _graphicsFPS++; + // } + if (ms > _lastFPS + 1000) { + std::cout << _physicsFPS << " / " << _graphicsFPS << " fps." << std::endl; + _lastFPS = ms; + _physicsFPS = 0; + _graphicsFPS = 0; + } } void World::Tick() @@ -786,15 +813,15 @@ void World::Add(Renderable *newElement, int layer) sysLog.Log("WARNING: Can't add a null element to the World."); return; } - + //Check to see if it's an Actor; give it a name if it doesn't have one Actor *a = dynamic_cast<Actor*> (newElement); if (a != NULL && !_processingDeferredAdds) { - // Ensures that the actor has a unique, non-empty name. + // Ensures that the actor has a unique, non-empty name. a->SetName(a->GetName()); } - + // If we're not locked, add directly to _elements. if (!_elementsLocked) { @@ -972,7 +999,7 @@ void World::SetSideBlockers(bool turnOn, float restitution) float thickness = 5.0f; //just so it's thick enough to avoid tunnelling Vector2 screenOrigin(((topRight.X - botLeft.X) * 0.5f) + botLeft.X, ((topRight.Y - botLeft.Y) * 0.5f) + botLeft.Y); - + //right blocker _blockers[0] = new PhysicsActor(); _blockers[0]->SetPosition(topRight.X + (thickness * 0.5f), screenOrigin.Y); @@ -992,7 +1019,7 @@ void World::SetSideBlockers(bool turnOn, float restitution) _blockers[1]->SetFriction(0.1f); _blockers[1]->SetRestitution(_blockerRestitution); _blockers[1]->InitPhysics(); - + //top blocker _blockers[2] = new PhysicsActor(); _blockers[2]->SetPosition(screenOrigin.X, topRight.Y + (thickness * 0.5f)); @@ -1002,7 +1029,7 @@ void World::SetSideBlockers(bool turnOn, float restitution) _blockers[2]->SetFriction(0.1f); _blockers[2]->SetRestitution(_blockerRestitution); _blockers[2]->InitPhysics(); - + //bottom blocker _blockers[3] = new PhysicsActor(); _blockers[3]->SetPosition(screenOrigin.X, botLeft.Y - (thickness * 0.5f)); @@ -1012,13 +1039,13 @@ void World::SetSideBlockers(bool turnOn, float restitution) _blockers[3]->SetFriction(0.1f); _blockers[3]->SetRestitution(_blockerRestitution); _blockers[3]->InitPhysics(); - + // We don't want these removed when we call ReloadLevel. for (int i=0; i<4; ++i) { _blockers[i]->Tag("NoDelete"); } - + theWorld.Add(_blockers[0]); theWorld.Add(_blockers[1]); theWorld.Add(_blockers[2]); diff --git a/Angel/Infrastructure/World.h b/Angel/Infrastructure/World.h @@ -1,29 +1,29 @@ ////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2008-2014, Shane Liesegang // All rights reserved. -// -// Redistribution and use in source and binary forms, with or without +// +// Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// -// * Redistributions of source code must retain the above copyright +// +// * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. -// * Neither the name of the copyright holder nor the names of any -// contributors may be used to endorse or promote products derived from +// * Neither the name of the copyright holder nor the names of any +// contributors may be used to endorse or promote products derived from // this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. ////////////////////////////////////////////////////////////////////////////// @@ -37,6 +37,8 @@ #include <Box2D/Box2D.h> +#include <ctime> + //forward declarations class Actor; class PhysicsActor; @@ -49,18 +51,18 @@ class Console; #define theWorld World::GetInstance() ///The central class that manages all aspects of the simulation -/** +/** * The World is the class that keeps track of all Renderables, handles the - * Update/Render loop, processes events, etc. - * - * Like the Camera, it uses the singleton pattern; you can't actually declare - * a new instance of a TagCollection. To access the World, use "theWorld" to - * retrieve the singleton object. "theWorld" is defined in both C++ and - * Lua. - * - * If you're not familiar with the singleton pattern, this paper is a good + * Update/Render loop, processes events, etc. + * + * Like the Camera, it uses the singleton pattern; you can't actually declare + * a new instance of a TagCollection. To access the World, use "theWorld" to + * retrieve the singleton object. "theWorld" is defined in both C++ and + * Lua. + * + * If you're not familiar with the singleton pattern, this paper is a good * starting point. (Don't be afraid that it's written by Microsoft.) - * + * * http://msdn.microsoft.com/en-us/library/ms954629.aspx */ @@ -68,30 +70,30 @@ class World : public b2ContactListener, public MessageListener { public: /** - * Used to access the singleton instance of this class. As a shortcut, - * you can just use "theWorld". - * + * Used to access the singleton instance of this class. As a shortcut, + * you can just use "theWorld". + * * @return The singleton */ static World& GetInstance(); - + /** * The initial call to get Angel up and running. Opens the window, sets - * up our display, and begins the Update/Render loop. - * + * up our display, and begins the Update/Render loop. + * * The values passed in here will be overridden by any values set in * the Preferences, with the WindowSettings table. (See the Preferences * documentation and the example preferences file in IntroGame for more * information.) - * + * * @param windowWidth The desired width (in pixels) of the window * @param windowHeight The desired height (in pixels) of the window * @param windowName The string that should appear in the window's title bar * @param antiAliasing Whether or not the window should be initialized with * anti-aliasing - * @param fullScreen Whether the game should be started in fullscreen mode. + * @param fullScreen Whether the game should be started in fullscreen mode. * Note that the resolution is determined from windowWidth and windowHeight, - * and that Angel will attempt to change the system's video mode + * and that Angel will attempt to change the system's video mode * accordingly. We don't do any detection of what modes are valid, so * make sure you're feeding this a legitimate resolution. * @param resizable Whether the user will be allowed to resize the game window @@ -100,7 +102,7 @@ public: * already initialized) */ bool Initialize(unsigned int windowWidth=1024, unsigned int windowHeight=768, String windowName="Angel Engine", bool antiAliasing=false, bool fullScreen=false, bool resizable=false); - + /** * Queries the video drivers to get a list of supported video modes for * fullscreen gameplay. You'll likely want to get a list of valid modes to give @@ -109,14 +111,14 @@ public: * * @return A list of video modes bundled, each bundled as a Vec3ui. The X * value is the width; the Y value is the height, and the Z-value - * represents the color depth. + * represents the color depth. */ std::vector<Vec3ui> GetVideoModes(); /** * Changes the dimension of the window while the game is running. Note that the * behavior is undefined if this method is called while in fullscreen mode. - * + * * @param windowWidth The new desired width * @param windowHeight The new desired height * @param windowName The new string to go in the window's title bar @@ -126,12 +128,12 @@ public: /** * Moves the window around on screen, relative to the system origin. Note that * behavior is undefined if this method is called while in fullscreen mode. - * + * * @param xPosition The new x position offset from the system origin * @param yPosition The new y position offset from the system origin */ void MoveWindow(int xPosition, int yPosition); - + #if !ANGEL_MOBILE /** * Returns a handle for the main window. For most games, you'll only have one @@ -146,256 +148,256 @@ public: /** * Intialize physics. If you're not using our built-in physics, you don't - * have to call this function, but no PhysicsActors will do anything - * until you do. - * + * have to call this function, but no PhysicsActors will do anything + * until you do. + * * @param gravity The gravity vector that will be applied to all PhysicsActors - * @param maxVertex The maximum vertex at which PhysicsActors will simulate. + * @param maxVertex The maximum vertex at which PhysicsActors will simulate. * Any PhysicsActors that go beyond this point will get "stuck" in the - * bounding box. - * @param minVertex The minimum vertex at which PhysicsActors will simulate. + * bounding box. + * @param minVertex The minimum vertex at which PhysicsActors will simulate. * Any PhysicsActors that go beyond this point will get "stuck" in the * bounding box. * @return True is successfully setup, false if physics were already initialized */ bool SetupPhysics(const Vector2& gravity = Vector2(0, -10), const Vector2& maxVertex = Vector2(100.0f, 100.0f), const Vector2& minVertex = Vector2(-100.0f, -100.0f)); - + /** - * Called when the game shuts down, does all cleanup. + * Called when the game shuts down, does all cleanup. */ void Destroy(); - + /** - * Removes all Actors from the world (pending a check to the + * Removes all Actors from the world (pending a check to the * GameManager::IsProtectedFromUnloadAll function) and resets the camera - * to its default positioning. + * to its default positioning. */ void ResetWorld(); - + /** * Called once, after your world setup is done and you're ready to kick - * things into motion. + * things into motion. */ void StartGame(); - + /** * Ends the game, has everything prepare for shutdown. Should only be - * called once, when you're ready to finish. + * called once, when you're ready to finish. */ void StopGame(); - + /** - * Execute a string of Lua code. - * + * Execute a string of Lua code. + * * @param code The string to execute */ void ScriptExec(const String& code); - + /** - * Loads a level from Config/Level/[levelName].lua. - * - * Each section of a level file specifies an Actor to be added to the world. + * Loads a level from Config/Level/[levelName].lua. + * + * Each section of a level file specifies an Actor to be added to the world. * The name of the section will be the name of the Actor, and the values - * in each section will be applied in addition to (or overriding) the + * in each section will be applied in addition to (or overriding) the * ones specified in the archetype. Check the Actor::Create function for - * more information on how archetypes are specified. - * + * more information on how archetypes are specified. + * * @see Actor::Create - * @param levelName + * @param levelName */ void LoadLevel(const String& levelName); - + /** * Get the amount of time that elapsed between the start of the last frame * and the start of the current frame. Useful for rate controlling any - * changes on your actors. - * + * changes on your actors. + * * @return The amount of time elapsed in seconds */ const float GetDT(); - + /** * Toggles the simulation off. Several classes and objects will still * receive updates (GameManager, Console, Camera, etc.), but all standard - * Actors will not receive Update calls until you call World::StartSimulation. - * + * Actors will not receive Update calls until you call World::StartSimulation. + * * @return Whether the simulation was successfully paused */ const bool PauseSimulation(); - + /** - * Toggles the simulation back on. - * + * Toggles the simulation back on. + * * @see World::PauseSimulation * @return Whether the simulation was successfully resumed */ const bool ResumeSimulation(); - + /** * Toggles the physics simulation off. - * + * * @return Whether the physics simulation was successfully paused */ const bool PausePhysics(); - + /** - * Toggles the physics simulation back on. - * + * Toggles the physics simulation back on. + * * @see World::PausePhysics * @return Whether the physics simulation was successfully resumed */ const bool ResumePhysics(); /** - * Sets the world's background color. White by default. - * + * Sets the world's background color. White by default. + * * @param bgColor The new background color */ void SetBackgroundColor(const Color& bgColor); - + /** * Add a Renderable to the World so it will start receiving Update and - * Render calls every frame. - * + * Render calls every frame. + * * @param *newElement The new object to insert into the world * @param layer The layer at which to insert it */ void Add(Renderable *newElement, int layer = 0); - + /** - * Add a Renderable to the World with a named layer. - * + * Add a Renderable to the World with a named layer. + * * @param *newElement The new object to insert into the world * @param layer The name of the layer at which to insert it */ void Add(Renderable *newElement, const String& layer); - + /** - * Remove a Renderable from the World. Does not deallocate any memory; - * you're responsible for doing that yourself. - * + * Remove a Renderable from the World. Does not deallocate any memory; + * you're responsible for doing that yourself. + * * @param *oldElement The element to remove */ void Remove(Renderable *oldElement); - + /** * Move a Renderable to a new layer - * + * * @param element The renderable to move * @param newLayer Its new home */ void UpdateLayer(Renderable* element, int newLayer); - + /** * Move a Renderable to a new layer by name - * + * * @param element The renderable to move * @param newLayerName The name of its new home */ void UpdateLayer(Renderable* element, const String& newLayerName); - + /** * Lets you name layers for easier reference later. This name can be - * used by the World::Add and World::UpdateLayer functions. - * + * used by the World::Add and World::UpdateLayer functions. + * * @param name The string to assign as a layer name * @param number The number to which this name should refer */ void NameLayer(const String& name, int number); - + /** - * Retrieve the layer number associated with a name. - * + * Retrieve the layer number associated with a name. + * * @param name The name to look up * @return The layer number. Will return 0 if the name has not been - * registered; note that 0 is still a valid layer. + * registered; note that 0 is still a valid layer. */ const int GetLayerByName(const String& name); - + /** * Get the set of layers and their associated Renderables - * + * * @return The world's layers */ RenderLayers& GetLayers() { return _layers; } - + /** * Register a new Console with the World. Only one Console can be - * activated at at time. - * + * activated at at time. + * * @param console The new Console that should accept input */ void RegisterConsole(Console* console); - + /** * Get a pointer to the current registered console - * + * * @return The current console */ Console* GetConsole(); - + /** * Get a reference to the Box2D world that's handling all the Physics - * - * @return + * + * @return */ b2World &GetPhysicsWorld(); - + /** * Lets you know if physics have been appropriately initialized with the - * World::SetupPhysics function. - * + * World::SetupPhysics function. + * * @return True if physics has been initialized */ const bool IsPhysicsSetUp() { return _physicsSetUp; } - + /** * Wakes up all physics bodies in the world. See the Box2D documentation - * for more information on what this means. + * for more information on what this means. */ void WakeAllPhysics(); - + /** - * Implementation of the b2ContactListener::BeginContact function. We - * use it to manage collision notifications. + * Implementation of the b2ContactListener::BeginContact function. We + * use it to manage collision notifications. */ virtual void BeginContact(b2Contact* contact); - + /** - * Implementation of the b2ContactListener::EndContact function. We - * use it to manage collision notifications. + * Implementation of the b2ContactListener::EndContact function. We + * use it to manage collision notifications. */ virtual void EndContact(b2Contact* contact); - + /** - * When working with physics, oftentimes you want to keep objects from - * going beyond the edge of the visible screen. This function sets up - * objects to block the edges so they can't. - * - * @param turnOn If true, side blockers are enabled, if false, they're + * When working with physics, oftentimes you want to keep objects from + * going beyond the edge of the visible screen. This function sets up + * objects to block the edges so they can't. + * + * @param turnOn If true, side blockers are enabled, if false, they're * disabled * @param restitution The restitution of the blockers (how bouncy they are) */ void SetSideBlockers(bool turnOn, float restitution=-1.0f); - + /** * Find out how much time has elapsed since the game started - * + * * @return Total elapsed time in seconds */ float GetCurrentTimeSeconds() { return ( float(_currTime) ); } - + /** - * Find out how much time has elapsed since a specific timestamp. - * + * Find out how much time has elapsed since a specific timestamp. + * * @param lastTime The time index you want to calculate the difference from * @return How much time has elapsed since lastTime */ float GetTimeSinceSeconds( float lastTime ) {return GetCurrentTimeSeconds() - lastTime;} - + /** * Draw a line for a specified length of time. - * + * * @param a The starting point of the line * @param b The ending point of the line * @param time The length of time the line will be drawn (less than 0 will draw it permanently) @@ -405,46 +407,46 @@ public: /** * Purge all debug drawing. - * + * */ void PurgeDebugDrawing(); /** * Check whether the simulation is running. See also StartSimulation() and StopSimulation(). - * + * * @return Whether the simulation is running */ const bool IsSimulationOn(); /** - * Set a GameManager object to be your high-level coordinator. - * + * Set a GameManager object to be your high-level coordinator. + * * @param gameManager The new manager */ void SetGameManager(GameManager* gameManager); - + /** * Get the current registered manager - * + * * @return The GameManager currently overseeing the game */ GameManager* GetGameManager() { return _gameManager; } - + /** - * Get an iterator to start cycling through all the Renderables that - * have been added to the World. - * + * Get an iterator to start cycling through all the Renderables that + * have been added to the World. + * * @return An iterator pointing to the first Renderable */ RenderableIterator GetFirstRenderable() { RenderableIterator iter; - return iter.begin(); + return iter.begin(); } - + /** * Get an iterator pointing to the last Renderable in the World. - * + * * @return An iterator at the end of the list */ RenderableIterator GetLastRenderable() @@ -452,22 +454,22 @@ public: RenderableIterator iter; return iter.end(); } - + /** - * Removes all Actors from the world (pending a check to the + * Removes all Actors from the world (pending a check to the * GameManager::IsProtectedFromUnloadAll function). */ void UnloadAll(); - + /** * Implementation of the MessageListener::ReceiveMessage function. Used * to get notifications of camera changes so the side blockers can be - * updated if they're enabled. - * - * @param m The message being delivered. + * updated if they're enabled. + * + * @param m The message being delivered. */ virtual void ReceiveMessage(Message *m); - + /** * Lets you know whether the current rendering device is high resolution * (like the iPhone 4's "Retina Display"). @@ -475,11 +477,11 @@ public: * @return Whether or not the screen is high resolution. */ const bool IsHighResScreen() { return _highResScreen; } - + /** * INTERNAL: This function is called by the OS setup functions to let Angel * know about the screen resolution. If you call in manually, expect - * weirdness. + * weirdness. * * @param highRes Whether or not we should be set up for high resolution rendering. */ @@ -488,39 +490,39 @@ public: /** * Lets you know whether the current display is antialiased. * - * @return Whether or not we're running with antialiasing (multisampling). + * @return Whether or not we're running with antialiasing (multisampling). */ const bool IsAntiAliased() { return _antiAliased; } - + /** * INTERNAL: This function is used by various OS systems to run the Angel - * update loop. If you call it manually, expect weirdness. + * update loop. If you call it manually, expect weirdness. */ void TickAndRender(); /** * INTERNAL: This function is used by various OS systems to run the Angel - * update loop. If you call it manually, expect weirdness. + * update loop. If you call it manually, expect weirdness. */ void Tick(); /** * INTERNAL: This function is used by various OS systems to run the Angel - * update loop. If you call it manually, expect weirdness. + * update loop. If you call it manually, expect weirdness. */ void Render(); /** * INTERNAL: This function is used by various OS systems to run the Angel - * update loop. If you call it manually, expect weirdness. - */ + * update loop. If you call it manually, expect weirdness. + */ void SetDT(float dt) { #if ANGEL_MOBILE _systemEstimatedDT = dt; #endif } - + protected: World(); static World* s_World; @@ -560,11 +562,17 @@ private: bool _initialized; bool _started; + struct timeval _tp; + unsigned long long _lastPhysics; + unsigned long long _lastGraphics; + int _physicsStep; + int _graphicsStep; + RenderLayers _layers; bool _processingDeferredAdds; - std::vector<RenderableLayerPair> _deferredAdds; + std::vector<RenderableLayerPair> _deferredAdds; std::vector<RenderableLayerPair> _deferredLayerChanges; std::vector<Renderable*> _deferredRemoves; std::map<String, int> _layerNames; @@ -574,7 +582,7 @@ private: b2World *_physicsWorld; bool _physicsSetUp; bool _physicsRunning; - + void SendCollisionNotifications(b2Contact* cp, bool beginning); std::map< PhysicsActor*, ActorSet > _currentTouches; diff --git a/Angel/Input/Input.cpp b/Angel/Input/Input.cpp @@ -34,6 +34,7 @@ #include "../Infrastructure/World.h" #include "../Infrastructure/Console.h" #include "../Input/InputManager.h" +#include "../../Sources/inc/Game.hpp" void charInput(GLFWwindow* window, unsigned int key) @@ -49,10 +50,12 @@ void keyboardInput(GLFWwindow* window, int key, int scancode, int state, int mod { if (state == GLFW_PRESS) { + if (Game::isWaitingForBind) + Game::currentGame->menu->getBind(key); /* Console event */ if (key == theWorld.GetConsole()->GetToggleConsoleKey()) { - theWorld.GetConsole()->Enable(!theWorld.GetConsole()->IsEnabled()); + //theWorld.GetConsole()->Enable(!theWorld.GetConsole()->IsEnabled()); return; } else if (theWorld.GetConsole()->GetSpecialInputDown(key)) @@ -62,11 +65,6 @@ void keyboardInput(GLFWwindow* window, int key, int scancode, int state, int mod if (theInput.OnKeyDown(key)) return; - - if (key == GLFW_KEY_ESCAPE) - { - theWorld.StopGame(); - } } else if (state == GLFW_REPEAT) { theInput.OnKeyDown(key); diff --git a/Angel/Input/InputManager.cpp b/Angel/Input/InputManager.cpp @@ -362,3 +362,14 @@ int InputManager::GetHashFromKeyName( const String& keyId ) return (*itr).second; } + +// Code by Louis +String InputManager::GetKeyNameFromHash(int key) { + KeyNameTable::iterator itr; + for (itr = this->_keyNameTable.begin(); itr != this->_keyNameTable.end(); itr++) { + if (itr->second == key) + return itr->first; + } + return "None"; +} +// End diff --git a/Angel/Input/InputManager.h b/Angel/Input/InputManager.h @@ -77,6 +77,7 @@ class InputManager typedef hashmap_ns::hash_map<int, bool> XboxButtonState; public: + friend class Menu; static InputManager &GetInstance(); static void Destroy(); @@ -105,6 +106,7 @@ protected: private: InputBinding* GetBinding( int hashVal ); int GetHashFromKeyName( const String& keyId ); + String GetKeyNameFromHash(int key); void ClearXboxButtonStates(); private: @@ -113,4 +115,4 @@ private: KeyNameTable _keyNameTable; BindingTable _bindingTable; XboxButtonState _xBoxButtonStates[MAX_CONTROLLERS]; -};- \ No newline at end of file +}; diff --git a/Angel/Libraries/Box2D-2.2.1/Box2D/Collision/Shapes/b2ChainShape.h b/Angel/Libraries/Box2D-2.2.1/Box2D/Collision/Shapes/b2ChainShape.h @@ -95,8 +95,8 @@ inline b2ChainShape::b2ChainShape() m_radius = b2_polygonRadius; m_vertices = NULL; m_count = 0; - m_hasPrevVertex = NULL; - m_hasNextVertex = NULL; + m_hasPrevVertex = false; + m_hasNextVertex = false; } #endif diff --git a/Angel/Libraries/glfw-3.0.3/deps/GL/glext.h b/Angel/Libraries/glfw-3.0.3/deps/GL/glext.h @@ -4130,8 +4130,13 @@ GLAPI void APIENTRY glVertexBlendARB (GLint count); #ifndef GL_ARB_vertex_buffer_object #define GL_ARB_vertex_buffer_object 1 -typedef ptrdiff_t GLsizeiptrARB; -typedef ptrdiff_t GLintptrARB; + +// Code by Louis +# ifndef __APPLE__ + typedef ptrdiff_t GLsizeiptrARB; + typedef ptrdiff_t GLintptrARB; +# endif +// End #define GL_BUFFER_SIZE_ARB 0x8764 #define GL_BUFFER_USAGE_ARB 0x8765 #define GL_ARRAY_BUFFER_ARB 0x8892 diff --git a/Angel/Messaging/Switchboard.cpp b/Angel/Messaging/Switchboard.cpp @@ -172,4 +172,27 @@ void Switchboard::SendAllMessages() SubscribeTo(_deferredAdds[i]._subscriber, _deferredAdds[i]._messageType); } _deferredAdds.clear(); -}- \ No newline at end of file +} + +void Switchboard::SendPauseMessages(void) { + while (!_messages.empty()) + { + String frontMessageName = _messages.front()->GetMessageName(); + std::cout << frontMessageName << std::endl; + if (_subscribers.find(frontMessageName) != _subscribers.end()) + { + std::set<MessageListener*>::iterator listenIt = _subscribers[frontMessageName].begin(); + while (listenIt != _subscribers[frontMessageName].end()) + { + if (this->_messages.front()->GetMessageName() == "escape") { + (*listenIt)->ReceiveMessage(this->_messages.front()); + std::cout << "Here" << std::endl; + //return ; + } + listenIt++; + } + } + delete _messages.front(); + _messages.pop(); + } +} diff --git a/Angel/Messaging/Switchboard.h b/Angel/Messaging/Switchboard.h @@ -108,6 +108,7 @@ public: */ const bool SubscribeTo(MessageListener* subscriber, const String& messageType); + /** * Lets a MessageListener stop receiving notifications of specific * name. MessageListeners automatically unsubscribe from all their Messages @@ -150,7 +151,8 @@ public: * directly in your game code. */ void SendAllMessages(); - + + void SendPauseMessages(); protected: Switchboard(); static Switchboard* s_Switchboard; diff --git a/Config/Bindings.json b/Config/Bindings.json @@ -0,0 +1,100 @@ +/* This file is generated by Grog-Like. DO NOT modify it. */ +{ + "General" : + { + "Backspace" : + { + "broadcast" : "deletePressed", + "key" : "BACKSPACE" + }, + "Enter" : + { + "broadcast" : "enterPressed", + "key" : "ENTER" + }, + "Escape" : + { + "broadcast" : "escape", + "key" : "ESCAPE" + } + }, + "Inventory" : + { + "Drop an Item" : + { + "broadcast" : "dropItem", + "key" : "V" + }, + "Equip an Item" : + { + "broadcast" : "equipSelectedItem", + "key" : "R" + }, + "Go to next Item" : + { + "broadcast" : "cycleInventory", + "key" : "TAB" + }, + "Pick an Item" : + { + "broadcast" : "pickupItemPressed", + "key" : "F" + } + }, + "Move" : + { + "Attack" : + { + "broadcast" : "attack", + "key" : "E" + }, + "Backward" : + { + "broadcast" : "backward", + "key" : "LEFT_ARROW" + }, + "Forward" : + { + "broadcast" : "forward", + "key" : "RIGHT_ARROW" + }, + "Jump" : + { + "broadcast" : "jump", + "key" : "SPACE" + }, + "Look Down" : + { + "broadcast" : "down", + "key" : "DOWN_ARROW" + }, + "Look Up" : + { + "broadcast" : "up", + "key" : "UP_ARROW" + }, + "Special Move" : + { + "broadcast" : "specialMove", + "key" : "T" + }, + "Swap Charcaters(Debug)" : + { + "broadcast" : "changerCharacter", + "key" : "P" + } + }, + "Targeting" : + { + "Target an Enemy" : + { + "broadcast" : "lockTarget", + "key" : "M" + }, + "Unlock Target" : + { + "broadcast" : "unlockTarget", + "key" : "K" + } + } +} diff --git a/Config/Settings.json b/Config/Settings.json @@ -0,0 +1,11 @@ +{ + "Resolution": { + "1024x720" : 1, + "1524x1020" : 0, + "FullScreen": 0 + }, + "Anti-Aliasing": { + "Yes": 1, + "No" : 0 + } +} diff --git a/Config/input_bindings.ini b/Config/input_bindings.ini @@ -1,30 +1,29 @@ -; This is the key-bindings file. -;; MOVEMENT - - SPACE = +jumpPressed - SPACE = -jumpReleased - RIGHT_ARROW = +forwardPressed - RIGHT_ARROW = -forwardReleased - LEFT_ARROW = +backwardPressed - LEFT_ARROW = -backwardReleased - - - -;; ORENTATION - UP_ARROW = +upPressed - DOWN_ARROW = +downPressed - UP_ARROW = -upReleased - DOWN_ARROW = -downReleased - -;; ATTACK - E = +attackPressed - E = -attackReleased - -;; OTHER ACTIONS - F = pickupItemPressed - R = equipSelectedItem - TAB = cycleInventory - -;; MENU - - ENTER = enterPressed +; This file is generated by Grog-Like. DO NOT modify it. +;; General + BACKSPACE = deletePressed + ENTER = enterPressed + ESCAPE = +escapePressed + ESCAPE = -escapeReleased +;; Inventory + V = dropItem + R = equipSelectedItem + TAB = cycleInventory + F = pickupItemPressed +;; Move + E = +attackPressed + E = -attackReleased + LEFT_ARROW = +backwardPressed + LEFT_ARROW = -backwardReleased + RIGHT_ARROW = +forwardPressed + RIGHT_ARROW = -forwardReleased + SPACE = +jumpPressed + SPACE = -jumpReleased + DOWN_ARROW = +downPressed + DOWN_ARROW = -downReleased + UP_ARROW = +upPressed + UP_ARROW = -upReleased + T = specialMove + P = changerCharacter +;; Targeting + M = lockTarget + K = unlockTarget diff --git a/MACOSX/Makefile b/MACOSX/Makefile @@ -1,39 +1,42 @@ NAME = rogue-like CC = g++ -CFLAGS = -std=c++0x -arch i386 -Wno-deprecated -g +CFLAGS = -std=c++0x -arch i386 -Wno-deprecated -g -Wno-error=unused-command-line-argument -Wno-error=null-conversion -Wno-return-type ANGEL_FLAG = -D ANGEL -SRCS = ../Sources/src/Elements.cpp \ - ../Sources/src/Game.cpp \ - ../Sources/src/main.cpp \ - ../Sources/src/Maps.cpp \ - ../Sources/src/Hero.cpp \ - ../Sources/src/Projectile.cpp \ - ../Sources/src/Room.cpp \ - ../Sources/src/LevelGenerator.cpp \ - ../Sources/src/Loot.cpp \ - ../Sources/src/EnemyList.cpp \ - ../Sources/src/Enemy.cpp \ - ../Sources/src/GameContactListener.cpp \ - ../Sources/src/ContactFilter.cpp \ - ../Sources/src/Weapon.cpp \ - ../Sources/src/Log.cpp \ - ../Sources/src/Armor.cpp \ +SRCS = ../Sources/src/Armor.cpp \ ../Sources/src/ArmorList.cpp \ ../Sources/src/Characters.cpp \ - ../Sources/src/Object.cpp \ - ../Sources/src/WeaponList.cpp \ - ../Sources/src/Map.cpp \ - ../Sources/src/Equipment.cpp \ ../Sources/src/Consumable.cpp \ + ../Sources/src/ContactFilter.cpp \ + ../Sources/src/Elements.cpp \ + ../Sources/src/Enemy.cpp \ + ../Sources/src/EnemyList.cpp \ + ../Sources/src/Equipment.cpp \ + ../Sources/src/Game.cpp \ + ../Sources/src/GameContactListener.cpp \ + ../Sources/src/Hero.cpp \ ../Sources/src/Hitbox.cpp \ + ../Sources/src/HUDTargeting.cpp \ ../Sources/src/HUDWindow.cpp \ + ../Sources/src/Inventory.cpp \ + ../Sources/src/LevelGenerator.cpp \ + ../Sources/src/Log.cpp \ + ../Sources/src/Loot.cpp \ + ../Sources/src/main.cpp \ + ../Sources/src/Map.cpp \ + ../Sources/src/Maps.cpp \ ../Sources/src/Menu.cpp \ + ../Sources/src/Object.cpp \ + ../Sources/src/PassivePattern.cpp \ + ../Sources/src/Pattern.cpp \ + ../Sources/src/Projectile.cpp \ + ../Sources/src/Quit.cpp \ ../Sources/src/Ring.cpp \ ../Sources/src/RingList.cpp \ + ../Sources/src/Room.cpp \ + ../Sources/src/SpecialMoves.cpp \ ../Sources/src/Tooltip.cpp \ - ../Sources/src/Inventory.cpp \ - ../Sources/src/Pattern.cpp \ - ../Sources/src/PassivePattern.cpp + ../Sources/src/Weapon.cpp \ + ../Sources/src/WeaponList.cpp \ OBJS = $(SRCS:.cpp=.o) @@ -87,10 +90,10 @@ $(NAME): angel json $(OBJS) quick: $(OBJS) $(CC) $(CFLAGS) $(ANGEL_FLAG) -o build/$(NAME) $^ $(INCLUDES) $(LIBS) $(FRAMEWORKS) $(LIBS_FLAG) $(LIBS_DIRS) - cd build/ && ./rogue-like + cd build/ && lldb ./rogue-like %.o: %.cpp - $(CC) $(CFLAGS) $(INCLUDES) $(FRAMEWORKS) $(LIBS_FLAG) $(LIBS_DIRS) -o $@ -c $^ + $(CC) $(CFLAGS) $(INCLUDES) $(FRAMEWORKS) $(LIBS_FLAG) $(LIBS_DIRS) -o $@ -c $^ json: $(CC) $(CFLAGS) -I../Tools/jsoncpp/include/ -c $(wildcard ../Tools/jsoncpp/src/lib_json/*.cpp) \ @@ -111,6 +114,6 @@ quick-clean: rm $(OBJS) exec: - cd build/ && ./rogue-like + cd build/ && lldb ./rogue-like re: clean all diff --git a/Makefile b/Makefile @@ -59,38 +59,41 @@ endif SYSSRCS = \ $(WRAPPER) -SRCS = ./Sources/src/Elements.cpp \ - ./Sources/src/Game.cpp \ - ./Sources/src/main.cpp \ - ./Sources/src/Maps.cpp \ - ./Sources/src/Hero.cpp \ - ./Sources/src/Projectile.cpp \ - ./Sources/src/Room.cpp \ - ./Sources/src/LevelGenerator.cpp \ - ./Sources/src/Loot.cpp \ - ./Sources/src/EnemyList.cpp \ - ./Sources/src/Enemy.cpp \ - ./Sources/src/GameContactListener.cpp \ - ./Sources/src/ContactFilter.cpp \ - ./Sources/src/Weapon.cpp \ - ./Sources/src/Log.cpp \ - ./Sources/src/Armor.cpp \ +SRCS = ./Sources/src/Armor.cpp \ ./Sources/src/ArmorList.cpp \ ./Sources/src/Characters.cpp \ - ./Sources/src/Object.cpp \ - ./Sources/src/WeaponList.cpp \ - ./Sources/src/Map.cpp \ - ./Sources/src/Equipment.cpp \ ./Sources/src/Consumable.cpp \ + ./Sources/src/ContactFilter.cpp \ + ./Sources/src/Elements.cpp \ + ./Sources/src/Enemy.cpp \ + ./Sources/src/EnemyList.cpp \ + ./Sources/src/Equipment.cpp \ + ./Sources/src/Game.cpp \ + ./Sources/src/GameContactListener.cpp \ + ./Sources/src/Hero.cpp \ ./Sources/src/Hitbox.cpp \ + ./Sources/src/HUDTargeting.cpp \ ./Sources/src/HUDWindow.cpp \ + ./Sources/src/Inventory.cpp \ + ./Sources/src/LevelGenerator.cpp \ + ./Sources/src/Log.cpp \ + ./Sources/src/Loot.cpp \ + ./Sources/src/main.cpp \ + ./Sources/src/Map.cpp \ + ./Sources/src/Maps.cpp \ ./Sources/src/Menu.cpp \ + ./Sources/src/Object.cpp \ + ./Sources/src/PassivePattern.cpp \ + ./Sources/src/Pattern.cpp \ + ./Sources/src/Projectile.cpp \ + ./Sources/src/Quit.cpp \ ./Sources/src/Ring.cpp \ ./Sources/src/RingList.cpp \ + ./Sources/src/Room.cpp \ + ./Sources/src/SpecialMoves.cpp \ ./Sources/src/Tooltip.cpp \ - ./Sources/src/Inventory.cpp \ - ./Sources/src/Pattern.cpp \ - ./Sources/src/PassivePattern.cpp + ./Sources/src/Weapon.cpp \ + ./Sources/src/WeaponList.cpp \ SYSOBJS = $(patsubst %.cpp,%.o,$(SYSSRCS)) OBJS = $(patsubst %.cpp,%.o,$(SRCS)) diff --git a/Maps/MapCastle_3.json b/Maps/MapCastle_3.json @@ -10,9 +10,9 @@ "width":27, "x":0, "y":0 - }, + }, { - "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 48, 48, 48, 48, 48, 48, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 48, 48, 48, 48, 48, 48, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 63, 63, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "height":16, "name":"Tile Layer 2", "opacity":1, @@ -347,4 +347,4 @@ "tilewidth":32, "version":1, "width":27 -}- \ No newline at end of file +} diff --git a/Resources/Elements/Archer.json b/Resources/Elements/Archer.json @@ -0,0 +1,134 @@ +{ + "infos": { + "name": "Archer", + "id": 0, + "HP": 50, + "maxHP": 50, + "mana": 120, + "maxMana": 120, + "sprites": "Resources/Images/Archer/archer_000.png", + "size": 1.3, + "hitboxType": "special", + "hitbox": "heroHitbox" + }, + "Actions": { + "starting": { + "weapon": "Bow", + "armor": "Robes", + "ring": "SmallRing", + "specialMove": "wallJump", + "inventorySlots": 3 + }, + "forward": { + "subscribe": "forward", + "beginFrame": 02, + "endFrame": 07, + "time": 0.1, + "force": 12 + }, + "backward": { + "subscribe": "backward", + "beginFrame": 08, + "endFrame": 13, + "time": 0.1, + "force": 12 + }, + "jump": { + "subscribe": "jump", + "max": 3, + "force": 8, + "rejump": 12, + "beginFrame_right": 2, + "beginFrame_left": 8, + "fallingFrame_right": 5, + "fallingFrame_left": 10, + "endFrame_right": 7, + "endFrame_left": 13, + "time": 0.1 + }, + "pickupItem": { + "subscribe": "pickupItem", + "beginFrame": 0, + "endFrame": 0, + "time": 0.1 + }, + "attack": { + "subscribe": "attack", + "beginFrame_right": 14, + "endFrame_right": 18, + "beginFrame_left": 19, + "endFrame_left": 23, + "beginFrame_down": 24, + "endFrame_down": 29, + "beginFrame_up": 30, + "endFrame_up": 35, + "time": 0.05 + }, + "loadAttack_charge": { + "beginFrame_right": 0, + "holdFrame_right": 0, + "endFrame_right": 0, + "beginFrame_left": 0, + "holdFrame_left": 0, + "endFrame_left": 0, + "time": 0.1 + }, + "loadAttack_done": { + "beginFrame_right": 0, + "endFrame_right": 0, + "beginFrame_left": 0, + "endFrame_left": 0, + "time": 0.1 + }, + "dash": { + "cooldown": 1, + "dashSpeed": 30, + "uptime": 0.15, + "time": 0.1 + }, + "charge": { + "cooldown": 1, + "chargeSpeed": 20, + "uptime": 1 + }, + "stomp": { + "cooldown": 0, + "stompSpeed": 50 + }, + "blink": { + "cooldown": 0, + "blinkRange": 4 + }, + "wallJump": { + "maxJump": 1, + "force": 6 + }, + "down": { + "subscribe": "down" + }, + "up": { + "subscribe": "up" + }, + "breath": { + "beginFrame_right": 0, + "endFrame_right": 0, + "beginFrame_left": 1, + "endFrame_left": 1, + "time": 0.3 + }, + "takeDamage": { + "beginFrame_right": 0, + "endFrame_right": 0, + "beginFrame_left": 0, + "endFrame_left": 0, + "time": 0.1 + }, + "death": { + "beginFrame_right": 0, + "endFrame_right": 0, + "beginFrame_left": 0, + "endFrame_left": 0, + "time": 0.2 + } + } +} diff --git a/Resources/Elements/Armors/ChestArmor.json b/Resources/Elements/Armors/ChestArmor.json @@ -1,7 +1,7 @@ { "infos": { "name": "ChestArmor", - "flavor": "Hey look, its a ARMOR. A pretty shitty one actually...", + "flavor": "Hey look, its a ARMOR.\nA pretty shitty one actually...", "lvlRequired": 1, "sprites": "Resources/Images/Armors/ChestArmor.png", "lootLevel": 1 diff --git a/Resources/Elements/Armors/Robes.json b/Resources/Elements/Armors/Robes.json @@ -1,13 +1,13 @@ { "infos": { "name": "Robes", - "flavor": "Hey look, its a ARMOR. A pretty shitty one actually...", + "flavor": "Hey look, its a ARMOR.\nA pretty shitty one actually...", "lvlRequired": 1, "sprites": "Resources/Images/Armors/Robes.png", "lootLevel": 2 }, "bonus": { - "hpBuff": 45, - "manaBuff": 90 + "hpBuff": 50, + "manaBuff": 25 } } diff --git a/Resources/Elements/Hero.json b/Resources/Elements/Hero.json @@ -1,107 +0,0 @@ -{ - "infos": { - "name": "Hero", - "id": 0, - "HP": 75, - "maxHP": 75, - "mana": 80, - "maxMana": 100, - "sprites": "Resources/Images/Hero/hero_000.png", - "size": 1.3, - "maxSpeed": 5, - "weapon": "Sword", - "hitboxType": "special", - "hitbox": "heroHitbox" - }, - "Actions": { - "forward": { - "subscribe": "forward", - "beginFrame": 20, - "endFrame": 27, - "time": 0.1, - "force": 7 - }, - "backward": { - "subscribe": "backward", - "beginFrame": 28, - "endFrame": 35, - "time": 0.1, - "force": 7 - }, - "jump": { - "subscribe": "jump", - "max": 3, - "force": 6, - "rejump": 10, - "beginFrame_right": 4, - "beginFrame_left": 12, - "fallingFrame_right": 8, - "fallingFrame_left": 16, - "endFrame_right": 11, - "endFrame_left": 19, - "time": 0.1 - }, - "pickupItem": { - "subscribe": "pickupItem", - "beginFrame": 8, - "endFrame": 10, - "time": 0.1 - }, - "attack": { - "subscribe": "attack", - "beginFrame_right": 36, - "endFrame_right": 39, - "beginFrame_left": 43, - "endFrame_left": 40, - "beginFrame_up": 61, - "endFrame_up": 63, - "beginFrame_down": 58, - "endFrame_down": 60, - "time": 0.1 - }, - "loadAttack_charge": { - "beginFrame_right": 64, - "holdFrame_right": 65, - "endFrame_right": 66, - "beginFrame_left": 69, - "holdFrame_left": 70, - "endFrame_left": 71, - "time": 0.1 - }, - "loadAttack_done": { - "beginFrame_right": 66, - "endFrame_right": 68, - "beginFrame_left": 71, - "endFrame_left": 73, - - "time": 0.1 - }, - "down": { - "subscribe": "down" - }, - "up": { - "subscribe": "up" - }, - "breath": { - "beginFrame_right": 0, - "endFrame_right": 1, - "beginFrame_left": 2, - "endFrame_left": 3, - "time": 0.3 - }, - "takeDamage": { - "beginFrame_right": 44, - "endFrame_right": 46, - "beginFrame_left": 47, - "endFrame_left": 49, - "time": 0.1 - }, - "death": { - "beginFrame_right": 50, - "endFrame_right": 57, - "beginFrame_left": 43, - "endFrame_left": 45, - "time": 0.2 - } - } -} diff --git a/Resources/Elements/Rings/NiceRing.json b/Resources/Elements/Rings/NiceRing.json @@ -1,7 +1,7 @@ { "infos": { "name": "NiceRing", - "flavor": "Hey look, its a FUCKING RING. A pretty shitty one actually...", + "flavor": "Hey look, its a FUCKING RING.\nA pretty shitty one actually...", "lvlRequired": 1, "sprites": "Resources/Images/Rings/NiceRing.png", "lootLevel": 2, diff --git a/Resources/Elements/Rings/SmallRing.json b/Resources/Elements/Rings/SmallRing.json @@ -1,7 +1,7 @@ { "infos": { "name": "SmallRing", - "flavor": "Hey look, its a FUCKING RING. A pretty shitty one actually...", + "flavor": "Hey look, its a FUCKING RING.\nA pretty shitty one actually...", "lvlRequired": 1, "sprites": "Resources/Images/Rings/SmallRing.png", "lootLevel": 1, diff --git a/Resources/Elements/Warrior.json b/Resources/Elements/Warrior.json @@ -0,0 +1,153 @@ +{ + "infos": { + "name": "Warrior", + "id": 0, + "HP": 75, + "maxHP": 75, + "mana": 80, + "maxMana": 80, + "sprites": "Resources/Images/Hero/hero_000.png", + "size": 1.3, + "hitboxType": "special", + "hitbox": "heroHitbox" + }, + "Actions": { + "starting": { + "weapon": "Sword", + "armor": "ChestArmor", + "ring": "NiceRing", + "specialMove": "stomp", + "inventorySlots": 2 + }, + "forward": { + "subscribe": "forward", + "beginFrame": 20, + "endFrame": 27, + "time": 0.1, + "force": 8 + }, + "backward": { + "subscribe": "backward", + "beginFrame": 28, + "endFrame": 35, + "time": 0.1, + "force": 8 + }, + "jump": { + "subscribe": "jump", + "max": 30, + "force": 6, + "rejump": 10, + "beginFrame_right": 4, + "beginFrame_left": 12, + "fallingFrame_right": 8, + "fallingFrame_left": 16, + "endFrame_right": 11, + "endFrame_left": 19, + "time": 0.1 + }, + "pickupItem": { + "subscribe": "pickupItem", + "beginFrame": 8, + "endFrame": 10, + "time": 0.1 + }, + "attack": { + "subscribe": "attack", + "beginFrame_right": 36, + "endFrame_right": 39, + "beginFrame_left": 43, + "endFrame_left": 40, + "beginFrame_up": 61, + "endFrame_up": 63, + "beginFrame_down": 58, + "endFrame_down": 60, + "time": 0.05 + }, + "loadAttack_charge": { + "beginFrame_right": 64, + "holdFrame_right": 65, + "endFrame_right": 66, + "beginFrame_left": 69, + "holdFrame_left": 70, + "endFrame_left": 71, + "time": 0.1 + }, + "loadAttack_done": { + "beginFrame_right": 66, + "endFrame_right": 68, + "beginFrame_left": 71, + "endFrame_left": 73, + "time": 0.1 + }, + "dash": { + "cooldown": 1, + "dashSpeed": 30, + "uptime": 0.15, + "beginFrame_right": 74, + "endFrame_right": 78, + "beginFrame_left": 79, + "endFrame_left": 83, + "time": 0.05 + }, + "charge": { + "cooldown": 1, + "chargeSpeed": 20, + "uptime": 1 + }, + "stomp": { + "cooldown": 0, + "stompSpeed": 50, + "beginFrame_right": 84, + "endFrame_right": 87, + "beginFrame_left": 84, + "endFrame_left": 87, + "time": 0.1 + }, + "blink": { + "cooldown": 0, + "blinkRange": 4 + }, + "fly": { + "force": 4, + "beginFrame_right": 44, + "beginFrame_left": 44, + "fallingFrame_right": 44, + "fallingFrame_left": 44, + "endFrame_right": 44, + "endFrame_left": 44, + "time": 0.1 + }, + "wallJump": { + "maxJump": 1, + "force": 6 + }, + "down": { + "subscribe": "down" + }, + "up": { + "subscribe": "up" + }, + "breath": { + "beginFrame_right": 0, + "endFrame_right": 1, + "beginFrame_left": 2, + "endFrame_left": 3, + "time": 0.3 + }, + "takeDamage": { + "beginFrame_right": 44, + "endFrame_right": 46, + "beginFrame_left": 47, + "endFrame_left": 49, + "time": 0.1 + }, + "death": { + "beginFrame_right": 50, + "endFrame_right": 57, + "beginFrame_left": 43, + "endFrame_left": 45, + "time": 0.2 + } + } +} diff --git a/Resources/Elements/Weapons/Bow.json b/Resources/Elements/Weapons/Bow.json @@ -1,12 +1,13 @@ { "infos": { "name": "Bow", - "flavor": "This bow is supposed to shoot arrows. Supposed.", + "flavor": "This bow is supposed to\nshoot arrows. Supposed.", "hitbox": "PROJECTILE", "size": 0.5, "active": 0.1, "lvlRequired": 1, - "damage": 2, + "critRate": 5, + "damage": 2, "pushback": 1, "recovery": 0.5, "attack": "ranged", diff --git a/Resources/Elements/Weapons/Sword.json b/Resources/Elements/Weapons/Sword.json @@ -1,11 +1,12 @@ { "infos": { "name": "Sword", - "flavor": "Hey look, its a sword. A pretty shitty one actually...", + "flavor": "Hey look, its a sword.\nA pretty shitty one actually...", "hitbox": "SWORD", "size": 1, "lvlRequired": 1, - "damage": 5, + "critRate": 5, + "damage": 5, "recovery": 1, "pushback": 5, "active": 0.2, diff --git a/Resources/Fonts/Market_Deco.ttf b/Resources/Fonts/Market_Deco.ttf Binary files differ. diff --git a/Resources/HUD/bag_empty.png b/Resources/HUD/bag_empty.png Binary files differ. diff --git a/Resources/HUD/bag_unavailable.png b/Resources/HUD/bag_unavailable.png Binary files differ. diff --git a/Resources/HUD/bg1.png b/Resources/HUD/bg1.png Binary files differ. diff --git a/Resources/HUD/bg2.png b/Resources/HUD/bg2.png Binary files differ. diff --git a/Resources/HUD/bg3.png b/Resources/HUD/bg3.png Binary files differ. diff --git a/Resources/HUD/gold.png b/Resources/HUD/gold.png Binary files differ. diff --git a/Resources/HUD/normal_stuff.png b/Resources/HUD/normal_stuff.png Binary files differ. diff --git a/Resources/HUD/perso_bg.png b/Resources/HUD/perso_bg.png Binary files differ. diff --git a/Resources/HUD/perso_pin.png b/Resources/HUD/perso_pin.png Binary files differ. diff --git a/Resources/HUD/spell_bg.png b/Resources/HUD/spell_bg.png Binary files differ. diff --git a/Resources/HUD/spells_bg.png b/Resources/HUD/spells_bg.png Binary files differ. diff --git a/Resources/HUD/tooltip_stuff_bg.png b/Resources/HUD/tooltip_stuff_bg.png Binary files differ. diff --git a/Resources/HUD/weapon_stuff.png b/Resources/HUD/weapon_stuff.png Binary files differ. diff --git a/Resources/Images/Blast/blast_000.png b/Resources/Images/Blast/blast_000.png Binary files differ. diff --git a/Resources/Images/Blast/blast_001.png b/Resources/Images/Blast/blast_001.png Binary files differ. diff --git a/Resources/Images/HUD/cible.png b/Resources/Images/HUD/cible.png Binary files differ. diff --git a/Resources/Images/HUD/selecItem.png b/Resources/Images/HUD/selecItem.png Binary files differ. diff --git a/Resources/Images/Hero/hero_074.png b/Resources/Images/Hero/hero_074.png Binary files differ. diff --git a/Resources/Images/Hero/hero_075.png b/Resources/Images/Hero/hero_075.png Binary files differ. diff --git a/Resources/Images/Hero/hero_076.png b/Resources/Images/Hero/hero_076.png Binary files differ. diff --git a/Resources/Images/Hero/hero_077.png b/Resources/Images/Hero/hero_077.png Binary files differ. diff --git a/Resources/Images/Hero/hero_078.png b/Resources/Images/Hero/hero_078.png Binary files differ. diff --git a/Resources/Images/Hero/hero_079.png b/Resources/Images/Hero/hero_079.png Binary files differ. diff --git a/Resources/Images/Hero/hero_080.png b/Resources/Images/Hero/hero_080.png Binary files differ. diff --git a/Resources/Images/Hero/hero_081.png b/Resources/Images/Hero/hero_081.png Binary files differ. diff --git a/Resources/Images/Hero/hero_082.png b/Resources/Images/Hero/hero_082.png Binary files differ. diff --git a/Resources/Images/Hero/hero_083.png b/Resources/Images/Hero/hero_083.png Binary files differ. diff --git a/Resources/Images/Hero/hero_084.png b/Resources/Images/Hero/hero_084.png Binary files differ. diff --git a/Resources/Images/Hero/hero_085.png b/Resources/Images/Hero/hero_085.png Binary files differ. diff --git a/Resources/Images/Hero/hero_086.png b/Resources/Images/Hero/hero_086.png Binary files differ. diff --git a/Resources/Images/Hero/hero_087.png b/Resources/Images/Hero/hero_087.png Binary files differ. diff --git a/Sources/inc/Characters.hpp b/Sources/inc/Characters.hpp @@ -27,15 +27,19 @@ # define __Characters__ # include "Inventory.hpp" +# include "SpecialMoves.hpp" # include "Weapon.hpp" # include "Armor.hpp" # include "Ring.hpp" # include "Log.hpp" +# include "HUDTargeting.hpp" class Inventory; class Weapon; class Armor; class Ring; +class SpecialMoves; +class HUDTargeting; # ifdef __APPLE__ # include "../../Tools/jsoncpp/include/json/json.h" @@ -55,6 +59,7 @@ class Characters : public Elements { friend class Game; friend class Pattern; friend class PassivePattern; + friend class SpecialMoves; enum Orientation { UP, @@ -80,9 +85,14 @@ class Characters : public Elements { void setMana(int mana); int getMaxMana(void); int getMaxHP(void); + int getLevel(void); Weapon *getWeapon(void); Armor *getArmor(void); Ring *getRing(void); + bool getCharging(void); + int getMaxInventory(void); + Inventory *getInventory(void); + void destroyTarget(void); // Virtual function, overwritten in childs virtual void actionCallback(std::string name, int status) {}; @@ -94,6 +104,9 @@ class Characters : public Elements { virtual void unequipRing(void); void changeCanMove(void); + std::list<std::string> getSubscribes(void); + void unsubscribeFromAll(void); + void subscribeToAll(void); //Moved in order to get loot infos outside of class Json::Value _getAttr(std::string category, std::string key); @@ -119,21 +132,41 @@ class Characters : public Elements { bool _attackPressed; int _isLoadingAttack; bool _fullChargedAttack; + int _speMoveReady; + bool _canAttack; + bool _isCharging; + bool _isStomping; + bool _isFlying; + bool _flyTrigger; + bool _isDashing; + int _hasDashed; + int _level; + std::string _speMove; + SpecialMoves* _eqMove; Weapon* _weapon; Armor* _armor; Ring* _ring; Elements* _item; Inventory* _inventory; + HUDTargeting* _target; + Actor *_blast; Characters::Orientation _orientation; Characters::Orientation _latOrientation; std::list<Elements*> _grounds; std::list<Elements*> _enemiesTouched; std::list<Elements*> _wallsLeft; - std::list<Elements*> _walls; + std::list<Elements*> _ceiling; std::list<Elements*> _wallsRight; + std::list<std::string> _subsc; + bool _forwardFlag; + bool _backwardFlag; + bool _doFlyFlag; Json::Value _getAttr(std::string key); void _setCategory(std::string category); + virtual void characterLoop(void); + virtual void _tryFly(void); + virtual void _resetBroadcastFlags(void); virtual void _forward(int status); virtual void _backward(int status); virtual void _up(int status); @@ -142,6 +175,12 @@ class Characters : public Elements { virtual void _attack(int status); virtual void _pickupItem(int status); virtual void _run(void); + virtual void _specialMove(void); + // virtual void _dash(void); + // virtual void _charge(void); + // virtual void _stomp(void); + // virtual void _blink(void); + // virtual void _fly(void); void _destroyEnemy(void); Elements* getItem(void); diff --git a/Sources/inc/Elements.hpp b/Sources/inc/Elements.hpp @@ -63,8 +63,8 @@ public: /* Virtual function, overridden in Childs */ virtual void callback(Elements * elem) { }; - virtual void BeginContact(Elements * elem, b2Contact *contact) { }; - virtual void EndContact(Elements * elem, b2Contact *contact) { }; + virtual void BeginContact(Elements * elem, b2Contact *contact) {}; + virtual void EndContact(Elements * elem, b2Contact *contact) {}; virtual void AnimCallback(String s); int getOrientationX(void); diff --git a/Sources/inc/Enemy.hpp b/Sources/inc/Enemy.hpp @@ -39,7 +39,7 @@ public: Enemy(std::string); ~Enemy(); - int takeDamage(int damage); + int takeDamage(int damage, int critRate); void actionCallback(std::string name, int status); void init(void); void BeginContact(Elements* m, b2Contact* contact); diff --git a/Sources/inc/Equipment.hpp b/Sources/inc/Equipment.hpp @@ -52,6 +52,7 @@ private: Armor* _armor; Ring* _ring; std::string _name; + std::string _flavor; }; #endif diff --git a/Sources/inc/Game.hpp b/Sources/inc/Game.hpp @@ -48,6 +48,7 @@ class Characters; # include "RingList.hpp" # include "LevelGenerator.hpp" # include "Tooltip.hpp" +# include "Menu.hpp" class ArmorList; class EnemyList; @@ -56,6 +57,7 @@ class WeaponList; class Hitbox; class HUDWindow; +class Menu; class Game { @@ -71,10 +73,12 @@ class Game { void displayEnemy(Elements & Enemy); void displayObject(Elements & Object); void showMap(void); + void changeCharacter(std::string); void displayHUD(void); void setHero(Characters *h); void moveCamera(void); void simulateHeroItemContact(void); + void reloadingHUD(void); Characters *getHero(void); static bool endGame; @@ -100,6 +104,7 @@ class Game { static Game* currentGame; Maps *maps; + Menu *menu; std::vector<Room*> *gameMap; Tooltip *tooltip; static int currentIds; @@ -121,6 +126,8 @@ class Game { static int minY; static int started; static int cameraTick; + static int isWaitingForBind; + static int reloadHUD; private: float beginXHero; diff --git a/Sources/inc/HUDTargeting.hpp b/Sources/inc/HUDTargeting.hpp @@ -0,0 +1,54 @@ + +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** +* File: HUDTargeting.hpp +* Creation: 2015-06-30 14:20 +* Matthieu Maudet <arkhane84@gmail.com> +*/ + +#ifndef __HUDTargeting__ +# define __HUDTargeting__ + +# include "../../Angel/Angel.h" +# include <list> +# include "Elements.hpp" + +class Enemy; + +class HUDTargeting : public Elements{ + + public: + + HUDTargeting(void); + ~HUDTargeting(void); + + void changeTarget(void); + + private: + + std::list<Enemy *> _enemies; + int _enemyId; + Enemy* _current; + b2DistanceJoint* _joint; + +}; + +#endif diff --git a/Sources/inc/HUDWindow.hpp b/Sources/inc/HUDWindow.hpp @@ -51,7 +51,7 @@ class HUDWindow : public HUDActor { int colorR; int colorG; int colorB; - int colorA; + float colorA; Characters *toFollow; int isFading; int isTalk; @@ -70,6 +70,7 @@ class HUDWindow : public HUDActor { HUDActor *addImage(std::string p, int x, int y); HUDActor *addImage(std::string path, int x, int y, float size); HUDActor *addImage(std::string path, int x, int y, float size, int layer); + HUDActor *addImage(std::string path, int x, int y, Vector2 size, int layer); void life(int l); void mana(int mana); void gold(int g); @@ -86,6 +87,11 @@ class HUDWindow : public HUDActor { void setMaxHP(int h); void bag(void); void initMinimapBackground(void); + void showHud(void); + void showBackgrounds(void); + void character(void); + void spells(void); + void clearHUD(void); private: Game *_g; @@ -95,6 +101,7 @@ class HUDWindow : public HUDActor { std::list<HUDActor *> _minimap; std::map<std::string, Elements*> _dialog; std::list<HUDWindow::Text *> _text; + std::list<HUDActor *> _allElems; HUDWindow::Text * _gold; int _maxMana; int _maxHP; diff --git a/Sources/inc/Hero.hpp b/Sources/inc/Hero.hpp @@ -32,7 +32,7 @@ class Hero : public Characters { public: - Hero(); + Hero(std::string); ~Hero(); void init(); @@ -40,5 +40,6 @@ class Hero : public Characters { virtual void EndContact(Elements* m, b2Contact* contact); virtual void actionCallback(std::string name, int status); void _takeDamage(Elements* m); + void setStartingValues(void); }; #endif diff --git a/Sources/inc/Inventory.hpp b/Sources/inc/Inventory.hpp @@ -46,6 +46,8 @@ public: std::string equipSelectedItem(void); void swapEquipmentAndInventory(std::string item); std::map<int, std::string> getItems(void); + int getSlots(void); + int getNumFocus(void); private: int _slots; diff --git a/Sources/inc/Loot.hpp b/Sources/inc/Loot.hpp @@ -36,6 +36,7 @@ class Armor; class Loot { public: Loot(Characters *c); + Loot(Characters *c, std::string toDrop); Loot(Characters *c, Weapon* toDrop); Loot(Characters *c, Armor* toDrop); Loot(Characters *c, Ring* toDrop); diff --git a/Sources/inc/Menu.hpp b/Sources/inc/Menu.hpp @@ -23,7 +23,21 @@ * Louis Solofrizzo <louis@ne02ptzero.me> */ -# include "Game.hpp" +# ifndef __MENU__ +# define __MENU__ +# include "Game.hpp" + +class Game; +class HUDWindow; +class Quit; + +typedef struct s_bind { + std::string name; + std::string broadcast; + std::string realKey; + std::string oldKey; + int key; +} t_bind; class Menu : public Actor { public: @@ -31,8 +45,38 @@ class Menu : public Actor { ~Menu(void); void showMenu(Game *game); void ReceiveMessage(Message *m); + void listMenu(void); + void removeBaseMenu(void); + void settings(int y = 0); + void removeSettings(void); + void parseSettings(void); + void applySettings(void); + void pauseMenu(void); + void getBind(int key); + void parseBindings(void); + void bindingMenu(int y = 0); + int applyBindings(void); + + std::map<std::string, std::list<t_bind *> > getBindings(void); private: + int _isUpper(std::string s); + Game *_game; HUDWindow *_window; + std::list<std::string> _menuChoices; + std::string _currentChoice; + int _inMenu; + std::map<std::string, std::map<std::string, int> > _settingsValues; + std::list<std::string> _elementsPauseMenu; + HUDActor *_fadeActor; + std::list<std::string> _pauseMenuText; + int _lastMenu; + int _isBinding; + std::map<std::string, std::list<t_bind *> > _bindingMenu; + std::map<std::string, std::list<t_bind *> >::iterator _bindingIterator; }; + +# include "Quit.hpp" + +#endif diff --git a/Sources/inc/Projectile.hpp b/Sources/inc/Projectile.hpp @@ -45,6 +45,7 @@ public: int getPushback(void); float getRecovery(void); int attackReady(void); + int getCritRate(void); void BeginContact(Elements *elem, b2Contact *contact); void EndContact(Elements *elem, b2Contact *contact); @@ -61,5 +62,7 @@ private: int _damage; int _pushback; float _recovery; + int _critRate; + }; #endif diff --git a/Sources/inc/Quit.hpp b/Sources/inc/Quit.hpp @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/**** +*** * File: Quit.hpp +* *** Creation: 2015-06-23 16:36 +*** * Ne02ptzero <louis@ne02ptzero.me> +* *** lsolofri@e2r12p22.42.fr +****/ + +#ifndef __QUIT__ +# define __QUIT__ + +# include "Menu.hpp" + +class Quit { + + public: + Quit(void); + ~Quit(void); + + static void quitGame(void); + static void writeBindings(std::map<std::string, std::list<t_bind *> > binds); + static int isUpper(std::string s); +}; + +#endif diff --git a/Sources/inc/SpecialMoves.hpp b/Sources/inc/SpecialMoves.hpp @@ -0,0 +1,61 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * File: SpecialMoves.hpp + * Creation: 2015-06-30 09:57 + * Matthieu Maudet<arkhane84@gmail.com> + */ + + #ifndef __SpecialMoves__ + # define __SpecialMoves__ + + # ifdef __APPLE__ + # include "../../Tools/jsoncpp/include/json/json.h" + # else + # include "json/json.h" + # endif + + #include "Characters.hpp" + + class Characters; + + class SpecialMoves { + + public: + SpecialMoves(void); + SpecialMoves(Characters*); + ~SpecialMoves(); + + Characters* character; + + void _setCategory(std::string category); + + virtual void _dash(void); + virtual void _charge(void); + virtual void _stomp(void); + virtual void _blink(void); + virtual void _fly(void); + + private: + std::string _category; + + }; + + #endif diff --git a/Sources/inc/Tooltip.hpp b/Sources/inc/Tooltip.hpp @@ -47,17 +47,19 @@ class Tooltip : public MessageListener { void tip(Elements *elem, Characters *c); void info(Elements *elem); - void clearInfo(void); + void clearInfo(int clean = 1); void ReceiveMessage(Message *m); private: - HUDActor *_equip; - std::string _name; - std::string _val; + HUDActor *_equip; + std::string _name; + std::string _flavor; + std::string _val; + Elements *_lastElem; }; # include "Characters.hpp" -#endif- \ No newline at end of file +#endif diff --git a/Sources/inc/Weapon.hpp b/Sources/inc/Weapon.hpp @@ -42,6 +42,7 @@ public: Weapon(std::string name); Weapon(Weapon* weapon); Weapon(Weapon* weapon, Characters* c); + Weapon(Weapon* weapon, Characters* c, int i); ~Weapon(void); void attack(Characters *c); @@ -55,14 +56,12 @@ public: std::string getAttack(void); std::string getSprite(void); float getActive(void); + int getCritRate(void); int getSize(void); int getLootLevel(void); int getDamage(void); int getPushback(void); float getRecovery(void); - int attackReady(void); - - void isAttacking(int i); private: std::map<std::string, std::map<std::string, Json::Value> > _attr; @@ -72,13 +71,13 @@ private: std::string _sprite; std::string _attack; std::string _type; - int _canAttack; int _lootLevel; float _recovery; float _active; int _size; int _damage; int _pushback; + int _critRate; void _initDirection(Weapon* w, Characters* c); void _readFile(std::string name); void _readFileFromFilename(std::string name); diff --git a/Sources/inc/main.hpp b/Sources/inc/main.hpp @@ -27,7 +27,7 @@ #ifndef __MAIN__ # define __MAIN__ -# define NAME "rogue-like" +# define NAME "Grog Like" # include "Maps.hpp" #endif diff --git a/Sources/src/.#PassivePattern.cpp b/Sources/src/.#PassivePattern.cpp @@ -0,0 +1 @@ +noich@debian.9189:1434459054+ \ No newline at end of file diff --git a/Sources/src/.#Pattern.cpp b/Sources/src/.#Pattern.cpp @@ -0,0 +1 @@ +noich@debian.9189:1434459054+ \ No newline at end of file diff --git a/Sources/src/Armor.cpp b/Sources/src/Armor.cpp @@ -46,6 +46,7 @@ Armor::Armor(Armor* Armor) { this->addAttribute("name", this->_name); this->_flavor = Armor->getFlavor(); this->_sprite = Armor->getSprite(); + this->addAttribute("sprite", this->_sprite); this->_lootLevel = Armor->getLootLevel(); if (Armor->getAttribute("hpBuff") != "") this->addAttribute("hpBuff", Armor->getAttribute("hpBuff")); @@ -96,8 +97,16 @@ void Armor::_parseJson(std::string file) { Log::warning("The class name is different with the name in the config file: " + this->_name + "/" + json["infos"].get("name", "").asString()); this->_name = json["infos"].get("name", "").asString(); this->_flavor = json["infos"].get("flavor", "").asString(); + + for (i = json["infos"].get("flavor","").begin(); i != json["infos"].get("flavor","").end(); i++) { + + std::cout << "pas lol" << std::endl; + + } + this->_lootLevel = json["infos"].get("lootLevel", "").asInt(); this->_sprite = json["infos"].get("sprites", "").asString(); + this->addAttribute("sprite", this->_sprite); for (i = json["bonus"].begin(); i != json["bonus"].end(); i++) this->addAttribute( i.key().asString(), (*i).asString()); this->addAttribute("type3", "Armor"); @@ -133,9 +142,11 @@ std::string Armor::getSprite(void) { return this->_sprite; } int Armor::getLootLevel(void) { return this->_lootLevel; } int Armor::getHp(void) { return this->_hp; } -/* SETTERS */ - void Armor::BeginContact(Elements *elem, b2Contact *contact) { + if (elem->getAttribute("type") != "ground") { + contact->SetEnabled(false); + contact->enableContact = false; + } } void Armor::EndContact(Elements *elem, b2Contact *contact) { diff --git a/Sources/src/Characters.cpp b/Sources/src/Characters.cpp @@ -24,39 +24,48 @@ */ # include "Characters.hpp" -#include <cstdlib> +# include <cstdlib> + //! Base constructor -Characters::Characters(void) { +Characters::Characters(void) : _level(1) { return ; } + //! Main constructor /** * Setting base physic, some attributes and some intern variables * @param name The name of the character (Enemy, Hero, etc ...) * @todo gotta parse the right number of slots from json for inventory */ -Characters::Characters(std::string name) : _name(name), _isRunning(0), _isJump(0) { +Characters::Characters(std::string name) : _name(name), _isRunning(0), _isJump(0), _level(1) { this->addAttribute("physic", "1"); - this->addAttribute("type", name); + this->addAttribute("class", name); this->SetDensity(1.0f); this->SetFriction(1); this->SetRestitution(0.0f); this->SetFixedRotation(true); this->_orientation = RIGHT; - this->_readFile(name); + this->_latOrientation = RIGHT; this->_canMove = true; + this->_canAttack = true; this->_canJump = true; - this->_inventory = new Inventory(3); + this->_isFlying = false; this->_invincibility = false; this->_grounds.clear(); - this->_walls.clear(); this->_item = nullptr; this->_isAttacking = 0; this->_gold = 0; this->_isLoadingAttack = 0; + this->_isStomping = 0; + this->_isDashing = 0; + this->_speMoveReady = 1; + this->_hasDashed = 0; this->SetLayer(100); + this->_readFile(name); + this->_eqMove = new SpecialMoves(this); + this->_isStomping = false; } //! Basic destructor @@ -70,13 +79,13 @@ Characters::~Characters(void) { * For more documentation on the json style, uh, just wait we write it. * @param name (std::string) */ + void Characters::_readFile(std::string name) { std::string file; std::stringstream buffer; std::ifstream fd; file = "./Resources/Elements/" + name + ".json"; - fd.open(file.c_str()); if (!fd.is_open()) Log::error("Can't open the file for the " + @@ -108,7 +117,6 @@ void Characters::_parseJson(std::string file) { this->_name = json["infos"].get("name", "").asString(); this->_id = json["infos"].get("id", "").asInt(); this->_size = json["infos"].get("size", "").asFloat(); - this->_maxSpeed = json["infos"].get("maxSpeed", "").asFloat(); this->_hp = json["infos"].get("HP", "").asInt(); if (json["infos"].get("maxHP", "").isConvertibleTo(Json::ValueType::intValue)) this->_maxHp = json["infos"].get("maxHP", "").asInt(); @@ -128,6 +136,8 @@ void Characters::_parseJson(std::string file) { if (v.key().asString() == "subscribe") { theSwitchboard.SubscribeTo(this, (*v).asString() + "Pressed"); theSwitchboard.SubscribeTo(this, (*v).asString() + "Released"); + this->_subsc.push_back((*v).asString() + "Pressed"); + //this->_subsc.push_back((*v).asString() + "Released"); } } } @@ -152,6 +162,16 @@ Json::Value Characters::_getAttr(std::string category, std::string key) { return nullptr; } +//! Loop function called on every frame. +/** + * Used to manage every frame based action on characters + */ +void Characters::characterLoop(void) { + this->_tryFly(); + this->_resetBroadcastFlags(); +} + + //! Set the current working category /** * This function is made for gain time and money, set first the category in this functions @@ -193,7 +213,7 @@ void Characters::ReceiveMessage(Message *m) { if (m->GetMessageName() == "canMove") { if (this->getHP() > 0) { - this->changeCanMove(); + this->_canMove = 1; if (this->_grounds.size() > 0) this->AnimCallback("base"); } @@ -244,7 +264,7 @@ void Characters::ReceiveMessage(Message *m) { this->_getAttr("jump", "fallingFrame_left").asInt(), this->_getAttr("jump", "endFrame_left").asInt() - 3, "jump"); } - else if (m->GetMessageName() == "destroyEnemy") { + else if (m->GetMessageName() == "destroyEnemy") { new Loot(this); this->_destroyEnemy(); return; @@ -277,6 +297,84 @@ void Characters::ReceiveMessage(Message *m) { else if (m->GetMessageName() == "cycleInventory") { this->_inventory->changeItemFocus(); } + else if (m->GetMessageName() == "dropItem") { + new Loot(this, this->_inventory->dropSelectedItem()); + } + else if (m->GetMessageName() == "specialMove") { + this->_specialMove(); + } + else if (m->GetMessageName() == "speMoveReady") { + theSwitchboard.UnsubscribeFrom(this, "speMoveReady"); + this->_speMoveReady = 1; + } + else if (m->GetMessageName() == "dashEnd") { + theSwitchboard.UnsubscribeFrom(this, "dashEnd"); + this->GetBody()->SetGravityScale(1); + Game::stopRunning(this); + this->GetBody()->SetLinearVelocity(b2Vec2(0, 0)); + } + else if (m->GetMessageName() == "chargeEnd") { + theSwitchboard.UnsubscribeFrom(this, "chargeEnd"); + this->_canMove = 1; + this->_isCharging = false; + this->_invincibility = false; + this->GetBody()->SetLinearVelocity(b2Vec2(0, 0)); + } + else if (m->GetMessageName() == "stompEnd") { + std::string orientation; + theSwitchboard.UnsubscribeFrom(this, "stompEnd"); + this->_invincibility = false; + this->_isStomping = false; + this->_isCharging = false; + this->GetBody()->SetBullet(false); + this->_setCategory("stomp"); + if (this->_latOrientation == RIGHT) { + orientation = "right"; + } else if (this->_latOrientation == LEFT) + orientation = "left"; + this->PlaySpriteAnimation(0.3f, SAT_OneShot, + this->_getAttr("beginFrame_" + orientation).asInt() + 2, + this->_getAttr("endFrame_" + orientation).asInt()); + Actor* blast = new Actor(); + blast->SetPosition(this->GetBody()->GetWorldCenter().x, this->GetBody()->GetWorldCenter().y); + blast->SetSprite("Resources/Images/Blast/blast_000.png", 0); + blast->SetSize(2, 1); + this->SetLayer(99); + blast->LoadSpriteFrames("Resources/Images/Blast/blast_000.png"); + theWorld.Add(blast); + theSwitchboard.SubscribeTo(this, "deleteStomp"); + theSwitchboard.DeferredBroadcast(new Message("deleteStomp"), .5f); + blast->PlaySpriteAnimation(0.1f, SAT_OneShot, 0, 1); + blast->ChangeColorTo(Color(1, 1, 1, 0), .5f); + this->_blast = blast; + } else if (m->GetMessageName() == "attackReady") { + this->_canAttack = true; + return; + } + else if (m->GetMessageName() == "lockTarget") { + // std::cout << "Debug lock (Characters.cpp l.354)" << std::endl; + if (this->_target == nullptr) + this->_target = new HUDTargeting(); + else + this->_target->changeTarget(); + + } + else if (m->GetMessageName() == "unlockTarget") { + destroyTarget(); + } else if (m->GetMessageName() == "deleteStomp") { + theWorld.Remove(this->_blast); + theSwitchboard.UnsubscribeFrom(this, "deleteStomp"); + } + + + // TEST - to be removed - + else if (m->GetMessageName() == "changeCharacter") { + if (this->getAttribute("class") == "Warrior") + Game::currentGame->changeCharacter("Archer"); + else + Game::currentGame->changeCharacter("Warrior"); + } + //END OF TEST for (i = this->_attr.begin(); i != this->_attr.end(); i++) { attrName = this->_getAttr(i->first, "subscribe").asString(); if (!strncmp(attrName.c_str(), m->GetMessageName().c_str(), strlen(attrName.c_str()))) { @@ -287,21 +385,22 @@ void Characters::ReceiveMessage(Message *m) { return; if (attrName == "forward") { this->_forward(status); - } else if (attrName == "backward") { + } if (attrName == "backward") { this->_backward(status); - } else if (attrName == "up") { + } if (attrName == "up") { this->_up(status); - } else if (attrName == "down") { + } if (attrName == "down") { this->_down(status); - } else if (attrName == "jump") { + } if (attrName == "jump") { this->_jump(status); - } else if (attrName == "attack") { + } if (attrName == "attack") { this->_attack(status); - } else if (attrName == "pickupItem") { + } if (attrName == "pickupItem") { this->_pickupItem(status); } this->_lastAction = attrName; this->actionCallback(attrName, status); + return ; } } } @@ -317,8 +416,8 @@ void Characters::AnimCallback(String s) { this->_setCategory("breath"); if (s == "base") { this->_isAttacking = 0; - if (this->_isRunning == 0 && this->_isAttacking == 0 && this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); + if (this->_isRunning == 0 && this->_isAttacking == 0 && this->_isLoadingAttack == 0 && + this->_grounds.size() > 0) { if (this->_latOrientation == LEFT) { this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("beginFrame_left").asInt(), @@ -332,18 +431,35 @@ void Characters::AnimCallback(String s) { this->_getAttr("beginFrame_right").asInt(), this->_getAttr("endFrame_right").asInt(), "base"); } + } else if (this->_grounds.size() == 0 && this->getAttribute("type") == "Hero") { + this->_setCategory("jump"); + if (this->_latOrientation == LEFT) { + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("fallingFrame_left").asInt(), + this->_getAttr("fallingFrame_left").asInt(), "base"); + } else if (this->_latOrientation == RIGHT) { + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("fallingFrame_right").asInt(), + this->_getAttr("fallingFrame_right").asInt(), "base"); + } else { + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("beginFrame_right").asInt(), + this->_getAttr("endFrame_right").asInt(), "base"); + } + } else if (this->_isAttacking == 0) { if (this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(1, 1)); if (this->_isRunning == 1) { this->_setCategory("forward"); } else if (this->_isRunning == 2) { this->_setCategory("backward"); } this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), - SAT_Loop, - this->_getAttr("beginFrame").asInt(), - this->_getAttr("endFrame").asInt()); + SAT_Loop, + this->_getAttr("beginFrame").asInt(), + this->_getAttr("endFrame").asInt()); } else { std::string orientation; if (this->_latOrientation == RIGHT) { @@ -351,12 +467,30 @@ void Characters::AnimCallback(String s) { } else if (this->_latOrientation == LEFT) orientation = "left"; this->_setCategory("loadAttack_charge"); - this->changeSizeTo(Vector2(2, 2)); + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(2, 2)); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, - this->_getAttr("endFrame_" + orientation).asInt(), - this->_getAttr("endFrame_" + orientation).asInt(), "loadAttack_charge"); + this->_getAttr("endFrame_" + orientation).asInt(), + this->_getAttr("endFrame_" + orientation).asInt(), "loadAttack_charge"); } } + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(1, 1)); + if (this->_isDashing == true) { + this->_isDashing = false; + this->_canMove = 1; + } + } else if (s == "endDash") { + this->_setCategory("dash"); + this->_isRunning = 0; + std::string orientation; + if (this->_latOrientation == RIGHT) + orientation = "right"; + else if (this->_latOrientation == LEFT) + orientation = "left"; + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("endFrame_" + orientation).asInt() - 1, + this->_getAttr("endFrame_" + orientation).asInt(), "base"); } } @@ -369,49 +503,81 @@ void Characters::AnimCallback(String s) { * @param contact The b2Contact object of the collision. See Box2D docs for more info. */ void Characters::BeginContact(Elements *elem, b2Contact *contact) { + if (this->_hp <= 0 && this->getAttribute("type") == "Hero") { + this->_heroDeath(); + return; + } if (elem->getAttributes()["type"] == "ground") { - if (this->_isAttacking == 0 && this->_isLoadingAttack == 0) - this->changeSizeTo(Vector2(1, 1)); + if (this->_isAttacking == 0 && this->_isLoadingAttack == 0) { + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(1, 1)); + } if (this->GetBody()->GetWorldCenter().y - 0.905 >= elem->GetBody()->GetWorldCenter().y) { if (this->_grounds.size() > 0) { contact->SetEnabled(false); - } - else { - this->GetBody()->SetLinearVelocity(b2Vec2(0, this->GetBody()->GetLinearVelocity().y)); - if (this->_hp <= 0) { - this->_heroDeath(); - return; + this->_hasDashed = 0; + } else { + if (this->_isCharging == 1) { + theSwitchboard.Broadcast(new Message("chargeEnd")); } - } - if (this->_isJump > 0) { + this->GetBody()->SetLinearVelocity(b2Vec2(0, this->GetBody()->GetLinearVelocity().y)); this->_isJump = 0; - if (this->_latOrientation == RIGHT && this->_isAttacking == false && this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); + this->_hasDashed = 0; + if (this->_latOrientation == RIGHT && this->_isAttacking == false && + this->_isLoadingAttack == 0 && this->_isDashing == false && + this->_isStomping == false) { + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(1, 1)); this->PlaySpriteAnimation(0.1f, SAT_OneShot, this->_getAttr("jump", "endFrame_right").asInt() - 2, this->_getAttr("jump", "endFrame_right").asInt(), "base"); } else if (this->_latOrientation == LEFT && - this->_isAttacking == false && - this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); + this->_isAttacking == false && + this->_isLoadingAttack == 0 && + this->_isStomping == false) { + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(1, 1)); this->PlaySpriteAnimation(0.1f, SAT_OneShot, this->_getAttr("jump", "endFrame_left").asInt() - 2, this->_getAttr("jump", "endFrame_left").asInt(), "base"); } } this->_grounds.push_back(elem); + if (this->_isStomping == true) { + theSwitchboard.Broadcast(new Message("stompEnd")); + new Weapon(this->_weapon, this, 1); + new Weapon(this->_weapon, this, -1); + } + } else if (this->GetBody()->GetWorldCenter().y <= elem->GetBody()->GetWorldCenter().y - 0.905) { + this->_ceiling.push_back(elem); } else if (this->GetBody()->GetWorldCenter().x >= elem->GetBody()->GetWorldCenter().x) { + if (this->_isCharging == 1) { + theSwitchboard.Broadcast(new Message("chargeEnd")); + } if (this->_wallsLeft.size() > 0) contact->SetEnabled(false); + else { + if (this->_speMove == "wallJump" && this->_grounds.size() == 0) { + this->GetBody()->SetGravityScale(0.3); + } + } this->_wallsLeft.push_back(elem); } else if (this->GetBody()->GetWorldCenter().x < elem->GetBody()->GetWorldCenter().x) { + if (this->_isCharging == 1) { + theSwitchboard.Broadcast(new Message("chargeEnd")); + } if (this->_wallsRight.size() > 0) contact->SetEnabled(false); + else { + if (this->_speMove == "wallJump" && this->_grounds.size() == 0) { + this->GetBody()->SetGravityScale(0.3); + } + } this->_wallsRight.push_back(elem); } if (elem->getAttribute("speType") == "canCross") { if (this->GetBody()->GetWorldCenter().y - 1 < - elem->GetBody()->GetWorldCenter().y) { + elem->GetBody()->GetWorldCenter().y) { contact->SetEnabled(false); contact->enableContact = false; } @@ -420,6 +586,10 @@ void Characters::BeginContact(Elements *elem, b2Contact *contact) { contact->enableContact = false; } } + if (elem->getAttribute("type") == "Object") { + contact->SetEnabled(false); + contact->enableContact = false; + } } } @@ -434,17 +604,22 @@ void Characters::EndContact(Elements *elem, b2Contact *contact) { if (elem->getAttributes()["type"] == "ground") { this->_wallsLeft.remove(elem); this->_wallsRight.remove(elem); + this->_ceiling.remove(elem); if (this->_grounds.size() == 1) { this->_grounds.remove(elem); if (this->_grounds.size() == 0) { this->_isJump++; - if (this->_lastAction == "forward" && this->_canMove && this->_isAttacking == false && this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); + if (this->_lastAction == "forward" && this->_canMove && + this->_isAttacking == false && this->_isLoadingAttack == 0) { + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(1, 1)); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("jump", "fallingFrame_right").asInt(), this->_getAttr("jump", "endFrame_right").asInt() - 3, "jump"); - } else if (this->_lastAction == "backward" && this->_canMove && this->_isAttacking == false && this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); + } else if (this->_lastAction == "backward" && this->_canMove && + this->_isAttacking == false && this->_isLoadingAttack == 0) { + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(1, 1)); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("jump", "fallingFrame_left").asInt(), this->_getAttr("jump", "endFrame_left").asInt() - 3, "jump"); @@ -453,6 +628,8 @@ void Characters::EndContact(Elements *elem, b2Contact *contact) { } else this->_grounds.remove(elem); + if (this->_wallsLeft.size() == 0 && this->_wallsRight.size() == 0 && this->_speMove == "wallJump") + this->GetBody()->SetGravityScale(1); } } @@ -472,6 +649,26 @@ void Characters::_run(void) { /****************************/ /* */ +/* CHARACTER LOOP */ +/* */ +/****************************/ + +void Characters::_tryFly(void) { + if (this->_flyTrigger == true) + this->GetBody()->SetLinearVelocity(b2Vec2(this->GetBody()->GetLinearVelocity().x, + this->_getAttr("fly","force").asFloat())); + else if (this->_grounds.size() == 0 && this->_canMove == 1 && this->_isFlying == true) + this->GetBody()->SetLinearVelocity(b2Vec2(this->GetBody()->GetLinearVelocity().x, -2)); +} + +void Characters::_resetBroadcastFlags(void) { + this->_forwardFlag = false; + this->_backwardFlag = false; + this->_doFlyFlag = false; +} + +/****************************/ +/* */ /* ACTIONS */ /* */ /****************************/ @@ -480,22 +677,29 @@ void Characters::_run(void) { /** * Making a Characters run forward. * This function handle the power size for moving, sprite animation, basicly everything. - * So, if you want to make some modification, use the intern callback (Characters::callback), or override + * So, if you want to make some modification, use the intern callback (Characters::callback), or override * this function in the children. * But, please, DO NOT modify this one. * @param status The status of the key (0 | 1) */ void Characters::_forward(int status) { + // static int i = 0; this->_setCategory("forward"); + if (this->_forwardFlag == true && status == 1) + return ; + this->_forwardFlag = true; + // std::cout << "here " << i << std::endl; + // i++; if (status == 1) { this->_orientation = RIGHT; this->_latOrientation = RIGHT; if ((this->GetSpriteFrame() < this->_getAttr("beginFrame").asInt() || (this->GetSpriteFrame() >= this->_getAttr("backward", "beginFrame").asInt() && - this->GetSpriteFrame() <= this->_getAttr("backward", "endFrame").asInt())) && !this->_isJump) + this->GetSpriteFrame() <= this->_getAttr("backward", "endFrame").asInt())) && + !this->_isJump && !this->_isLoadingAttack && !this->_isFlying) this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_Loop, this->_getAttr("beginFrame").asInt(), this->_getAttr("endFrame").asInt()); - else if (this->_isJump) { + else if (this->_isJump && !this->_isLoadingAttack && !this->_isFlying) { this->_setCategory("jump"); if (this->GetSpriteFrame() >= this->_getAttr("beginFrame_left").asInt() && this->GetSpriteFrame() <= this->_getAttr("endFrame_left").asInt()) this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, @@ -505,8 +709,8 @@ void Characters::_forward(int status) { } else if (this->_isLoadingAttack) { this->_setCategory("loadAttack_charge"); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, - this->_getAttr("endFrame_right").asInt(), - this->_getAttr("endFrame_right").asInt(), "loadAttack_charge"); + this->_getAttr("endFrame_right").asInt(), + this->_getAttr("endFrame_right").asInt(), "loadAttack_charge"); this->_setCategory("forward"); } Game::startRunning(this); @@ -520,8 +724,8 @@ void Characters::_forward(int status) { if (!this->_isJump && !this->_isAttacking) this->AnimCallback("base"); } else { - if (this->_wallsRight.size() == 0 && this->_canMove == true) - this->GetBody()->SetLinearVelocity(b2Vec2(this->_getAttr("force").asFloat(), this->GetBody()->GetLinearVelocity().y)); + if (this->_wallsRight.size() == 0 && this->_canMove == true && this->_isRunning != 0) + this->GetBody()->SetLinearVelocity(b2Vec2(this->_getAttr("force").asFloat(), this->GetBody()->GetLinearVelocity().y)); } return ; } @@ -535,14 +739,20 @@ void Characters::_forward(int status) { */ void Characters::_backward(int status) { this->_setCategory("backward"); + if (this->_backwardFlag == true && status == 1) + return ; + this->_backwardFlag = true; if (status == 1) { - this->_orientation = LEFT; - this->_latOrientation = LEFT; - if (this->GetSpriteFrame() < this->_getAttr("beginFrame").asInt() && !this->_isJump) + if (this->getAttribute("type") == "Hero") { + this->_orientation = LEFT; + this->_latOrientation = LEFT; + } + if (this->GetSpriteFrame() < this->_getAttr("beginFrame").asInt() && + !this->_isJump && !this->_isLoadingAttack) this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_Loop, this->_getAttr("beginFrame").asInt(), this->_getAttr("endFrame").asInt()); - else if (this->_isJump) { + else if (this->_isJump && !this->_isLoadingAttack) { this->_setCategory("jump"); if (this->GetSpriteFrame() >= this->_getAttr("beginFrame_right").asInt() && this->GetSpriteFrame() <= this->_getAttr("endFrame_right").asInt()) this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, @@ -552,8 +762,8 @@ void Characters::_backward(int status) { } else if (this->_isLoadingAttack) { this->_setCategory("loadAttack_charge"); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, - this->_getAttr("endFrame_left").asInt(), - this->_getAttr("endFrame_left").asInt(), "loadAttack_charge"); + this->_getAttr("endFrame_left").asInt(), + this->_getAttr("endFrame_left").asInt(), "loadAttack_charge"); this->_setCategory("backward"); } Game::startRunning(this); @@ -567,8 +777,9 @@ void Characters::_backward(int status) { if (!this->_isJump && !this->_isAttacking) this->AnimCallback("base"); } else { - if (this->_wallsLeft.size() == 0 && this->_canMove == true) - this->GetBody()->SetLinearVelocity(b2Vec2(-this->_getAttr("force").asFloat(), this->GetBody()->GetLinearVelocity().y)); + if (this->_wallsLeft.size() == 0 && this->_canMove == true && this->_isRunning != 0) { + this->GetBody()->SetLinearVelocity(b2Vec2(-this->_getAttr("force").asFloat(), this->GetBody()->GetLinearVelocity().y)); + } } return ; } @@ -582,35 +793,65 @@ void Characters::_backward(int status) { */ void Characters::_jump(int status) { this->_setCategory("jump"); - - if (status == 1 && this->_canJump == true) { - this->_canJump = false; - if (this->_isJump == 0 || (this->_isJump < this->_getAttr("max").asInt())) { - if (this->_isJump >= 1) { - this->GetBody()->SetLinearVelocity(b2Vec2(this->GetBody()->GetLinearVelocity().x, this->_getAttr("rejump").asFloat())); - } - else { - this->ApplyLinearImpulse(Vector2(0, this->_getAttr("force").asFloat()), Vector2(0, 0)); - } - if (this->_isAttacking == false && this->_isLoadingAttack == 0) { - this->changeSizeTo(Vector2(1, 1)); - if (this->_latOrientation == RIGHT) { + if (_isFlying == 0) { + if (status == 1 && this->_canJump == true) { + this->_canJump = false; + if (this->_speMove == "wallJump" && this->_grounds.size() == 0 && + (this->_wallsLeft.size() > 0 || this->_wallsRight.size() > 0)) { + this->GetBody()->SetGravityScale(1); + if (this->_wallsLeft.size() > 0 && this->_wallsRight.size() == 0) { + this->GetBody()->SetLinearVelocity(b2Vec2(5, this->_getAttr("rejump").asFloat())); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("beginFrame_right").asInt(), this->_getAttr("endFrame_right").asInt() - 3, "jump"); - } - else if (this->_latOrientation == LEFT) { + } else if (this->_wallsRight.size() > 0 && this->_wallsLeft.size() == 0) { + this->GetBody()->SetLinearVelocity(b2Vec2(-5, this->_getAttr("rejump").asFloat())); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("beginFrame_left").asInt(), this->_getAttr("endFrame_left").asInt() - 3, "jump"); + } else + this->GetBody()->SetLinearVelocity(b2Vec2(0, this->_getAttr("rejump").asFloat())); + Game::stopRunning(this); + } else if (this->_isJump == 0 || (this->_isJump < this->_getAttr("max").asInt())) { + if (this->_isJump >= 1) { + this->GetBody()->SetLinearVelocity(b2Vec2(this->GetBody()->GetLinearVelocity().x, + this->_getAttr("rejump").asFloat())); + if (this->_isAttacking == false && this->_isLoadingAttack == 0) { + if (this->getAttribute("class") == "Warrior" && this->_isDashing == false) + this->changeSizeTo(Vector2(1, 1)); + if (this->_latOrientation == RIGHT) { + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("beginFrame_right").asInt(), + this->_getAttr("endFrame_right").asInt() - 3, "jump"); + } + } + } else { + this->ApplyLinearImpulse(Vector2(0, this->_getAttr("force").asFloat()), Vector2(0, 0)); } + if (this->_isAttacking == false && this->_isLoadingAttack == 0) { + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(1, 1)); + if (this->_latOrientation == RIGHT) { + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("beginFrame_right").asInt(), + this->_getAttr("endFrame_right").asInt() - 3, "jump"); + } else if (this->_latOrientation == LEFT) { + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("beginFrame_left").asInt(), + this->_getAttr("endFrame_left").asInt() - 3, "jump"); + } + } + if (this->_grounds.size() == 0) + this->_isJump++; } - if (this->_grounds.size() == 0) - this->_isJump++; + } else if (status == 0) { + this->_canJump = true; } - } - else if (status == 0) { - this->_canJump = true; + } else { //Hero is flying + if (this->_doFlyFlag == true && status == 1) + return ; + this->_doFlyFlag = true; + this->_flyTrigger = (status ? 1 : 0); } return ; } @@ -666,30 +907,31 @@ void Characters::_down(int status) { * @sa Weapon::attack */ void Characters::_attack(int status) { - if (status == 1 && this->_weapon->attackReady() == 1) { + if (status == 1 && this->_canAttack == true) { if (!this->_attackPressed && !this->_isLoadingAttack) { this->_attackPressed = 1; theSwitchboard.SubscribeTo(this, "startChargeAttack"); theSwitchboard.DeferredBroadcast(new Message("startChargeAttack"), - 0.3f); + 0.3f); } if (this->_isLoadingAttack == 1 && this->_attackPressed == 1) { this->_attackPressed = 0; this->_fullChargedAttack = false; theSwitchboard.SubscribeTo(this, "fullChargedAttack"); theSwitchboard.DeferredBroadcast(new Message("fullChargedAttack"), - 0.5f); + 0.5f); this->actionCallback("loadAttack_charge", 1); } } - else if (status == 0 && this->_weapon->attackReady() == 1 && (this->_fullChargedAttack == true || this->_isLoadingAttack == 0)) { + else if (status == 0 && this->_canAttack == true && (this->_fullChargedAttack == true || this->_isLoadingAttack == 0)) { + theSwitchboard.UnsubscribeFrom(this, "fullChargedAttack"); theSwitchboard.UnsubscribeFrom(this, "startChargeAttack"); this->_isAttacking = 1; this->_isLoadingAttack = 0; this->_attackPressed = 0; theSwitchboard.DeferredBroadcast(new Message("enableAttackHitbox"), - 0.05f); + 0.05f); } else if (status == 0) { theSwitchboard.UnsubscribeFrom(this, "fullChargedAttack"); theSwitchboard.UnsubscribeFrom(this, "startChargeAttack"); @@ -721,11 +963,30 @@ void Characters::_pickupItem(int status) { this->_inventory->addItemToInventory(this->_item->getAttribute("name")); } theSwitchboard.Broadcast(new Message("DeleteEquipment" + - this->_item->GetName())); + this->_item->GetName())); this->_item = nullptr; } +//! Executes special move +/** + * Executes the characters special move, based on which one he picked up at the beginning + * @todo should not be based off the json config + */ + +void Characters::_specialMove(void) { + if (this->_speMove == "dash") + this->_eqMove->_dash(); + else if (this->_speMove == "charge") + this->_eqMove->_charge(); + else if (this->_speMove == "stomp") + this->_eqMove->_stomp(); + else if (this->_speMove == "blink") + this->_eqMove->_blink(); + else if (this->_speMove == "fly") + this->_eqMove->_fly(); +} + //! Equip a weapon /** * Equip a new weapon to the Character, and update the HUD. @@ -752,11 +1013,19 @@ void Characters::unequipWeapon(void) { */ void Characters::equipArmor(Armor* armor) { this->_armor = new Armor(armor); - if (this->_armor->getAttribute("hpBuff") != "") - this->_maxHp += std::stoi(this->_armor->getAttribute("hpBuff")); - if (this->_armor->getAttribute("manaBuff") != "") - this->_maxMana += std::stoi(this->_armor->getAttribute("manaBuff")); + if (this->_armor->getAttribute("hpBuff") != ""){ + this->_maxHp += std::stoi(this->_armor->getAttribute("hpBuff")); + this->_hp += std::stoi(this->_armor->getAttribute("hpBuff")); + } + if (this->_armor->getAttribute("manaBuff") != ""){ + this->_maxMana += std::stoi(this->_armor->getAttribute("manaBuff")); + this->_mana += std::stoi(this->_armor->getAttribute("manaBuff")); + } Game::getHUD()->items(this->_armor); + Game::getHUD()->setMaxHP(this->_maxHp); + Game::getHUD()->life(this->_hp); + Game::getHUD()->setMaxMana(this->_maxMana); + Game::getHUD()->mana(this->_mana); } //! Unequip a armor @@ -766,10 +1035,21 @@ void Characters::equipArmor(Armor* armor) { */ void Characters::unequipArmor(void) { this->_inventory->swapEquipmentAndInventory(this->_armor->getAttribute("name")); - if (this->_armor->getAttribute("hpBuff") != "") - this->_maxHp -= std::stoi(this->_armor->getAttribute("hpBuff")); - if (this->_armor->getAttribute("manaBuff") != "") - this->_maxMana -= std::stoi(this->_armor->getAttribute("manaBuff")); + if (this->_armor->getAttribute("hpBuff") != "") { + this->_maxHp -= std::stoi(this->_armor->getAttribute("hpBuff")); + if (this->_hp > this->_maxHp) + this->_hp = this->_maxHp; + } + if (this->_armor->getAttribute("manaBuff") != "") { + this->_maxMana -= std::stoi(this->_armor->getAttribute("manaBuff")); + if (this->_mana > this->_maxMana) + this->_mana = this->_maxMana; + } + Game::getHUD()->items(this->_armor); + Game::getHUD()->setMaxHP(this->_maxHp); + Game::getHUD()->life(this->_hp); + Game::getHUD()->setMaxMana(this->_maxMana); + Game::getHUD()->mana(this->_mana); } //! Equip a ring @@ -779,11 +1059,19 @@ void Characters::unequipArmor(void) { */ void Characters::equipRing(Ring* ring) { this->_ring = new Ring(ring); - if (this->_ring->getAttribute("hpBuff") != "") - this->_maxHp += std::stoi(this->_ring->getAttribute("hpBuff")); - if (this->_ring->getAttribute("manaBuff") != "") - this->_maxMana += std::stoi(this->_ring->getAttribute("manaBuff")); + if (this->_ring->getAttribute("hpBuff") != "") { + this->_maxHp += std::stoi(this->_ring->getAttribute("hpBuff")); + this->_hp += std::stoi(this->_ring->getAttribute("hpBuff")); + } + if (this->_ring->getAttribute("manaBuff") != "") { + this->_maxMana += std::stoi(this->_ring->getAttribute("manaBuff")); + this->_mana += std::stoi(this->_ring->getAttribute("manaBuff")); + } Game::getHUD()->items(this->_ring); + Game::getHUD()->setMaxHP(this->_maxHp); + Game::getHUD()->life(this->_hp); + Game::getHUD()->setMaxMana(this->_maxMana); + Game::getHUD()->mana(this->_mana); } //! Unequip a ring @@ -793,10 +1081,16 @@ void Characters::equipRing(Ring* ring) { */ void Characters::unequipRing(void) { this->_inventory->swapEquipmentAndInventory(this->_ring->getAttribute("name")); - if (this->_ring->getAttribute("hpBuff") != "") - this->_maxHp -= std::stoi(this->_ring->getAttribute("hpBuff")); - if (this->_ring->getAttribute("manaBuff") != "") - this->_maxMana -= std::stoi(this->_ring->getAttribute("manaBuff")); + if (this->_ring->getAttribute("hpBuff") != "") { + this->_maxHp -= std::stoi(this->_ring->getAttribute("hpBuff")); + if (this->_hp > this->_maxHp) + this->_hp = this->_maxHp; + } + if (this->_ring->getAttribute("manaBuff") != "") { + this->_maxMana -= std::stoi(this->_ring->getAttribute("manaBuff")); + if (this->_mana > this->_maxMana) + this->_mana = this->_maxMana; + } } //! Set basics hp @@ -825,13 +1119,26 @@ void Characters::setMana(int mana) { //! Destroy an Enemy. /** - * Made theSwitchboard Unsubscribe from the object, and destroy it. + * Make theSwitchboard Unsubscribe from the object, and destroy it. */ void Characters::_destroyEnemy(void) { theSwitchboard.UnsubscribeFrom(this, "destroyEnemy"); Game::addToDestroyList(this); } +//! Destroy current target. +/** + * Destroy target if hero have one. + */ +void Characters::destroyTarget(void) { + if (this->_target != nullptr) { + // std::cout << "destroyTarget (Characters.cpp l.1077)" << std::endl; + Game::addToDestroyList(this->_target); + this->_target = nullptr; + } +} + + //! Animation for the Hero death /** * A beautiful for the Hero death. @@ -848,10 +1155,33 @@ void Characters::_heroDeath(void) { ghost->SetSprite("Resources/Images/Ghost/ghost_000.png", 0); ghost->LoadSpriteFrames("Resources/Images/Ghost/ghost_000.png"); ghost->MoveTo(Vector2(this->GetBody()->GetWorldCenter().x, this->GetBody()->GetWorldCenter().y + 7), 4); - theWorld.Add(ghost); + theWorld.Add(ghost); ghost->PlaySpriteAnimation(0.2f, SAT_OneShot, 0, 10, "ghost"); } +/** + * Unsubscribe the character to all the broadcasts + */ +void Characters::unsubscribeFromAll(void) { + std::list<std::string>::iterator it; + + for (it = this->_subsc.begin(); it != this->_subsc.end(); it++) { + theSwitchboard.UnsubscribeFrom(this, *it); + } +} + +/** + * Subscribe the character to all the broadcasts + */ +void Characters::subscribeToAll(void) { + std::list<std::string>::iterator it; + + for (it = this->_subsc.begin(); it != this->_subsc.end(); it++) { + theSwitchboard.SubscribeTo(this, *it); + } +} + +/* GETTERS */ Characters::Orientation Characters::getOrientation(void) { return this->_orientation; } std::string Characters::getLastAction(void) { return this->_lastAction; }; Elements* Characters::getItem(void) { return this->_item; } @@ -862,3 +1192,10 @@ int Characters::getMaxHP(void) { return this->_maxHp; }; int Characters::getGold(void) { return this->_gold; }; void Characters::changeCanMove(void) { this->_canMove = (this->_canMove ? false : true); }; Weapon *Characters::getWeapon(void) { return this->_weapon; }; +Armor *Characters::getArmor(void) { return this->_armor; }; +Ring *Characters::getRing(void) { return this->_ring; }; +bool Characters::getCharging(void) { return this->_isCharging; } +std::list<std::string> Characters::getSubscribes(void) { return this->_subsc; }; +int Characters::getLevel(void) { return this->_level; }; +int Characters::getMaxInventory(void) { return this->_inventory->getSlots(); }; +Inventory *Characters::getInventory(void) { return this->_inventory; }; diff --git a/Sources/src/Consumable.cpp b/Sources/src/Consumable.cpp @@ -105,6 +105,10 @@ Consumable::Consumable(std::string type, std::string value, Characters* c) { * @todo This function is actually doing nothing. */ void Consumable::BeginContact(Elements *elem, b2Contact *contact) { + if (elem->getAttribute("type") != "ground") { + contact->SetEnabled(false); + contact->enableContact = false; + } } //! Destructor diff --git a/Sources/src/ContactFilter.cpp b/Sources/src/ContactFilter.cpp @@ -28,22 +28,22 @@ bool ContactFilter::ShouldCollide(b2Fixture* fixA, b2Fixture* fixB) { - Elements* attrA; - Elements* attrB; + // Elements* attrA; + // Elements* attrB; - attrA = static_cast<Elements*>(fixB->GetBody()->GetUserData()); - attrB = static_cast<Elements*>(fixA->GetBody()->GetUserData()); - if (static_cast<Elements*>(fixA->GetBody()->GetUserData())->getAttribute("type") == "Hero") { - Elements* attrA = static_cast<Elements*>(fixA->GetBody()->GetUserData()); - Elements* attrB = static_cast<Elements*>(fixB->GetBody()->GetUserData()); - } - if (attrA->getAttribute("type") == "Hero") - if (attrA->getAttribute("type") == "Object" && attrB->getAttribute("type") != "ground" - || attrB->getAttribute("type") == "Object" && attrA->getAttribute("type") != "ground") { - if (attrA->getAttribute("type") == "Hero") - attrA->BeginContact(attrB, nullptr); - return false; - } + // attrA = static_cast<Elements*>(fixB->GetBody()->GetUserData()); + // attrB = static_cast<Elements*>(fixA->GetBody()->GetUserData()); + // if (static_cast<Elements*>(fixA->GetBody()->GetUserData())->getAttribute("type") == "Hero") { + // Elements* attrA = static_cast<Elements*>(fixA->GetBody()->GetUserData()); + // Elements* attrB = static_cast<Elements*>(fixB->GetBody()->GetUserData()); + // } + // if (attrA->getAttribute("type") == "Hero") + // if (attrA->getAttribute("type") == "Object" && attrB->getAttribute("type") != "ground" + // || attrB->getAttribute("type") == "Object" && attrA->getAttribute("type") != "ground") { + // if (attrA->getAttribute("type") == "Hero") + // attrA->BeginContact(attrB, nullptr); + // return false; + // } // if (attrA->getAttribute("type") == "Hero" && // attrB->getAttribute("type") == "ground" && // attrB->getAttribute("speType") == "canCross") { diff --git a/Sources/src/Elements.cpp b/Sources/src/Elements.cpp @@ -143,7 +143,6 @@ void Elements::display(void) { this->setFrameSprite(this->_frame - 1); } else this->SetColor(0, 0, 0, 0); - this->SetSize(1.00f); this->SetDrawShape(ADS_Square); if (this->getAttribute("type") == "wall" || this->getAttribute("type") == "ground") { this->SetDensity(0); @@ -207,7 +206,6 @@ void Elements::AnimCallback(String s) { this->_animIt = this->_animationList.begin(); this->PlaySpriteAnimation((*this->_animIt)->time, SAT_OneShot, (*this->_animIt)->frame, (*this->_animIt)->frame, "baseAnimation"); this->setFrameSprite((*this->_animIt)->frame); - } } @@ -217,3 +215,4 @@ void Elements::addAnimation(int frame, float time) { anim->time = time; this->_animationList.push_back(anim); } + diff --git a/Sources/src/Enemy.cpp b/Sources/src/Enemy.cpp @@ -93,27 +93,25 @@ void Enemy::BeginContact(Elements* m, b2Contact *contact) { if (m->getAttribute("type") == "ground") { Game::startRunning(this); this->_isTakingDamage = 0; - } - if (m->getAttribute("type") == "HeroWeaponHitBox") { + } else if (m->getAttribute("type") == "HeroWeaponHitBox") { + Characters *h = Game::currentGame->getHero(); this->GetBody()->SetLinearVelocity(b2Vec2(-2, 2)); Game::stopRunning(this); - if (this->takeDamage(w->getDamage()) == 1) { - this->_isTakingDamage = 1; - if (this->GetBody()->GetWorldCenter().x > m->GetBody()->GetWorldCenter().x) { + if (this->takeDamage(w->getDamage(), w->getCritRate()) == 1) { + if (this->GetBody()->GetWorldCenter().x > h->GetBody()->GetWorldCenter().x) { this->ApplyLinearImpulse(Vector2(w->getPushback(), w->getPushback()), Vector2(0,0)); } else { this->ApplyLinearImpulse(Vector2(-w->getPushback(), w->getPushback()), Vector2(0,0)); } - } - else { + } else { this->GetBody()->SetLinearVelocity(b2Vec2(0, 0)); } } else if (m->getAttribute("type") == "HeroProjectile") { + Characters *h = Game::currentGame->getHero(); this->GetBody()->SetLinearVelocity(b2Vec2(-2, 2)); Game::stopRunning(this); - this->_isTakingDamage = 1; - if (this->takeDamage(p->getDamage()) == 1) { - if (this->GetBody()->GetWorldCenter().x > m->GetBody()->GetWorldCenter().x) { + if (this->takeDamage(p->getDamage(), p->getCritRate()) == 1) { + if (this->GetBody()->GetWorldCenter().x > h->GetBody()->GetWorldCenter().x) { this->ApplyLinearImpulse(Vector2(p->getPushback(), p->getPushback()), Vector2(0,0)); } else { this->ApplyLinearImpulse(Vector2(-p->getPushback(), p->getPushback()), Vector2(0,0)); @@ -123,26 +121,24 @@ void Enemy::BeginContact(Elements* m, b2Contact *contact) { this->GetBody()->SetLinearVelocity(b2Vec2(0, 0)); } } else if (m->getAttribute("type") == "Hero") { - this->_isTakingDamage = 1; - if (this->_orientation == LEFT) - this->_orientation = RIGHT; - else - this->_orientation = LEFT; - if (this->GetBody()->GetWorldCenter().x > m->GetBody()->GetWorldCenter().x) { - this->GetBody()->SetLinearVelocity(b2Vec2(2, 2)); + Game::stopRunning(this); + if (static_cast<Hero*>(m)->getCharging() == true) { + this->takeDamage(static_cast<Characters*>(m)->getWeapon()->getDamage(), static_cast<Characters*>(m)->getWeapon()->getCritRate()); + if (this->GetBody()->GetWorldCenter().x > m->GetBody()->GetWorldCenter().x) { + this->GetBody()->SetLinearVelocity(b2Vec2(10, 10)); + } else { + this->GetBody()->SetLinearVelocity(b2Vec2(-10, 10)); + } } else { - this->GetBody()->SetLinearVelocity(b2Vec2(-2, 2)); + if (this->GetBody()->GetWorldCenter().x > m->GetBody()->GetWorldCenter().x) { + this->GetBody()->SetLinearVelocity(b2Vec2(2, 2)); + } else { + this->GetBody()->SetLinearVelocity(b2Vec2(-2, 2)); + } } this->actionCallback("heroHit", 0); } - else if (m->getAttribute("type") == "Enemy") { - if (this->_orientation == LEFT) - this->_orientation = RIGHT; - else - this->_orientation = LEFT; - } else if (m->getAttribute("speType") == "spikes") { - this->_isTakingDamage = 1; if (this->GetBody()->GetWorldCenter().x > m->GetBody()->GetWorldCenter().x) { this->ApplyLinearImpulse(Vector2(5, 5), Vector2(0,0)); } else { @@ -165,11 +161,21 @@ void Enemy::EndContact(Elements *m, b2Contact *contact) { //! Take Damage /** * Function that applies damage - * In this function, we reduce the HP (no way ?), reduce the speed, play a sprite animation. + * In this function, we reduce the HP, reduce the speed, play a sprite animation. * @param damage The damage amount */ -int Enemy::takeDamage(int damage) { +int Enemy::takeDamage(int damage, int critRate) { + if (this->_isTakingDamage == 1) + return 1; + this->_isTakingDamage = 1; + if (this->_hp <= 0) + return 0; this->actionCallback("takeDamage", 0); + if ((rand() % critRate + 1) == critRate) { + damage *= 2 ; + Game::getHUD()->setText("Crit !", Game::currentGame->getHero(), + Vector3(255, 0, 0), 1, 0); + } if (this->_hp - damage <= 0) { this->_isDead = true; this->actionCallback("death", 0); diff --git a/Sources/src/Equipment.cpp b/Sources/src/Equipment.cpp @@ -66,6 +66,8 @@ Equipment::Equipment(Weapon *w, Characters* c): Object() { this->_weapon = new Weapon(w); this->_name = w->getName(); this->addAttribute("name", w->getName()); + this->_flavor = w->getFlavor(); + this->addAttribute("flavor", w->getFlavor()); this->SetSprite(this->_weapon->getSprite()); this->SetName("loot"); theSwitchboard.SubscribeTo(this, "DeleteEquipment" + this->GetName()); @@ -81,6 +83,8 @@ Equipment::Equipment(Armor *w, Characters* c): Object() { this->_armor = new Armor(w); this->_name = w->getName(); this->addAttribute("name", w->getName()); + this->_flavor = w->getFlavor(); + this->addAttribute("flavor", w->getFlavor()); this->SetSprite(this->_armor->getSprite()); this->SetName("loot"); theSwitchboard.SubscribeTo(this, "DeleteEquipment" + this->GetName()); @@ -95,6 +99,8 @@ Equipment::Equipment(Ring *w, Characters* c): Object() { this->_ring = new Ring(w); this->_name = w->getName(); this->addAttribute("name", w->getName()); + this->_flavor = w->getFlavor(); + this->addAttribute("flavor", w->getFlavor()); this->SetSprite(this->_ring->getSprite()); this->SetName("loot"); theSwitchboard.SubscribeTo(this, "DeleteEquipment" + this->GetName()); @@ -117,9 +123,10 @@ Equipment::~Equipment(void) { * @param contact The Box2D contact object. */ void Equipment::BeginContact(Elements *elem, b2Contact *contact) { - // if (elem->getAttributes()["type"] == "Hero"){ - // Game::getHUD()->setText(this->_weapon->getFlavor(), 450, 50); - // } + if (elem->getAttribute("type") != "ground") { + contact->SetEnabled(false); + contact->enableContact = false; + } } //! End of collision callback @@ -144,6 +151,8 @@ Ring* Equipment::getRing(void) { return this->_ring; } std::string Equipment::getName(void) { return this->_name; } + + //! Intern broadcasts function. /** * The Receive Message function. diff --git a/Sources/src/Game.cpp b/Sources/src/Game.cpp @@ -34,7 +34,7 @@ */ Game::Game(void) : _hero((new Characters())) { #ifdef __APPLE__ - theWorld.Initialize(1920, 1080, NAME, false, false); + theWorld.Initialize(1024, 720, NAME, true, false); #else theWorld.Initialize(1024, 720, NAME, false, false); #endif @@ -85,7 +85,7 @@ void Game::start(void) { Game::rList = new RingList(); this->tooltip = new Tooltip(); Game::currentGame = this; - Hero *hero = new Hero(); + Hero *hero = new Hero("Warrior"); @@ -98,20 +98,18 @@ void Game::start(void) { // Log::info("NbEnemy:" + trouver le nombre d ennemy); // Log::info("NbMaps: " + info sur la sauvegarde (nivau du hero, gold etc...)); - //theCamera.LockTo(hero); Game::currentX = levelGenerator->getStartX(); Game::currentY = levelGenerator->getStartY(); theCamera.SetPosition(this->maps->getMapXY()[Game::currentY][Game::currentX].getXMid(), this->maps->getMapXY()[Game::currentY][Game::currentX].getYMid() + 1.8, 9.001); this->maps->_XYMap[Game::currentY][Game::currentX] = this->maps->getMapXY()[Game::currentY][Game::currentX].display(); + + Game::addHUDWindow(new HUDWindow()); this->displayHero(*(hero)); hero->init(); - - hero->equipWeapon(Game::wList->getWeapon("Sword")); - hero->equipRing(Game::rList->getRing("SmallRing")); - hero->equipArmor(Game::aList->getArmor("ChestArmor")); this->setHero(hero); this->displayHUD(); + hero->setStartingValues(); Game::started = 1; } @@ -185,6 +183,8 @@ void Game::checkHeroPosition(void) { if (Game::started == 1) { Game::currentGame->moveCamera(); Game::currentGame->simulateHeroItemContact(); + Game::currentGame->getHero()->characterLoop(); + Game::currentGame->reloadingHUD(); } } @@ -224,6 +224,8 @@ void Game::moveCamera(void) { asChanged = true; } if (asChanged) { + // std::cout << "SHAME ! (game.cpp l.228)" << std::endl; + this->_hero->destroyTarget(); this->maps->_XYMap[Game::currentY][Game::currentX] = this->maps->getMapXY()[Game::currentY][Game::currentX].display(); theCamera.SetPosition(this->maps->getMapXY()[Game::currentY][Game::currentX].getXMid(), this->maps->getMapXY()[Game::currentY][Game::currentX].getYMid() + 1.8); @@ -253,11 +255,13 @@ void Game::addElement(Elements & elem) { * @param elem The element to delete (The reference is important !) */ void Game::delElement(Elements* elem) { - for (int i = 0; Game::elementMap[i]; i++) { - if (Game::elementMap[i] == elem) - Game::elementMap.erase(i); + for (int i = 0; i < Game::elementMap.size(); i++) { + if (Game::elementMap[i]) { + if (Game::elementMap[i]->getId() == elem->getId()) { + Game::elementMap.erase(i); + } + } } - //delete elem; } //! Collision intern callbacks @@ -311,11 +315,12 @@ bool Game::destroyAllBodies(void) { theWorld.PausePhysics(); int i; Game::getHUD()->setText("YOU ARE DEAD", 400, 400, Vector3(1, 0, 0), 1, "dead"); - for (i = 0; i < Game::elementMap.size() - 2; i++) { + for (i = 0; i < Game::elementMap.size(); i++) { if (Game::elementMap[i] && Game::elementMap[i]->getAttribute("type") != "Hero") { Game::elementMap[i]->ChangeColorTo(Color(0, 0, 0, 1), 1, "PauseGame"); - if (Game::elementMap[i]->getAttribute("physic") != "") + if (Game::elementMap[i]->getAttribute("physic") != "") { theWorld.GetPhysicsWorld().DestroyBody((Game::elementMap[i])->GetBody()); + } theWorld.Remove(Game::elementMap[i]); } } @@ -324,8 +329,10 @@ bool Game::destroyAllBodies(void) { } else { for (std::list<Elements*>::iterator it = Game::bodiesToDestroy.begin(); it != Game::bodiesToDestroy.end(); it++) { if ((*it)->getAttribute("physic") != "") { - (*it)->GetBody()->SetActive(false); - theWorld.GetPhysicsWorld().DestroyBody((*it)->GetBody()); + if ((*it)->GetBody()) { + (*it)->GetBody()->SetActive(false); + theWorld.GetPhysicsWorld().DestroyBody((*it)->GetBody()); + } } theWorld.Remove(*it); Game::delElement(*it); @@ -375,6 +382,24 @@ void Game::makeItRun(void) { } } +//! Changing character +/** + * Will be called early on selection screen + */ + +void Game::changeCharacter(std::string name) { + Game::addToDestroyList(this->getHero()); + + Hero *hero = new Hero(name); + + this->displayHero(*(hero)); + hero->init(); + this->setHero(hero); + + hero->setStartingValues(); + +} + //! Intern callback for display text /** * Callback for each frame, to display the text in the HUDs. @@ -428,30 +453,39 @@ HUDWindow *Game::getHUD(void) { * @todo This function is nasty, we need a recap here. */ void Game::displayHUD(void) { - HUDWindow *w = new HUDWindow(); + HUDWindow *w = Game::getHUD(); Characters* hero = Game::getHero(); - w->SetPosition(theCamera.GetWindowWidth() / 2 - 100, 50); - w->SetSize(theCamera.GetWindowWidth() - 200, 100.0f); - w->SetSprite("Resources/Images/HUD/background_hud.png"); - w->SetDrawShape(ADS_Square); - w->SetLayer(-1); - w->addImage("Resources/Images/HUD/perso.png", 100, 50); - theWorld.Add(w); + Game *g = this; w->setGame(g); - w->setMaxMana(hero->getMaxMana()); + w->showHud(); w->setMaxHP(hero->getMaxHP()); - w->life(hero->getHP()); - w->mana(hero->getMana()); w->gold(0); - w->bag(); - w->initMinimapBackground(); - w->minimap(); - - // Work - /* w->setText("Burp.", this->_hero, Vector3(0, 0, 0), 0, 1);*/ + // Work + //w->setText("Burp.", this->_hero, Vector3(0, 0, 0), 0, 1); /*w->removeText("Burp.");*/ - Game::addHUDWindow(w); +} + +void Game::reloadingHUD(void) { + if (Game::reloadHUD) { + + theWorld.Render(); + Game::getHUD()->clearHUD(); + Game::getHUD()->showBackgrounds(); + Game::getHUD()->character(); + Game::getHUD()->spells(); + Game::getHUD()->bag(); + Game::getHUD()->minimap(); + Game::getHUD()->life(this->getHero()->getHP()); + Game::getHUD()->bag(); + Game::getHUD()->mana(this->getHero()->getMana()); + Game::getHUD()->items(this->getHero()->getWeapon()); + Game::getHUD()->items(this->getHero()->getArmor()); + Game::getHUD()->items(this->getHero()->getRing()); + Game::getHUD()->consumable(this->getHero()->getInventory()->getItems()); + Game::getHUD()->gold(this->getHero()->getGold()); + Game::reloadHUD = 0; + } } /* SETTERS */ @@ -481,3 +515,5 @@ int Game::currentY = 0; Game* Game::currentGame = 0; int Game::started = 0; int Game::cameraTick = 0; +int Game::isWaitingForBind = 0; +int Game::reloadHUD = 0; diff --git a/Sources/src/HUDTargeting.cpp b/Sources/src/HUDTargeting.cpp @@ -0,0 +1,85 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** +* File: HUDTargeting.cpp +* Creation: 2015-06-30 14:20 +* Matthieu Maudet <arkhane84@gmail.com> +*/ + +# include "HUDTargeting.hpp" + +//! Constructor +/** + * Basic constructor + */ + + HUDTargeting::HUDTargeting(void) { + _enemies = Game::currentGame->maps->_XYMap[Game::currentY][Game::currentX].getEnemies(); + std::cout << _enemies.size() << std::endl; + if (_enemies.size() > 0) { + this->_enemyId = 0; + this->_joint = nullptr; + this->SetSize(0.6); + this->SetName("TargetGizmo"); + this->SetDrawShape(ADS_Square); + this->SetColor(1, 0, 0, 1); + this->SetSprite("Resources/Images/HUD/cible.png"); + this->SetLayer(101); + this->addAttribute("physic", "1"); + this->SetDensity(0.0001); + this->SetFixedRotation(true); + this->SetIsSensor(true); + this->SetPosition(this->_enemies.front()->GetBody()->GetWorldCenter().x, this->_enemies.front()->GetBody()->GetWorldCenter().y); + this->InitPhysics(); + changeTarget(); + + theWorld.Add(this); + } + } + + //! Destructor + /** + * Basic destructor + */ + HUDTargeting::~HUDTargeting(void) { + return; + } + + + void HUDTargeting::changeTarget(void) { + std::list<Enemy *>::iterator it; + if (_enemies.size() > 0) { + for (it = this->_enemies.begin(); it != this->_enemies.end(); it++) { + if ((*it)->getId() != _enemyId) { + _current = *it; + _enemyId = _current->getId(); + if (this->_joint != nullptr) + theWorld.GetPhysicsWorld().DestroyJoint(this->_joint); + this->GetBody()->SetTransform(b2Vec2(this->_current->GetBody()->GetWorldCenter().x, this->_current->GetBody()->GetWorldCenter().y), 0); + b2DistanceJointDef jointDef; + jointDef.Initialize(_current->GetBody(), this->GetBody(), b2Vec2(_current->GetBody()->GetWorldCenter().x, _current->GetBody()->GetWorldCenter().y), + this->GetBody()->GetWorldCenter()); + jointDef.collideConnected = false; + this->_joint = (b2DistanceJoint*)theWorld.GetPhysicsWorld().CreateJoint(&jointDef); + return ; + } + } + } + } diff --git a/Sources/src/HUDWindow.cpp b/Sources/src/HUDWindow.cpp @@ -31,8 +31,12 @@ */ HUDWindow::HUDWindow(void) : HUDActor() { RegisterFont("Resources/font.ttf", 14, "Gamefont"); - RegisterFont("Resources/font.ttf", 8, "SmallGamefont"); + RegisterFont("Resources/font.ttf", 14, "Gamefont"); + RegisterFont("Resources/font.ttf", 10, "MediumGamefont"); RegisterFont("Resources/Fonts/fail.otf", 80, "dead"); + RegisterFont("Resources/Fonts/Market_Deco.ttf", 80, "title"); + RegisterFont("Resources/Fonts/Market_Deco.ttf", 40, "smallTitle"); + this->_hearts.clear(); return; } @@ -230,6 +234,7 @@ void HUDWindow::displayText(void) { if ((*i)->isFading) { DrawGameText((*i)->str, (*i)->font, x, y - (*i)->y, theCamera.GetRotation()); (*i)->y += 1; + (*i)->colorA -= 0.05f; } else if ((*i)->isTalk) { DrawGameText((*i)->str, (*i)->font, x - 5, y - (*i)->y + 5, theCamera.GetRotation()); } else { @@ -254,6 +259,7 @@ HUDActor *HUDWindow::addImage(std::string path, int x, int y) { tmp->SetDrawShape(ADS_Square); tmp->SetLayer(100); theWorld.Add(tmp); + this->_allElems.push_back(tmp); return tmp; } @@ -273,6 +279,7 @@ HUDActor *HUDWindow::addImage(std::string path, int x, int y, float size) { tmp->SetDrawShape(ADS_Square); tmp->SetLayer(100); theWorld.Add(tmp); + this->_allElems.push_back(tmp); return tmp; } @@ -293,9 +300,33 @@ HUDActor *HUDWindow::addImage(std::string path, int x, int y, float size, int la tmp->SetDrawShape(ADS_Square); tmp->SetLayer(layer); theWorld.Add(tmp); + this->_allElems.push_back(tmp); return tmp; } +//! Add an image +/** + * Add an image in the HUD + * @param path The path of the img + * @param x X position + * @param y Y position + * @param size Size, X Y in float (Vector2). + * @param layer The desired layer + */ +HUDActor *HUDWindow::addImage(std::string path, int x, int y, Vector2 size, int layer) { + HUDActor *tmp = new HUDActor(); + tmp->SetSprite(path); + tmp->SetPosition(x, y); + tmp->SetSize(size.X, size.Y); + tmp->SetDrawShape(ADS_Square); + tmp->SetLayer(layer); + theWorld.Add(tmp); + this->_allElems.push_back(tmp); + return tmp; +} + + + //! Display HP function /** @@ -305,35 +336,28 @@ HUDActor *HUDWindow::addImage(std::string path, int x, int y, float size, int la * @todo Empty heart, half-heart. */ void HUDWindow::life(int life) { - int x, v, sLife = life; + int x, v, sLife = life, y, size; std::list<HUDActor *>::iterator i; int index; - HUDActor *tmp; - for (i = this->_hearts.begin(), index = 0; i != this->_hearts.end(); i++, index++) + y = theCamera.GetWindowHeight() / 20 * 0.9; + size = theCamera.GetWindowWidth() / 20 * 0.6; + for (i = this->_hearts.begin(), index = 0; i != this->_hearts.end(); i++, index++) { + (*(i))->ChangeColorTo(Color(0, 0, 0, 0), 0); theWorld.Remove(*(i)); + } this->_hearts.clear(); - for (x = 200; life > 0; x += 25) { - if (x == 200) { - this->addImage("Resources/Images/HUD/hp.png", (x - 30), 35, 28.0f); + for (x = theCamera.GetWindowWidth() / 20 * 3; life > 0; x += theCamera.GetWindowWidth() / 35) { + if (x == theCamera.GetWindowWidth() / 20 * 3) { + this->_hearts.push_back(this->addImage("Resources/Images/HUD/hp.png", (x - theCamera.GetWindowWidth() / 30), y, size - 2)); } if (life >= 25) { - tmp = new HUDActor(); - tmp->SetSprite("Resources/Images/HUD/heart.png"); - tmp->SetPosition(x, 35); - tmp->SetSize(30.0f); - theWorld.Add(tmp); - this->_hearts.push_back(tmp); + this->_hearts.push_back(this->addImage("Resources/Images/HUD/heart.png", x, y, size, 100)); life -= 25; } } if (sLife < this->_maxHP) { - for (v = 0; (this->_maxHP - sLife) > v; v += 25) { - tmp = new HUDActor(); - tmp->SetSprite("Resources/Images/HUD/empty_heart.png"); - tmp->SetPosition((x + v), 38); - tmp->SetSize(30); - theWorld.Add(tmp); - this->_hearts.push_back(tmp); + for (v = 0; (this->_maxHP - sLife) > v; v += 25, x += theCamera.GetWindowWidth() / 35) { + this->_hearts.push_back(this->addImage("Resources/Images/HUD/empty_heart.png", x, y + 2, size - 3, 105)); } } } @@ -346,23 +370,26 @@ void HUDWindow::life(int life) { */ void HUDWindow::mana(int mana) { std::list<HUDActor *>::iterator i; - int x = 200, y, max = this->_maxMana; + float x = theCamera.GetWindowWidth() / 20 * 3.05; + int y, max = this->_maxMana; + float yHeight = theCamera.GetWindowHeight() / 20 * 1.56, size = theCamera.GetWindowWidth() / 20 * 0.25; for (i = this->_mana.begin(); i != this->_mana.end(); i++) theWorld.Remove(*(i)); this->_mana.clear(); - this->addImage("Resources/Images/HUD/mp.png", (x - 30), 60, 26.0f); - this->addImage("Resources/Images/HUD/mp_bar_first.png", x, 60, 12.0f); - x += 11; - for (y = 0; y < (mana - 1); y += 10, x += 11) { - this->addImage("Resources/Images/HUD/mp_bar_mid.png", x, 60, 12.0f); + this->_mana.push_back(this->addImage("Resources/Images/HUD/mp.png", (x - theCamera.GetWindowWidth() / 30), yHeight, size * 2)); + x -= theCamera.GetWindowWidth() / 80 * 0.8; + this->_mana.push_back(this->addImage("Resources/Images/HUD/mp_bar_first.png", x, yHeight, size)); + x += theCamera.GetWindowWidth() / 80; + for (y = 0; y < (mana - 1); y += 10, x += theCamera.GetWindowWidth() / 80) { + this->_mana.push_back(this->addImage("Resources/Images/HUD/mp_bar_mid.png", x, yHeight, size)); } if (y == max) - this->addImage("Resources/Images/HUD/mp_bar_full_end.png", x, 60, 12.0f); + this->_mana.push_back(this->addImage("Resources/Images/HUD/mp_bar_full_end.png", x, yHeight, size)); else { - for (; y < max; y += 10, x += 11) - this->addImage("Resources/Images/HUD/mp_bar_empty.png", x, 60, 12.0f); - this->addImage("Resources/Images/HUD/mp_bar_empty_end.png", x, 60, 12.0f); + for (; y < max; y += 10, x += theCamera.GetWindowWidth() / 80) + this->_mana.push_back(this->addImage("Resources/Images/HUD/mp_bar_empty.png", x, yHeight, size)); + this->_mana.push_back(this->addImage("Resources/Images/HUD/mp_bar_empty_end.png", x, yHeight, size)); } } @@ -373,9 +400,13 @@ void HUDWindow::mana(int mana) { * @param gold The gold number */ void HUDWindow::gold(int gold) { - this->addImage("Resources/Images/HUD/xp.png", 340, 50, 20.0f); - this->addImage("Resources/Images/HUD/gold.png", 360, 50, 20.0f); - this->_gold = this->setText(std::to_string(gold), 375, 55, Vector3(246.0f, 255.0f, 0.0f), 1); + float x = theCamera.GetWindowWidth() / 20 * 2.37; + int y = theCamera.GetWindowHeight() / 20 * 2.2; + float size = theCamera.GetWindowWidth() / 20 * 0.41; + + this->addImage("Resources/Images/HUD/xp.png", x, y, Vector2(size + 3.5, size), 100); + this->addImage("Resources/Images/HUD/gold.png", x + (theCamera.GetWindowWidth() / 40 * 1.2), y, size); + this->_gold = this->setText(std::to_string(gold), x + theCamera.GetWindowWidth() / 40 * 2, y + theCamera.GetWindowHeight() / 20 * 0.15, Vector3(246.0f, 255.0f, 0.0f), 1); } //! MAJ gold function @@ -385,9 +416,11 @@ void HUDWindow::gold(int gold) { * @param gold The new gold number */ void HUDWindow::updateGold(int gold) { + float x = theCamera.GetWindowWidth() / 20 * 2.37; + int y = theCamera.GetWindowHeight() / 20 * 2.2; + this->removeText(this->_gold); - this->_gold = this->setText((std::to_string(gold)), 375, 55, - Vector3(246.0f, 255.0f, 0.0f), 1); + this->_gold = this->setText(std::to_string(gold), x + theCamera.GetWindowWidth() / 40 * 2, y + theCamera.GetWindowHeight() / 20 * 0.15, Vector3(246.0f, 255.0f, 0.0f), 1); } //! Display items (Weapon) @@ -398,8 +431,8 @@ void HUDWindow::updateGold(int gold) { * @param w The Weapon equipped. */ void HUDWindow::items(Weapon *w) { - this->addImage("Resources/Images/HUD/weapon_background.png", 770, 50, 60.0f); - this->addImage(w->getSprite(), 770, 50, 40.0f); + this->addImage("Resources/HUD/weapon_stuff.png", (theCamera.GetWindowWidth() / 20 * 11), theCamera.GetWindowHeight() / 20, theCamera.GetWindowWidth() / 20); + this->addImage(w->getSprite(), (theCamera.GetWindowWidth() / 20 * 11), theCamera.GetWindowHeight() / 20, theCamera.GetWindowWidth() / 20 * 0.7); } //! Display items (Armor) @@ -410,8 +443,8 @@ void HUDWindow::items(Weapon *w) { * @param a The Armor equipped. */ void HUDWindow::items(Armor *a) { - this->addImage("Resources/Images/HUD/weapon_background.png", 710, 50, 40.0f); - this->addImage(a->getSprite(), 710, 50, 30.0f); + this->addImage("Resources/HUD/normal_stuff.png", (theCamera.GetWindowWidth() / 20 * 9.8), theCamera.GetWindowHeight() / 20, theCamera.GetWindowWidth() / 20); + this->addImage(a->getSprite(), (theCamera.GetWindowWidth() / 20 * 9.8), theCamera.GetWindowHeight() / 20, theCamera.GetWindowWidth() / 20 * 0.7); } //! Display items (Ring) @@ -422,8 +455,8 @@ void HUDWindow::items(Armor *a) { * @param r The Ring equipped. */ void HUDWindow::items(Ring *r) { - this->addImage("Resources/Images/HUD/weapon_background.png", 660, 50, 40.0f); - this->addImage(r->getSprite(), 660, 50, 30.0f); + this->addImage("Resources/HUD/normal_stuff.png", (theCamera.GetWindowWidth() / 20 * 8.5), theCamera.GetWindowHeight() / 20, theCamera.GetWindowWidth() / 20); + this->addImage(r->getSprite(), (theCamera.GetWindowWidth() / 20 * 8.5), theCamera.GetWindowHeight() / 20, theCamera.GetWindowWidth() / 20 * 0.7); } //! Display armor @@ -454,26 +487,36 @@ void HUDWindow::boots(void) { * @todo Same here, no callback or object. */ void HUDWindow::consumable(std::map<int, std::string> items) { - int i, x; + int i, x, y, size; std::list<HUDActor *>::iterator it; + Elements *w; for (it = this->_bag.begin(); it != this->_bag.end(); it++) theWorld.Remove((*it)); - for (i = 0, x = 445; i < 4; i++, x += 47) { + x = theCamera.GetWindowWidth() / 20 * 8.3; + y = theCamera.GetWindowHeight() / 20 * 2.3; + size = theCamera.GetWindowWidth() / 20 * 0.5; + for (i = 0; i < 4; i++, x += theCamera.GetWindowWidth() / 20) { if (items[i] != "") { HUDActor *tmp; if (Game::wList->checkExists(items[i])) { - Weapon *w = new Weapon(Game::wList->getWeapon(items[i])); - tmp = this->addImage(w->getSprite(), x, 50, 30); + w = new Weapon(Game::wList->getWeapon(items[i])); + tmp = this->addImage(w->getAttribute("sprite"), x, y, size); } else if (Game::aList->checkExists(items[i])) { - Armor* w = new Armor(Game::aList->getArmor(items[i])); - tmp = this->addImage(w->getSprite(), x, 50, 30); + w = new Armor(Game::aList->getArmor(items[i])); + tmp = this->addImage(w->getAttribute("sprite"), x, y, size); } else if (Game::rList->checkExists(items[i])) { - Ring* w = new Ring(Game::rList->getRing(items[i])); - tmp = this->addImage(w->getSprite(), x, 50, 30); + w = new Ring(Game::rList->getRing(items[i])); + tmp = this->addImage(w->getAttribute("sprite"), x, y, size); } this->_bag.push_back(tmp); + if (i == this->_g->getHero()->getInventory()->getNumFocus()) { + Game::currentGame->tooltip->clearInfo(); + Game::currentGame->tooltip->info(w); + tmp = this->addImage("Resources/Images/HUD/selecItem.png", x, y, size + 15); + this->_bag.push_back(tmp); + } } } } @@ -498,7 +541,9 @@ void HUDWindow::_drawDoor(Vector2 size, Vector2 position) { t->SetDrawShape(ADS_Square); t->SetPosition(position.X, position.Y); t->SetSize(size.X, size.Y); + t->SetLayer(100); theWorld.Add(t); + this->_allElems.push_back(t); this->_minimap.push_back(t); } @@ -537,17 +582,19 @@ void HUDWindow::minimap(void) { else tmp->SetColor(1, 1, 1); tmp->SetDrawShape(ADS_Square); + tmp->SetLayer(100); theWorld.Add(tmp); + this->_allElems.push_back(tmp); this->_minimap.push_back(tmp); if (Game::currentGame->maps->getMapXY()[y2][x2 + 1].getXStart()) - this->_drawDoor(Vector2(1, 5), Vector2(x + (40 / 2), y)); + this->_drawDoor(Vector2(1, 5), Vector2(x + 1 + (40 / 2), y)); if (Game::currentGame->maps->getMapXY()[y2][x2 - 1].getXStart()) this->_drawDoor(Vector2(1, 5), Vector2(x - (40 / 2), y)); if (Game::currentGame->maps->getMapXY()[y2 - 1][x2].getXStart()) this->_drawDoor(Vector2(5, 1), Vector2(x, y - (27 / 2) - 1)); if (Game::currentGame->maps->getMapXY()[y2 + 1][x2].getXStart()) - this->_drawDoor(Vector2(5, 1), Vector2(x, y + (27 / 2) - 1)); + this->_drawDoor(Vector2(5, 1), Vector2(x, y + (27 / 2) + 1)); } } } @@ -557,20 +604,62 @@ void HUDWindow::minimap(void) { * This function display an empty bag at the beggining of the game */ void HUDWindow::bag(void) { + int i, x, available; + + available = this->_g->getHero()->getMaxInventory(); + for (i = 0, x = theCamera.GetWindowWidth() / 20 * 8.3; i < 4; i++, x += theCamera.GetWindowWidth() / 20) { + if (i >= available) + this->addImage("Resources/HUD/bag_unavailable.png", x, theCamera.GetWindowHeight() / 20 * 2.3, theCamera.GetWindowWidth() / 20 * 0.65); + else + this->addImage("Resources/HUD/bag_empty.png", x, theCamera.GetWindowHeight() / 20 * 2.3, theCamera.GetWindowWidth() / 20 * 0.65); + } +} + +void HUDWindow::showHud(void) { + this->showBackgrounds(); + this->character(); + this->spells(); + this->bag(); + this->minimap(); +} + +void HUDWindow::showBackgrounds(void) { + int x, y, height, length; + + x = theCamera.GetWindowWidth() / 5 * 3; + y = (theCamera.GetWindowHeight() / 10); + this->addImage("Resources/HUD/bg1.png", x - ((theCamera.GetWindowWidth() / 5) * 1.5), y - (y / 4), + Vector2(x, (y * 1.5) ), 2); + this->addImage("Resources/HUD/bg2.png", x + (theCamera.GetWindowWidth() / 10), y - (y / 4), + Vector2(theCamera.GetWindowWidth() / 5 * 1.5, y * 1.3), 1); + this->addImage("Resources/HUD/bg3.png", (theCamera.GetWindowWidth() - theCamera.GetWindowWidth() / 10), y - (y / 4), + Vector2(theCamera.GetWindowWidth() / 5, y * 1.5), 2); +} + +void HUDWindow::character(void) { + this->addImage("Resources/HUD/perso_bg.png", (theCamera.GetWindowWidth() / 20) * 1.1, theCamera.GetWindowHeight() / 20 * 1.5, + theCamera.GetWindowWidth() / 13, 3); + this->addImage("Resources/HUD/perso_pin.png", theCamera.GetWindowWidth() / 20 * 0.4, theCamera.GetWindowHeight() / 20 * 0.8, + theCamera.GetWindowWidth() / 32, 5); + this->addImage(this->_g->getHero()->getAttribute("spritesFrame"), theCamera.GetWindowWidth() / 20 * 1.1, theCamera.GetWindowHeight() / 20 * 1.5, + theCamera.GetWindowWidth() / 18, 4); HUDActor *bag = new HUDActor(); - int i, x; - - bag->SetSize(200, 60); - bag->SetPosition(theCamera.GetWindowWidth() - 510, 50); - bag->SetSprite("Resources/Images/bag.png"); - bag->SetDrawShape(ADS_Square); - theWorld.Add(bag); - - for (i = 0, x = 445; i < 4; i++, x += 47) { - this->addImage("Resources/Images/bag_slot.png", x, 51, 40); - this->addImage("Resources/Images/round.png", x + 15, 65, 20, 200); - this->setText("S-" + std::to_string(i + 1), x + 10, 67, Vector3(255, 255, 255), 1, "SmallGamefont"); + this->setText("Lvl " + std::to_string(this->_g->getHero()->getLevel()), theCamera.GetWindowWidth() / 20 * 0.2, theCamera.GetWindowHeight() / 20 * 0.9, Vector3(1, 1, 1), 1, "MediumGamefont"); +} + +void HUDWindow::spells(void) { + this->addImage("Resources/HUD/spells_bg.png", (theCamera.GetWindowWidth() / 20) * 7, theCamera.GetWindowHeight() / 20 * 1.5, + Vector2(theCamera.GetWindowWidth() / 15, theCamera.GetWindowHeight() / 10 * 1.2), 5); +} + +void HUDWindow::clearHUD(void) { + std::list<HUDActor *>::iterator it; + + for (it = this->_allElems.begin(); it != this->_allElems.end(); it++) { + theWorld.Remove(*it); } + this->removeText(this->_gold); + this->removeText("Lvl " + std::to_string(this->_g->getHero()->getLevel())); } void HUDWindow::setGame(Game *g) { this->_g = g; }; diff --git a/Sources/src/Hero.cpp b/Sources/src/Hero.cpp @@ -29,14 +29,21 @@ /** * This constructor is making some subscribtions for himself. */ -Hero::Hero(void) : Characters("Hero") { +Hero::Hero(std::string name) : Characters(name) { theSwitchboard.SubscribeTo(this, "canMove"); theSwitchboard.SubscribeTo(this, "endInvincibility"); theSwitchboard.SubscribeTo(this, "enableAttackHitbox"); theSwitchboard.SubscribeTo(this, "disableAttackHitbox"); theSwitchboard.SubscribeTo(this, "equipSelectedItem"); theSwitchboard.SubscribeTo(this, "cycleInventory"); - + theSwitchboard.SubscribeTo(this, "dropItem"); + theSwitchboard.SubscribeTo(this, "attackReady"); + theSwitchboard.SubscribeTo(this, "specialMove"); + theSwitchboard.SubscribeTo(this, "changeCharacter"); + theSwitchboard.SubscribeTo(this, "lockTarget"); + theSwitchboard.SubscribeTo(this, "unlockTarget"); + this->addAttribute("type", "Hero"); + this->_inventory = new Inventory(this->_getAttr("starting", "inventorySlots").asInt()); return ; } @@ -68,10 +75,10 @@ void Hero::init(void) { void Hero::actionCallback(std::string name, int status) { std::string orientation; float x = 2, y = 1; - if (name == "attack" && status == 0 && this->_weapon->attackReady() == 1 && + if (name == "attack" && status == 0 && this->_canAttack == true && this->_fullChargedAttack == false && this->_isLoadingAttack == 0 && this->_isAttacking == 1) { - this->_weapon->isAttacking(0); + this->_canAttack = false; if (this->_orientation == RIGHT) { orientation = "right"; } else if (this->_orientation == LEFT) { @@ -83,16 +90,15 @@ void Hero::actionCallback(std::string name, int status) { x = 1; y = 2.5f; orientation = "down"; } - this->changeSizeTo(Vector2(x, y)); + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(x, y)); this->_setCategory("attack"); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, - this->_getAttr("beginFrame_" + - orientation).asInt(), - this->_getAttr("endFrame_" + - orientation).asInt(), "base"); + this->_getAttr("beginFrame_" + orientation).asInt(), + this->_getAttr("endFrame_" + orientation).asInt(), "base"); } else if (name == "attack" && status == 0 && - this->_weapon->attackReady() == 1 && + this->_canAttack == true && this->_fullChargedAttack == true) { if (this->_orientation == RIGHT) { orientation = "right"; @@ -106,14 +112,11 @@ void Hero::actionCallback(std::string name, int status) { orientation = "down"; } this->_setCategory("loadAttack_done"); - this->_weapon->isAttacking(0); this->_isLoadingAttack = 0; this->_fullChargedAttack = false; - this->changeSizeTo(Vector2(2, 2)); - if (this->_latOrientation == LEFT) - this->GetBody()->SetLinearVelocity(b2Vec2(-5, 3)); - else - this->GetBody()->SetLinearVelocity(b2Vec2(5, 3)); + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(2, 2)); + this->_canAttack = false; this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("beginFrame_" + orientation).asInt(), this->_getAttr("endFrame_" + orientation).asInt(), "base"); @@ -123,12 +126,31 @@ void Hero::actionCallback(std::string name, int status) { } else if (this->_latOrientation == LEFT) orientation = "left"; this->_setCategory("loadAttack_charge"); - this->changeSizeTo(Vector2(2, 2)); + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(2, 2)); this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, this->_getAttr("beginFrame_" + orientation).asInt(), this->_getAttr("endFrame_" + orientation).asInt()); + } else if (name == "dash") { + if (this->_latOrientation == RIGHT) { + orientation = "right"; + } else if (this->_latOrientation == LEFT) + orientation = "left"; + this->changeSizeTo(Vector2(2, 1)); + this->_setCategory("dash"); + this->PlaySpriteAnimation(this->_getAttr("time").asFloat(), SAT_OneShot, + this->_getAttr("beginFrame_" + orientation).asInt(), + this->_getAttr("endFrame_" + orientation).asInt() - 2, "endDash"); + } else if (name == "stomp") { + if (this->_latOrientation == RIGHT) { + orientation = "right"; + } else if (this->_latOrientation == LEFT) + orientation = "left"; + this->PlaySpriteAnimation(this->_getAttr("stomp", "time").asFloat(), SAT_OneShot, + this->_getAttr("stomp", "beginFrame_" + orientation).asInt(), + this->_getAttr("stomp", "endFrame_" + orientation).asInt() - 2, "base"); } - return ; + return; } //! Begin collision function @@ -140,12 +162,17 @@ void Hero::actionCallback(std::string name, int status) { */ void Hero::BeginContact(Elements* elem, b2Contact *contact) { Characters::BeginContact(elem, contact); - if (elem->getAttribute("type") == "Enemy" && elem->isDead() == false) { if (this->_invincibility == false) this->_takeDamage(elem); else { this->_enemiesTouched.push_back(elem); + if (this->_isStomping == true) { + this->GetBody()->SetLinearVelocity(b2Vec2(0, 3)); + theSwitchboard.Broadcast(new Message("stompEnd")); + new Weapon(this->_weapon, this, 1); + new Weapon(this->_weapon, this, -1); + } } } else if (elem->getAttribute("type") == "Object") { @@ -173,12 +200,19 @@ void Hero::BeginContact(Elements* elem, b2Contact *contact) { } } else if (elem->getAttribute("type2") == "Equipment") { + Game::currentGame->tooltip->clearInfo(); Game::currentGame->tooltip->info(elem); this->_item = elem; } } if (elem->getAttribute("type") == "ground" && elem->getAttribute("speType") == "spikes") { + if (this->_isStomping == true) { + theSwitchboard.Broadcast(new Message("stompEnd")); + this->_invincibility = false; + new Weapon(this->_weapon, this, 1); + new Weapon(this->_weapon, this, 1); + } if (this->_invincibility == false) this->_takeDamage(elem); else @@ -207,7 +241,7 @@ void Hero::EndContact(Elements *elem, b2Contact *contact) { this->_enemiesTouched.remove(elem); } if (elem->getAttribute("type2") == "Equipment") { - Game::currentGame->tooltip->clearInfo(); + Game::currentGame->tooltip->clearInfo(0); } /* if (elem->getAttribute("speType") == "water")*/ /*this->GetBody()->SetGravityScale(1);*/ @@ -224,13 +258,14 @@ void Hero::_takeDamage(Elements* elem) { Game::stopRunning(this); this->_isRunning = 0; this->_isJump = 1; - this->changeSizeTo(Vector2(1, 1)); + if (this->getAttribute("class") == "Warrior") + this->changeSizeTo(Vector2(1, 1)); if (this->_invincibility == false) { - this->changeCanMove(); - this->setHP(this->getHP() - 25); - theSwitchboard.DeferredBroadcast(new Message("canMove"), 0.4f); - theSwitchboard.DeferredBroadcast(new Message("endInvincibility"), 1.5f); - Game::getHUD()->life(this->getHP()); + this->_canMove = 0; + this->setHP(this->getHP() - 25); + theSwitchboard.DeferredBroadcast(new Message("canMove"), 0.4f); + theSwitchboard.DeferredBroadcast(new Message("endInvincibility"), 1.5f); + Game::getHUD()->life(this->getHP()); } if (this->GetBody()->GetWorldCenter().x >= elem->GetBody()->GetWorldCenter().x) { this->ApplyLinearImpulse(Vector2(4, 4), Vector2(0, 0)); @@ -252,3 +287,11 @@ void Hero::_takeDamage(Elements* elem) { theSwitchboard.DeferredBroadcast(new Message("colorDamageBlink1"), 0.1f); this->_invincibility = true; } + +void Hero::setStartingValues(void) { + this->_setCategory("starting"); + this->equipWeapon(Game::wList->getWeapon(this->_getAttr("weapon").asString())); + this->equipArmor(Game::aList->getArmor(this->_getAttr("armor").asString())); + this->equipRing(Game::rList->getRing(this->_getAttr("ring").asString())); + this->_speMove = this->_getAttr("specialMove").asString(); +} diff --git a/Sources/src/Inventory.cpp b/Sources/src/Inventory.cpp @@ -40,15 +40,23 @@ Inventory::Inventory(int slots): _slots(slots), _focused(0), _inInventory(0) { * to target another item for dropping/equipping */ void Inventory::changeItemFocus(void) { - if (this->_slots == 1) + if (this->_slots == 1 || this->_inInventory == 1) return; else if (this->_focused < this->_slots - 1) { this->_focused++; } else - this->_focused = 0; - std::cout << this->_focused << ": " << this->_items[this->_focused] << std::endl; - - + this->_focused = 0; + Game::getHUD()->consumable(this->_items); + Elements *w = nullptr; + if (Game::wList->checkExists(this->_items[this->_focused])) { + w = new Weapon(Game::wList->getWeapon(this->_items[this->_focused])); + } else if (Game::aList->checkExists(this->_items[this->_focused])) { + w = new Armor(Game::aList->getArmor(this->_items[this->_focused])); + } else if (Game::rList->checkExists(this->_items[this->_focused])) { + w = new Ring(Game::rList->getRing(this->_items[this->_focused])); + } + //if (w != nullptr) { + //} } @@ -61,13 +69,17 @@ void Inventory::changeItemFocus(void) { */ int Inventory::addItemToInventory(std::string item) { - if (!this->_items.empty() && this->_inInventory > 0 && - this->_items[this->_focused] != "") - return 1; - else { - this->_items[this->_focused] = item; - this->_inInventory++; + int i; + bool done = false; + for (i = 0; i < this->_slots; i++) { + if (this->_items[i] == "" && done == false) { + this->_items[i] = item; + done = true; + } } + if (done == false) + return 1; + this->_inInventory++; Game::getHUD()->consumable(this->_items); } @@ -76,6 +88,8 @@ std::string Inventory::getCurrentFocus(void) { return this->_items[this->_focused]; } +int Inventory::getNumFocus(void) { return this->_focused; }; + void Inventory::swapEquipmentAndInventory(std::string item) { this->_items[this->_focused] = item; } @@ -87,6 +101,7 @@ std::string Inventory::dropSelectedItem(void) { itemName = this->_items[this->_focused]; this->_items[this->_focused].clear(); this->_inInventory--; + Game::getHUD()->consumable(this->_items); return itemName; } @@ -99,3 +114,4 @@ std::string Inventory::equipSelectedItem(void) { /* GETTERS */ std::map<int, std::string> Inventory::getItems(void) { return this->_items; }; +int Inventory::getSlots(void) { return this->_slots; }; diff --git a/Sources/src/Loot.cpp b/Sources/src/Loot.cpp @@ -34,12 +34,12 @@ Loot::Loot(Characters* c) { int i; - if (rand() % 100 <= c->_getAttr("loot", "consumableRate").asInt()) { - if (rand() % 2 == 0) { - new Consumable("HP", c->_getAttr("loot", "HPReward").asString(), c); - } else - new Consumable("gold", c->_getAttr("loot", "XPReward").asString(), c); - } else if (rand() % 100 <= c->_getAttr("loot", "equipmentRate").asInt()) { + /* if (rand() % 100 <= c->_getAttr("loot", "consumableRate").asInt()) {*/ + //if (rand() % 2 == 0) { + //new Consumable("HP", c->_getAttr("loot", "HPReward").asString(), c); + /*} else*/ + // new Consumable("gold", c->_getAttr("loot", "XPReward").asString(), c); + /* } else if (rand() % 100 <= c->_getAttr("loot", "equipmentRate").asInt()) {*/ int rant; rant = rand() % 3; if (rant == 1) @@ -48,7 +48,17 @@ Loot::Loot(Characters* c) { new Equipment(Game::aList->getArmorRandom(c->_getAttr("loot", "EqReward").asInt()), c); else new Equipment(Game::rList->getRingRandom(c->_getAttr("loot", "EqReward").asInt()), c); - } + /*}*/ +} + + +Loot::Loot(Characters* c, std::string toDrop) { + if (Game::wList->checkExists(toDrop)) + new Equipment(Game::wList->getWeapon(toDrop), c); + else if (Game::aList->checkExists(toDrop)) + new Equipment(Game::aList->getArmor(toDrop), c); + else if (Game::rList->checkExists(toDrop)) + new Equipment(Game::rList->getRing(toDrop), c); } Loot::Loot(Characters* c, Weapon *toDrop) { diff --git a/Sources/src/Map.cpp b/Sources/src/Map.cpp @@ -219,8 +219,10 @@ void Map::destroyMap(void) { // Pause enemies for (en = this->_enemies.begin(); en != this->_enemies.end(); en++) { - if (!(*en)->dead()) + if (!(*en)->dead()) { + Game::stopRunning((*en)); (*en)->GetBody()->SetActive(false); + } } } diff --git a/Sources/src/Menu.cpp b/Sources/src/Menu.cpp @@ -26,15 +26,14 @@ # include "Menu.hpp" //! Basic constructor -Menu::Menu(void) { +Menu::Menu(void) : _currentChoice("Start Game"), _fadeActor(nullptr) { theSwitchboard.SubscribeTo(this, "enterPressed"); theSwitchboard.SubscribeTo(this, "downPressed"); theSwitchboard.SubscribeTo(this, "upPressed"); + theSwitchboard.SubscribeTo(this, "specialMove"); theSwitchboard.SubscribeTo(this, "PauseGame"); -// Rebind key -// Show text Menu -// While make a choice -// Launch game + theSwitchboard.SubscribeTo(this, "deletePressed"); + theSwitchboard.SubscribeTo(this, "escapePressed"); } //! Basic destructor @@ -52,13 +51,13 @@ void Menu::showMenu(Game *game) { HUDWindow *w = new HUDWindow(); this->_game = game; - w->setText("grog \\grog\\: spirits (originally rum) mixed with water.", theCamera.GetWindowWidth() / 2 - 100, theCamera.GetWindowHeight() / 2 - 20, Vector3(255.0f, 255.0f, 255.0f), 1); - w->setText("drunk \\drungk\\ v. Past participle of drink. adj. 1. a. Intoxicated with alcoholic liquor to the point of impairment of physical and mental faculties.", theCamera.GetWindowWidth() / 2 - 450, theCamera.GetWindowHeight() / 2, Vector3(255.0f, 255.0f, 255.0f), 1); - w->setText("Press <ENTER> to start", theCamera.GetWindowWidth() / 2 - 40, theCamera.GetWindowHeight() / 2 + 40, - Vector3(255.0f, 255.0f, 255.0f), 1); - theWorld.SetBackgroundColor(*(new Color(0, 0, 0))); - theCamera.SetPosition(0, 0); + theWorld.SetBackgroundColor(*(new Color(.26f, .26f, .26f))); + this->_menuChoices.push_back("Start Game"); + this->_menuChoices.push_back("Settings"); + this->_menuChoices.push_back("Bindings"); + this->_menuChoices.push_back("Exit"); this->_window = w; + this->listMenu(); theWorld.Add(w); Game::addHUDWindow(w); theWorld.StartGame(); @@ -71,15 +70,557 @@ void Menu::showMenu(Game *game) { * @param m The Message Object */ void Menu::ReceiveMessage(Message *m) { - if (Game::started != 1) { + std::list<std::string>::iterator it; + + if (this->_inMenu == 1) { + if (m->GetMessageName() == "enterPressed") { + if (this->_currentChoice == "Start Game") { + theSwitchboard.UnsubscribeFrom(this, "upPressed"); + theSwitchboard.UnsubscribeFrom(this, "downPressed"); + Game::removeHUDWindow(this->_window); + this->_game->start(); + this->_window = Game::getHUD(); + this->_inMenu = 0; + } else if (this->_currentChoice == "Settings") { + this->removeBaseMenu(); + this->_currentChoice = "Anti-Aliasing"; + this->_lastMenu = 1; + this->settings(); + } else if (this->_currentChoice == "Exit") { + Quit::quitGame(); + } else if (this->_currentChoice == "Bindings") { + this->removeBaseMenu(); + this->_lastMenu = 1; + this->_inMenu = 4; + this->bindingMenu(); + } + } else if (m->GetMessageName() == "downPressed") { + it = std::find(this->_menuChoices.begin(), this->_menuChoices.end(), this->_currentChoice); + if ((++it) != this->_menuChoices.end()) { + this->_currentChoice = *(it); + this->listMenu(); + } + } else if (m->GetMessageName() == "upPressed") { + it = std::find(this->_menuChoices.begin(), this->_menuChoices.end(), this->_currentChoice); + if (it != this->_menuChoices.begin()) { + this->_currentChoice = *(--it); + this->listMenu(); + } + } + } else if (this->_inMenu == 2) { if (m->GetMessageName() == "enterPressed") { - theSwitchboard.UnsubscribeFrom(this, "enterPressed"); - theSwitchboard.UnsubscribeFrom(this, "upPressed"); - theSwitchboard.UnsubscribeFrom(this, "downPressed"); - Game::removeHUDWindow(this->_window); - this->_game->start(); - } else if (m->GetMessageName() == "PauseGame") { - //theWorld.PauseSimulation(); + std::map<std::string, int>::iterator it; + + for (it = this->_settingsValues[this->_currentChoice].begin(); it != this->_settingsValues[this->_currentChoice].end(); it++) { + if (it->second == 1) { + if (++it != this->_settingsValues[this->_currentChoice].end()) { + --it; + this->_settingsValues[this->_currentChoice][it->first] = 0; + ++it; + this->_settingsValues[this->_currentChoice][it->first] = 1; + } else { + --it; + this->_settingsValues[this->_currentChoice][it->first] = 0; + this->_settingsValues[this->_currentChoice][this->_settingsValues[this->_currentChoice].begin()->first] = 1; + } + } + } + if (this->_lastMenu == 3) + this->settings(theCamera.GetWindowHeight() / 2 - 100); + else + this->settings(); + } else if (m->GetMessageName() == "downPressed") { + std::map<std::string, std::map<std::string, int> >::iterator it; + it = this->_settingsValues.find(this->_currentChoice); + if ((++it) != this->_settingsValues.end()) { + this->_currentChoice = it->first; + if (this->_lastMenu == 3) + this->settings(theCamera.GetWindowHeight() / 2 - 100); + else + this->settings(); + } + } else if (m->GetMessageName() == "upPressed") { + std::map<std::string, std::map<std::string, int> >::iterator it; + it = this->_settingsValues.find(this->_currentChoice); + if (it->first != this->_settingsValues.begin()->first) { + it--; + this->_currentChoice = it->first; + if (this->_lastMenu == 3) + this->settings(theCamera.GetWindowHeight() / 2 - 100); + else + this->settings(); + } + } else if (m->GetMessageName() == "deletePressed") { + this->removeSettings(); + this->applySettings(); + if (this->_lastMenu == 1) { + this->_currentChoice = "Start Game"; + this->listMenu(); + } else if (this->_lastMenu == 3) { + this->_currentChoice = "Settings"; + this->_inMenu = 3; + this->pauseMenu(); + } + } + } else if (this->_inMenu == 3) { + if (m->GetMessageName() == "downPressed") { + std::list<std::string>::iterator it; + + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end() && (*it) != this->_currentChoice; it++); + if ((++it) != this->_pauseMenuText.end()) { + this->_currentChoice = *it; + this->pauseMenu(); + } + } else if (m->GetMessageName() == "upPressed") { + std::list<std::string>::iterator it; + + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end() && (*it) != this->_currentChoice; it++); + if (it != this->_pauseMenuText.begin()) { + --it; + this->_currentChoice = *it; + this->pauseMenu(); + } + } else if (m->GetMessageName() == "enterPressed") { + if (this->_currentChoice == "Quit") { + Quit::quitGame(); + } else if (this->_currentChoice == "Settings") { + std::list<std::string>::iterator it; + + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end(); it++) + this->_window->removeText(*it); + this->_window->removeText("PAUSE"); + this->_lastMenu = 3; + this->_inMenu = 2; + this->_currentChoice = "Anti-Aliasing"; + this->settings(theCamera.GetWindowHeight() / 2 - 100); + } else if (this->_currentChoice == "Bindings") { + std::list<std::string>::iterator it; + + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end(); it++) + this->_window->removeText(*it); + this->_window->removeText("PAUSE"); + this->_lastMenu = 3; + this->_inMenu = 4; + this->bindingMenu(theCamera.GetWindowHeight() / 2 - 175); + } + } + } else if (this->_inMenu == 4) { + if (m->GetMessageName() == "downPressed") { + std::map<std::string, std::list<t_bind *> >::iterator it = this->_bindingIterator; + std::list<t_bind *>::iterator it2; + + for (it2 = it->second.begin(); it2 != it->second.end() && (*it2)->name != this->_currentChoice; it2++); + if (++it2 == it->second.end()) { + if (++it != this->_bindingMenu.end() && it->first != "General") { + this->_bindingIterator = it; + this->_currentChoice = (*it->second.begin())->name; + } + } else { + this->_currentChoice = (*it2)->name; + } + if (this->_lastMenu == 3) + this->bindingMenu(theCamera.GetWindowHeight() / 2 - 175); + else + this->bindingMenu(); + } else if (m->GetMessageName() == "upPressed") { + std::map<std::string, std::list<t_bind *> >::iterator it = this->_bindingIterator; + std::list<t_bind *>::iterator it2; + + for (it2 = it->second.begin(); it2 != it->second.end() && (*it2)->name != this->_currentChoice; it2++); + if (it2 == it->second.begin()) { + if (it != this->_bindingMenu.begin()) { + --it; + if (it->first != "General") { + this->_bindingIterator = it; + it2 = it->second.end(); + it2--; + this->_currentChoice = (*it2)->name; + } + } + } else { + it2--; + this->_currentChoice = (*it2)->name; + } + if (this->_lastMenu == 3) + this->bindingMenu(theCamera.GetWindowHeight() / 2 - 175); + else + this->bindingMenu(); + } else if (m->GetMessageName() == "enterPressed") { + std::map<std::string, std::list<t_bind *> >::iterator it = this->_bindingIterator; + std::list<t_bind *>::iterator it2; + + for (it2 = it->second.begin(); it2 != it->second.end() && (*it2)->name != this->_currentChoice; it2++); + this->_window->removeText((*it2)->realKey); + (*it2)->oldKey = (*it2)->realKey; + (*it2)->realKey = "<Press a Key>"; + if (this->_lastMenu == 3) + this->bindingMenu(theCamera.GetWindowHeight() / 2 - 175); + else + this->bindingMenu(); + Game::isWaitingForBind = 1; + } else if (m->GetMessageName() == "deletePressed") { + std::map<std::string, std::list<t_bind *> >::iterator it; + std::list<t_bind *>::iterator it2; + + if (this->applyBindings()) { + for (it = this->_bindingMenu.begin(); it != this->_bindingMenu.end(); it++) { + this->_window->removeText(it->first); + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + this->_window->removeText((*it2)->name); + this->_window->removeText((*it2)->realKey); + } + } + this->_window->removeText("Bindings"); + if (this->_lastMenu == 1) { + this->_inMenu = 1; + this->_currentChoice = "Start Game"; + this->listMenu(); + } else if (this->_lastMenu == 3) { + this->_inMenu = 3; + this->_currentChoice = "Settings"; + this->pauseMenu(); + } + } + } + } + + if (m->GetMessageName() == "escapePressed") { + if (this->_inMenu == 0) { + std::list<std::string> subs = Game::currentGame->getHero()->getSubscribes(); + std::list<std::string>::iterator it; + + for (it = subs.begin(); it != subs.end(); it++) + theSwitchboard.SubscribeTo(this, *it); + Game::currentGame->getHero()->unsubscribeFromAll(); + theWorld.PausePhysics(); + this->_inMenu = 3; + this->pauseMenu(); + } else if (this->_inMenu == 1) { + Quit::quitGame(); + } else if (this->_inMenu == 2 || this->_inMenu == 4) { + this->ReceiveMessage(new Message("deletePressed")); + } else { + std::list<std::string>::iterator it; + + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end(); it++) + this->_window->removeText(*it); + theWorld.Remove(this->_fadeActor); + this->_window->removeText("PAUSE"); + std::list<std::string> subs = Game::currentGame->getHero()->getSubscribes(); + + for (it = subs.begin(); it != subs.end(); it++) + theSwitchboard.UnsubscribeFrom(this, *it); + + Game::currentGame->getHero()->subscribeToAll(); + theWorld.ResumePhysics(); + this->_inMenu = 0; + this->_fadeActor = nullptr; + this->_pauseMenuText.clear(); } } } + +void Menu::listMenu(void) { + std::list<std::string>::iterator it; + int x = (theCamera.GetWindowWidth() / 2), y = (theCamera.GetWindowHeight() / 2); + + this->_inMenu = 1; + for (it = this->_menuChoices.begin(); it != this->_menuChoices.end(); it++) + this->_window->removeText(*it); + this->_window->removeText("Grog Like"); + for (it = this->_menuChoices.begin(); it != this->_menuChoices.end(); it++, y += 20) { + if (this->_currentChoice == *it) { + this->_window->setText(*it, x - ((*it).length() / 2 * 6), y, Vector3(255, 0, 0), 1); + } else { + this->_window->setText(*it, x - ((*it).length() / 2 * 6), y, Vector3(255, 255, 255), 1); + } + } + this->_window->setText("Grog Like", (theCamera.GetWindowWidth() / 2) - 200, (theCamera.GetWindowHeight() / 2) - 100, + Vector3(255.0f, 255.0f, 255.0f), 1, "title"); +} + +void Menu::removeBaseMenu(void) { + std::list<std::string>::iterator it; + + for (it = this->_menuChoices.begin(); it != this->_menuChoices.end(); it++) + this->_window->removeText(*it); + this->_window->removeText("Grog Like"); +} + +void Menu::settings(int y) { + int x = theCamera.GetWindowWidth() / 2; + y = (y ? y : theCamera.GetWindowHeight() / 2 - 250); + std::map<std::string, std::map<std::string, int> >::iterator it; + std::map<std::string, int>::iterator it2; + + if (this->_settingsValues.size() == 0) + this->parseSettings(); + this->_window->removeText("Settings"); + for (it = this->_settingsValues.begin(); it != this->_settingsValues.end(); it++) { + this->_window->removeText(it->first); + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) + this->_window->removeText(it2->first); + } + + this->_inMenu = 2; + this->_window->setText("Settings", (x - 180), y, Vector3(255, 255, 255), 1, "title"); + + y += 80; + for (it = this->_settingsValues.begin(); it != this->_settingsValues.end(); it++, y += 20) { + if (this->_currentChoice == it->first) + this->_window->setText(it->first, x - 200, y, Vector3(255, 0, 0), 1); + else + this->_window->setText(it->first, x - 200, y, Vector3(255, 255, 255), 1); + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + if (it2->second == 1) { + this->_window->setText(it2->first, x + 100, y, Vector3(255, 255, 255), 1); + } + } + } +} + +void Menu::removeSettings(void) { + std::map<std::string, std::map<std::string, int> >::iterator it; + std::map<std::string, int>::iterator it2; + + this->_window->removeText("Settings"); + for (it = this->_settingsValues.begin(); it != this->_settingsValues.end(); it++) { + this->_window->removeText(it->first); + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) + this->_window->removeText(it2->first); + } +} + +void Menu::parseSettings(void) { + std::stringstream buffer; + std::ifstream fd; + Json::Reader read; + Json::Value json; + Json::ValueIterator i, v; + int j; + + fd.open("Config/Settings.json"); + if (!fd.is_open()) + Log::error("Can't find Config/Settings.json"); + buffer << fd.rdbuf(); + + if (!read.parse(buffer, json)) + Log::error("Error in json syntax :\n" + read.getFormattedErrorMessages()); + + for (i = json.begin(); i != json.end(); i++) { + this->_settingsValues[i.key().asString()] = std::map<std::string, int>(); + for (j = 0, v = (*i).begin(); v != (*i).end(); v++, j++) { + if (!j) + this->_settingsValues[i.key().asString()][v.key().asString()] = 1; + else + this->_settingsValues[i.key().asString()][v.key().asString()] = 0; + } + } +} + +void Menu::parseBindings(void) { + std::stringstream buffer; + std::ifstream fd; + Json::Reader read; + Json::Value json; + Json::ValueIterator i, v, j; + t_bind *tmp; + + fd.open("Config/Bindings.json"); + if (!fd.is_open()) + Log::error("Can't find Config/Settings.json"); + buffer << fd.rdbuf(); + + if (!read.parse(buffer, json)) + Log::error("Error in json syntax :\n" + read.getFormattedErrorMessages()); + + for (i = json.begin(); i != json.end(); i++) { + this->_bindingMenu[i.key().asString()] = std::list<t_bind *>(); + for (v = (*i).begin(); v != (*i).end(); v++) { + tmp = new t_bind(); + tmp->name = v.key().asString(); + for (j = (*v).begin(); j != (*v).end(); j++) { + if (j.key().asString() == "broadcast") + tmp->broadcast = (*j).asString(); + else if (j.key().asString() == "key") { + tmp->key = theInput.GetHashFromKeyName((*j).asString()); + tmp->realKey = (*j).asString(); + } + } + this->_bindingMenu[i.key().asString()].push_back(tmp); + } + } + this->_bindingIterator = this->_bindingMenu.begin(); + this->_bindingIterator++; + this->_currentChoice = (*(this->_bindingIterator)->second.begin())->name; +} + +void Menu::applySettings(void) { + std::map<std::string, std::map<std::string, int> >::iterator it; + std::map<std::string, int>::iterator it2; + + for (it = this->_settingsValues.begin(); it != this->_settingsValues.end(); it++) { + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + if (it2->second == 1) { + if (it->first == "Resolution") { + if (it2->first == "1024x720") { + glfwSetWindowSize(theWorld.GetMainWindow(), 1024, 720); + theCamera.ResizeCallback(theWorld.GetMainWindow(), 1024, 720); + } else if (it2->first == "1524x1020") { + glfwSetWindowSize(theWorld.GetMainWindow(), 1524, 1020); + theCamera.ResizeCallback(theWorld.GetMainWindow(), 1524, 1020); + } else if (it2->first == "FullScreen") { + const GLFWvidmode *mode = glfwGetVideoMode(glfwGetPrimaryMonitor()); + glfwSetWindowSize(theWorld.GetMainWindow(), mode->width, mode->height); + theCamera.ResizeCallback(theWorld.GetMainWindow(), mode->width, mode->height); + } + glfwSetWindowPos(theWorld.GetMainWindow(), 0, 0); + } else if (it->first == "Anti-Aliasing") { + if (it2->first == "Yes") { + glfwWindowHint(GLFW_SAMPLES, 4); + } else { + glfwWindowHint(GLFW_SAMPLES, 0); + } + } + } + } + } + if (Game::started == 1) { + Game::reloadHUD = 1; + } +} + +void Menu::pauseMenu(void) { + if (this->_fadeActor == nullptr) { + HUDActor *fade = new HUDActor(); + + fade->SetSize(100000, 100000); + fade->SetColor(0, 0, 0, 0.5f); + fade->SetLayer(100000); + theWorld.Add(fade); + this->_fadeActor = fade; + this->_pauseMenuText.push_back("Settings"); + this->_pauseMenuText.push_back("Bindings"); + this->_pauseMenuText.push_back("Quit"); + this->_currentChoice = "Settings"; + goto render; + } else { +render: + std::list<std::string>::iterator it; + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end(); it++) + this->_window->removeText(*it); + this->_window->removeText("PAUSE"); + + int x = theCamera.GetWindowWidth() / 2, y = theCamera.GetWindowHeight() / 2; + + this->_window->setText("PAUSE", (theCamera.GetWindowWidth() / 2) - 100, (theCamera.GetWindowHeight() / 2) - 100, + Vector3(255.0f, 255.0f, 255.0f), 1, "title"); + for (it = this->_pauseMenuText.begin(); it != this->_pauseMenuText.end(); it++, y += 20) { + if (*it == this->_currentChoice) + this->_window->setText(*it, x - ((*it).length() / 2 * 6), y, Vector3(255, 0, 0), 1); + else + this->_window->setText(*it, x - ((*it).length() / 2 * 6), y, Vector3(255, 255, 255), 1); + } + } +} + +void Menu::getBind(int key) { + std::map<std::string, std::list<t_bind *> >::iterator it = this->_bindingIterator; + std::list<t_bind *>::iterator it2, tmp; + + for (it2 = it->second.begin(); it2 != it->second.end() && (*it2)->name != this->_currentChoice; it2++); + this->_window->removeText((*it2)->realKey); + if (key <= 90 && key >= 65) + key += 32; + (*it2)->key = key; + (*it2)->realKey = theInput.GetKeyNameFromHash(key); + tmp = it2; + + for (it = this->_bindingMenu.begin(); it != this->_bindingMenu.end(); it++) { + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + if ((*it2)->key == (*tmp)->key && it2 != tmp) { + (*it2)->key = 0; + (*it2)->realKey = "<None>"; + } + } + } + if (this->_lastMenu == 3) + this->bindingMenu(theCamera.GetWindowHeight() / 2 - 175); + else + this->bindingMenu(); + Game::isWaitingForBind = 0; +} + +void Menu::bindingMenu(int y) { + int x = theCamera.GetWindowWidth() / 2; + y = (y ? y : theCamera.GetWindowHeight() / 2 - 250); + std::map<std::string, std::list<t_bind *> >::iterator it; + std::list<t_bind *>::iterator it2; + + if (!this->_bindingMenu.size()) { + this->parseBindings(); + } + + for (it = this->_bindingMenu.begin(); it != this->_bindingMenu.end(); it++) { + this->_window->removeText(it->first); + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + this->_window->removeText((*it2)->name); + this->_window->removeText((*it2)->realKey); + } + } + this->_window->removeText("Bindings"); + + this->_window->setText("Bindings", (x - 180), y, Vector3(255, 255, 255), 1, "title"); + y += 70; + for (it = this->_bindingMenu.begin(); it != this->_bindingMenu.end(); it++) { + if (it->first != "General") { + this->_window->setText(it->first, x - ((it->first).length() / 2 * 16) - 50, y, Vector3(255, 255, 255), 1, "smallTitle"); + y += 20; + for (it2 = it->second.begin(); it2 != it->second.end(); it2++, y += 20) { + if (this->_currentChoice == (*it2)->name) + this->_window->setText((*it2)->name, x - 150, y, Vector3(255, 0, 0), 1); + else + this->_window->setText((*it2)->name, x - 150, y, Vector3(255, 255, 255), 1); + this->_window->setText((*it2)->realKey, x + 50, y, Vector3(255, 255, 255), 1); + } + y += 20; + } + } +} + +int Menu::applyBindings(void) { + std::map<std::string, std::list<t_bind *> >::iterator it; + std::list<t_bind *>::iterator it2; + + for (it = this->_bindingMenu.begin(); it != this->_bindingMenu.end(); it++) { + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + if ((*it2)->key == 0) + return 0; + } + } + + for (it = this->_bindingMenu.begin(); it != this->_bindingMenu.end(); it++) { + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + theInput.UnbindKey((*it2)->oldKey); + if (this->_isUpper((*it2)->broadcast)) { + theInput.BindKey((*it2)->realKey, (*it2)->broadcast); + } else { + theInput.BindKey((*it2)->realKey, "+" + (*it2)->broadcast + "Pressed"); + theInput.BindKey((*it2)->realKey, "-" + (*it2)->broadcast + "Released"); + } + } + } + return 1; +} + +int Menu::_isUpper(std::string s) { + int i; + + for (i = 0; i < s.size(); i++) { + if (s[i] >= 'A' && s[i] <= 'Z') + return 1; + } + return 0; +} + +std::map<std::string, std::list<t_bind *> > Menu::getBindings(void) { return this->_bindingMenu; }; diff --git a/Sources/src/Object.cpp b/Sources/src/Object.cpp @@ -45,7 +45,10 @@ Object::Object(void) { * @param contact (b2Contact *) * @note This function is called just before a collision */ + void Object::BeginContact(Elements *elem, b2Contact *contact) { + contact->SetEnabled(false); + contact->enableContact = false; } //! Destructor diff --git a/Sources/src/Projectile.cpp b/Sources/src/Projectile.cpp @@ -40,6 +40,7 @@ Projectile::Projectile(Weapon* w, Characters* c){ this->_damage = w->getDamage(); this->_pushback = w->getPushback(); this->_recovery = w->getRecovery(); + this->_critRate = w->getCritRate(); this->SetSize(0.5f); this->SetShapeType(PhysicsActor::SHAPETYPE_BOX); this->SetSprite("Resources/Images/arrow.png"); @@ -48,13 +49,15 @@ Projectile::Projectile(Weapon* w, Characters* c){ this->SetRestitution(0.0f); this->SetFixedRotation(true); this->SetIsSensor(true); - if (c->getAttributes()["type"] == "Hero") + if (c->getAttribute("type") == "Hero") { this->addAttribute("type", "HeroProjectile"); + } else this->addAttribute("type", "Projectile"); this->Tag("projectile"); + this->addAttribute("physic", "1"); this->_initDirection(w, c); - theSwitchboard.DeferredBroadcast(new Message("canAttack"), this->_recovery); + theSwitchboard.DeferredBroadcast(new Message("attackReady"), this->_recovery); theWorld.Add(this); } @@ -103,6 +106,7 @@ int Projectile::getSize(void) { return this->_size; } int Projectile::getDamage(void) { return this->_damage; } int Projectile::getPushback(void) { return this->_pushback; } float Projectile::getRecovery(void) { return this->_recovery; } +int Projectile::getCritRate(void) { return this->_critRate; } void Projectile::ReceiveMessage(Message *m) { } @@ -116,7 +120,7 @@ void Projectile::ReceiveMessage(Message *m) { * @param contact The b2Contact object of the collision. See Box2D docs for more info. */ void Projectile::BeginContact(Elements *m, b2Contact *c) { - if (m->getAttribute("type") == "Object" ) + if (m->getAttribute("type") == "Object" || m->getAttribute("type") == "Hero") return; Game::addToDestroyList(this); } diff --git a/Sources/src/Quit.cpp b/Sources/src/Quit.cpp @@ -0,0 +1,93 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/**** +*** * File: Quit.cpp +* *** Creation: 2015-06-23 16:35 +*** * Ne02ptzero <louis@ne02ptzero.me> +* *** lsolofri@e2r12p22.42.fr +****/ + +#include "Quit.hpp" + +/** + * Default constructor + */ +Quit::Quit(void) { + return ; +} + +/** + * Destructor + */ +Quit::~Quit(void) { + return ; +} + +void Quit::quitGame(void) { + Menu *menu = Game::currentGame->menu; + Quit::writeBindings(menu->getBindings()); + exit(0); +} + +void Quit::writeBindings(std::map<std::string, std::list<t_bind *> > binds) { + std::map<std::string, std::list<t_bind *> >::iterator it; + std::list<t_bind *>::iterator it2; + Json::Value root; + std::ofstream jsonFile, luaFile; + + if (binds.size() != 0) { + jsonFile.open("Config/Bindings.json", std::ofstream::out | std::ofstream::trunc); + luaFile.open("Config/input_bindings.ini", std::ofstream::out | std::ofstream::trunc); + if (!jsonFile.is_open() || !luaFile.is_open()) { + Log::error("A binding file is missing (Bindings.json / input_bindings.ini)"); + } + + jsonFile << "/* This file is generated by Grog-Like. DO NOT modify it. */" << std::endl; + luaFile << "; This file is generated by Grog-Like. DO NOT modify it." << std::endl; + for (it = binds.begin(); it != binds.end(); it++) { + luaFile << ";; " << it->first << std::endl; + for (it2 = it->second.begin(); it2 != it->second.end(); it2++) { + // Json file + root[it->first][(*it2)->name]["broadcast"] = (*it2)->broadcast; + root[it->first][(*it2)->name]["key"] = (*it2)->realKey; + + // Lua file + if (!Quit::isUpper((*it2)->broadcast)) { + luaFile << "\t" << (*it2)->realKey << " = +" << (*it2)->broadcast << "Pressed" << std::endl; + luaFile << "\t" << (*it2)->realKey << " = -" << (*it2)->broadcast << "Released" << std::endl; + } else { + luaFile << "\t" << (*it2)->realKey << " = " << (*it2)->broadcast << std::endl; + } + } + } + jsonFile << root << std::endl; + } +} + +int Quit::isUpper(std::string s) { + int i; + + for (i = 0; i < s.size(); i++) { + if (s[i] >= 'A' && s[i] <= 'Z') + return 1; + } + return 0; +} + diff --git a/Sources/src/Ring.cpp b/Sources/src/Ring.cpp @@ -46,6 +46,7 @@ Ring::Ring(Ring* Ring) { this->_sprite = Ring->getSprite(); this->addAttribute("type3", "Ring"); this->addAttribute("name", this->_name); + this->addAttribute("sprite", this->_sprite); this->_lootLevel = Ring->getLootLevel(); if (Ring->getAttribute("hpBuff") != "") this->addAttribute("hpBuff", Ring->getAttribute("hpBuff")); @@ -102,6 +103,7 @@ void Ring::_parseJson(std::string file) { this->addAttribute( i.key().asString(), (*i).asString()); this->addAttribute("type3", "Armor"); this->addAttribute("type3", "Ring"); + this->addAttribute("sprite", this->_sprite); } //! Function called to get an attr value from the parsed json @@ -136,6 +138,10 @@ int Ring::getLootLevel(void) { return this->_lootLevel; } /* SETTERS */ void Ring::BeginContact(Elements *elem, b2Contact *contact) { + if (elem->getAttribute("type") != "ground") { + contact->SetEnabled(false); + contact->enableContact = false; + } } void Ring::EndContact(Elements *elem, b2Contact *contact) { diff --git a/Sources/src/SpecialMoves.cpp b/Sources/src/SpecialMoves.cpp @@ -0,0 +1,217 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * File: SpecialMoves.cpp + * Creation: 2015-06-30 09:57 + * Matthieu Maudet<arkhane84@gmail.com> + */ + + # include "SpecialMoves.hpp" + # include <cstdlib> + + + + //! Base constructor + SpecialMoves::SpecialMoves(void) { + + } + + //! Main constructor + SpecialMoves::SpecialMoves(Characters* charac) : character(charac) { + + } + + //! Basic destructor + SpecialMoves::~SpecialMoves(void) { + } + + //! Set the current working category + /** + * This function is made for gain time and money, set first the category in this functions + * then call the function _getAttr(std::string key). + * See _getAttr(std::string key) for more info. + * @param category The name of the category + * @sa SpecialMoves::_getAttr + */ + void SpecialMoves::_setCategory(std::string category) { + this->character->_category = category; + } + + + //! Special move: dash + /** + * Character executes a dash if the cooldown is up and the conditions allows it + * Properties of dash - no gravity, take damage, cant move + * @sa SpecialMoves::_specialMove() + */ + + void SpecialMoves::_dash(void) { + this->character->_setCategory("dash"); + if (this->character->_isAttacking == 0 && this->character->_canMove == 1 && this->character->_hasDashed == 0 && + this->character->_isDashing == false) { + this->character->_isDashing = true; + this->character->GetBody()->SetGravityScale(0); + this->character->actionCallback("dash", 0); + this->character->_canMove = 0; + if (this->character->_grounds.size() == 0) + this->character->_hasDashed = 1; + theSwitchboard.SubscribeTo(this->character, "dashEnd"); + theSwitchboard.DeferredBroadcast(new Message("dashEnd"), + this->character->_getAttr("uptime").asFloat()); + if (this->character->_latOrientation == Characters::LEFT) + this->character->GetBody()->SetLinearVelocity(b2Vec2(-this->character->_getAttr("dashSpeed").asInt(), 0)); + else if (this->character->_latOrientation == Characters::RIGHT) + this->character->GetBody()->SetLinearVelocity(b2Vec2(this->character->_getAttr("dashSpeed").asInt(), 0)); + } + } + + //! Special move: charge + /** + * Character executes a charge if the cooldown is up and the conditions allows it + * Properties of charge - invincibility, can move + * @sa SpecialMoves::_specialMove() + */ + + void SpecialMoves::_charge(void) { + this->character->_setCategory("charge"); + if (this->character->_isAttacking == 0 && this->character->_canMove == 1 && this->character->_speMoveReady == 1 && this->character->_grounds.size() > 0) { + this->character->_speMoveReady = 0; + this->character->_invincibility = true; + this->character->_isCharging = true; + this->character->_canMove = 0; + theSwitchboard.SubscribeTo(this->character, "speMoveReady"); + theSwitchboard.SubscribeTo(this->character, "chargeEnd"); + theSwitchboard.DeferredBroadcast(new Message("speMoveReady"), + this->character->_getAttr("cooldown").asFloat()); + theSwitchboard.DeferredBroadcast(new Message("chargeEnd"), + this->character->_getAttr("uptime").asFloat()); + if (this->character->_latOrientation == Characters::LEFT) + this->character->GetBody()->SetLinearVelocity(b2Vec2(-this->character->_getAttr("chargeSpeed").asInt(), 0)); + else if (this->character->_latOrientation == Characters::RIGHT) + this->character->GetBody()->SetLinearVelocity(b2Vec2(this->character->_getAttr("chargeSpeed").asInt(), 0)); + } + } + + //! Special move: stomp + /** + * If airborne, will allow you to slam the ground and deal damage to enemies + * Properties of stomp - invincibility, can move + * @sa SpecialMoves::_specialMove() + */ + + void SpecialMoves::_stomp(void) { + this->character->_setCategory("stomp"); + if (this->character->_isAttacking == 0 && this->character->_canMove == 1 && this->character->_speMoveReady == 1 + && this->character->_grounds.size() == 0) { + this->character->_speMoveReady = 0; + this->character->GetBody()->SetBullet(true); + this->character->_invincibility = true; + this->character->actionCallback("stomp", 0); + this->character->_isStomping = true; + this->character->_isCharging = true; + theSwitchboard.SubscribeTo(this->character, "speMoveReady"); + theSwitchboard.SubscribeTo(this->character, "stompEnd"); + theSwitchboard.DeferredBroadcast(new Message("speMoveReady"), + this->character->_getAttr("cooldown").asFloat()); + this->character->GetBody()->SetLinearVelocity(b2Vec2(0, -this->character->_getAttr("stompSpeed").asInt())); + } + } + + + //! Special move: blink + /** + * Teleports the player in the direction he's facing + * Properties of blink - instant + * @sa SpecialMoves::_specialMove() + */ + + void SpecialMoves::_blink(void) { + this->character->_setCategory("blink"); + Map m = Game::currentGame->maps->getMapXY()[Game::currentY][Game::currentX]; + int x = (this->character->GetBody()->GetWorldCenter().x) - m.getXStart(); + int y = -((this->character->GetBody()->GetWorldCenter().y) - m.getYStart() - 0.5); + int range = this->character->_getAttr("blinkRange").asInt(); + std::vector<std::vector<int>> t = m.getPhysicMap(); + + if (this->character->_isAttacking == 0 && this->character->_canMove == 1 && this->character->_speMoveReady == 1) { + this->character->_speMoveReady = 0; + theSwitchboard.SubscribeTo(this->character, "speMoveReady"); + theSwitchboard.DeferredBroadcast(new Message("speMoveReady"), + this->character->_getAttr("cooldown").asFloat()); + if (this->character->_orientation == Characters::UP) { + while (range > 0) { + if (y - range > 0 && !t[y - range][x]) + break; + range--; + } + if (range > 0) + this->character->GetBody()->SetTransform(b2Vec2(this->character->GetBody()->GetWorldCenter().x, + this->character->GetBody()->GetWorldCenter().y + range), 0); + } + else if (this->character->_orientation == Characters::DOWN) { + while (range > 0) { + if (y + range < (t.size() - 2) && !t[y + range][x]) + break; + range--; + } + range--; + if (range > 0) + this->character->GetBody()->SetTransform(b2Vec2(this->character->GetBody()->GetWorldCenter().x, + this->character->GetBody()->GetWorldCenter().y - range), 0); + } + else if (this->character->_orientation == Characters::RIGHT) { + while (range > 0) { + if (x + range < t[y].size() && !t[y][x + range]) + break; + range--; + } + if (range > 0) + this->character->GetBody()->SetTransform(b2Vec2(this->character->GetBody()->GetWorldCenter().x + range, + this->character->GetBody()->GetWorldCenter().y), 0); + } + else if (this->character->_orientation == Characters::LEFT) { + while (range > 0) { + if (x - range > 0 && !t[y][x - range]) + break; + range--; + } + if (range > 0) + this->character->GetBody()->SetTransform(b2Vec2(this->character->GetBody()->GetWorldCenter().x - range, + this->character->GetBody()->GetWorldCenter().y), 0); + } + if (range > 0) { + b2PolygonShape box = Game::hList->getHitbox(this->character->_hitbox); + b2Shape *shape = &box; + this->character->GetBody()->DestroyFixture(this->character->GetBody()->GetFixtureList()); + this->character->GetBody()->CreateFixture(shape, 1); + } + } + } + + //! Special move: fly + /** + * Toggles fly mode on. When it's on, the jump button makes the character fly + * Properties of fly - toggle + * @sa SpecialMoves::_specialMove() + */ + + void SpecialMoves::_fly(void) { + this->character->_isFlying = (this->character->_isFlying ? false : true); + } diff --git a/Sources/src/Tooltip.cpp b/Sources/src/Tooltip.cpp @@ -30,7 +30,7 @@ * Basic constructor */ -Tooltip::Tooltip() : _name("") { +Tooltip::Tooltip() : _name("") , _flavor(""), _lastElem(nullptr) { theSwitchboard.SubscribeTo(this, "deleteTip"); return ; } @@ -45,7 +45,7 @@ Tooltip::Tooltip() : _name("") { Tooltip::~Tooltip() { return ; } - + //! Parse the type of the loot /** * Parse the type and set color and value @@ -74,25 +74,61 @@ void Tooltip::tip(Elements *elem, Characters *c) { } void Tooltip::info(Elements *elem) { - if (this->_name == "") { - HUDActor *equip = new HUDActor(); + std::string tmp; + int i = 0; + float x = theCamera.GetWindowWidth() / 20 * 11.3; + float y = 30; + + + if (this->_name == "" && this->_flavor == "") { HUDWindow *hud = Game::getHUD(); - this->_equip = equip; this->_name = elem->getAttribute("name"); + this->_flavor = elem->getAttribute("flavor"); - equip->SetSize(200, 100); - equip->SetPosition(theCamera.GetWindowWidth() - 100, 50); - equip->SetColor(0, 0, 0); - equip->SetDrawShape(ADS_Square); - theWorld.Add(equip); - hud->setText(this->_name,theCamera.GetWindowWidth() - 100, 50); + hud->setText(this->_name , x + theCamera.GetWindowWidth() / 40 * 2, y + theCamera.GetWindowHeight() / 20 * 0.15, Vector3(0, 0, 0), 1); + for (y = 45; i < this->_flavor.size(); i++) { + if (this->_flavor[i] == '\n') { + hud->setText(tmp, x + theCamera.GetWindowWidth() / 40 * 2, y + theCamera.GetWindowHeight() / 20 * 0.15, Vector3(0, 0, 0), 1); + tmp.clear(); + y += 15; + } else + tmp = tmp + this->_flavor[i]; + } + hud->setText(tmp, x + theCamera.GetWindowWidth() / 40 * 2, y + theCamera.GetWindowHeight() / 20 * 0.15, Vector3(0, 0, 0), 1); } return ; } -void Tooltip::clearInfo(void) { - theWorld.Remove(this->_equip); +void Tooltip::clearInfo(int clean) { + std::string tmp; + int i; + + Game::getHUD()->removeText(this->_name); + for (i = 0; i < this->_flavor.size(); i++) { + if (this->_flavor[i] == '\n') { + Game::getHUD()->removeText(tmp); + tmp.clear(); + } else + tmp = tmp + this->_flavor[i]; + } + Game::getHUD()->removeText(tmp); + this->_name = ""; + this->_flavor = ""; + + if (clean == 0) { + Elements *w; + tmp = Game::currentGame->getHero()->getInventory()->getCurrentFocus(); + if (tmp != "") { + if (Game::wList->checkExists(tmp)) + w = new Weapon(Game::wList->getWeapon(tmp)); + else if (Game::aList->checkExists(tmp)) + w = new Armor(Game::aList->getArmor(tmp)); + else if (Game::rList->checkExists(tmp)) + w = new Ring(Game::rList->getRing(tmp)); + this->info(w); + } + } } void Tooltip::ReceiveMessage(Message *m) { diff --git a/Sources/src/Weapon.cpp b/Sources/src/Weapon.cpp @@ -32,7 +32,6 @@ */ Weapon::Weapon(std::string name) : _name(name) { this->_readFile(name); - this->_canAttack = 1; } //!Constructor called by hero/equipment class, to copy a parsed version from weaponlist @@ -45,6 +44,7 @@ Weapon::Weapon(Weapon* weapon) { this->_name = weapon->getName(); this->addAttribute("name", this->_name); this->_flavor = weapon->getFlavor(); + this->addAttribute("flavor", this->_flavor); this->_damage = weapon->getDamage(); this->_recovery = weapon->getRecovery(); this->_active = weapon->getActive(); @@ -53,13 +53,49 @@ Weapon::Weapon(Weapon* weapon) { this->_pushback = weapon->getPushback(); this->_sprite = weapon->getSprite(); this->_lootLevel = weapon->getLootLevel(); + this->addAttribute("sprite", this->_sprite); this->addAttribute("type3", "Weapon"); - this->_canAttack = 1; - - theSwitchboard.SubscribeTo(this, "canAttack"); + this->_critRate = weapon->getCritRate(); } +//! Constructor called when stomping, create a hitbox on each side of the char +/** + * Hitbox for the stomp + * @param w the weapon currently used to deal the damage + * @param c the character for the localisation + * @param i left or right spawn + */ +Weapon::Weapon(Weapon* w, Characters* c, int i) { + this->_name = w->getName(); + this->_flavor = w->getFlavor(); + this->_damage = w->getDamage(); + this->_recovery = w->getRecovery(); + this->_active = w->getActive(); + this->_size = w->getSize(); + this->_attack = w->getAttack(); + this->_pushback = w->getPushback(); + this->SetSize(1); + this->_critRate = w->getCritRate(); + this->SetName("HeroWeaponHitbox"); + if (c->getAttributes()["type"] == "Hero") + this->addAttribute("type", "HeroWeaponHitBox"); + else + this->addAttribute("type", "WeaponHitBox"); + this->SetDrawShape(ADS_Square); + this->SetColor(1, 1, 1, 0); + this->addAttribute("physic", "1"); + this->_hitboxType = "special"; + this->_hitbox = "octogonHitbox"; + this->SetDensity(0); + this->SetFixedRotation(true); + this->Tag("weaponhitbox"); + this->SetIsSensor(true); + theSwitchboard.SubscribeTo(this, "deleteWeapon" + this->GetName()); + theSwitchboard.DeferredBroadcast(new Message("deleteWeapon" + this->GetName()), w->getActive()); + this->SetPosition(c->GetBody()->GetWorldCenter().x + i, c->GetBody()->GetWorldCenter().y); + Game::bodiesToCreate.push_back(this); +} //! Constructor called when attacking, creates the defined hitbox /** @@ -77,8 +113,8 @@ Weapon::Weapon(Weapon* w, Characters* c) { this->_size = w->getSize(); this->_attack = w->getAttack(); this->_pushback = w->getPushback(); - this->_canAttack = 1; this->SetSize(1); + this->_critRate = w->getCritRate(); this->SetName("HeroWeaponHitbox"); if (c->getAttributes()["type"] == "Hero") this->addAttribute("type", "HeroWeaponHitBox"); @@ -93,9 +129,9 @@ Weapon::Weapon(Weapon* w, Characters* c) { this->SetFixedRotation(true); this->Tag("weaponhitbox"); this->SetIsSensor(true); - theSwitchboard.SubscribeTo(this, "deleteWeapon"); - theSwitchboard.DeferredBroadcast(new Message("deleteWeapon"), w->getActive()); - theSwitchboard.DeferredBroadcast(new Message("canAttack"), w->getRecovery()); + theSwitchboard.SubscribeTo(this, "deleteWeapon" + this->GetName()); + theSwitchboard.DeferredBroadcast(new Message("deleteWeapon" + this->GetName()), w->getActive()); + theSwitchboard.DeferredBroadcast(new Message("attackReady"), w->getRecovery()); this->_initDirection(w, c); theWorld.Add(this); } @@ -197,6 +233,8 @@ void Weapon::_parseJson(std::string file) { this->_pushback = json["infos"].get("pushback", "").asFloat(); this->_attack = json["infos"].get("attack", "").asString(); this->_sprite = json["infos"].get("sprites", "").asString(); + this->_critRate = json["infos"].get("critRate", "").asInt(); + this->addAttribute("sprite", this->_sprite); this->addAttribute("type3", "Weapon"); } @@ -229,40 +267,42 @@ Json::Value Weapon::_getAttr(std::string category, std::string key) { * @param: linearVelocity (b2Vec2) */ void Weapon::attack(Characters *c) { - if (this->_attack == "melee") + if (this->_attack == "melee") { new Weapon(this, c); + } else if (this->_attack == "ranged") new Projectile(this, c); } void Weapon::ReceiveMessage(Message *m) { - if (m->GetMessageName() == "deleteWeapon") { + if (m->GetMessageName() == "deleteWeapon" + this->GetName()) { Game::addToDestroyList(this); theSwitchboard.UnsubscribeFrom(this, "deleteWeapon"); theSwitchboard.Broadcast(new Message("disableAttackHitbox")); } - if (m->GetMessageName() == "canAttack") - this->_canAttack = 1; } /* GETTERS */ -std::string Weapon::getName(void) { return this->_name; } -std::string Weapon::getFlavor(void) { return this->_flavor; } -std::string Weapon::getSprite(void) { return this->_sprite; } -std::string Weapon::getAttack(void) { return this->_attack; } +std::string Weapon::getName(void) { return this->_name; } +std::string Weapon::getFlavor(void) { return this->_flavor; } +std::string Weapon::getSprite(void) { return this->_sprite; } +std::string Weapon::getAttack(void) { return this->_attack; } int Weapon::getLootLevel(void) { return this->_lootLevel; } -float Weapon::getActive(void) { return this->_active; } -int Weapon::getSize(void) { return this->_size; } -int Weapon::getDamage(void) { return this->_damage; } -int Weapon::getPushback(void) { return this->_pushback; } -float Weapon::getRecovery(void) { return this->_recovery; } -int Weapon::attackReady(void) { return this->_canAttack; } +float Weapon::getActive(void) { return this->_active; } +int Weapon::getSize(void) { return this->_size; } +int Weapon::getDamage(void) { return this->_damage; } +int Weapon::getPushback(void) { return this->_pushback; } +float Weapon::getRecovery(void) { return this->_recovery; } +int Weapon::getCritRate(void) { return this->_critRate; } /* SETTERS */ -void Weapon::isAttacking(int i) {this->_canAttack = i;} void Weapon::BeginContact(Elements *elem, b2Contact *contact) { + if (elem->getAttribute("type") != "ground") { + contact->SetEnabled(false); + contact->enableContact = false; + } } void Weapon::EndContact(Elements *elem, b2Contact *contact) { diff --git a/Sources/src/main.cpp b/Sources/src/main.cpp @@ -62,12 +62,15 @@ int main(int ac, char **av) { srand(time(NULL)); game->readMaps(); MouseDebugger l; - + + Game::currentGame = game; if (ac > 1 && (std::string(av[1]) == "--no-menu")) { game->start(); theWorld.StartGame(); } - else + else { + game->menu = menu; menu->showMenu(game); + } return 0; }