diff --git a/Bonus.cpp b/Bonus.cpp index 91685e4..b620342 100755 --- a/Bonus.cpp +++ b/Bonus.cpp @@ -8,6 +8,4 @@ Bonus::Bonus(const std::string &bonusName, const std::string &filename, const st _name = bonusName; loadObj(filename, materials, scale); setCollider(false); - - a_rotate("a_rotation", Point4D{0, 2*M_PI, 0}, 4, Animation::Continue, Animation::linear); } diff --git a/CMakeLists.txt b/CMakeLists.txt index f422a17..9911f04 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ add_executable(shooter engine/physics/Simplex.h engine/physics/Solver.cpp engine/physics/Solver.h + engine/Object.cpp engine/Object.h engine/gui/Button.cpp engine/gui/Button.h @@ -85,7 +86,7 @@ add_executable(shooter engine/network/UDPSocket.h engine/network/config.h engine/animation/AFunction.h - PlayerController.cpp PlayerController.h engine/Keyboard.cpp engine/Keyboard.h engine/Mouse.cpp engine/Mouse.h) + PlayerController.cpp PlayerController.h engine/Keyboard.cpp engine/Keyboard.h engine/Mouse.cpp engine/Mouse.h Shooter.cpp Shooter.h) if(APPLE OR UNIX) include_directories(/usr/local/include) diff --git a/Client.cpp b/Client.cpp index 6b495c0..4c89560 100755 --- a/Client.cpp +++ b/Client.cpp @@ -3,39 +3,20 @@ // #include "Client.h" + +#include #include "utils/Log.h" #include "Bonus.h" void Client::updatePacket() { sf::Packet packet; - packet << MsgType::ClientUpdate << _player->position().x() << _player->position().y() << _player->position().z() << _player->angle().y() << _player->camera()->angleLeftUpLookAt().x(); + packet << MsgType::ClientUpdate << _player->position().x() << _player->position().y() << _player->position().z() << _player->angle().y() << _player->headAngle(); _socket.send(packet, _socket.serverId()); } void Client::spawnPlayer(sf::Uint16 id) { - std::string name = "Player_" + std::to_string(id); - _players.insert({ id, std::make_shared() }); - (*_world).addBody(_players[id], name); - _players[id]->setVisible(true); - _players[id]->setAcceleration(Point4D{0, 0, 0}); - - // add head and other stuff: - _world->loadBody(name + "_head", "../obj/cube.obj", "", Point4D{0.7, 0.7, 0.7}); - _world->body(name + "_head")->translate(Point4D{0, 2, 0}); - _world->body(name + "_head")->setCollider(false); - _players[id]->attach(_world->body(name + "_head")); - - _world->loadBody(name + "_eye1", "../obj/cube.obj", "", Point4D{0.2, 0.2, 0.05}); - _world->body(name + "_eye1")->translate(Point4D{0.3, 2.1, 0.7}); - _world->body(name + "_eye1")->setCollider(false); - _world->body(name + "_eye1")->setColor({147, 159, 255}); - _world->body(name + "_head")->attach(_world->body(name + "_eye1")); - - _world->loadBody(name + "_eye2", "../obj/cube.obj", "", Point4D{0.2, 0.2, 0.05}); - _world->body(name + "_eye2")->translate(Point4D{-0.3, 2.1, 0.7}); - _world->body(name + "_eye2")->setCollider(false); - _world->body(name + "_eye2")->setColor({147, 159, 255}); - _world->body(name + "_head")->attach(_world->body(name + "_eye2")); + if(_spawnPlayerCallBack != nullptr) + _spawnPlayerCallBack(id); } void Client::processInit(sf::Packet& packet) { @@ -64,8 +45,8 @@ void Client::processUpdate(sf::Packet& packet) { _players[targetId]->setHealth(buf[3]); _players[targetId]->rotateToAngle(Point4D{0, buf[4], 0}); - _world->body(name + "_head")->rotate(Matrix4x4::RotationY(buf[4]) * Point4D{1, 0, 0}, - buf[5] - _players[targetId]->headAngle()); + _players[targetId]->attached("head")->rotate(Matrix4x4::RotationY(buf[4]) * Point4D{1, 0, 0}, buf[5] - _players[targetId]->headAngle()); + _players[targetId]->setHeadAngle(buf[5]); } else if (targetId == _socket.ownId()) { _player->setHealth(buf[3]); @@ -83,13 +64,8 @@ void Client::processNewClient(sf::Packet& packet) { void Client::processDisconnect(sf::Uint16 targetId) { if (targetId != _socket.ownId() && _players.count(targetId)) { - std::string name = "Player_" + std::to_string(targetId); - _world->removeBody(name); - _world->removeBody(name + "_head"); - _world->removeBody(name + "_eye1"); - _world->removeBody(name + "_eye2"); - _players.erase(targetId); + _removePlayerCallBack(targetId); } } @@ -126,49 +102,34 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) { p1 = Point4D(dbuff[0], dbuff[1], dbuff[2]); p2 = Point4D(dbuff[3], dbuff[4], dbuff[5]); - - tmp = "Client_fireTraces_" + std::to_string(fireTraces++); - _world->addBody(std::make_shared(Mesh::LineTo(p1, p2, 0.05)), tmp); - _world->body(tmp)->setCollider(false); - - _world->body(tmp)->a_color(tmp + "_fadeOut", {255, 255, 255, 0}, 1, Animation::None, Animation::linear); - _world->body("Player_im")->a_function(tmp + "delete", [this, tmp](){ deleteTrace(_world, tmp); }, 1, 2); + if(_addFireTraceCallBack != nullptr) + _addFireTraceCallBack(p1, p2); break; case MsgType::InitBonuses: while (packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]) { - tmp2 = tmp.substr(6, tmp.size()-3-5); - _world->addBody(std::make_shared(tmp, "../obj/" + tmp2 + ".obj", "../obj/" + tmp2 + "_mat.txt", - Point4D{3, 3, 3}), tmp); - _world->body(tmp)->translateToPoint(Point4D(dbuff[0], dbuff[1], dbuff[2])); + if(_addBonusCallBack != nullptr) + _addBonusCallBack(tmp, Point4D(dbuff[0], dbuff[1], dbuff[2])); } break; case MsgType::AddBonus: packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]; - - tmp2 = tmp.substr(6, tmp.size()-3-5); - _world->addBody(std::make_shared(tmp, "../obj/" + tmp2 + ".obj", "../obj/" + tmp2 + "_mat.txt", - Point4D{3, 3, 3}), tmp); - _world->body(tmp)->translateToPoint(Point4D(dbuff[0], dbuff[1], dbuff[2])); + if(_addBonusCallBack != nullptr) + _addBonusCallBack(tmp, Point4D(dbuff[0], dbuff[1], dbuff[2])); break; case MsgType::RemoveBonus: packet >> tmp; - _world->removeBody(tmp); + if(_removeBonusCallBack != nullptr) + _removeBonusCallBack(tmp); break; } } void Client::processDisconnected() { for (auto it = _players.begin(); it != _players.end();) { - std::string name = "Player_" + std::to_string(it->first); - - _world->removeBody(name); - _world->removeBody(name + "_head"); - _world->removeBody(name + "_eye1"); - _world->removeBody(name + "_eye2"); - _players.erase(it++); + processDisconnect(it++->first); } } @@ -188,13 +149,36 @@ void Client::addTrace(const Point4D& from, const Point4D& to) { _socket.send(packet, _socket.serverId()); } -void Client::deleteTrace(std::shared_ptr world, const std::string &traceName) { - world->removeBody(traceName); -} - void Client::takeBonus(const std::string& bonusName) { sf::Packet packet; packet << MsgType::RemoveBonus << bonusName; _socket.send(packet, _socket.serverId()); + + if(_removeBonusCallBack != nullptr) + _removeBonusCallBack(bonusName); +} + +void Client::addPlayer(sf::Uint16 id, std::shared_ptr player) { + _players.insert({ id, player }); +} + +void Client::setSpawnPlayerCallBack(std::function spawn) { + _spawnPlayerCallBack = std::move(spawn); +} + +void Client::setRemovePlayerCallBack(std::function remove) { + _removePlayerCallBack = std::move(remove); +} + +void Client::setAddFireTraceCallBack(std::function addTrace) { + _addFireTraceCallBack = std::move(addTrace); +} + +void Client::setAddBonusCallBack(std::function addBonus) { + _addBonusCallBack = std::move(addBonus); +} + +void Client::setRemoveBonusCallBack(std::function removeBonus) { + _removeBonusCallBack = std::move(removeBonus); } diff --git a/Client.h b/Client.h index ee517c8..ef20ef9 100755 --- a/Client.h +++ b/Client.h @@ -12,19 +12,27 @@ class Client : public ClientUDP { private: - std::shared_ptr _player; - std::shared_ptr _world; - std::map> _players{}; - - int fireTraces = 0; + std::shared_ptr _player; void spawnPlayer(sf::Uint16 id); + + std::function _spawnPlayerCallBack; + std::function _removePlayerCallBack; + std::function _addFireTraceCallBack; + std::function _addBonusCallBack; + std::function _removeBonusCallBack; public: - Client(std::shared_ptr player, std::shared_ptr world) : _player(player), _world(world) {}; + Client(std::shared_ptr player) : _player(player){}; void updatePacket() override; + void setSpawnPlayerCallBack(std::function spawn); + void setRemovePlayerCallBack(std::function remove); + void setAddFireTraceCallBack(std::function addTrace); + void setAddBonusCallBack(std::function addBonus); + void setRemoveBonusCallBack(std::function removeBonus); + void processInit(sf::Packet& packet) override; void processUpdate(sf::Packet& packet) override; void processNewClient(sf::Packet& packet) override; @@ -40,7 +48,7 @@ public: void addTrace(const Point4D& from, const Point4D& to); - void deleteTrace(std::shared_ptr world, const std::string& traceName); + void addPlayer(sf::Uint16 id, std::shared_ptr player); }; diff --git a/Player.cpp b/Player.cpp index cc1188d..0088517 100755 --- a/Player.cpp +++ b/Player.cpp @@ -7,47 +7,11 @@ #include "ResourceManager.h" #include "utils/Log.h" -void Player::update() { - -} - 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 - double xPos = 10; - double yPos = _screen->height() - 10 - 10; - - double width = _screen->width()/2 - 20; - double height = 10; - - _screen->drawTetragon(Point4D{xPos, yPos}, - Point4D{xPos + width, yPos}, - Point4D{xPos + width, yPos + height}, - Point4D{xPos, yPos + height}, - { static_cast((_healthMax - _health)/_healthMax * 255), static_cast(_health * 255 / _healthMax), 0, 100 }); - - _screen->drawTetragon(Point4D{xPos, yPos - 15}, - Point4D{xPos + width * _ability / _abilityMax, yPos - 15}, - Point4D{xPos + width * _ability / _abilityMax, yPos - 15 + height}, - Point4D{xPos, yPos - 15 + height}, - { 255, 168, 168, 100 }); - - auto balance = _weapons[_selectedWeapon]->balance(); - - _screen->drawText(std::to_string((int)balance.first),Point4D{150, static_cast(_screen->height() - 50 - 100)},100, sf::Color(0, 0, 0, 100)); - _screen->drawText(std::to_string((int)balance.second),Point4D{50, static_cast(_screen->height() - 50 - 50)},50, sf::Color(0, 0, 0, 70)); - - _screen->drawText("KILLS: " + std::to_string((int)_kills) + " | " + "DEATHS: " + std::to_string((int)_deaths), - Point4D{10, 10},25, sf::Color(0, 0, 0, 100)); -} - void Player::playDeath() { _deathSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/classic_hurt.ogg")); _deathSound.play(); @@ -81,7 +45,6 @@ void Player::collisionWithObject(const std::string &objName, std::shared_ptrremoveBody(objName); _takeBonusCallBack(objName); } } @@ -89,45 +52,44 @@ void Player::collisionWithObject(const std::string &objName, std::shared_ptr weapon) { _changeWeaponSound.play(); - if(!_weapons.empty()) { - for(auto& w : _weapons) { - if (w->name() == weapon->name()) { - w->addAmmo(w->initialPack()); - return; - } + for(auto& w : _weapons) { + if (w->name() == weapon->name()) { + w->addAmmo(w->initialPack()); + return; } } _weapons.push_back(weapon); - _weapons.back()->attachToPlayer(*this); + attach(weapon, weapon->name()); _weapons.back()->translate(position()); _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, Point4D{0, 1, 0}, _angle.y()); - _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, _camera->left(), _camera->angleLeftUpLookAt().x()); + _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, left(), headAngle()); _weapons.back()->setAddTraceCallBack(_addTraceCallBack); - _changeWeaponSound.play(); } void Player::initWeapons() { if(!_weapons.empty()) { - _weapons[_selectedWeapon]->removeFromWorld(_world); + for(auto weapon : _weapons) + unattach(weapon->name()); + + _removeWeaponCallBack(_weapons[_selectedWeapon]); _weapons.clear(); } _selectedWeapon = 0; addWeapon(std::make_shared()); - - _weapons[_selectedWeapon]->addToWorld(_world); + _addWeaponCallBack(_weapons[_selectedWeapon]); } void Player::nextWeapon() { if(_weapons.size() > 1) { // change '_selectedWeapon' - _weapons[_selectedWeapon]->removeFromWorld(_world); + _removeWeaponCallBack(_weapons[_selectedWeapon]); _selectedWeapon = (_selectedWeapon + 1) % _weapons.size(); - _weapons[_selectedWeapon]->addToWorld(_world); + _addWeaponCallBack(_weapons[_selectedWeapon]); Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon)); _changeWeaponSound.play(); } @@ -136,19 +98,19 @@ void Player::nextWeapon() { void Player::previousWeapon() { if(_weapons.size() > 1) { // change '_selectedWeapon' - _weapons[_selectedWeapon]->removeFromWorld(_world); + _removeWeaponCallBack(_weapons[_selectedWeapon]); if (_selectedWeapon > 0) _selectedWeapon = (_selectedWeapon - 1) % _weapons.size(); else _selectedWeapon = _weapons.size() - 1; - _weapons[_selectedWeapon]->addToWorld(_world); + _addWeaponCallBack(_weapons[_selectedWeapon]); Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon)); _changeWeaponSound.play(); } } void Player::fire() { - auto damagedPlayers = _weapons[_selectedWeapon]->fire(_world, _camera); + auto damagedPlayers = _weapons[_selectedWeapon]->fire(_rayCastFunction, attached("camera")->position(), attached("camera")->lookAt()); for(auto& damagedPlayer : damagedPlayers) { sf::Uint16 targetId = std::stoi(damagedPlayer.first.substr(7)); _damagePlayerCallBack(targetId, damagedPlayer.second); diff --git a/Player.h b/Player.h index 4ae1687..7274184 100755 --- a/Player.h +++ b/Player.h @@ -26,16 +26,11 @@ private: double _headAngle = 0; - unsigned _kills = 0; - unsigned _deaths = 0; + int _kills = 0; + int _deaths = 0; double _g = 35; - std::shared_ptr _camera; - std::shared_ptr _screen; - - std::shared_ptr _world; - // sounds sf::Sound _killSound; sf::Sound _deathSound; @@ -51,7 +46,12 @@ private: std::function _damagePlayerCallBack; std::function _addTraceCallBack; std::function _takeBonusCallBack; + std::function _fireCallBack; + std::function)> _addWeaponCallBack; + std::function)> _removeWeaponCallBack; + + std::function(const Point4D&, const Point4D&)> _rayCastFunction; public: Player() { loadObj("../obj/cube.obj", "", Point4D{0.5, 1.9, 0.5}); @@ -68,23 +68,7 @@ public: setCollisionCallBack([this](const std::string& objName, std::shared_ptr obj) {collisionWithObject(objName, obj);}); }; - void update(); - - void attachCamera(std::shared_ptr camera, std::shared_ptr screen) { - _camera = camera; - _screen = screen; - - _camera->translateToPoint(position() + Point4D{0, 1.8, 0}); - this->attach(_camera); - } - - void attachWorld(std::shared_ptr world, const Point4D& pos = Point4D{0, 30, 0}) { - _world = world; - - translate(pos); - - initWeapons(); - } + [[nodiscard]] std::string name() const { return "Player_" + _name; } void setHealth(double h) { _health = h; @@ -93,13 +77,12 @@ public: _ability = a; } - void nextWeapon(); - void previousWeapon(); - void fire(); - void reload(); - + [[nodiscard]] double health() const { return _health; } [[nodiscard]] double ability() const { return _ability; } + [[nodiscard]] double maxHealth() const { return _healthMax; } + [[nodiscard]] double maxAbility() const { return _abilityMax; } + void setFullHealth() { _health = _healthMax; _fullHealthSound.play(); @@ -109,32 +92,19 @@ public: _fullAbilitySound.play(); } + void initWeapons(); + void addWeapon(std::shared_ptr weapon); + [[nodiscard]] std::pair balance() const{ return _weapons[_selectedWeapon]->balance();} - void setDamagePlayerCallBack(std::function hit) { - _damagePlayerCallBack = std::move(hit); - } - - void setAddTraceCallBack(std::function add) { - _addTraceCallBack = std::move(add); - } - - void setTakeBonusCallBack(std::function take) { - _takeBonusCallBack = std::move(take); - } - - [[nodiscard]] double health() const { return _health; } - [[nodiscard]] std::string name() const { return "Player_" + _name; } - - - std::shared_ptr camera() { return _camera; } - - // This is for situation when you want to store the position of the head but you dont have attached camera - void setHeadAngle(double a) { _headAngle = a; } - [[nodiscard]] double headAngle() const { return _headAngle; }; + void nextWeapon(); + void previousWeapon(); + void fire(); + void reload(); void rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v, double val); - void drawStats(); + [[nodiscard]] int kills() const {return _kills;} + [[nodiscard]] int deaths() const {return _deaths;} void addKill() { _kills++; } void addDeath() { _deaths++; } @@ -142,11 +112,30 @@ public: void playDeath(); void playKill(); + void setDamagePlayerCallBack(std::function hit) { + _damagePlayerCallBack = std::move(hit); + } + void setAddTraceCallBack(std::function add) { + _addTraceCallBack = std::move(add); + } + void setTakeBonusCallBack(std::function take) { + _takeBonusCallBack = std::move(take); + } + void setAddWeaponCallBack(std::function)> addWeapon) { + _addWeaponCallBack = addWeapon; + } + void setRemoveWeaponCallBack(std::function)> removeWeapon) { + _removeWeaponCallBack = std::move(removeWeapon); + } + void setRayCastFunction(std::function(const Point4D&, const Point4D&)> rayCastFunction) { + _rayCastFunction = std::move(rayCastFunction); + } + + // This is for situation when you want to store the position of the head but you dont have attached camera + void setHeadAngle(double a) { _headAngle = a; } + [[nodiscard]] double headAngle() const { return _headAngle; }; + void collisionWithObject(const std::string& objName, std::shared_ptr obj); - - void addWeapon(std::shared_ptr weapon); - - void initWeapons(); }; diff --git a/PlayerController.cpp b/PlayerController.cpp index 9d21218..10cfa08 100644 --- a/PlayerController.cpp +++ b/PlayerController.cpp @@ -3,11 +3,16 @@ // #include "PlayerController.h" +#include "utils/Log.h" +#include "animation/AColor.h" +#include "animation/AFunction.h" +#include "animation/AWait.h" +#include "animation/ATranslate.h" +#include "animation/ATranslateToPoint.h" PlayerController::PlayerController(std::shared_ptr player, - std::shared_ptr world, std::shared_ptr keyboard, - std::shared_ptr mouse) : _player(player), _world(world), _keyboard(keyboard), _mouse(mouse) { + std::shared_ptr mouse) : _player(player), _keyboard(keyboard), _mouse(mouse) { _slowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/slow_mo.ogg")); _unSlowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/unslow_mo.ogg")); } @@ -38,51 +43,50 @@ void PlayerController::update() { Keyboard::isKeyPressed(sf::Keyboard::W) || Keyboard::isKeyPressed(sf::Keyboard::S)); - // in case when the camera is attached we make some animation during running - if(_inRunning && !_player->camera()->isInAnim()) { - _player->camera()->a_translate("hor_oscil", -_player->camera()->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos); - _player->camera()->a_wait("hor_oscil", 0); - _player->camera()->a_translate("hor_oscil", _player->camera()->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos); + std::shared_ptr camera = _player->attached("camera"); + if(_inRunning) { + if (!camera->isInAnim()) { + camera->animate("hor_oscil", new ATranslate(camera, -camera->left() / 6, 0.3,Animation::LoopOut::None, Animation::cos)); + camera->animate("hor_oscil", new AWait(0)); + camera->animate("hor_oscil", new ATranslate(camera, camera->left() / 6, 0.3, Animation::LoopOut::None, Animation::cos)); - _player->camera()->a_translate("vert_oscil", -Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); - _player->camera()->a_wait("vert_oscil", 0); - _player->camera()->a_translate("vert_oscil", Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); - _player->camera()->a_wait("vert_oscil", 0); - _player->camera()->a_translate("vert_oscil", -Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); - _player->camera()->a_wait("vert_oscil", 0); - _player->camera()->a_translate("vert_oscil", Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos); - - _player->camera()->a_translateToPoint("init", _player->position() + Point4D{0, 1.8, 0}, 0.3/coeff, Animation::None, Animation::cos); + camera->animate("vert_oscil", new ATranslate(camera, -Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::cos)); + camera->animate("vert_oscil", new AWait(0)); + camera->animate("vert_oscil", new ATranslate(camera, Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None,Animation::cos)); + camera->animate("vert_oscil", new AWait(0)); + camera->animate("vert_oscil", new ATranslate(camera, -Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::cos)); + camera->animate("vert_oscil", new AWait(0)); + camera->animate("vert_oscil", new ATranslate(camera, Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::cos)); + camera->animate("init", new ATranslateToPoint( camera, _player->position() + Point4D{0, 1.8, 0}, 0.3, Animation::None, Animation::cos)); + } } else if(inRunning_old && !_inRunning) { - _player->camera()->a_stopAllAnimations(); - - _player->camera()->a_translateToPoint("init", _player->position() + Point4D{0, 1.8, 0}, 0.15/coeff, Animation::None, Animation::cos); + camera->stopAllAnimations(); + camera->animate("init", new ATranslateToPoint( camera, _player->position() + Point4D{0, 1.8, 0}, 0.15, Animation::None, Animation::cos)); } - auto rayToFloor = (*_world).rayCast(_player->position(), _player->position() + Point4D{0, -5, 0}); - // Left and right + if (Keyboard::isKeyPressed(sf::Keyboard::A)) { - _player->translate(_player->camera()->left() * Time::deltaTime() * _walkSpeed * coeff); + _player->translate(_player->left() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) _player->setVelocity(Point4D{0,0,0}); } if (Keyboard::isKeyPressed(sf::Keyboard::D)) { - _player->translate(-_player->camera()->left() * Time::deltaTime() * _walkSpeed * coeff); + _player->translate(-_player->left() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) _player->setVelocity(Point4D{0,0,0}); } // Forward and backward if (Keyboard::isKeyPressed(sf::Keyboard::W)) { - _player->translate(_player->camera()->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * _walkSpeed * coeff); + _player->translate(_player->lookAt() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) _player->setVelocity(Point4D{0,0,0}); } if (Keyboard::isKeyPressed(sf::Keyboard::S)) { - _player->translate(-_player->camera()->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * _walkSpeed * coeff); + _player->translate(-_player->lookAt() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) _player->setVelocity(Point4D{0,0,0}); @@ -109,21 +113,21 @@ void PlayerController::update() { } // Mouse movement - Point4D disp = _mouse->getMouseDisplacement(); + Point4D displacement = _mouse->getMouseDisplacement(); - _player->rotate(Point4D{0, -disp.x() / 1000.0, 0}); - _player->setVelocity(Matrix4x4::RotationY(-disp.x() / 1000.0) * _player->velocity()); + _player->rotate(Point4D{0, -displacement.x() / 1000.0, 0}); + _player->setVelocity(Matrix4x4::RotationY(-displacement.x() / 1000.0) * _player->velocity()); - double rotationLeft = disp.y() / 1000.0; + double rotationLeft = displacement.y() / 1000.0; // You can only see in range [-90 : 90] grad - if (_player->camera()->angleLeftUpLookAt().x() + rotationLeft > M_PI / 2) - rotationLeft = M_PI / 2 - _player->camera()->angleLeftUpLookAt().x(); - if (_player->camera()->angleLeftUpLookAt().x() + rotationLeft < -M_PI / 2) - rotationLeft = -M_PI / 2 - _player->camera()->angleLeftUpLookAt().x(); + if (_player->headAngle() + rotationLeft > M_PI / 2) + rotationLeft = M_PI / 2 - _player->headAngle(); + if (_player->headAngle() + rotationLeft < -M_PI / 2) + rotationLeft = -M_PI / 2 - _player->headAngle(); - _player->camera()->rotateLeft(rotationLeft); - _player->rotateWeaponsRelativePoint(_player->position() + Point4D{0, 1.8, 0}, _player->camera()->left(), rotationLeft); + _player->setHeadAngle(_player->headAngle() + rotationLeft); + _player->rotateWeaponsRelativePoint(_player->position() + Point4D{0, 1.8, 0}, _player->left(), rotationLeft); if (_keyboard->isKeyTapped(sf::Keyboard::Right) || _keyboard->isKeyTapped(sf::Keyboard::E)) { _player->nextWeapon(); @@ -141,11 +145,9 @@ void PlayerController::update() { _player->reload(); } - if (_inRunning && _player->inCollision() && _walkSound.getStatus() != sf::Sound::Status::Playing) { - if ((_player->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.play(); - } + if ((_inRunning || _player->velocity().sqrAbs() > 3) && _player->inCollision() && _walkSound.getStatus() != sf::Sound::Status::Playing) { + int soundNum = round((double) rand() / RAND_MAX * 5) + 1; + _walkSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/stonestep" + std::to_string(soundNum) + ".ogg")); + _walkSound.play(); } } diff --git a/PlayerController.h b/PlayerController.h index 2f88bfb..5622aa5 100644 --- a/PlayerController.h +++ b/PlayerController.h @@ -12,8 +12,6 @@ class PlayerController { private: std::shared_ptr _player; - std::shared_ptr _world; - std::shared_ptr _keyboard; std::shared_ptr _mouse; @@ -30,7 +28,7 @@ private: double _jumpHeight = 3; double _walkSpeed = 10; public: - PlayerController(std::shared_ptr player, std::shared_ptr world, std::shared_ptr keyboard, std::shared_ptr mouse); + PlayerController(std::shared_ptr player, std::shared_ptr keyboard, std::shared_ptr mouse); void update(); }; diff --git a/Shooter.cpp b/Shooter.cpp new file mode 100644 index 0000000..3767d77 --- /dev/null +++ b/Shooter.cpp @@ -0,0 +1,269 @@ +// +// Created by Иван Ильин on 22.09.2021. +// + +#include "Shooter.h" +#include +#include "animation/AColor.h" +#include "animation/AFunction.h" +#include "animation/ATranslate.h" +#include "animation/ARotate.h" + +using namespace std; + +// Read server/client settings and start both. +// If client doesn't connect to the localhost - server doesn't start. +void Shooter::InitNetwork() +{ + std::string clientIp; + sf::Uint16 clientPort; + sf::Uint16 serverPort; + std::ifstream connectFile("connect.txt", std::ifstream::in); + + // If failed to read client settings + if (!connectFile.is_open() || !(connectFile >> clientIp >> clientPort) || sf::IpAddress(clientIp) == sf::IpAddress::None) + { + connectFile.close(); + // Create file and write default settings + clientIp = "127.0.0.1"; + clientPort = 54000; + std::ofstream temp("connect.txt", std::ofstream::out); + temp << clientIp << std::endl << clientPort; + temp.close(); + } + connectFile.close(); + + // If failed to read server settings + connectFile.open("server.txt", std::ifstream::in); + if (!connectFile.is_open() || !(connectFile >> serverPort)) + { + connectFile.close(); + // Create file and write default settings + serverPort = 54000; + std::ofstream temp("server.txt", std::ofstream::out); + temp << serverPort; + temp.close(); + } + connectFile.close(); + + if (clientIp == sf::IpAddress::LocalHost) { + server->start(serverPort); + if(server->isWorking()) + server->generateBonuses(); + } + + client->connect(clientIp, clientPort); + + client->setSpawnPlayerCallBack([this](sf::Uint16 id){ spawnPlayer(id); }); + client->setRemovePlayerCallBack([this](sf::Uint16 id){ removePlayer(id); }); + client->setAddFireTraceCallBack([this](const Point4D& from, const Point4D& to){ addFireTrace(from, to); }); + client->setAddBonusCallBack([this](const std::string& bonusName, const Point4D& position){ addBonus(bonusName, position); }); + client->setRemoveBonusCallBack([this](const std::string& bonusName){ removeBonus(bonusName); }); +} + +void Shooter::start() { + // This code executed once in the beginning: + setDebugText(false); + setUpdateWorld(false); + + mouse->setMouseCursorVisible(true); + + world->loadMap("../maps/map1.obj", "map", Point4D{5, 5, 5}); + + player = std::make_shared(); + playerController = std::make_shared(player, keyboard, mouse); + + player->setAddTraceCallBack([this](const Point4D& from, const Point4D& to){ client->addTrace(from, to); addFireTrace(from, to); }); + player->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); }); + player->setRayCastFunction([this](const Point4D& from, const Point4D& to) { return world->rayCast(from, to); }); + player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); }); + + player->setAddWeaponCallBack([this](std::shared_ptr weapon){ addWeapon(weapon); }); + player->setRemoveWeaponCallBack([this](std::shared_ptr weapon){ removeWeapon(weapon); }); + player->initWeapons(); + + camera->translateToPoint(player->position() + Point4D{0, 1.8, 0}); + player->attach(camera, "camera"); + + world->addBody(player, player->name()); + player->translate(Point4D{0, 10, 0}); + + client = std::make_shared(player); + server = std::make_shared(); + + // windows init: + mainMenu.title("Main menu"); + mainMenu.setBackgroundTexture("../textures/back.png", 1.1, 1.1, screen->width(), screen->height()); + + mainMenu.addButton(screen->width()/2, 200, 200, 20, [this] () { this->play(); }, "Play", 5, 5, "../textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "../engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "../sound/click.ogg"); + mainMenu.addButton(screen->width()/2, 350, 200, 20, [this] () { this->player->translateToPoint(Point4D{0, 0, 0}); this->player->setVelocity({}); this->play(); }, "Respawn", 5, 5, "../textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "../engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "../sound/click.ogg"); + + mainMenu.addButton(screen->width()/2, 500, 200, 20, [this] () { client->disconnect(); server->stop(); this->exit();}, "Exit", 5, 5, "../textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "../engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "../sound/click.ogg"); + + // connecting to the server + InitNetwork(); + // Waiting for connect and updating server if it's same window + while (client->isWorking() && !client->connected()) + { + client->update(); + server->update(); + Time::update(); + } + // If connect fail - return to menu + if (!client->isWorking()) + { + inGame = false; + server->stop(); + } +} + +void Shooter::update() { + // This code executed every time step: + + server->update(); + client->update(); + + // Check all input after this condition please + if (!screen->hasFocus()) + return; + + if(keyboard->isKeyTapped(sf::Keyboard::Escape)) { + inGame = !inGame; + mouse->setMouseCursorVisible(!inGame); + } + + if(inGame) { + screen->setTitle("Shooter"); + playerController->update(); + mouse->setMouseInCenter(); + camera->rotateLeft(player->headAngle() - camera->angleLeftUpLookAt().x()); + + } else { + mainMenu.update(); + } + + setUpdateWorld(inGame); + + // background sounds and music control + if(backgroundNoise.getStatus() != sf::Sound::Status::Playing) { + backgroundNoise.setBuffer(*ResourceManager::loadSoundBuffer("../sound/backNoise.ogg")); + backgroundNoise.play(); + } +} + +void Shooter::gui() { + + sf::Sprite sprite; + sprite.setTexture(*ResourceManager::loadTexture("../textures/gui.png")); + sprite.setTextureRect(sf::IntRect(243, 3, 9, 9)); + sprite.scale(3, 3); + sprite.setPosition(screen->width() / 2.0 - 27.0/2.0, screen->height() / 2 - 27.0/2.0); + sprite.setColor(sf::Color(0,0,0, 200)); + screen->drawSprite(sprite); + + // health player stats + drawPlayerStats(); +} + +void Shooter::drawPlayerStats() { + // health bar + double xPos = 10; + double yPos = screen->height() - 10 - 10; + + int width = screen->width()/2 - 20; + int height = 10; + + screen->drawTetragon(Point4D{xPos, yPos}, + Point4D{xPos + width * player->health() / player->maxHealth(), yPos}, + Point4D{xPos + width * player->health() / player->maxHealth(), yPos + height}, + Point4D{xPos, yPos + height}, + { static_cast((player->maxHealth() - player->health())/player->maxHealth() * 255), static_cast(player->health() * 255 / player->maxHealth()), 0, 100 }); + + screen->drawTetragon(Point4D{xPos, yPos - 15}, + Point4D{xPos + width * player->ability() / player->maxAbility(), yPos - 15}, + Point4D{xPos + width * player->ability() / player->maxAbility(), yPos - 15 + height}, + Point4D{xPos, yPos - 15 + height}, + { 255, 168, 168, 100 }); + + auto balance = player->balance(); + + screen->drawText(std::to_string((int)balance.first),Point4D{150, static_cast(screen->height() - 50 - 100)},100, sf::Color(0, 0, 0, 100)); + screen->drawText(std::to_string((int)balance.second),Point4D{50, static_cast(screen->height() - 50 - 50)},50, sf::Color(0, 0, 0, 70)); + + screen->drawText("KILLS: " + std::to_string(player->kills()) + " | " + "DEATHS: " + std::to_string(player->deaths()), + Point4D{10, 10},25, sf::Color(0, 0, 0, 100)); +} + +void Shooter::play() { + inGame = true; + mouse->setMouseCursorVisible(false); +} + +void Shooter::spawnPlayer(sf::Uint16 id) { + std::string name = "Player_" + std::to_string(id); + std::shared_ptr newPlayer = std::make_shared(); + newPlayer->setCollision(false); + + client->addPlayer(id, newPlayer); + world->addBody(newPlayer, name); + newPlayer->setVisible(true); + newPlayer->setAcceleration(Point4D{0, 0, 0}); + + // add head and other stuff: + world->loadBody(name + "_head", "../obj/cube.obj", "", Point4D{0.7, 0.7, 0.7}); + world->body(name + "_head")->translate(Point4D{0, 2, 0}); + world->body(name + "_head")->setCollider(false); + newPlayer->attach(world->body(name + "_head"), "head"); + + world->loadBody(name + "_eye1", "../obj/cube.obj", "", Point4D{0.2, 0.2, 0.05}); + world->body(name + "_eye1")->translate(Point4D{0.3, 2.1, 0.7}); + world->body(name + "_eye1")->setCollider(false); + world->body(name + "_eye1")->setColor({147, 159, 255}); + world->body(name + "_head")->attach(world->body(name + "_eye1"), "eye1"); + + world->loadBody(name + "_eye2", "../obj/cube.obj", "", Point4D{0.2, 0.2, 0.05}); + world->body(name + "_eye2")->translate(Point4D{-0.3, 2.1, 0.7}); + world->body(name + "_eye2")->setCollider(false); + world->body(name + "_eye2")->setColor({147, 159, 255}); + world->body(name + "_head")->attach(world->body(name + "_eye2"), "eye2"); +} + +void Shooter::removePlayer(sf::Uint16 id) { + std::string name = "Player_" + std::to_string(id); + world->removeBody(name); + world->removeBody(name + "_head"); + world->removeBody(name + "_eye1"); + world->removeBody(name + "_eye2"); +} + +void Shooter::addFireTrace(const Point4D &from, const Point4D &to) { + std::string traceName = "Client_fireTraces_" + std::to_string(fireTraces++); + world->addBody(std::make_shared(Mesh::LineTo(from, to, 0.05)), traceName); + world->body(traceName)->setCollider(false); + + world->body(traceName)->animate(traceName + "_fadeOut", new AColor(world->body(traceName), {255, 255, 255, 0})); + world->body("Player_im")->animate(traceName + "delete", new AFunction([this, traceName](){ deleteFireTrace(traceName); }, 1, 2)); +} + +void Shooter::deleteFireTrace(const std::string& traceName) { + world->removeBody(traceName); +} + +void Shooter::addBonus(const string &bonusName, const Point4D &position) { + std::string name = bonusName.substr(6, bonusName.size()-3-5); + world->addBody(std::make_shared(bonusName, "../obj/" + name + ".obj", "../obj/" + name + "_mat.txt", Point4D{3, 3, 3}), bonusName); + world->body(bonusName)->translateToPoint(position); + world->body(bonusName)->animate("a_rotation", new ARotate(world->body(bonusName), Point4D{0, 2*M_PI, 0}, 4, Animation::Continue, Animation::linear)); +} + +void Shooter::removeBonus(const string &bonusName) { + world->removeBody(bonusName); +} + +void Shooter::addWeapon(std::shared_ptr weapon) { + world->addBody(weapon, weapon->name()); +} + +void Shooter::removeWeapon(std::shared_ptr weapon) { + world->removeBodyInstantly(weapon->name()); +} diff --git a/Shooter.h b/Shooter.h new file mode 100644 index 0000000..255dd4b --- /dev/null +++ b/Shooter.h @@ -0,0 +1,57 @@ +// +// Created by Иван Ильин on 22.09.2021. +// + +#ifndef SHOOTER_SHOOTER_H +#define SHOOTER_SHOOTER_H + +#include "Engine.h" +#include "Player.h" +#include "PlayerController.h" +#include "PlayerController.h" +#include "gui/Window.h" + +#include "Client.h" +#include "Server.h" + + +class Shooter : public Engine { +private: + std::shared_ptr player; + std::shared_ptr playerController; + + sf::Sound backgroundNoise; + + Window mainMenu; + + std::shared_ptr server; + std::shared_ptr client; + + bool inGame = false; + + int fireTraces = 0; + + void start() override; + void update() override; + + void gui() override; + + void play(); + + void drawPlayerStats(); + void InitNetwork(); + + void spawnPlayer(sf::Uint16 id); + void removePlayer(sf::Uint16 id); + void addFireTrace(const Point4D& from, const Point4D& to); + void deleteFireTrace(const std::string& traceName); + void addBonus(const std::string& bonusName, const Point4D& position); + void removeBonus(const std::string& bonusName); + void addWeapon(std::shared_ptr weapon); + void removeWeapon(std::shared_ptr weapon); +public: + Shooter() : mainMenu(screen, mouse) {}; +}; + + +#endif //SHOOTER_SHOOTER_H diff --git a/engine/Camera.cpp b/engine/Camera.cpp index ff65b70..af1e542 100755 --- a/engine/Camera.cpp +++ b/engine/Camera.cpp @@ -76,7 +76,6 @@ std::vector &Camera::project(std::shared_ptr mesh) { void Camera::init(int width, int height, double fov, double ZNear, double ZFar) { // We need to init camera only after creation or changing width, height, fov, ZNear or ZFar. // Because here we calculate matrix that does not change during the motion of _objects or camera - _w = width; _h = height; _aspect = (double)width / (double)height; _P = Matrix4x4::Projection(fov, _aspect, ZNear, ZFar); _S = Matrix4x4::ScreenSpace(width, height); @@ -127,108 +126,3 @@ void Camera::clear() { _triangles.clear(); _V = Matrix4x4::View(_left, _up, _lookAt, _position); } - -void Camera::rotateX(double rx) { - _angle = Point4D{_angle.x() + rx, _angle.y(), _angle.z()}; - _left = Matrix4x4::RotationX(rx) * _left; - _up = Matrix4x4::RotationX(rx) * _up; - _lookAt = Matrix4x4::RotationX(rx) * _lookAt; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), Point4D{rx, 0, 0}); -} - -void Camera::rotateY(double ry) { - _angle = Point4D{_angle.x(), _angle.y() + ry, _angle.z()}; - _left = Matrix4x4::RotationY(ry) * _left; - _up = Matrix4x4::RotationY(ry) * _up; - _lookAt = Matrix4x4::RotationY(ry) * _lookAt; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), Point4D{0, ry, 0}); -} - -void Camera::rotateZ(double rz) { - _angle = Point4D{_angle.x(), _angle.y(), _angle.z() + rz}; - _left = Matrix4x4::RotationZ(rz) * _left; - _up = Matrix4x4::RotationZ(rz) * _up; - _lookAt = Matrix4x4::RotationZ(rz) * _lookAt; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), Point4D{0, 0, rz}); -} - -void Camera::rotate(const Point4D& r) { - rotateX(r.x()); - rotateY(r.y()); - rotateZ(r.z()); -} - - -void Camera::rotate(const Point4D& v, double rv) { - _left = Matrix4x4::Rotation(v, rv) * _left; - _up = Matrix4x4::Rotation(v, rv) * _up; - _lookAt = Matrix4x4::Rotation(v, rv) * _lookAt; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), v, rv); -} - -void Camera::rotateLeft(double rl) { - _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x() + rl, _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z()}; - - rotate(_left, rl); - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), _left, rl); -} - -void Camera::rotateUp(double ru) { - _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y() + ru, _angleLeftUpLookAt.z()}; - rotate(_up, ru); - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), _up, ru); -} - -void Camera::rotateLookAt(double rlAt) { - _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z() + rlAt}; - rotate(_lookAt, rlAt); - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), _lookAt, rlAt); -} - -void Camera::rotateRelativePoint(const Point4D &s, const Point4D &r) { - _angle = _angle + r; - - // Translate XYZ by vector r1 - Point4D r1 = _position - s; - // In translated coordinate system we rotate camera and position - Point4D r2 = Matrix4x4::Rotation(r)*r1; - rotate(r); - - // After rotation we translate XYZ by vector -r2 and recalculate position - _position = s + r2; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(s, r); -} - -void Camera::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { - // Translate XYZ by vector r1 - Point4D r1 = _position - s; - // In translated coordinate system we rotate camera and position - Point4D r2 = Matrix4x4::Rotation(v, r)*r1; - rotate(v, r); - - // After rotation we translate XYZ by vector -r2 and recalculate position - _position = s + r2; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(s, v, r); -} - -void Camera::translateToPoint(const Point4D &point) { - translate(point - _position); -} diff --git a/engine/Camera.h b/engine/Camera.h index fe74659..58d1f23 100755 --- a/engine/Camera.h +++ b/engine/Camera.h @@ -10,30 +10,20 @@ #include "Plane.h" #include "Mesh.h" -class Camera : public Object, public Animatable{ +class Camera : public Object{ private: - Point4D _angleLeftUpLookAt; - - Point4D _left = Point4D{1, 0, 0, 0}; // internal X - Point4D _up = Point4D{0, 1, 0, 0}; // internal Y - Point4D _lookAt = Point4D{0, 0, 1, 0}; // internal Z - Matrix4x4 _S; // screen space matrix Matrix4x4 _P; // projections matrix Matrix4x4 _V; // camera matrix - double _aspect = 0; - // To accelerate calculations we can use precalculated matrix that does not chance Matrix4x4 _SP; // screen-space-projections matrix - std::vector _triangles; - std::vector _clipPlanes; + std::vector _triangles{}; + std::vector _clipPlanes{}; bool _ready = false; - - double _w = 0; - double _h = 0; + double _aspect = 0; public: Camera() = default; Camera(const Camera& camera) = delete; @@ -46,42 +36,6 @@ public: [[nodiscard]] int buffSize() const { return _triangles.size(); } std::vector& sorted(); - - [[nodiscard]] Point4D position() const override { return _position; } - [[nodiscard]] Point4D angle() const override { return _angle; } - [[nodiscard]] Point4D angleLeftUpLookAt() const { return _angleLeftUpLookAt; } - - [[nodiscard]] Point4D eye() const { return _position; } - [[nodiscard]] Point4D left() const { return _left; } - [[nodiscard]] Point4D right() const { return -_left; } - [[nodiscard]] Point4D up() const { return _up; } - [[nodiscard]] Point4D down() const { return -_up; } - [[nodiscard]] Point4D lookAt() const { return _lookAt; } - - void translate(const Point4D& dv) override { - _position = _position + dv; - - for(auto attached : _attachedObjects) - attached->translate(dv); - } - - void translateToPoint(const Point4D& point); - - void rotateX(double rx); - void rotateY(double ry); - void rotateZ(double rz); - void rotate(const Point4D& r) override; - - void rotate(const Point4D& v, double rv) override; - - void rotateLeft(double rl); - void rotateUp(double ru); - void rotateLookAt(double rlAt); - - // Rotate body around XYZ by (r.x, r.y, r.z) radians relative val 'point4D' - void rotateRelativePoint(const Point4D& s, const Point4D& r) override; - // Rotate body around normalised vector 'v' by 'r' radians relative val 'point4D' - void rotateRelativePoint(const Point4D& s, const Point4D& v, double r) override; }; diff --git a/engine/Engine.cpp b/engine/Engine.cpp index 18bac95..6330063 100755 --- a/engine/Engine.cpp +++ b/engine/Engine.cpp @@ -47,7 +47,7 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name, // hence we can set '_updateWorld' equal to false in setUpdateWorld(bool): if(_updateWorld) { - camera->a_update(); + camera->update_animations(); camera->clear(); world->update(); @@ -80,9 +80,9 @@ void Engine::exit() { void Engine::printDebugText() const { if (_debugText) { screen->debugText(_name + "\n\n X: " + - std::to_string((camera->eye().x())) + "\n Y: " + - std::to_string((camera->eye().y())) + "\n Z: " + - std::to_string((camera->eye().z())) + "\n\n" + + std::to_string((camera->position().x())) + "\n Y: " + + std::to_string((camera->position().y())) + "\n Z: " + + std::to_string((camera->position().z())) + "\n\n" + std::to_string(screen->width()) + "x" + std::to_string(screen->height()) + "\n" + std::to_string(Time::fps()) + diff --git a/engine/Engine.h b/engine/Engine.h index 0874769..046dbb8 100755 --- a/engine/Engine.h +++ b/engine/Engine.h @@ -30,21 +30,20 @@ protected: std::shared_ptr world; std::shared_ptr camera; + virtual void start() {}; + virtual void update() {}; + + void setDebugText(bool value) { _debugText = value; } + void setUpdateWorld(bool value) { _updateWorld = value; } + + virtual void gui(){} public: Engine(); virtual ~Engine() = default; void create(int screenWidth = 1920, int screenHeight = 1080, const std::string& name = "engine", bool verticalSync = true, sf::Color background = sf::Color(255, 255, 255), sf::Uint32 style = sf::Style::Default); - - virtual void start() {}; - virtual void update() {}; void exit(); - - void setDebugText(bool value) { _debugText = value; } - void setUpdateWorld(bool value) { _updateWorld = value; } - - virtual void gui(){} }; diff --git a/engine/Mesh.cpp b/engine/Mesh.cpp index 96c3f38..0b5c520 100755 --- a/engine/Mesh.cpp +++ b/engine/Mesh.cpp @@ -46,31 +46,18 @@ Mesh Mesh::Obj(const std::string& filename) { } void Mesh::rotate(const Point4D &r) { - _angle = _angle + r; + Object::rotate(r); *this *= Matrix4x4::Rotation(r); - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), r); } void Mesh::rotate(const Point4D &v, double r) { + Object::rotate(v, r); *this *= Matrix4x4::Rotation(v, r); - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(position(), v, r); } void Mesh::scale(const Point4D &s) { + Object::scale(s); *this *= Matrix4x4::Scale(s); - - // TODO: scale attached objects -} - -void Mesh::translate(const Point4D &t) { - _position = _position + t; - - for(auto attached : _attachedObjects) - attached->translate(t); } Mesh &Mesh::operator=(const Mesh &mesh) { @@ -81,48 +68,13 @@ Mesh &Mesh::operator=(const Mesh &mesh) { } void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &r) { - _angle = _angle + r; - - // Translate XYZ by vector r1 - Point4D r1 = _position - s; - *this *= Matrix4x4::Translation(r1); - - // In translated coordinate system we rotate body and position - Matrix4x4 rotationMatrix = Matrix4x4::Rotation(r); - Point4D r2 = rotationMatrix*r1; - *this *= rotationMatrix; - - // After rotation we translate XYZ by vector -r2 and recalculate position - *this *= Matrix4x4::Translation(-r2); - _position = s + r2; - - if(_attachedObjects.empty()) - return; - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(s, r); + Object::rotateRelativePoint(s, r); + *this *= Matrix4x4::Rotation(r); } void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { - // Translate XYZ by vector r1 - Point4D r1 = _position - s; - *this *= Matrix4x4::Translation(r1); - - // In translated coordinate system we rotate body and position - Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, r); - Point4D r2 = rotationMatrix*r1; - *this *= rotationMatrix; - - // After rotation we translate XYZ by vector -r2 and recalculate position - *this *= Matrix4x4::Translation(-r2); - _position = s + r2; - - for(auto attached : _attachedObjects) - attached->rotateRelativePoint(s, v, r); -} - - -void Mesh::translateToPoint(const Point4D &point) { - translate(point - _position); + Object::rotateRelativePoint(s, v, r); + *this *= Matrix4x4::Rotation(v, r); } void Mesh::setColor(sf::Color c) { diff --git a/engine/Mesh.h b/engine/Mesh.h index 4b1ab2f..e284cdb 100755 --- a/engine/Mesh.h +++ b/engine/Mesh.h @@ -11,7 +11,7 @@ #include #include "Object.h" -class Mesh : public Object, public Animatable { +class Mesh : public Object { private: std::vector _tris; sf::Color _color = sf::Color(255, 245, 194); @@ -29,12 +29,10 @@ public: Mesh& loadObj(const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); [[nodiscard]] std::vectorconst &triangles() const { return _tris; } - [[nodiscard]] std::vector& triangles() override { return _tris; } - void setTriangles(const std::vector& t) override { _tris = t; } + [[nodiscard]] std::vector& triangles() { return _tris; } + void setTriangles(const std::vector& t) { _tris = t; } // Translate body - void translate(const Point4D& t) override; - void translateToPoint(const Point4D& point); // Rotate body around XYZ axes void rotate(const Point4D& r) override; // Rotate body around normalised vector 'v' by 'r' radians @@ -43,15 +41,10 @@ public: void rotateRelativePoint(const Point4D& point4D, const Point4D& r) override; // Rotate body around normalised vector 'v' by 'r' radians relative val 'point4D' void rotateRelativePoint(const Point4D& point4D, const Point4D& v, double r) override; - void scale(const Point4D& s); + void scale(const Point4D& s) override; - void rotateToAngle(const Point4D& v) { rotate(v - _angle); } - - [[nodiscard]] Point4D position() const override { return _position; } - [[nodiscard]] Point4D angle() const override { return _angle; } - - [[nodiscard]] sf::Color color() const override { return _color; } - void setColor(sf::Color c) override; + [[nodiscard]] sf::Color color() const { return _color; } + void setColor(sf::Color c); Mesh static Obj(const std::string& filename); Mesh static LineTo(const Point4D& from, const Point4D& to, double line_width = 0.1, sf::Color color = {150, 150, 150, 255}); diff --git a/engine/Mouse.cpp b/engine/Mouse.cpp index dbf1fb6..231102e 100644 --- a/engine/Mouse.cpp +++ b/engine/Mouse.cpp @@ -14,9 +14,9 @@ Point4D Mouse::getMouseDisplacement() const { sf::Vector2 mousePos = sf::Mouse::getPosition(*_window); sf::Vector2 center = sf::Vector2(_window->getSize().x/2, _window->getSize().y/2); - sf::Vector2 disp = mousePos - center; + sf::Vector2 displacement = mousePos - center; //setMouseInCenter(); - return Point4D(disp.x, disp.y, 0, 0); + return Point4D(displacement.x, displacement.y, 0, 0); } void Mouse::setMouseInCenter() const { diff --git a/engine/Object.cpp b/engine/Object.cpp new file mode 100755 index 0000000..ef56b3e --- /dev/null +++ b/engine/Object.cpp @@ -0,0 +1,128 @@ +// +// Created by Иван Ильин on 15.03.2021. +// + +#include "Object.h" +#include "utils/Matrix4x4.h" +#include "utils/Log.h" + +void Object::translate(const Point4D &dv) { + _position = _position + dv; + + for(auto attached : _attachedObjects) + attached.second->translate(dv); +} + +void Object::scale(const Point4D &s) { + for(auto attached : _attachedObjects) + attached.second->scale(s); +} + +void Object::rotate(const Point4D &r) { + _angle = _angle + r; + + Matrix4x4 rotationMatrix = Matrix4x4::RotationZ(r.z())*Matrix4x4::RotationY(r.y())*Matrix4x4::RotationX(r.z()); + + _left = rotationMatrix * _left; + _up = rotationMatrix * _up; + _lookAt = rotationMatrix * _lookAt; + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(position(), r); +} + +void Object::rotate(const Point4D &v, double rv) { + Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, rv); + _left = rotationMatrix * _left; + _up = rotationMatrix * _up; + _lookAt = rotationMatrix * _lookAt; + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(position(), v, rv); +} + +void Object::rotateRelativePoint(const Point4D &s, const Point4D &r) { + _angle = _angle + r; + + // Translate XYZ by vector r1 + Point4D r1 = _position - s; + + // In translated coordinate system we rotate body and position + Matrix4x4 rotationMatrix = Matrix4x4::Rotation(r); + Point4D r2 = rotationMatrix*r1; + + _left = rotationMatrix * _left; + _up = rotationMatrix * _up; + _lookAt = rotationMatrix * _lookAt; + + // After rotation we translate XYZ by vector -r2 and recalculate position + _position = s + r2; + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(s, r); +} + +void Object::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { + // Translate XYZ by vector r1 + Point4D r1 = _position - s; + // In translated coordinate system we rotate body and position + Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, r); + Point4D r2 = rotationMatrix*r1; + + _left = rotationMatrix * _left; + _up = rotationMatrix * _up; + _lookAt = rotationMatrix * _lookAt; + + // After rotation we translate XYZ by vector -r2 and recalculate position + _position = s + r2; + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(s, v, r); +} + +void Object::rotateLeft(double rl) { + _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x() + rl, _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z()}; + + rotate(_left, rl); + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(position(), _left, rl); +} + +void Object::rotateUp(double ru) { + _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y() + ru, _angleLeftUpLookAt.z()}; + rotate(_up, ru); + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(position(), _up, ru); +} + +void Object::rotateLookAt(double rlAt) { + _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z() + rlAt}; + rotate(_lookAt, rlAt); + + for(auto attached : _attachedObjects) + attached.second->rotateRelativePoint(position(), _lookAt, rlAt); +} + +void Object::translateToPoint(const Point4D &point) { + translate(point - _position); +} + +void Object::rotateToAngle(const Point4D &v) { + rotate(v - _angle); +} + +std::shared_ptr Object::attached(const std::string &name) { + if(_attachedObjects.count(name) == 0) + Log::log("Object::attached: object '" + name + "' does not exist."); + return _attachedObjects.find(name)->second; +} + +void Object::attach(std::shared_ptr object, const std::string &name) { + _attachedObjects.emplace(name, object); +} + +void Object::unattach(const std::string &name) { + _attachedObjects.erase(name); +} diff --git a/engine/Object.h b/engine/Object.h index 04350da..49c8aa7 100755 --- a/engine/Object.h +++ b/engine/Object.h @@ -5,32 +5,49 @@ #ifndef ENGINE_OBJECT_H #define ENGINE_OBJECT_H -#include +#include #include "utils/Point4D.h" #include +#include "animation/Animatable.h" -class Object { +class Object : public Animatable { protected: - std::vector> _attachedObjects; + Point4D _left = Point4D{1, 0, 0, 0}; // internal X + Point4D _up = Point4D{0, 1, 0, 0}; // internal Y + Point4D _lookAt = Point4D{0, 0, 1, 0}; // internal Z + + std::map> _attachedObjects; Point4D _position; Point4D _angle; + Point4D _angleLeftUpLookAt; public: Object() = default; - virtual void translate(const Point4D& dv) {} - virtual void rotate(const Point4D& r) {} - virtual void rotateRelativePoint(const Point4D& point4D, const Point4D& r) {} - virtual void rotate(const Point4D& v, double rv) {} - virtual void rotateRelativePoint(const Point4D& s, const Point4D& v, double r) {} + virtual void translate(const Point4D& dv); + virtual void translateToPoint(const Point4D& point); + virtual void scale(const Point4D& s); + virtual void rotate(const Point4D& r); + virtual void rotate(const Point4D& v, double rv); + virtual void rotateToAngle(const Point4D& v); + virtual void rotateRelativePoint(const Point4D& s, const Point4D& r); + virtual void rotateRelativePoint(const Point4D& s, const Point4D& v, double r); [[nodiscard]] Point4D position() const { return _position; } [[nodiscard]] Point4D angle() const { return _angle; } + [[nodiscard]] Point4D angleLeftUpLookAt() const { return _angleLeftUpLookAt; } - void attach(std::shared_ptr object) { - _attachedObjects.push_back(object); - } + [[nodiscard]] Point4D left() const { return _left; } + [[nodiscard]] Point4D up() const { return _up; } + [[nodiscard]] Point4D lookAt() const { return _lookAt; } + + void rotateLeft(double rl); + void rotateUp(double ru); + void rotateLookAt(double rlAt); + + void attach(std::shared_ptr object, const std::string& name); + void unattach(const std::string& name); + std::shared_ptr attached(const std::string& name); }; - #endif //MINECRAFT_3DZAVR_OBJECT_H diff --git a/engine/World.cpp b/engine/World.cpp index f5a5f33..3a2eef0 100755 --- a/engine/World.cpp +++ b/engine/World.cpp @@ -95,7 +95,7 @@ void World::checkCollision(const std::string& body) { void World::update() { for (auto &m : _objects) { - m.second->a_update(); + m.second->update_animations(); m.second->updatePhysicsState(); checkCollision(m.first); } diff --git a/engine/animation/AColor.h b/engine/animation/AColor.h index 6465840..53353ca 100755 --- a/engine/animation/AColor.h +++ b/engine/animation/AColor.h @@ -7,14 +7,18 @@ #include "Animatable.h" #include "Animation.h" +#include "Mesh.h" class AColor : public Animation { private: + std::shared_ptr _mesh; + sf::Color newColor; sf::Color startColor; public: - AColor(const sf::Color &color, double duration, LoopOut looped, InterpolationType interpolationType) { + AColor(std::shared_ptr mesh, const sf::Color &color, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::linear) { + _mesh = mesh; _duration = duration; _looped = looped; _intType = interpolationType; @@ -23,15 +27,15 @@ public: newColor = color; } - bool update(Animatable& obj) override { + bool update() override { if(!_started) - startColor = obj.color(); + startColor = _mesh->color(); Point4D start(startColor.r, startColor.g, startColor.b, startColor.a); Point4D end(newColor.r, newColor.g, newColor.b, newColor.a); Point4D mid = start + (end - start)*_p; - obj.setColor(sf::Color(static_cast(mid.x()), static_cast(mid.y()), static_cast(mid.z()), static_cast(mid.w()))); + _mesh->setColor(sf::Color(static_cast(mid.x()), static_cast(mid.y()), static_cast(mid.z()), static_cast(mid.w()))); return updateState(); } diff --git a/engine/animation/AFunction.h b/engine/animation/AFunction.h index e81ffd3..f901450 100755 --- a/engine/animation/AFunction.h +++ b/engine/animation/AFunction.h @@ -16,7 +16,7 @@ private: std::function _callBack; public: - AFunction(std::function function, int calls, double duration, LoopOut looped, InterpolationType interpolationType) { + explicit AFunction(std::function function, int calls = 1, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::linear) { _callBack = std::move(function); _allCalls = calls; _duration = duration; @@ -24,7 +24,7 @@ public: _intType = interpolationType; } - bool update(Animatable& obj) override { + bool update() override { if(_allCalls != 0 && _p >= (double)(_calls+1) / (_allCalls+1)) { _calls++; _callBack(); diff --git a/engine/animation/ARotate.h b/engine/animation/ARotate.h index d346330..d5aacff 100755 --- a/engine/animation/ARotate.h +++ b/engine/animation/ARotate.h @@ -7,12 +7,16 @@ #include "Animatable.h" #include "Animation.h" +#include "Object.h" class ARotate : public Animation { private: + std::shared_ptr _object; + Point4D value; public: - ARotate(const Point4D& r, double duration, LoopOut looped, InterpolationType interpolationType) { + ARotate(std::shared_ptr object, const Point4D& r, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + _object = object; _duration = duration; _looped = looped; _intType = interpolationType; @@ -20,8 +24,8 @@ public: value = r; } - bool update(Animatable& obj) override { - obj.rotate(value * _dp); + bool update() override { + _object->rotate(value * _dp); return updateState(); } }; diff --git a/engine/animation/AScale.h b/engine/animation/AScale.h index b57ba31..37f11ec 100755 --- a/engine/animation/AScale.h +++ b/engine/animation/AScale.h @@ -7,14 +7,17 @@ #include "Animatable.h" #include "Animation.h" +#include "Mesh.h" class AScale : public Animation { private: - Point4D value; + std::shared_ptr _mesh; - std::vector triangles; + Point4D value; + std::vector triangles{}; public: - AScale(const Point4D &s, double duration, LoopOut looped, InterpolationType interpolationType) { + AScale(std::shared_ptr mesh, const Point4D &s, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + _mesh = mesh; _duration = duration; _looped = looped; _intType = interpolationType; @@ -23,15 +26,15 @@ public: value = s; } - bool update(Animatable& obj) override { + bool update() override { if(!_started) - triangles = obj.triangles(); + triangles = _mesh->triangles(); std::vector newTriangles; for(auto &t : triangles) { newTriangles.emplace_back(t * Matrix4x4::Scale(Point4D{1, 1, 1} + (value - Point4D{1, 1, 1}) * _p)); } - obj.setTriangles(newTriangles); + _mesh->setTriangles(newTriangles); return updateState(); } }; diff --git a/engine/animation/ATranslate.h b/engine/animation/ATranslate.h index 4b469c3..92af632 100755 --- a/engine/animation/ATranslate.h +++ b/engine/animation/ATranslate.h @@ -7,12 +7,16 @@ #include "Animatable.h" #include "Animation.h" +#include "Object.h" class ATranslate : public Animation { private: + std::shared_ptr _object; + Point4D value; public: - ATranslate(const Point4D& t, double duration, LoopOut looped, InterpolationType interpolationType) { + ATranslate(std::shared_ptr object, const Point4D& t, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + _object = object; _duration = duration; _looped = looped; _intType = interpolationType; @@ -20,14 +24,10 @@ public: value = t; } - bool update(Animatable& obj) override { - obj.translate(value * _dp); + bool update() override { + _object->translate(value * _dp); return updateState(); } - - [[nodiscard]] int type() const override { - return 2; - } }; #endif //INC_3DZAVR_ATRANSLATE_H diff --git a/engine/animation/ATranslateToPoint.h b/engine/animation/ATranslateToPoint.h index 223dafc..85ba5bb 100755 --- a/engine/animation/ATranslateToPoint.h +++ b/engine/animation/ATranslateToPoint.h @@ -7,13 +7,17 @@ #include "Animatable.h" #include "Animation.h" +#include "Object.h" class ATranslateToPoint : public Animation { private: + std::shared_ptr _object; + Point4D point; Point4D value; public: - ATranslateToPoint(const Point4D& p, double duration, LoopOut looped, InterpolationType interpolationType) { + ATranslateToPoint(std::shared_ptr object, const Point4D& p, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + _object = object; _duration = duration; _looped = looped; _intType = interpolationType; @@ -21,11 +25,11 @@ public: point = p; } - bool update(Animatable& obj) override { + bool update() override { if(!_started) { - value = point - obj.position(); + value = point - _object->position(); } - obj.translate(value * _dp); + _object->translate(value * _dp); return updateState(); } diff --git a/engine/animation/AWait.h b/engine/animation/AWait.h index eab8b17..6366477 100755 --- a/engine/animation/AWait.h +++ b/engine/animation/AWait.h @@ -9,22 +9,16 @@ #include "Animation.h" class AWait : public Animation { -private: - Point4D value; public: - explicit AWait(double duration) { + explicit AWait(double duration = 1) { _duration = duration; _intType = linear; _waitFor = true; } - bool update(Animatable& obj) override { + bool update() override { return updateState(); } - - [[nodiscard]] int type() const override { - return 1; - } }; #endif //INC_3DZAVR_AWAIT_H diff --git a/engine/animation/Animatable.cpp b/engine/animation/Animatable.cpp index 65fa8f1..98a3a5d 100755 --- a/engine/animation/Animatable.cpp +++ b/engine/animation/Animatable.cpp @@ -14,6 +14,7 @@ #include "AFunction.h" #include "AColor.h" +/* void Animatable::a_translate(const std::string& listName, const Point4D &t, double duration, @@ -30,7 +31,7 @@ void Animatable::a_translateToPoint(const std::string& listName, animations[listName].emplace_back(new ATranslateToPoint(point, duration, looped, interpolationType)); } -void Animatable::a_rotate(const std::string& listName, +void Animatable::a_rotate(c const Point4D &r, double duration, Animation::LoopOut looped, @@ -63,8 +64,9 @@ void Animatable::a_function(const std::string &listName, Animation::InterpolationType interpolationType) { animations[listName].emplace_back(new AFunction(std::move(function), calls, duration, looped, interpolationType)); } +*/ -void Animatable::a_update() { +void Animatable::update_animations() { for (auto& [listName, animationList] : animations) { @@ -74,18 +76,21 @@ void Animatable::a_update() { // If it the front animation is 'a_wait()' we should wait until waiting time is over if (it.operator*()->waitFor()) { - if (!it.operator*()->update(*this)) + if (!it.operator*()->update()) animationList.erase(it); continue; } - // Otherwise we iterate over all animation until we meet animations.end() or wait animation while (!animationList.empty() && (it != animationList.end()) && (!it.operator*()->waitFor())) { - if (!it.operator*()->update(*this)) + if (!it.operator*()->update()) animationList.erase(it++); else it++; } } } + +void Animatable::animate(const std::string &listName, Animation* anim) { + animations[listName].emplace_back(anim); +} diff --git a/engine/animation/Animatable.h b/engine/animation/Animatable.h index 87574f8..1a0bebd 100755 --- a/engine/animation/Animatable.h +++ b/engine/animation/Animatable.h @@ -8,7 +8,6 @@ #include #include "../Triangle.h" -//class Animation; #include "Animation.h" #include #include @@ -21,50 +20,13 @@ protected: public: Animatable() = default; virtual ~Animatable() = default; - // All methods about animation begins with 'a_' - void a_translate(const std::string& listName, - const Point4D& t, - double duration = 1, - Animation::LoopOut looped = Animation::None, - Animation::InterpolationType interpolationType = Animation::bezier); - void a_translateToPoint(const std::string& listName, - const Point4D& point, - double duration = 1, - Animation::LoopOut looped = Animation::None, - Animation::InterpolationType interpolationType = Animation::bezier); - void a_rotate(const std::string& listName, - const Point4D& r, - double duration = 1, - Animation::LoopOut looped = Animation::None, - Animation::InterpolationType interpolationType = Animation::bezier); + void animate(const std::string& listName, Animation* anim); - void a_scale(const std::string& listName, - const Point4D& s, - double duration = 1, - Animation::LoopOut looped = Animation::None, - Animation::InterpolationType interpolationType = Animation::bezier); + void update_animations(); - void a_wait(const std::string& listName, double duration = 1); - - void a_function(const std::string& listName, - std::function function, - int calls = 1, - double duration = 1, - Animation::LoopOut looped = Animation::None, - Animation::InterpolationType interpolationType = Animation::bezier); - - void a_color(const std::string& listName, - const sf::Color& color, - double duration = 1, - Animation::LoopOut looped = Animation::None, - Animation::InterpolationType interpolationType = Animation::bezier); - - - void a_update(); - - void a_stopAllAnimations() { animations.clear(); } - void a_stopAnimationList(const std::string& name) { animations[name].clear(); } + void stopAllAnimations() { animations.clear(); } + void stopAnimationList(const std::string& name) { animations[name].clear(); } [[nodiscard]] bool isInAnim() const { for(auto& animList : animations) @@ -74,19 +36,6 @@ public: } [[nodiscard]] bool isInAnimList(const std::string& name) { return !animations[name].empty(); } - - // methods to override: - // If you want to create new animation you can either add new virtual function here - // or override one of the following function: - [[nodiscard]] virtual Point4D position() const { return Point4D{}; } - [[nodiscard]] virtual Point4D angle() const { return Point4D{}; } - virtual void translate(const Point4D& dv) {} - virtual void rotate(const Point4D& r) {} - [[nodiscard]] virtual std::vector& triangles() { return *(std::vector*)(new std::vector()); } - virtual void setTriangles(const std::vector& tris) {} - - [[nodiscard]] virtual sf::Color color() const {return sf::Color(); } - virtual void setColor(sf::Color c) { } }; #endif //INC_3DZAVR_ANIMATABLE_H diff --git a/engine/animation/Animation.h b/engine/animation/Animation.h index d22f0dc..ac92052 100755 --- a/engine/animation/Animation.h +++ b/engine/animation/Animation.h @@ -54,9 +54,7 @@ public: // You should override this method for your particular animation - virtual bool update(Animatable& obj) = 0; - - [[nodiscard]] virtual int type() const{return 0;} + virtual bool update() = 0; }; #endif //INC_3DZAVR_ANIMATION_H diff --git a/main.cpp b/main.cpp index aabbc88..d24629f 100755 --- a/main.cpp +++ b/main.cpp @@ -2,193 +2,10 @@ // Created by Иван Ильин on 06.02.2021. // -#include "Engine.h" -#include -#include "Player.h" -#include "ResourceManager.h" -#include "gui/Window.h" -#include "PlayerController.h" - -#include "Client.h" -#include "Server.h" -#include +#include "Shooter.h" using namespace std; -// Read server/client settings and start both. -// If client doesn't connect to the localhost - server doesn't start. -void InitNetwork(shared_ptr server, shared_ptr client) -{ - std::string clientIp; - sf::Uint16 clientPort; - sf::Uint16 serverPort; - std::ifstream connectfile("connect.txt", std::ifstream::in); - - // If failed to read client settings - if (!connectfile.is_open() || !(connectfile >> clientIp >> clientPort) || sf::IpAddress(clientIp) == sf::IpAddress::None) - { - connectfile.close(); - // Create file and write default settings - clientIp = "127.0.0.1"; - clientPort = 54000; - std::ofstream temp("connect.txt", std::ofstream::out); - temp << clientIp << std::endl << clientPort; - temp.close(); - } - connectfile.close(); - - // If failed to read server settings - connectfile.open("server.txt", std::ifstream::in); - if (!connectfile.is_open() || !(connectfile >> serverPort)) - { - connectfile.close(); - // Create file and write default settings - serverPort = 54000; - std::ofstream temp("server.txt", std::ofstream::out); - temp << serverPort; - temp.close(); - } - connectfile.close(); - - if (clientIp == sf::IpAddress::LocalHost) { - server->start(serverPort); - if(server->isWorking()) - server->generateBonuses(); - } - - client->connect(clientIp, clientPort); -} - -class Shooter : public Engine { -private: - shared_ptr player; - shared_ptr playerController; - - sf::Sound backgroundNoise; - - Window mainMenu; - - shared_ptr server; - shared_ptr client; - - bool inGame = false; - -public: - Shooter() : mainMenu(screen, mouse) {}; - - void start() override; - void update() override; - - void gui() override; - - void play(); -}; - -void Shooter::start() { - // This code executed once in the beginning: - setDebugText(false); - - mouse->setMouseCursorVisible(true); - - world->loadMap("../maps/map1.obj", "map", Point4D{5, 5, 5}); - - player = std::make_shared(); - playerController = std::make_shared(player, world, keyboard, mouse); - - client = std::make_shared(player, world); - server = std::make_shared(); - - player->setAddTraceCallBack([this](const Point4D& from, const Point4D& to){ client->addTrace(from, to); }); - player->attachCamera(camera, screen); - player->attachWorld(world); - - setUpdateWorld(false); - - world->addBody(player, player->name()); - - player->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); }); - player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); }); - - - // windows init: - mainMenu.title("Main menu"); - mainMenu.setBackgroundTexture("../textures/back.png", 1.1, 1.1, screen->width(), screen->height()); - - mainMenu.addButton(screen->width()/2, 200, 200, 20, [this] () { this->play(); }, "Play", 5, 5, "../textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "../engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "../sound/click.ogg"); - mainMenu.addButton(screen->width()/2, 350, 200, 20, [this] () { this->player->translateToPoint(Point4D{0, 0, 0}); this->player->setVelocity({}); this->play(); }, "Respawn", 5, 5, "../textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "../engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "../sound/click.ogg"); - - mainMenu.addButton(screen->width()/2, 500, 200, 20, [this] () { client->disconnect(); server->stop(); this->exit();}, "Exit", 5, 5, "../textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "../engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "../sound/click.ogg"); - - // connecting to the server - InitNetwork(server, client); - // Waiting for connect and updating server if it's same window - while (client->isWorking() && !client->connected()) - { - client->update(); - server->update(); - Time::update(); - } - // If connect fail - return to menu - if (!client->isWorking()) - { - inGame = false; - server->stop(); - } -} - -void Shooter::update() { - // This code executed every time step: - - server->update(); - client->update(); - - // Check all input after this condition please - if (!screen->hasFocus()) - return; - - if(keyboard->isKeyTapped(sf::Keyboard::Escape)) { - inGame = !inGame; - mouse->setMouseCursorVisible(!inGame); - } - - if(inGame) { - screen->setTitle("Shooter"); - player->update(); - playerController->update(); - mouse->setMouseInCenter(); - } else { - mainMenu.update(); - } - - setUpdateWorld(inGame); - - // background sounds and music control - if(backgroundNoise.getStatus() != sf::Sound::Status::Playing) { - backgroundNoise.setBuffer(*ResourceManager::loadSoundBuffer("../sound/backNoise.ogg")); - backgroundNoise.play(); - } -} - -void Shooter::gui() { - - sf::Sprite sprite; - sprite.setTexture(*ResourceManager::loadTexture("../textures/gui.png")); - sprite.setTextureRect(sf::IntRect(243, 3, 9, 9)); - sprite.scale(3, 3); - sprite.setPosition(screen->width() / 2.0 - 27.0/2.0, screen->height() / 2 - 27.0/2.0); - sprite.setColor(sf::Color(0,0,0, 200)); - screen->drawSprite(sprite); - - // health player stats - player->drawStats(); -} - -void Shooter::play() { - inGame = true; - - mouse->setMouseCursorVisible(!inGame); -} - int main() { Shooter game; diff --git a/weapon/Shotgun.cpp b/weapon/Shotgun.cpp index 25617a1..af02c4e 100755 --- a/weapon/Shotgun.cpp +++ b/weapon/Shotgun.cpp @@ -4,6 +4,8 @@ #include #include "Shotgun.h" +#include "animation/AColor.h" +#include "animation/AFunction.h" using namespace std; @@ -23,7 +25,7 @@ Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, " } std::map -Shotgun::processFire(std::shared_ptr world, std::shared_ptr camera) { +Shotgun::processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& pos, const Point4D& direction) { std::map damagedPlayers; for(int i = 0; i < 15; i++) { @@ -31,24 +33,14 @@ Shotgun::processFire(std::shared_ptr world, std::shared_ptr camer Point4D randV(10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX)); // damage player - auto rayCast = world->rayCast(camera->position(), camera->position() + camera->lookAt() * 1000 + randV); + auto rayCast = rayCastFunction(pos, pos + direction * 1000 + randV); if (rayCast.second.find("Player") != std::string::npos) { - damagedPlayers[rayCast.second] += _damage / (1.0 + (camera->position() - rayCast.first).abs()); + damagedPlayers[rayCast.second] += _damage / (1.0 + (pos - rayCast.first).abs()); } - // add trace line - Point4D to = rayCast.first.w() == -1 ? camera->position() + camera->lookAt() * 1000 + randV: rayCast.first; - string traceName = _name + "_trace_nr_" + std::to_string(fireTraces++); - Point4D from = _objects[_name + "_" + to_string(9)]->position() + - _objects[_name + "_" + to_string(9)]->triangles()[0][0]; - world->addBody(make_shared(Mesh::LineTo(from, to, 0.05)), traceName); - world->body(traceName)->setCollider(false); - - // remove trace line after some time - world->body(traceName)->a_color("color_trace", {255, 255, 255, 0}, 1, Animation::None, Animation::linear); - world->body("map_0")->a_function(traceName + "delete", [world, traceName]() { deleteTrace(world, traceName); }, - 1, 2); - addTraceCallBack(from, to); + Point4D to = rayCast.first.w() == -1 ? pos + direction * 1000 + randV: rayCast.first; + Point4D from = position() + triangles().back()[0]; + _addTraceCallBack(from, to); } diff --git a/weapon/Shotgun.h b/weapon/Shotgun.h index f3aaba9..ffeda22 100755 --- a/weapon/Shotgun.h +++ b/weapon/Shotgun.h @@ -10,7 +10,7 @@ class Shotgun : public Weapon { public: explicit Shotgun(int ammo = 15, const std::string& weaponName = "shotgun"); - std::map processFire(std::shared_ptr world, std::shared_ptr camera) override; + std::map processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction) override; }; diff --git a/weapon/Weapon.cpp b/weapon/Weapon.cpp index 478724a..da6887a 100755 --- a/weapon/Weapon.cpp +++ b/weapon/Weapon.cpp @@ -3,15 +3,21 @@ // #include +#include #include "Weapon.h" #include "ResourceManager.h" #include "utils/Log.h" +#include "animation/AColor.h" +#include "animation/AFunction.h" using namespace std; -Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Point4D& scale, const Point4D& translate, const Point4D& rotate) { +Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Point4D& scale, const Point4D& t, const Point4D& r) { _name = weaponName; + + /* auto objs = Mesh::LoadObjects(objFileName, matFileName, scale); + for(int i = 0; i < objs.size(); i++) { string meshName = _name + "_" + to_string(i); @@ -25,10 +31,16 @@ Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, co _objects.insert({meshName, std::make_shared(obj)}); } + */ + loadObj(objFileName, matFileName, scale); + setCollider(false); + rotate(r); + translate(t); + noAmmoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/no_ammo.ogg")); } -std::map Weapon::fire(std::shared_ptr world, std::shared_ptr camera) { +std::map Weapon::fire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction) { if(_clipAmmo == 0) { reload(); if(_clipAmmo == 0) @@ -44,7 +56,7 @@ std::map Weapon::fire(std::shared_ptr world, std::sh fireSound.play(); Log::log("Weapon::fire (" + std::to_string(_stockAmmo) + " : " + std::to_string(_clipAmmo) + ")"); - return processFire(world, camera); + return processFire(std::move(rayCastFunction), position, direction); } void Weapon::reload() { @@ -63,68 +75,22 @@ void Weapon::reload() { _lastReloadTime = Time::time(); } -void Weapon::addToWorld(shared_ptr world) { - for(auto& obj : _objects) { - world->addBody(obj.second, obj.first); - } -} - -void Weapon::removeFromWorld(shared_ptr world) { - for(auto& obj : _objects) { - world->removeBodyInstantly(obj.first); - } -} - - -void Weapon::attachToPlayer(Mesh &player) { - for(auto& obj : _objects) { - player.attach(obj.second); - } -} - -void Weapon::rotate(const Point4D& point4D, double val) { - for(auto& mesh : _objects) - mesh.second->rotate(point4D, val); -} - -void Weapon::translate(const Point4D &point4D) { - for(auto& mesh : _objects) - mesh.second->translate(point4D); -} - -void Weapon::deleteTrace(shared_ptr world, const std::string& traceName) { - world->removeBody(traceName); -} - -void Weapon::rotateRelativePoint(const Point4D &point4D, const Point4D &v, double val) { - for(auto& mesh : _objects) - mesh.second->rotateRelativePoint(point4D, v, val); -} - -std::map Weapon::processFire(shared_ptr world, shared_ptr camera) { +std::map Weapon::processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& pos, const Point4D& direction) { std::map damagedPlayers; //generate random vector Point4D randV(10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX)); // damage player - auto rayCast = world->rayCast(camera->position(), camera->position() + camera->lookAt() * 1000 + randV); + auto rayCast = rayCastFunction(pos, pos + direction * 1000 + randV); if(rayCast.second.find("Player") != std::string::npos) { - damagedPlayers[rayCast.second] += _damage/(1.0 + (camera->position() - rayCast.first).abs()); + damagedPlayers[rayCast.second] += _damage/(1.0 + (pos - rayCast.first).abs()); } // add trace line - Point4D to = rayCast.first.w() == -1 ? camera->position() + camera->lookAt() * 1000 + randV: rayCast.first; - string traceName = _name + "_trace_nr_" + std::to_string(fireTraces++); - Point4D from = _objects[_name + "_" + to_string(_objects.size()-1)]->position() + _objects[_name + "_" + to_string(_objects.size()-1)]->triangles()[0][0]; - world->addBody(make_shared(Mesh::LineTo(from, to, 0.05)), traceName); - world->body(traceName)->setCollider(false); - - // remove trace line after some time - world->body(traceName)->a_color("color_trace", {255, 255, 255, 0}, 1, Animation::None, Animation::linear); - world->body("Player_im")->a_function(traceName + "delete", [world, traceName](){deleteTrace(world, traceName); }, 1, 2); - - addTraceCallBack(from, to); + Point4D to = rayCast.first.w() == -1 ? pos + direction * 1000 + randV: rayCast.first; + Point4D from = position() + triangles().back()[0]; + _addTraceCallBack(from, to); return damagedPlayers; } diff --git a/weapon/Weapon.h b/weapon/Weapon.h index 0e33506..e4efd2b 100755 --- a/weapon/Weapon.h +++ b/weapon/Weapon.h @@ -13,7 +13,7 @@ #include "Mesh.h" #include "utils/Time.h" -class Weapon { +class Weapon : public RigidBody { protected: int _initialPack = 100; // how much ammo do you have when you find the weapon @@ -28,7 +28,6 @@ protected: double _spreading = 2.0; std::string _name = "Weapon_name"; - std::map> _objects; double _lastFireTime = -INFINITY; double _lastReloadTime = -INFINITY; @@ -37,40 +36,28 @@ protected: sf::Sound reloadSound; sf::Sound noAmmoSound; - static void deleteTrace(std::shared_ptr world, const std::string& traceName); - int fireTraces = 0; - std::function addTraceCallBack; + std::function _addTraceCallBack; + + virtual std::map processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction); public: Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Point4D& scale, const Point4D& translate, const Point4D& rotate); - std::map fire(std::shared_ptr world, std::shared_ptr camera); + std::map fire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction); void reload(); - void addToWorld(std::shared_ptr world); - void removeFromWorld(std::shared_ptr world); - - void attachToPlayer(Mesh& player); - [[nodiscard]] std::pair balance() const{ return std::make_pair(_clipAmmo, _stockAmmo); } - void rotateRelativePoint(const Point4D& point4D, const Point4D& v, double val); - - void rotate(const Point4D& point4D, double val); - void translate(const Point4D& point4D); - void setAddTraceCallBack(std::function add) { - addTraceCallBack = std::move(add); + _addTraceCallBack = std::move(add); } [[nodiscard]] std::string name() const { return _name; } void addAmmo(int ammoAdd) { _stockAmmo += ammoAdd; } - virtual std::map processFire(std::shared_ptr world, std::shared_ptr camera); - [[nodiscard]] int initialPack() const {return _initialPack; } };