void GameController::update(float dt) { if(!state) { throw GameControllerException("Current game state is null, cannot update."); } if(enqueuedNextState) { if(outTransition) { HIKARI_LOG(debug4) << "Has out transition"; if(outTransition->isComplete()) { HIKARI_LOG(debug4) << "Transition complete!"; outTransition.reset(); gotoNextState(); } else { outTransition->update(dt); } } else { gotoNextState(); } } else { if(inTransition) { HIKARI_LOG(debug4) << "Has in transition"; if(inTransition->isComplete()) { HIKARI_LOG(debug4) << "In transition complete!"; inTransition.reset(); } else { inTransition->update(dt); } } else { state->update(dt); } } }
void Hero::performJump() { if(isClimbing) { isClimbing = false; setVelocityY(0); HIKARI_LOG(debug4) << "Started fall from ladder at " << getPosition().getY(); } else { setVelocityY(jumpVelocity.getY()); HIKARI_LOG(debug4) << "Started jump at " << getPosition().getY(); } }
void GameController::setState(const StatePtr & statePtr) { if(statePtr) { state->onExit(); HIKARI_LOG(debug) << "<GameController> exited \"" << state->getName() << "\" state."; prevState = state->getName(); currState = statePtr->getName(); state = statePtr; state->onEnter(); HIKARI_LOG(debug) << "<GameController> entered \"" << state->getName() << "\" state."; } }
void GameController::setState(const std::string &name) { auto found = states.find(name); if(found == std::end(states)) { throw GameControllerException("Tried to set state to an unregistered state: \"" + name + "\"."); } else { state->onExit(); HIKARI_LOG(debug) << "<GameController> exited \"" << state->getName() << "\" state."; prevState = state->getName(); currState = name; state = found->second; state->onEnter(); HIKARI_LOG(debug) << "<GameController> entered \"" << state->getName() << "\" state."; } }
void GameController::addState(const std::string &name, const StatePtr &state) { if(states.find(name) == std::end(states)) { states[name] = state; HIKARI_LOG(debug) << "<GameController> added state \"" << name << "\"."; } else { throw GameControllerException("Tried to register more than one state: \"" + name + "\"."); } }
void Hero::kill() { if(auto events = getEventBus().lock()) { EventDataPtr imDeadNow(new EntityDeathEventData(getId(), EntityDeathEventData::Hero)); events->queueEvent(imDeadNow); } else { HIKARI_LOG(debug4) << "No event manager."; } }
bool NSFSoundStream::open(const std::string& fileName) { sf::Lock lock(mutex); if(!FileSystem::exists(fileName)) { return false; } int length = 0; auto fs = FileSystem::openFileRead(fileName); fs->seekg (0, std::ios::end); length = static_cast<int>(fs->tellg()); fs->seekg (0, std::ios::beg); std::unique_ptr<char[]> nsfFileBuffer(new char[length]); fs->read(nsfFileBuffer.get(), length); // To honor the contract of returning false on failure, // catch these exceptions and return false instead? Good/bad? try { gme_type_t file_type = gme_identify_extension(fileName.c_str()); if(!file_type) { return false; } for(std::size_t i = 0; i < samplerCount; ++i) { auto sampleEmu = std::shared_ptr<Music_Emu>(file_type->new_emu()); if(!sampleEmu) { return false; } // Must set sample rate before loading data handleError(sampleEmu->set_sample_rate(SAMPLE_RATE)); handleError(gme_load_data(sampleEmu.get(), nsfFileBuffer.get(), length)); sampleEmu->start_track(-1); sampleEmu->ignore_silence(false); auto sampleBuffer = std::make_shared<std::vector<short>>(masterBufferSize); std::fill(std::begin(*sampleBuffer), std::end(*sampleBuffer), 0); availableSamplers.push(std::make_pair(sampleEmu, sampleBuffer)); // sampleEmus.push_back(std::move(sampleEmu)); } trackInfo.reset(new track_info_t()); } catch(std::runtime_error& ex) { HIKARI_LOG(debug) << ex.what(); return false; } initialize(2, SAMPLE_RATE); //setCurrentTrack(0); return true; }
void GuiService::buildFontMap(const Json::Value & fontConfig) { auto fontNames = fontConfig.getMemberNames(); std::for_each(std::begin(fontNames), std::end(fontNames), [&](const std::string & fontName) { HIKARI_LOG(debug3) << "Creating font \"" << fontName << "\""; auto & fontSettings = fontConfig[fontName]; bool isConfigValid = false; if(fontSettings.isMember("image")) { if(fontSettings.isMember("glyphs")) { if(fontSettings.isMember("glyphSize")) { isConfigValid = true; } } } if(isConfigValid) { std::string imageName = fontSettings["image"].asString(); std::string glyphs = fontSettings["glyphs"].asString(); int glyphSize = fontSettings["glyphSize"].asInt(); if(FileSystem::exists(imageName)) { auto glyphImage = std::shared_ptr<gcn::Image>(gcn::Image::load(imageName)); if(glyphImage) { this->fontImageMap.insert(std::make_pair(fontName, glyphImage)); auto font = std::make_shared<gcn::FixedImageFont>(glyphImage.get(), glyphSize, glyphs); this->fontMap.insert(std::make_pair(fontName, font)); HIKARI_LOG(debug3) << "Font \"" << fontName << "\" successfully loaded."; } else { HIKARI_LOG(warning) << "Font image for \"" << fontName << "\" could not be loaded; ignoring."; } } else { HIKARI_LOG(warning) << "Font image for \"" << fontName << "\" could not be found; ignoring."; } } else { HIKARI_LOG(warning) << "Font \"" << fontName << "\" is not properly defined; ignoring."; } }); }
void Room::traceLadders() { for(int x = 0; x < getWidth(); ++x) { bool topFound = false; bool bottomFound = false; int ladderTop = 0; int ladderX = 0; int ladderBottom = 0; for(int y = 0; y < getHeight(); ++y) { int attribute = attr[x + (y * getWidth())]; if(TileAttribute::hasAttribute(attribute, TileAttribute::LADDER)) { if(!topFound) { topFound = true; ladderTop = y; ladderX = x; } // Find ladder at the bottom of the map if(y == getHeight() - 1) { if(topFound) { bottomFound = true; ladderBottom = y + 1; } } } else { if(topFound) { if(!bottomFound) { bottomFound = true; ladderBottom = y; } } } if(topFound && bottomFound) { ladders.emplace_back( BoundingBox<float>( static_cast<float>(((getX() + ladderX) * getGridSize()) + 4 ), // ladder top left X (in pixels) static_cast<float>((getY() + ladderTop) * getGridSize() ), // ladder top left Y (in pixels) static_cast<float>(getGridSize() - 4 - 4 ), // ladder width (in pixels) static_cast<float>((ladderBottom - ladderTop) * getGridSize()) // ladder height (in pixels) ) ); HIKARI_LOG(debug4) << "Found ladder at " << ladders.back(); topFound = false; bottomFound = false; ladderX = 0; ladderBottom = 0; ladderTop = 0; } } } }
void StageSelectStateConfig::extractValuesFromJson(const Json::Value & config) { if(!config.isNull()) { musicName = config.get("music", "None").asString(); backgroundImage = config.get("background", "None").asString(); foregroundImage = config.get("foreground", "None").asString(); // Extract portraits portraits = extractPortraits(config.get("portraits", Json::Value())); // Extract sprites if(config.isMember("sprites")) { const auto & spritesJson = config.get("sprites", Json::Value()); if(spritesJson.isMember("cursor")) { const auto & cursorSpriteJson = spritesJson.get("cursor", Json::Value()); cursorInfo.first = cursorSpriteJson.get("animationSet", "").asString(); cursorInfo.second = cursorSpriteJson.get("animationName", "").asString(); } if(spritesJson.isMember("eye")) { const auto & eyeSpriteJson = spritesJson.get("eye", Json::Value()); eyeInfo.first = eyeSpriteJson.get("animationSet", "").asString(); eyeInfo.second = eyeSpriteJson.get("animationName", "").asString(); } } // Extract eye positions if(config.isMember("eyePositions")) { const auto & positionsJson = config.get("eyePositions", Json::Value()); for(unsigned int i = 0, length = positionsJson.size(); i < length; ++i) { const auto & positionPairJson = positionsJson[i]; // an array of two objects const auto & positionRightJson = positionPairJson[0u]; // the first object is the right eye const auto & positionLeftJson = positionPairJson[1u]; // the second object is the left eye float rightEyeX = positionRightJson.get("x", 0).asFloat(); float rightEyeY = positionRightJson.get("y", 0).asFloat(); float leftEyeX = positionLeftJson.get("x", 0).asFloat(); float leftEyeY = positionLeftJson.get("y", 0).asFloat(); Point2D<float> rightEyePosition(rightEyeX, rightEyeY); Point2D<float> leftEyePosition(leftEyeX, leftEyeY); eyePositions.push_back(std::make_pair(rightEyePosition, leftEyePosition)); } } HIKARI_LOG(debug4) << "Found " << portraits.size() << " portrait(s)."; } }
Shot Weapon::fire(GameWorld & world, WeaponFireEventData & eventData) const { HIKARI_LOG(debug4) << "Weapon::fire executed. name=" << getName(); std::list<std::weak_ptr<GameObject>> spawnedObjects; std::for_each(std::begin(actions), std::end(actions), [this, &world, &eventData, &spawnedObjects](const std::shared_ptr<WeaponAction> & action) { if(action) { spawnedObjects.push_back(action->apply(world, *this, eventData)); } }); return Shot(spawnedObjects); }
bool EventBusImpl::addListener(const EventListenerDelegate & eventDelegate, const EventType & type) { // This will create a list of one doesn't exist. EventListenerList & eventListenerList = eventListeners[type]; for(auto it = std::begin(eventListenerList); it != std::end(eventListenerList); ++it) { if(eventDelegate == (*it)) { HIKARI_LOG(error) << "Attempting to double-register a delegate."; return false; } } eventListenerList.push_back(eventDelegate); return true; }
void GameController::requestStateChange(const std::string & stateName, std::unique_ptr<StateTransition> outTransition, std::unique_ptr<StateTransition> inTransition) { auto found = states.find(stateName); HIKARI_LOG(debug) << "State change requested"; if(found != std::end(states)) { HIKARI_LOG(debug) << "Found the next state: " << stateName; enqueuedNextState = found->second; if(outTransition) { outTransition->setExitingState(state); outTransition->setEnteringState(enqueuedNextState); this->outTransition = std::move(outTransition); } if(inTransition) { inTransition->setExitingState(state); inTransition->setEnteringState(enqueuedNextState); this->inTransition = std::move(inTransition); } } }
void Hero::IsShootingState::enter() { hero.isShooting = true; cooldown = (15.0f * (1.0f / 60.0f)); // this should actually be the weapon's cooldown... cooldownTimer = cooldown; HIKARI_LOG(debug4) << "Shooting now!"; if(hero.actionController) { auto const * controller = hero.actionController.get(); if(controller->shouldMoveLeft()) { hero.setDirection(Directions::Left); } else if(controller->shouldMoveRight()) { hero.setDirection(Directions::Right); } } hero.chooseAnimation(); hero.fireWeapon(); }
void Hero::update(float dt) { if(wasUnderWaterLastFrame != isUnderWater) { if(wasUnderWaterLastFrame) { HIKARI_LOG(debug4) << "I'm not in water anymore!"; body.setGravityApplicationThreshold(1); } else { HIKARI_LOG(debug4) << "I'm jumping in the water NOW!"; body.setGravityApplicationThreshold(3); // Only emit event when plunging in to a body of water. if(auto events = this->getEventBus().lock()) { events->triggerEvent(EventDataPtr(new EntityStateChangeEventData(getId(), "water"))); } } } wasUnderWaterLastFrame = isUnderWater; if(const auto & room = getRoom()) { const int gridSize = room->getGridSize(); if(invincibilityTimer > 0.0f) { invincibilityTimer -= dt; isInvincible = true; } else { isInvincible = false; isBlinking = false; isVisible = true; } if(isBlinking) { blinkTimer -= dt; if(blinkTimer <= 0.0f) { blinkTimer = 0.0667f; isVisible = !isVisible; } } // // Check if we're in a tunnel // if(isSliding) { const auto & bbox = body.getBoundingBox(); const int startingX = static_cast<int>(bbox.getLeft()); const int endingX = static_cast<int>(bbox.getRight()); const int y = static_cast<int>(bbox.getTop()) - 1; // Subtract 1 to test the tile directly *above* Rockman isInTunnel = false; int topLeftTile = room->getAttributeAt(startingX / gridSize, y / gridSize); int topRightTile = room->getAttributeAt((endingX - 1) / gridSize, y / gridSize); // Only check the top left and top right points if(((topLeftTile != Room::NO_TILE) && TileAttribute::hasAttribute(topLeftTile, TileAttribute::SOLID)) || ((topRightTile != Room::NO_TILE) && TileAttribute::hasAttribute(topRightTile, TileAttribute::SOLID))) { isInTunnel = true; } } // Check if we're under water or starting to enter water { int bodyPositionTile = room->getAttributeAt( static_cast<int>(getPosition().getX()) / gridSize, static_cast<int>(getPosition().getY()) / gridSize); if((bodyPositionTile != Room::NO_TILE) && TileAttribute::hasAttribute(bodyPositionTile, TileAttribute::WATER)) { isUnderWater = true; } else { isUnderWater = false; } } // // State machine updates // if(temporaryMobilityState) { MobilityState::StateChangeAction action = temporaryMobilityState->update(dt); if(MobilityState::NEXT == action) { popTemporaryMobilityState(); } } else { if(shootingState) { // Handle state change request actions... ShootingState::StateChangeAction action = shootingState->update(dt); if(ShootingState::NEXT == action) { if(nextShootingState) { changeShootingState(std::move(nextShootingState)); } } } if(mobilityState) { // Handle state change request actions... MobilityState::StateChangeAction action = mobilityState->update(dt); if(MobilityState::NEXT == action) { if(nextMobilityState) { changeMobilityState(std::move(nextMobilityState)); } } } } } Entity::update(dt); }
void KeyboardInput::processEvent(const sf::Event &keyboardEvent) { if(keyboardEvent.type == sf::Event::KeyPressed) { HIKARI_LOG(debug3) << "Pressed a key!"; switch(keyboardEvent.key.code) { case sf::Keyboard::Up: currentState.buttonUp = BUTTON_PUSHED; break; case sf::Keyboard::Right: currentState.buttonRight = BUTTON_PUSHED; break; case sf::Keyboard::Down: currentState.buttonDown = BUTTON_PUSHED; break; case sf::Keyboard::Left: currentState.buttonLeft = BUTTON_PUSHED; break; case sf::Keyboard::A: currentState.buttonShoot = BUTTON_PUSHED; currentState.buttonStart = BUTTON_PUSHED; break; case sf::Keyboard::S: currentState.buttonJump = BUTTON_PUSHED; break; case sf::Keyboard::Return: currentState.buttonStart = BUTTON_PUSHED; break; case sf::Keyboard::Escape: currentState.buttonCancel = BUTTON_PUSHED; break; default: break; } } else if(keyboardEvent.type == sf::Event::KeyReleased) { HIKARI_LOG(debug3) << "Released a key!"; switch(keyboardEvent.key.code) { case sf::Keyboard::Up: currentState.buttonUp = !BUTTON_PUSHED; break; case sf::Keyboard::Right: currentState.buttonRight = !BUTTON_PUSHED; break; case sf::Keyboard::Down: currentState.buttonDown = !BUTTON_PUSHED; break; case sf::Keyboard::Left: currentState.buttonLeft = !BUTTON_PUSHED; break; case sf::Keyboard::A: currentState.buttonStart = !BUTTON_PUSHED; currentState.buttonShoot = !BUTTON_PUSHED; break; case sf::Keyboard::S: currentState.buttonJump = !BUTTON_PUSHED; break; case sf::Keyboard::Return: currentState.buttonStart = !BUTTON_PUSHED; break; case sf::Keyboard::Escape: currentState.buttonCancel = !BUTTON_PUSHED; break; default: break; } } }
void Hero::performSlide() { HIKARI_LOG(debug4) << "Started sliding!"; }
ObjectRemovedEventData::~ObjectRemovedEventData() { // Do nothing! HIKARI_LOG(debug1) << "~ObjectRemovedEventData()"; }
void NothingEffect::unapply() { // Nothing to do here! HIKARI_LOG(info) << "NothingEffect::unapply()"; }
NothingEffect::NothingEffect(const NothingEffect &proto) { HIKARI_LOG(debug) << "NothingEffect copy constructor"; }
void Hero::NotShootingState::enter() { hero.isShooting = false; HIKARI_LOG(debug4) << "Not shooting!"; hero.chooseAnimation(); }
void GameController::DefaultStateTransition::update(float dt) { HIKARI_LOG(debug4) << "DefaultStateTransition::update()"; }