super huge code refactoring

master
Vectozavr 2021-10-03 00:36:07 +07:00
parent b0a457ce47
commit 8a0221ed77
35 changed files with 774 additions and 846 deletions

View File

@ -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);
}

View File

@ -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)

View File

@ -3,39 +3,20 @@
//
#include "Client.h"
#include <utility>
#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<Player>() });
(*_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<RigidBody>(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<Bonus>(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<Bonus>(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> 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> player) {
_players.insert({ id, player });
}
void Client::setSpawnPlayerCallBack(std::function<void(sf::Uint16)> spawn) {
_spawnPlayerCallBack = std::move(spawn);
}
void Client::setRemovePlayerCallBack(std::function<void(sf::Uint16)> remove) {
_removePlayerCallBack = std::move(remove);
}
void Client::setAddFireTraceCallBack(std::function<void(const Point4D &, const Point4D &)> addTrace) {
_addFireTraceCallBack = std::move(addTrace);
}
void Client::setAddBonusCallBack(std::function<void(const std::string &, const Point4D &)> addBonus) {
_addBonusCallBack = std::move(addBonus);
}
void Client::setRemoveBonusCallBack(std::function<void(const std::string &)> removeBonus) {
_removeBonusCallBack = std::move(removeBonus);
}

View File

@ -12,19 +12,27 @@
class Client : public ClientUDP {
private:
std::shared_ptr<Player> _player;
std::shared_ptr<World> _world;
std::map<sf::Uint16, std::shared_ptr<Player>> _players{};
int fireTraces = 0;
std::shared_ptr<Player> _player;
void spawnPlayer(sf::Uint16 id);
std::function<void(sf::Uint16)> _spawnPlayerCallBack;
std::function<void(sf::Uint16)> _removePlayerCallBack;
std::function<void(const Point4D&, const Point4D&)> _addFireTraceCallBack;
std::function<void(const std::string&, const Point4D&)> _addBonusCallBack;
std::function<void(const std::string&)> _removeBonusCallBack;
public:
Client(std::shared_ptr<Player> player, std::shared_ptr<World> world) : _player(player), _world(world) {};
Client(std::shared_ptr<Player> player) : _player(player){};
void updatePacket() override;
void setSpawnPlayerCallBack(std::function<void(sf::Uint16)> spawn);
void setRemovePlayerCallBack(std::function<void(sf::Uint16)> remove);
void setAddFireTraceCallBack(std::function<void(const Point4D&, const Point4D&)> addTrace);
void setAddBonusCallBack(std::function<void(const std::string&, const Point4D&)> addBonus);
void setRemoveBonusCallBack(std::function<void(const std::string&)> 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> world, const std::string& traceName);
void addPlayer(sf::Uint16 id, std::shared_ptr<Player> player);
};

View File

@ -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<sf::Uint8>((_healthMax - _health)/_healthMax * 255), static_cast<sf::Uint8>(_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<double>(_screen->height() - 50 - 100)},100, sf::Color(0, 0, 0, 100));
_screen->drawText(std::to_string((int)balance.second),Point4D{50, static_cast<double>(_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_ptr<Rig
setFullAbility();
if(objName.find("Bonus") != std::string::npos) {
_world->removeBody(objName);
_takeBonusCallBack(objName);
}
}
@ -89,45 +52,44 @@ void Player::collisionWithObject(const std::string &objName, std::shared_ptr<Rig
void Player::addWeapon(std::shared_ptr<Weapon> 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);
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<Gun>());
_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);

View File

@ -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> _camera;
std::shared_ptr<Screen> _screen;
std::shared_ptr<World> _world;
// sounds
sf::Sound _killSound;
sf::Sound _deathSound;
@ -51,7 +46,12 @@ private:
std::function<void(sf::Uint16 targetId, double)> _damagePlayerCallBack;
std::function<void(const Point4D&, const Point4D&)> _addTraceCallBack;
std::function<void(const std::string&)> _takeBonusCallBack;
std::function<void(const std::string&)> _fireCallBack;
std::function<void(std::shared_ptr<Weapon>)> _addWeaponCallBack;
std::function<void(std::shared_ptr<Weapon>)> _removeWeaponCallBack;
std::function<std::pair<Point4D, std::string>(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<RigidBody> obj) {collisionWithObject(objName, obj);});
};
void update();
void attachCamera(std::shared_ptr<Camera> camera, std::shared_ptr<Screen> screen) {
_camera = camera;
_screen = screen;
_camera->translateToPoint(position() + Point4D{0, 1.8, 0});
this->attach(_camera);
}
void attachWorld(std::shared_ptr<World> 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> weapon);
[[nodiscard]] std::pair<double, double> balance() const{ return _weapons[_selectedWeapon]->balance();}
void setDamagePlayerCallBack(std::function<void(sf::Uint16 targetId, double)> hit) {
_damagePlayerCallBack = std::move(hit);
}
void setAddTraceCallBack(std::function<void(const Point4D&, const Point4D&)> add) {
_addTraceCallBack = std::move(add);
}
void setTakeBonusCallBack(std::function<void(const std::string&)> take) {
_takeBonusCallBack = std::move(take);
}
[[nodiscard]] double health() const { return _health; }
[[nodiscard]] std::string name() const { return "Player_" + _name; }
std::shared_ptr<Camera> 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<void(sf::Uint16 targetId, double)> hit) {
_damagePlayerCallBack = std::move(hit);
}
void setAddTraceCallBack(std::function<void(const Point4D&, const Point4D&)> add) {
_addTraceCallBack = std::move(add);
}
void setTakeBonusCallBack(std::function<void(const std::string&)> take) {
_takeBonusCallBack = std::move(take);
}
void setAddWeaponCallBack(std::function<void(std::shared_ptr<Weapon>)> addWeapon) {
_addWeaponCallBack = addWeapon;
}
void setRemoveWeaponCallBack(std::function<void(std::shared_ptr<Weapon>)> removeWeapon) {
_removeWeaponCallBack = std::move(removeWeapon);
}
void setRayCastFunction(std::function<std::pair<Point4D, std::string>(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<RigidBody> obj);
void addWeapon(std::shared_ptr<Weapon> weapon);
void initWeapons();
};

