// // Created by Иван Ильин on 14.03.2021. // #include "Player.h" #include "Screen.h" #include "ResourceManager.h" #include "utils/Log.h" void Player::update() { if(inCollision()) p_velocity -= p_velocity*Time::deltaTime()*2; if(isInSlowMo) { if(_ability > 0) _ability -= Time::deltaTime(); else { _ability = 0; isInSlowMo = false; setVelocity(velocity()*slowMoCoefficient); setAcceleration(p_acceleration*slowMoCoefficient*slowMoCoefficient); slowMoSound.stop(); unSlowMoSound.play(); } } double coeff = isInSlowMo ? 1.0/slowMoCoefficient : 1.0; bool inRunning_old = inRunning; inRunning = _screen != nullptr && (Screen::isKeyPressed(sf::Keyboard::A) || Screen::isKeyPressed(sf::Keyboard::D) ||Screen::isKeyPressed(sf::Keyboard::W) || Screen::isKeyPressed(sf::Keyboard::S)); // in case when the camera is attached we make some animation during running if(_camera != nullptr && inRunning && !_camera->isInAnim()) { _camera->a_translate("hor_oscil", -_camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_wait("hor_oscil", 0); _camera->a_translate("hor_oscil", _camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_translate("vert_oscil", -Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_wait("vert_oscil", 0); _camera->a_translate("vert_oscil", Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_wait("vert_oscil", 0); _camera->a_translate("vert_oscil", -Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_wait("vert_oscil", 0); _camera->a_translate("vert_oscil", Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.3/coeff, Animation::None, Animation::cos); } else if(_camera != nullptr && inRunning_old && !inRunning) { _camera->a_stopAllAnimations(); _camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.15/coeff, Animation::None, Animation::cos); } auto rayToFloor = (*_world).rayCast(position(), position() + Point4D{0, -5, 0}); if(_world != nullptr && _screen != nullptr && _camera != nullptr) { // Left and right if (Screen::isKeyPressed(sf::Keyboard::A)) { translate(_camera->left() * Time::deltaTime() * walkSpeed * coeff); if(inCollision()) setVelocity(Point4D{0,0,0}); } if (Screen::isKeyPressed(sf::Keyboard::D)) { translate(-_camera->left() * Time::deltaTime() * walkSpeed * coeff); if(inCollision()) setVelocity(Point4D{0,0,0}); } // Forward and backward if (Screen::isKeyPressed(sf::Keyboard::W)) { translate(_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * walkSpeed * coeff); if(inCollision()) setVelocity(Point4D{0,0,0}); } if (Screen::isKeyPressed(sf::Keyboard::S)) { translate(-_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * walkSpeed * coeff); if(inCollision()) setVelocity(Point4D{0,0,0}); } if (_ability > 0 && !isInSlowMo && Screen::isKeyPressed(sf::Keyboard::LShift)) { // slow mo isInSlowMo = true; setVelocity(velocity()/slowMoCoefficient); setAcceleration(p_acceleration/(slowMoCoefficient*slowMoCoefficient)); unSlowMoSound.stop(); slowMoSound.play(); } else if (isInSlowMo && !Screen::isKeyPressed(sf::Keyboard::LShift)) { isInSlowMo = false; setVelocity(velocity()*slowMoCoefficient); setAcceleration(p_acceleration*slowMoCoefficient*slowMoCoefficient); slowMoSound.stop(); unSlowMoSound.play(); } if (Screen::isKeyPressed(sf::Keyboard::Space) && inCollision()) { addVelocity(Point4D{0, std::abs(_collisionNormal.y())*sqrt(2 * g * jumpHeight)*coeff, 0}); translate(Point4D{0, Time::deltaTime() * walkSpeed * 2 * coeff, 0}); } // Mouse movement Point4D disp = _screen->getMouseDisplacement(); rotate(Point4D{0, -disp.x() / 1000.0, 0}); p_velocity = Matrix4x4::RotationY(-disp.x() / 1000.0)*p_velocity; double rotationLeft = disp.y() / 1000.0; // You can only see in range [-90 : 90] grad if (_camera->angleLeftUpLookAt().x() + rotationLeft > M_PI / 2) rotationLeft = M_PI / 2 - _camera->angleLeftUpLookAt().x(); if (_camera->angleLeftUpLookAt().x() + rotationLeft < -M_PI / 2) rotationLeft = -M_PI / 2 - _camera->angleLeftUpLookAt().x(); _camera->rotateLeft(rotationLeft); rotateWeaponsRelativePoint(position() + Point4D{0, 1.8, 0}, _camera->left(), rotationLeft); if (_screen->isKeyTapped(sf::Keyboard::Right) || _screen->isKeyTapped(sf::Keyboard::E)) { if(_weapons.size() > 1) { // change '_selectedWeapon' _weapons[_selectedWeapon]->removeFromWorld(_world); _selectedWeapon = (_selectedWeapon + 1) % _weapons.size(); _weapons[_selectedWeapon]->addToWorld(_world); Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon)); changeWeaponSound.play(); } } if (_screen->isKeyTapped(sf::Keyboard::Left) || _screen->isKeyTapped(sf::Keyboard::Q)) { if(_weapons.size() > 1) { // change '_selectedWeapon' _weapons[_selectedWeapon]->removeFromWorld(_world); if (_selectedWeapon > 0) _selectedWeapon = (_selectedWeapon - 1) % _weapons.size(); else _selectedWeapon = _weapons.size() - 1; _weapons[_selectedWeapon]->addToWorld(_world); Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon)); changeWeaponSound.play(); } } if (_screen->isButtonPressed(sf::Mouse::Button::Left)) { auto damagedPlayers = _weapons[_selectedWeapon]->fire(_world, _camera); for(auto& damagedPlayer : damagedPlayers) { sf::Uint16 targetId = std::stoi(damagedPlayer.first.substr(7)); damagePlayerCallBack(targetId, damagedPlayer.second); } } if(Screen::isKeyPressed(sf::Keyboard::R)) { _weapons[_selectedWeapon]->reload(); } if (inRunning && inCollision() && walkSound.getStatus() != sf::Sound::Status::Playing) { if ((position() - rayToFloor.first).abs() < 2) { int soundNum = round((double) rand() / RAND_MAX * 5) + 1; walkSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/stonestep" + std::to_string(soundNum) + ".ogg")); //walkSound.setVolume(30); walkSound.play(); } } } } void Player::rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v, double val) { for(auto& weapon : _weapons) weapon->rotateRelativePoint(point4D, v, val); } void Player::drawStats() { if(_screen == nullptr) return; // health bar int xPos = 10; int yPos = _screen->height() - 10 - 10; int width = _screen->width()/2 - 20; int height = 10; sf::ConvexShape polygon1; polygon1.setPointCount(4); sf::ConvexShape polygon2; polygon2.setPointCount(4); polygon1.setPoint(0, sf::Vector2f((float)xPos, (float)yPos)); polygon1.setPoint(1, sf::Vector2f((float)(xPos + width), (float)yPos)); polygon1.setPoint(2, sf::Vector2f((float)(xPos + width), (float)(yPos + height))); polygon1.setPoint(3, sf::Vector2f((float)xPos, (float)(yPos + height))); polygon2.setPoint(0, sf::Vector2f((float)xPos, (float)yPos)); polygon2.setPoint(1, sf::Vector2f((float)xPos + width * _health / _healthMax, (float)yPos)); polygon2.setPoint(2, sf::Vector2f((float)xPos + width * _health / _healthMax, (float)(yPos + height))); polygon2.setPoint(3, sf::Vector2f((float)xPos, (float)(yPos + height))); polygon1.setFillColor({ 255, 174, 174, 100 }); polygon2.setFillColor({ static_cast((_healthMax - _health)/_healthMax * 255), static_cast(_health * 255 / _healthMax), 0, 100 }); polygon1.setOutlineThickness(3); _screen->window.draw(polygon2); // ability bar sf::ConvexShape polygon3; polygon3.setPointCount(4); polygon3.setPoint(0, sf::Vector2f((float)xPos, (float)yPos - 15)); polygon3.setPoint(1, sf::Vector2f((float)xPos + width * _ability / _abilityMax, (float)yPos - 15)); polygon3.setPoint(2, sf::Vector2f((float)xPos + width * _ability / _abilityMax, (float)(yPos - 15 + height))); polygon3.setPoint(3, sf::Vector2f((float)xPos, (float)(yPos - 15 + height))); polygon3.setFillColor({ 255, 168, 168, 100 }); _screen->window.draw(polygon3); // ammo sf::Text text_health; text_health.setFont(*ResourceManager::loadFont("../engine/fonts/Roboto-Medium.ttf")); // text health text_health.setCharacterSize(20); text_health.setFillColor(sf::Color::White); text_health.setStyle(sf::Text::Italic); text_health.setPosition(0, 0); text_health.setString(std::to_string((int)_health)); // text ammo sf::Text text_ammo1(text_health); sf::Text text_ammo2(text_health); int ammo1Size = 100; int ammo2Size = 50; auto balance = _weapons[_selectedWeapon]->balance(); text_ammo1.setCharacterSize(ammo1Size); text_ammo1.setString(std::to_string((int)balance.first)); text_ammo1.setPosition(150, _screen->height() - 50 - ammo1Size); text_ammo1.setFillColor(sf::Color(0, 0, 0, 100)); _screen->window.draw(text_ammo1); text_ammo2.setCharacterSize(ammo2Size); text_ammo2.setString(std::to_string((int)balance.second)); text_ammo2.setPosition(50, _screen->height() - 50 - ammo2Size); text_ammo2.setFillColor(sf::Color(0, 0, 0, 70)); _screen->window.draw(text_ammo2); // text killSound/deathSound stats sf::Text text_kills(text_health); text_kills.setStyle(sf::Text::Bold); text_kills.setString("KILLS: " + std::to_string((int)_kills) + " | " + "DEATHS: " + std::to_string((int)_deaths)); text_kills.setFillColor(sf::Color(0, 0, 0, 100)); text_kills.setCharacterSize(ammo2Size/2); text_kills.setPosition(10, 10); _screen->window.draw(text_kills); sf::Text text_deaths(text_health); text_deaths.setString(std::to_string((int)_deaths)); text_deaths.setFillColor(sf::Color(100, 0, 0, 100)); text_deaths.setCharacterSize(ammo2Size); text_deaths.setPosition(10, ammo2Size + 10); } void Player::playDeath() { deathSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/classic_hurt.ogg")); deathSound.play(); } void Player::playKill() { killSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/kill.ogg")); killSound.play(); } void Player::collisionWithObject(const std::string &objName, const std::shared_ptr &obj) { if(objName.find("Bonus_gun") != std::string::npos) addWeapon(std::make_shared()); if(objName.find("Bonus_shotgun") != std::string::npos) addWeapon(std::make_shared()); if(objName.find("Bonus_ak47") != std::string::npos) addWeapon(std::make_shared()); if(objName.find("Bonus_gold_ak47") != std::string::npos) addWeapon(std::make_shared()); if(objName.find("Bonus_rifle") != std::string::npos) addWeapon(std::make_shared()); if(objName.find("Bonus_hill") != std::string::npos) setFullHealth(); if(objName.find("Bonus_ability") != std::string::npos) setFullAbility(); if(objName.find("Bonus") != std::string::npos) { _world->removeMesh(objName); takeBonusCallBack(objName); } } void Player::addWeapon(const std::shared_ptr &weapon) { changeWeaponSound.play(); if(!_weapons.empty()) { for(auto& w : _weapons) { if (w->name() == weapon->name()) { w->addAmmo(w->initialPack()); return; } } } _weapons.push_back(weapon); _weapons.back()->attachToPlayer(*this); _weapons.back()->translate(position()); _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, Point4D{0, 1, 0}, p_angle.y()); _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, _camera->left(), _camera->angleLeftUpLookAt().x()); _weapons.back()->setAddTraceCallBack(addTraceCallBack); changeWeaponSound.play(); } void Player::initWeapons() { if(!_weapons.empty()) { _weapons[_selectedWeapon]->removeFromWorld(_world); _weapons.clear(); } _selectedWeapon = 0; addWeapon(std::make_shared()); _weapons[_selectedWeapon]->addToWorld(_world); }