Merge request of CREAsTIVE-master branch with conflicts resolution
commit
d722d60d9e
2
3dzavr
2
3dzavr
|
@ -1 +1 @@
|
|||
Subproject commit f80ebaf4522310a7560c19e6da2a3a8f36f2eb16
|
||||
Subproject commit 5217578e1500cbe567ddf13a44fffd60e3ad445c
|
|
@ -28,6 +28,8 @@ add_executable(${CMAKE_PROJECT_NAME}
|
|||
ShooterConsts.h
|
||||
network/ShooterMsgType.h
|
||||
network/ShooterMsgType.cpp
|
||||
network/Chat.cpp
|
||||
network/Chat.h
|
||||
# 3d engine:
|
||||
3dzavr/engine/Consts.h
|
||||
3dzavr/engine/math/Vec4D.h
|
||||
|
|
95
Shooter.cpp
95
Shooter.cpp
|
@ -8,9 +8,9 @@
|
|||
#include "3dzavr/engine/animation/Animations.h"
|
||||
#include "ShooterConsts.h"
|
||||
#include "3dzavr/engine/io/SoundController.h"
|
||||
#include "network/Chat.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() {
|
||||
|
@ -65,6 +65,7 @@ void Shooter::initNetwork() {
|
|||
client->setRemoveBonusCallBack([this](const ObjectNameTag &bonusName) { removeBonus(bonusName); });
|
||||
client->setChangeEnemyWeaponCallBack(
|
||||
[this](const std::string &weaponName, sf::Uint16 id) { changeEnemyWeapon(weaponName, id); });
|
||||
|
||||
}
|
||||
|
||||
void Shooter::start() {
|
||||
|
@ -96,7 +97,7 @@ void Shooter::start() {
|
|||
camera->translateToPoint(player->position() + Vec3D{0, 1.8, 0});
|
||||
player->attach(camera);
|
||||
world->addBody(player);
|
||||
|
||||
|
||||
// Waiting for connect and updating server if it's same window
|
||||
while (client->isWorking() && !client->connected()) {
|
||||
client->update();
|
||||
|
@ -130,11 +131,11 @@ void Shooter::start() {
|
|||
server->stop();
|
||||
this->exit();
|
||||
}, "Exit", 5, 5, ShooterConsts::MAIN_MENU_GUI, {0, 66}, {0, 86}, {0, 46}, Consts::MEDIUM_FONT, {255, 255, 255});
|
||||
client->setChatManager(chat);
|
||||
}
|
||||
|
||||
void Shooter::update() {
|
||||
// This code executed every time step:
|
||||
|
||||
server->update();
|
||||
client->update();
|
||||
|
||||
|
@ -142,41 +143,86 @@ void Shooter::update() {
|
|||
if (!screen->hasFocus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::Escape)) {
|
||||
inGame = !inGame;
|
||||
screen->setMouseCursorVisible(!inGame);
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::Enter)) {
|
||||
if (isTypingMessage) {
|
||||
client->sendMessage(message);
|
||||
message = "";
|
||||
}
|
||||
isTypingMessage = !isTypingMessage;
|
||||
}
|
||||
if (!isTypingMessage) {
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::Escape)) {
|
||||
inGame = !inGame;
|
||||
screen->setMouseCursorVisible(!inGame);
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::O)) {
|
||||
setGlEnable(!glEnable());
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::O)) {
|
||||
setGlEnable(!glEnable());
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::Tab)) {
|
||||
setDebugInfo(!showDebugInfo());
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::P)) {
|
||||
screen->startRender();
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::L)) {
|
||||
screen->stopRender();
|
||||
}
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::Tab)) {
|
||||
setDebugInfo(!showDebugInfo());
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::P)) {
|
||||
screen->startRender();
|
||||
}
|
||||
|
||||
if (keyboard->isKeyTapped(sf::Keyboard::L)) {
|
||||
screen->stopRender();
|
||||
}
|
||||
|
||||
|
||||
if (inGame) {
|
||||
screen->setTitle(ShooterConsts::PROJECT_NAME);
|
||||
playerController->update();
|
||||
|
||||
if (isTypingMessage) {
|
||||
string symbols = screen->getInputSymbols();
|
||||
for (char s : symbols) {
|
||||
if (s == (char)8) {//backspace
|
||||
message = message.substr(0, message.size() - 1);
|
||||
}
|
||||
else if (s == (char)27) {//escape
|
||||
message = ""; //FIXME: не работает потому что isKeyTapped имеют задержку,
|
||||
isTypingMessage = false; //т. е. этот код выполняется после нажатия на ESC,
|
||||
} // но при следующем цикле при проверке isKeyTapped(ESC) возвращается TRUE
|
||||
else if (message.length() < ShooterConsts::MAX_MESSAGE_LENGTH && s!=(char)13) {//13=enter
|
||||
message += s;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
playerController->update();
|
||||
}
|
||||
|
||||
} else {
|
||||
mainMenu.update();
|
||||
}
|
||||
|
||||
|
||||
setUpdateWorld(inGame);
|
||||
|
||||
// background sounds and music control
|
||||
if (SoundController::getStatus(SoundTag("background")) != sf::Sound::Status::Playing) {
|
||||
SoundController::loadAndPlay(SoundTag("background"), ShooterConsts::BACK_NOISE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Shooter::drawChat() {
|
||||
sf::Color chatColor = isTypingMessage? sf::Color(50, 50, 50, 255) : sf::Color(50, 50, 50, chat->update(Time::deltaTime()));
|
||||
string chatText = isTypingMessage ? chat->getChat() : chat->getChatPreview();
|
||||
|
||||
screen->drawText(chatText, Vec2D{ 0, (double)screen->height()*0.25 }, 20, chatColor);
|
||||
|
||||
if (isTypingMessage){
|
||||
screen->drawTetragon(
|
||||
Vec2D{ (double)screen->width() * 0.05, (double)screen->height() * 0.7 },
|
||||
Vec2D{ (double)screen->width() * 0.95, (double)screen->height() * 0.7 },
|
||||
Vec2D{ (double)screen->width() * 0.95, (double)screen->height() * 0.7+40 },
|
||||
Vec2D{ (double)screen->width() * 0.05, (double)screen->height() * 0.7+40 }, sf::Color(150, 150, 150, 150));
|
||||
screen->drawText(message, Vec2D{(double)screen->width() * 0.05, (double)screen->height() * 0.7}, 30, sf::Color(0, 0, 0, 255));
|
||||
}
|
||||
}
|
||||
|
||||
void Shooter::gui() {
|
||||
|
@ -192,6 +238,7 @@ void Shooter::gui() {
|
|||
// health player stats
|
||||
drawPlayerStats();
|
||||
drawStatsTable();
|
||||
drawChat();
|
||||
}
|
||||
|
||||
void Shooter::drawStatsTable() {
|
||||
|
|
|
@ -26,6 +26,9 @@ private:
|
|||
|
||||
std::shared_ptr<ShooterServer> server = std::make_shared<ShooterServer>();
|
||||
std::shared_ptr<ShooterClient> client = std::make_shared<ShooterClient>(player);
|
||||
std::shared_ptr<ChatManager> chat = std::make_shared<ChatManager>();
|
||||
bool isTypingMessage = false;
|
||||
string message = "";
|
||||
|
||||
bool inGame = false;
|
||||
int fireTraces = 0;
|
||||
|
@ -34,6 +37,7 @@ private:
|
|||
void start() override;
|
||||
void update() override;
|
||||
void gui() override;
|
||||
void drawChat();
|
||||
void play();
|
||||
void drawPlayerStats();
|
||||
void drawStatsTable();
|
||||
|
|
|
@ -15,6 +15,7 @@ namespace ShooterConsts {
|
|||
const double SLOW_MO_COEFFICIENT = 5;
|
||||
const double FIRE_DISTANCE = 1000;
|
||||
const double BONUS_RECHARGE_TIME = 30;
|
||||
const int MAX_MESSAGE_LENGTH = 70;
|
||||
|
||||
const std::string PLAYER_NAME = "Player";
|
||||
const std::string PROJECT_NAME = "Shooter";
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
#include "Chat.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
void ChatManager::addNewMessage(std::string author, std::string message) {
|
||||
hide = 7.0;
|
||||
messages.push_back(message);
|
||||
authors.push_back(author);
|
||||
isChatUpdate = true;
|
||||
if (messages.size() > 20) {
|
||||
messages.erase(messages.begin());
|
||||
}
|
||||
}
|
||||
int ChatManager::update(double delta) {
|
||||
hide = std::max(hide-delta, 0.0);
|
||||
return std::min((int)(hide * 255.0), 255);
|
||||
|
||||
}
|
||||
std::string ChatManager::getChat() {
|
||||
updateChat(); return chatStr;
|
||||
}
|
||||
std::string ChatManager::getChatPreview() {
|
||||
updateChat(); return chatStrPrev;
|
||||
}
|
||||
|
||||
void ChatManager::updateChat() {
|
||||
if (isChatUpdate) {
|
||||
isChatUpdate = false;
|
||||
int size = messages.size();
|
||||
chatStr = "";
|
||||
chatStrPrev = "";
|
||||
for (int messageIndex = size - 1; messageIndex >= 0; messageIndex--)
|
||||
{
|
||||
if (messageIndex > size - 6) {
|
||||
chatStrPrev += authors[messageIndex] + ": " + messages[messageIndex] + "\n";
|
||||
}
|
||||
chatStr += authors[messageIndex] + ": " + messages[messageIndex] + "\n";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
//#ifndef SHOOTER_SHOOTERSERVER_H
|
||||
#ifndef CHAT_H
|
||||
#define CHAT_H
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ChatManager final {
|
||||
private:
|
||||
std::vector<std::string> messages;
|
||||
std::vector<std::string> authors;
|
||||
bool isChatUpdate = true;
|
||||
std::string chatStr = "";
|
||||
std::string chatStrPrev = "";
|
||||
double hide = 0.0;
|
||||
void updateChat();
|
||||
public:
|
||||
void addNewMessage(std::string author, std::string message);
|
||||
int update(double delta);
|
||||
std::string getChat();
|
||||
std::string getChatPreview();
|
||||
};
|
||||
#endif
|
|
@ -29,7 +29,6 @@ void ShooterClient::processInit(sf::Packet &packet) {
|
|||
if (_spawnPlayerCallBack != nullptr) {
|
||||
_spawnPlayerCallBack(targetId);
|
||||
}
|
||||
|
||||
_players[targetId]->translateToPoint(Vec3D{x, y, z});
|
||||
_players[targetId]->setHealth(health);
|
||||
_players[targetId]->setKills(kills);
|
||||
|
@ -46,7 +45,7 @@ void ShooterClient::processUpdate(sf::Packet &packet) {
|
|||
while (packet >> targetId >> x >> y >> z >> health >> bodyAngle >> headAngle >> playerName) {
|
||||
if (_players.count(targetId)) {
|
||||
std::string name = "Enemy_" + std::to_string(targetId);
|
||||
|
||||
|
||||
Vec3D newPosition = Vec3D{x, y, z};
|
||||
|
||||
bool isAnimate = (_players[targetId]->position() - newPosition).sqrAbs() > 0.2;
|
||||
|
@ -123,6 +122,18 @@ void ShooterClient::processDisconnect(sf::Uint16 targetId) {
|
|||
}
|
||||
}
|
||||
|
||||
void ShooterClient::sendMessage(string message){
|
||||
|
||||
if (message.length() == 0)
|
||||
return;
|
||||
chatManager->addNewMessage(_player->playerNickName(), message);
|
||||
sf::Packet packet;
|
||||
packet << MsgType::Custom << ShooterMsgType::newMessage << message;
|
||||
_socket.send(packet, _socket.serverId());
|
||||
}
|
||||
void ShooterClient::newMessage(string message, string name) {
|
||||
chatManager->addNewMessage(name, message);
|
||||
}
|
||||
|
||||
void ShooterClient::processCustomPacket(sf::Packet &packet) {
|
||||
sf::Uint16 buffId[2];
|
||||
|
@ -131,6 +142,7 @@ void ShooterClient::processCustomPacket(sf::Packet &packet) {
|
|||
|
||||
ShooterMsgType type;
|
||||
packet >> type;
|
||||
string name, message;
|
||||
|
||||
switch (type) {
|
||||
case ShooterMsgType::Kill:
|
||||
|
@ -227,6 +239,11 @@ void ShooterClient::processCustomPacket(sf::Packet &packet) {
|
|||
_changeEnemyWeaponCallBack(tmp, buffId[0]);
|
||||
}
|
||||
break;
|
||||
case ShooterMsgType::newMessage:
|
||||
|
||||
packet >> name >> message;
|
||||
newMessage(message, name);
|
||||
break;
|
||||
default:
|
||||
Log::log("ShooterClient::processCustomPacket: unknown message type " +
|
||||
std::to_string(static_cast<int>(type)));
|
||||
|
@ -304,7 +321,7 @@ ShooterClient::setChangeEnemyWeaponCallBack(std::function<void(const std::string
|
|||
_changeEnemyWeaponCallBack = std::move(changeEnemyWeapon);
|
||||
}
|
||||
|
||||
void ShooterClient::requestMap(std::string clientIp, std::string *current_map) {
|
||||
void ShooterClient::requestMap(const std::string& clientIp, std::string *current_map) {
|
||||
Log::log("---------[FTP server]---------");
|
||||
sf::Ftp ftp;
|
||||
sf::Ftp::Response connectResponse = ftp.connect(clientIp, 21);
|
||||
|
@ -316,7 +333,8 @@ void ShooterClient::requestMap(std::string clientIp, std::string *current_map) {
|
|||
if (dirResponse.isOk()) {
|
||||
const std::vector<std::string>& listing = dirResponse.getListing();
|
||||
|
||||
if (listing.size()!=0) {
|
||||
|
||||
if (listing.size() != 0) {
|
||||
for (std::vector<std::string>::const_iterator it = listing.begin(); it != listing.end(); ++it)
|
||||
Log::log("- "+*it);
|
||||
|
||||
|
@ -327,12 +345,12 @@ void ShooterClient::requestMap(std::string clientIp, std::string *current_map) {
|
|||
std::string map_path = listing.at(0);
|
||||
map_path = "./obj/maps"+map_path.substr(map_path.find("/"));
|
||||
Log::log("Map set to: "+map_path);
|
||||
*current_map = map_path;
|
||||
*current_map = map_path;
|
||||
}
|
||||
} else {
|
||||
Log::log("there is no map file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftp.disconnect();
|
||||
} else {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../3dzavr/engine/network/ClientUDP.h"
|
||||
#include "../player/Player.h"
|
||||
#include <SFML/Config.hpp>
|
||||
#include "Chat.h"
|
||||
|
||||
class ShooterClient final : public ClientUDP {
|
||||
private:
|
||||
|
@ -22,9 +23,15 @@ private:
|
|||
std::function<void(const std::string &, const Vec3D &)> _addBonusCallBack;
|
||||
std::function<void(const ObjectNameTag &)> _removeBonusCallBack;
|
||||
std::function<void(const std::string &, sf::Uint16)> _changeEnemyWeaponCallBack;
|
||||
|
||||
std::shared_ptr<ChatManager> chatManager;
|
||||
public:
|
||||
explicit ShooterClient(std::shared_ptr<Player> player) : _player(player) {};
|
||||
|
||||
void sendMessage(std::string message);
|
||||
|
||||
void newMessage(std::string message, std::string name);
|
||||
|
||||
void updatePacket() override;
|
||||
|
||||
void setSpawnPlayerCallBack(std::function<void(sf::Uint16)> spawn);
|
||||
|
@ -59,9 +66,11 @@ public:
|
|||
|
||||
void changeWeapon(const std::string &weaponName);
|
||||
|
||||
void setChatManager(std::shared_ptr<ChatManager> chat) { chatManager = chat; };
|
||||
|
||||
void addPlayer(sf::Uint16 id, std::shared_ptr<Player> player);
|
||||
|
||||
void requestMap(std::string clientIp, std::string *current_map);
|
||||
static void requestMap(const std::string& clientIp, std::string *current_map);
|
||||
|
||||
[[nodiscard]] std::map<sf::Uint16, std::shared_ptr<Player>> const &players() const { return _players; }
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@ enum class ShooterMsgType {
|
|||
InitBonuses,
|
||||
AddBonus,
|
||||
RemoveBonus,
|
||||
ChangeWeapon
|
||||
ChangeWeapon,
|
||||
newMessage
|
||||
};
|
||||
|
||||
sf::Packet &operator<<(sf::Packet &packet, ShooterMsgType type);
|
||||
|
|
|
@ -79,6 +79,7 @@ void ShooterServer::processCustomPacket(sf::Packet &packet, sf::Uint16 senderId)
|
|||
double damage;
|
||||
std::string tmp;
|
||||
double newHealth;
|
||||
std::string message;
|
||||
|
||||
ShooterMsgType type;
|
||||
packet >> type;
|
||||
|
@ -140,6 +141,18 @@ void ShooterServer::processCustomPacket(sf::Packet &packet, sf::Uint16 senderId)
|
|||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case ShooterMsgType::newMessage:
|
||||
|
||||
packet >> message;
|
||||
sendPacket << MsgType::Custom << ShooterMsgType::newMessage << _players[senderId]->playerNickName() << message;
|
||||
if (message.length() == 0)
|
||||
break;
|
||||
for (auto& player : _players) {
|
||||
if (player.first != senderId) {
|
||||
_socket.send(sendPacket, player.first);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log::log("ShooterServer::processCustomPacket: unknown message type " +
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../weapon/Rifle.h"
|
||||
#include "../ShooterConsts.h"
|
||||
|
||||
|
||||
class Player final : public RigidBody {
|
||||
private:
|
||||
double _health = ShooterConsts::HEALTH_MAX;
|
||||
|
|
Loading…
Reference in New Issue