View File

@ -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> player,
std::shared_ptr<World> world,
std::shared_ptr<Keyboard> keyboard,
std::shared_ptr<Mouse> mouse) : _player(player), _world(world), _keyboard(keyboard), _mouse(mouse) {
std::shared_ptr<Mouse> 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<Object> 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) {
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();
}
}
}

View File

@ -12,8 +12,6 @@
class PlayerController {
private:
std::shared_ptr<Player> _player;
std::shared_ptr<World> _world;
std::shared_ptr<Keyboard> _keyboard;
std::shared_ptr<Mouse> _mouse;
@ -30,7 +28,7 @@ private:
double _jumpHeight = 3;
double _walkSpeed = 10;
public:
PlayerController(std::shared_ptr<Player> player, std::shared_ptr<World> world, std::shared_ptr<Keyboard> keyboard, std::shared_ptr<Mouse> mouse);
PlayerController(std::shared_ptr<Player> player, std::shared_ptr<Keyboard> keyboard, std::shared_ptr<Mouse> mouse);
void update();
};

269
Shooter.cpp Normal file
View File

@ -0,0 +1,269 @@
//
// Created by Иван Ильин on 22.09.2021.
//
#include "Shooter.h"
#include <fstream>
#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<Player>();
playerController = std::make_shared<PlayerController>(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> weapon){ addWeapon(weapon); });
player->setRemoveWeaponCallBack([this](std::shared_ptr<Weapon> 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<Client>(player);
server = std::make_shared<Server>();
// 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<sf::Uint8>((player->maxHealth() - player->health())/player->maxHealth() * 255), static_cast<sf::Uint8>(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<double>(screen->height() - 50 - 100)},100, sf::Color(0, 0, 0, 100));
screen->drawText(std::to_string((int)balance.second),Point4D{50, static_cast<double>(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<Player> newPlayer = std::make_shared<Player>();
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<RigidBody>(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<Bonus>(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> weapon) {
world->addBody(weapon, weapon->name());
}
void Shooter::removeWeapon(std::shared_ptr<Weapon> weapon) {
world->removeBodyInstantly(weapon->name());
}

57
Shooter.h Normal file
View File

@ -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> player;
std::shared_ptr<PlayerController> playerController;
sf::Sound backgroundNoise;
Window mainMenu;
std::shared_ptr<Server> server;
std::shared_ptr<Client> 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> weapon);
void removeWeapon(std::shared_ptr<Weapon> weapon);
public:
Shooter() : mainMenu(screen, mouse) {};
};
#endif //SHOOTER_SHOOTER_H

View File

@ -76,7 +76,6 @@ std::vector<Triangle> &Camera::project(std::shared_ptr<Mesh> 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);
}

View File

@ -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<Triangle> _triangles;
std::vector<Plane> _clipPlanes;
std::vector<Triangle> _triangles{};
std::vector<Plane> _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<Triangle>& 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;
};

View File

@ -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()) +

View File

@ -30,21 +30,20 @@ protected:
std::shared_ptr<World> world;
std::shared_ptr<Camera> 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(){}
};

View File

