super huge code refactoring
parent
b0a457ce47
commit
8a0221ed77
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
104
Client.cpp
104
Client.cpp
|
@ -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);
|
||||
}
|
||||
|
|
22
Client.h
22
Client.h
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
70
Player.cpp
70
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<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;
|
||||
}
|
||||
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);
|
||||
|
|
99
Player.h
99
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> _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();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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()) +
|
||||
|
|
|
@ -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(){}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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});
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
185
main.cpp
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue