/* Copyright 2014 Michele "King_DuckZ" Santullo This file is part of CloonelJump. CloonelJump is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. CloonelJump is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with CloonelJump. If not, see . */ #include "gameplaysceneclassic.hpp" #include "character.hpp" #include "moversine.hpp" #include "sdlmain.hpp" #include "inputbag.hpp" #include "key.hpp" #include "moverleftright.hpp" #include "moverworld.hpp" #include "tiledwallpaper.hpp" #include "texture.hpp" #include "platformsystem.hpp" #include "CloonelJumpConfig.h" #include #include #include #include namespace cloonel { namespace { enum GameActionType { GameAction_Left, GameAction_Right }; enum { CollisionID_Platforms, CollisionID_Player, CollisionID_Enemies }; void OnCharacterBounce (MoverSine* parMover, const Line&, const float2&) { parMover->ResetToBounce(); } } //unnamed namespace ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- GameplaySceneClassic::GameplaySceneClassic (SDLMain* parSdlMain) : GameplayScene(parSdlMain) { //TODO: replace the hardcoded bindings with something more customizable. InputBag& input = *InputBagObject(); input.AddAction(GameAction_Left, Key(InputDevice_Keyboard, SDL_SCANCODE_LEFT), "Move left"); input.AddAction(GameAction_Right, Key(InputDevice_Keyboard, SDL_SCANCODE_RIGHT), "Move right"); } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- GameplaySceneClassic::~GameplaySceneClassic() noexcept { Destroy(); } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- void GameplaySceneClassic::OnPrepare() { const float halfRefHeight = static_cast(REFERENCE_HEIGHT) / 2.0f; Collider& collider = *this->GetCollider(); const float2 charaRefSize(static_cast(REFERENCE_CHARA_WIDTH), static_cast(REFERENCE_CHARA_HEIGHT)); std::unique_ptr moverSine(new MoverSine()); std::unique_ptr player(new Character("resources/graphics/player.png", SDLObject(), charaRefSize)); std::unique_ptr moverLeftRight(new MoverLeftRight(1.5f, 5.0f, 40.0f)); std::unique_ptr moverWorld(new MoverWorld(halfRefHeight)); std::unique_ptr wallpaper(new TiledWallpaper("resources/graphics/background_tile.png", SDLObject())); std::unique_ptr platforms(new PlatformSystem("resources/graphics/platform.png", SDLObject(), this, halfRefHeight * 0.9f)); player->Prepare(); platforms->Prepare(); moverSine->RegisterPlaceable(player.get()); moverSine->RegisterPlaceable(moverWorld.get()); //Keep an invisible mover moverLeftRight->RegisterPlaceable(player.get()); moverWorld->RegisterPlaceable(player.get()); //It compensates the position when the chara goes over the mid moverWorld->RegisterPlaceable(moverWorld.get()); //The mover has to be in sync with the character moverWorld->RegisterPlaceable(platforms.get()); wallpaper->Reload(); { auto regPlayerCollision(std::bind(&Collider::RegisterBar, &collider, CollisionID_Player, std::placeholders::_1)); player->RegisterForCollision(regPlayerCollision); auto regPlatfCollision(std::bind(&Collider::RegisterBar, &collider, CollisionID_Platforms, std::placeholders::_1)); auto unregPlatfCollision(std::bind(&Collider::UnregisterBar, &collider, CollisionID_Platforms, std::placeholders::_1)); platforms->RegisterForCollision(regPlatfCollision, unregPlatfCollision); } player->SetOnBounceCallback(std::bind(&OnCharacterBounce, moverSine.get(), std::placeholders::_1, std::placeholders::_2)); std::swap(moverSine, m_moverSine); std::swap(player, m_player); std::swap(moverLeftRight, m_moverLeftRight); std::swap(moverWorld, m_moverWorld); std::swap(wallpaper, m_wallpaper); std::swap(platforms, m_platforms); AddMover(m_moverSine.get()); AddMover(m_moverLeftRight.get()); AddDrawable(m_wallpaper.get()); AddMover(m_moverWorld.get()); m_platforms->AddDrawables(); AddDrawable(m_player.get()); const float jumpPower = halfRefHeight * 0.71f; m_moverSine->SetPower(jumpPower); collider.TieGroups(CollisionID_Platforms, CollisionID_Player); //collider.TieGroups(CollisionID_Enemies, CollisionID_Player); } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- void GameplaySceneClassic::Destroy() noexcept { GameplayScene::Destroy(); //Destroy in reverse creation order m_platforms = std::move(std::unique_ptr(nullptr)); m_wallpaper = std::move(std::unique_ptr(nullptr)); m_moverWorld = std::move(std::unique_ptr(nullptr)); m_moverLeftRight = std::move(std::unique_ptr(nullptr)); m_player = std::move(std::unique_ptr(nullptr)); m_moverSine = std::move(std::unique_ptr(nullptr)); } ///-------------------------------------------------------------------------- ///-------------------------------------------------------------------------- void GameplaySceneClassic::OnPreUpdate() { InputBag& input = *InputBagObject(); if (IsPressed(input, GameAction_Left)) { m_moverLeftRight->SetMovement(MoverLeftRight::MovementDirection_Left); } else if (IsPressed(input, GameAction_Right)) { m_moverLeftRight->SetMovement(MoverLeftRight::MovementDirection_Right); } else { m_moverLeftRight->SetMovement(MoverLeftRight::MovementDirection_Still); } m_platforms->SpawnPlatforms(); } } //namespace cloonel