@ -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) {

View File

@ -11,7 +11,7 @@
#include <SFML/Graphics.hpp>
#include "Object.h"
class Mesh : public Object, public Animatable {
class Mesh : public Object {
private:
std::vector<Triangle> _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::vector<Triangle>const &triangles() const { return _tris; }
[[nodiscard]] std::vector<Triangle>& triangles() override { return _tris; }
void setTriangles(const std::vector<Triangle>& t) override { _tris = t; }
[[nodiscard]] std::vector<Triangle>& triangles() { return _tris; }
void setTriangles(const std::vector<Triangle>& 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});

View File

@ -14,9 +14,9 @@ Point4D Mouse::getMouseDisplacement() const {
sf::Vector2<int> mousePos = sf::Mouse::getPosition(*_window);
sf::Vector2<int> center = sf::Vector2<int>(_window->getSize().x/2, _window->getSize().y/2);
sf::Vector2<int> disp = mousePos - center;
sf::Vector2<int> displacement = mousePos - center;
//setMouseInCenter();
return Point4D(disp.x, disp.y, 0, 0);
return Point4D(displacement.x, displacement.y, 0, 0);
}
void Mouse::setMouseInCenter() const {

128
engine/Object.cpp Executable file
View File

@ -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> 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> object, const std::string &name) {
_attachedObjects.emplace(name, object);
}
void Object::unattach(const std::string &name) {
_attachedObjects.erase(name);
}

View File

@ -5,32 +5,49 @@
#ifndef ENGINE_OBJECT_H
#define ENGINE_OBJECT_H
#include <vector>
#include <map>
#include "utils/Point4D.h"
#include <memory>
#include "animation/Animatable.h"
class Object {
class Object : public Animatable {
protected:
std::vector<std::shared_ptr<Object>> _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<std::string, std::shared_ptr<Object>> _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> 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> object, const std::string& name);
void unattach(const std::string& name);
std::shared_ptr<Object> attached(const std::string& name);
};
#endif //MINECRAFT_3DZAVR_OBJECT_H

View File

@ -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);
}

View File

@ -7,14 +7,18 @@
#include "Animatable.h"
#include "Animation.h"
#include "Mesh.h"
class AColor : public Animation {
private:
std::shared_ptr<Mesh> _mesh;
sf::Color newColor;
sf::Color startColor;
public:
AColor(const sf::Color &color, double duration, LoopOut looped, InterpolationType interpolationType) {
AColor(std::shared_ptr<Mesh> 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<sf::Uint8>(mid.x()), static_cast<sf::Uint8>(mid.y()), static_cast<sf::Uint8>(mid.z()), static_cast<sf::Uint8>(mid.w())));
_mesh->setColor(sf::Color(static_cast<sf::Uint8>(mid.x()), static_cast<sf::Uint8>(mid.y()), static_cast<sf::Uint8>(mid.z()), static_cast<sf::Uint8>(mid.w())));
return updateState();
}

View File

@ -16,7 +16,7 @@ private:
std::function<void()> _callBack;
public:
AFunction(std::function<void()> function, int calls, double duration, LoopOut looped, InterpolationType interpolationType) {
explicit AFunction(std::function<void()> 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();

View File

@ -7,12 +7,16 @@
#include "Animatable.h"
#include "Animation.h"
#include "Object.h"
class ARotate : public Animation {
private:
std::shared_ptr<Object> _object;
Point4D value;
public:
ARotate(const Point4D& r, double duration, LoopOut looped, InterpolationType interpolationType) {
ARotate(std::shared_ptr<Object> 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();
}
};

View File

@ -7,14 +7,17 @@
#include "Animatable.h"
#include "Animation.h"
#include "Mesh.h"
class AScale : public Animation {
private:
Point4D value;
std::shared_ptr<Mesh> _mesh;
std::vector<Triangle> triangles;
Point4D value;
std::vector<Triangle> triangles{};
public:
AScale(const Point4D &s, double duration, LoopOut looped, InterpolationType interpolationType) {
AScale(std::shared_ptr<Mesh> 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<Triangle> 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();
}
};

View File

@ -7,12 +7,16 @@
#include "Animatable.h"
#include "Animation.h"
#include "Object.h"
class ATranslate : public Animation {
private:
std::shared_ptr<Object> _object;
Point4D value;
public:
ATranslate(const Point4D& t, double duration, LoopOut looped, InterpolationType interpolationType) {
ATranslate(std::shared_ptr<Object> 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

View File

@ -7,13 +7,17 @@
#include "Animatable.h"
#include "Animation.h"
#include "Object.h"
class ATranslateToPoint : public Animation {
private:
std::shared_ptr<Object> _object;
Point4D point;
Point4D value;
public:
ATranslateToPoint(const Point4D& p, double duration, LoopOut looped, InterpolationType interpolationType) {
ATranslateToPoint(std::shared_ptr<Object> 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();
}

View File

@ -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

View File

@ -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);
}

View File

@ -8,7 +8,6 @@
#include <list>
#include "../Triangle.h"
//class Animation;
#include "Animation.h"
#include <iostream>
#include <functional>
@ -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<void()> 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<Triangle>& triangles() { return *(std::vector<Triangle>*)(new std::vector<Triangle>()); }
virtual void setTriangles(const std::vector<Triangle>& tris) {}
[[nodiscard]] virtual sf::Color color() const {return sf::Color(); }
virtual void setColor(sf::Color c) { }
};
#endif //INC_3DZAVR_ANIMATABLE_H

View File

@ -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

185
main.cpp
View File

@ -2,193 +2,10 @@
// Created by Иван Ильин on 06.02.2021.
//
#include "Engine.h"
#include <iostream>
#include "Player.h"
#include "ResourceManager.h"
#include "gui/Window.h"
#include "PlayerController.h"
#include "Client.h"
#include "Server.h"
#include <fstream>
#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> server, shared_ptr<Client> 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> player;
shared_ptr<PlayerController> playerController;
sf::Sound backgroundNoise;
Window mainMenu;
shared_ptr<Server> server;
shared_ptr<Client> 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<Player>();
playerController = std::make_shared<PlayerController>(player, world, keyboard, mouse);
client = std::make_shared<Client>(player, world);
server = std::make_shared<Server>();
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;

View File

@ -4,6 +4,8 @@
#include <ResourceManager.h>
#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<std::string, double>
Shotgun::processFire(std::shared_ptr<World> world, std::shared_ptr<Camera> camera) {
Shotgun::processFire(std::function<std::pair<Point4D, std::string>(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& pos, const Point4D& direction) {
std::map<std::string, double> damagedPlayers;
for(int i = 0; i < 15; i++) {
@ -31,24 +33,14 @@ Shotgun::processFire(std::shared_ptr<World> world, std::shared_ptr<Camera> 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<RigidBody>(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);
}

View File

@ -10,7 +10,7 @@
class Shotgun : public Weapon {
public:
explicit Shotgun(int ammo = 15, const std::string& weaponName = "shotgun");
std::map<std::string, double> processFire(std::shared_ptr<World> world, std::shared_ptr<Camera> camera) override;
std::map<std::string, double> processFire(std::function<std::pair<Point4D, std::string>(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction) override;
};

View File

@ -3,15 +3,21 @@
//
#include <sstream>
#include <utility>
#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<RigidBody>(obj)});
}
*/
loadObj(objFileName, matFileName, scale);
setCollider(false);
rotate(r);
translate(t);
noAmmoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/no_ammo.ogg"));
}
std::map<std::string, double> Weapon::fire(std::shared_ptr<World> world, std::shared_ptr<Camera> camera) {
std::map<std::string, double> Weapon::fire(std::function<std::pair<Point4D, std::string>(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction) {
if(_clipAmmo == 0) {
reload();
if(_clipAmmo == 0)
@ -44,7 +56,7 @@ std::map<std::string, double> Weapon::fire(std::shared_ptr<World> 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> world) {
for(auto& obj : _objects) {
world->addBody(obj.second, obj.first);
}
}
void Weapon::removeFromWorld(shared_ptr<World> 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> 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<std::string, double> Weapon::processFire(shared_ptr<World> world, shared_ptr<Camera> camera) {
std::map<std::string, double> Weapon::processFire(std::function<std::pair<Point4D, std::string>(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& pos, const Point4D& direction) {
std::map<std::string, double> 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<RigidBody>(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;
}

View File

@ -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<std::string, std::shared_ptr<RigidBody>> _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> world, const std::string& traceName);
int fireTraces = 0;
std::function<void(const Point4D&, const Point4D&)> addTraceCallBack;
std::function<void(const Point4D&, const Point4D&)> _addTraceCallBack;
virtual std::map<std::string, double> processFire(std::function<std::pair<Point4D, std::string>(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<std::string, double> fire(std::shared_ptr<World> world, std::shared_ptr<Camera> camera);
std::map<std::string, double> fire(std::function<std::pair<Point4D, std::string>(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction);
void reload();
void addToWorld(std::shared_ptr<World> world);
void removeFromWorld(std::shared_ptr<World> world);
void attachToPlayer(Mesh& player);
[[nodiscard]] std::pair<double, double> 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<void(Point4D, Point4D)> 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<std::string, double> processFire(std::shared_ptr<World> world, std::shared_ptr<Camera> camera);
[[nodiscard]] int initialPack() const {return _initialPack; }
};