2021-10-02 20:36:07 +03:00
|
|
|
|
//
|
|
|
|
|
// Created by Иван Ильин on 22.09.2021.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "Shooter.h"
|
|
|
|
|
#include <fstream>
|
2021-10-18 09:21:09 +03:00
|
|
|
|
#include <utility>
|
2021-11-09 22:54:20 +03:00
|
|
|
|
#include "engine/animation/Animations.h"
|
2021-10-16 20:22:55 +03:00
|
|
|
|
#include "ShooterConsts.h"
|
2022-07-11 16:58:05 +03:00
|
|
|
|
#include "engine/io/SoundController.h"
|
2022-07-22 22:52:54 +03:00
|
|
|
|
#include "network/Chat.h"
|
2021-10-02 20:36:07 +03:00
|
|
|
|
using namespace std;
|
|
|
|
|
// Read server/client settings and start both.
|
|
|
|
|
// If client doesn't connect to the localhost - server doesn't start.
|
2021-11-13 18:30:12 +03:00
|
|
|
|
void Shooter::initNetwork() {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
std::string clientIp;
|
|
|
|
|
sf::Uint16 clientPort;
|
|
|
|
|
sf::Uint16 serverPort;
|
2021-10-26 09:40:35 +03:00
|
|
|
|
std::string playerName;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
std::ifstream connectFile("connect.txt", std::ifstream::in);
|
|
|
|
|
|
|
|
|
|
// If failed to read client settings
|
2021-10-31 11:39:08 +03:00
|
|
|
|
if (!connectFile.is_open() || !(connectFile >> clientIp >> clientPort >> playerName) ||
|
|
|
|
|
sf::IpAddress(clientIp) == sf::IpAddress::None) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
connectFile.close();
|
|
|
|
|
// Create file and write default settings
|
|
|
|
|
clientIp = "127.0.0.1";
|
|
|
|
|
clientPort = 54000;
|
2021-10-26 09:40:35 +03:00
|
|
|
|
playerName = "PlayerName";
|
2021-10-02 20:36:07 +03:00
|
|
|
|
std::ofstream temp("connect.txt", std::ofstream::out);
|
2021-10-26 09:40:35 +03:00
|
|
|
|
temp << clientIp << std::endl << clientPort << std::endl << playerName;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
temp.close();
|
|
|
|
|
}
|
|
|
|
|
connectFile.close();
|
|
|
|
|
|
|
|
|
|
// If failed to read server settings
|
|
|
|
|
connectFile.open("server.txt", std::ifstream::in);
|
2021-10-31 11:39:08 +03:00
|
|
|
|
if (!connectFile.is_open() || !(connectFile >> serverPort)) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
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);
|
2021-10-31 11:39:08 +03:00
|
|
|
|
if (server->isWorking())
|
2021-10-02 20:36:07 +03:00
|
|
|
|
server->generateBonuses();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
client->connect(clientIp, clientPort);
|
2021-10-28 16:58:02 +03:00
|
|
|
|
player->setPlayerNickName(playerName);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-28 17:06:10 +03:00
|
|
|
|
// TODO: encapsulate call backs inside ShooterClient
|
2021-10-31 11:39:08 +03:00
|
|
|
|
client->setSpawnPlayerCallBack([this](sf::Uint16 id) { spawnPlayer(id); });
|
|
|
|
|
client->setRemovePlayerCallBack([this](sf::Uint16 id) { removePlayer(id); });
|
|
|
|
|
client->setAddFireTraceCallBack([this](const Vec3D &from, const Vec3D &to) { addFireTrace(from, to); });
|
|
|
|
|
client->setAddBonusCallBack(
|
|
|
|
|
[this](const std::string &bonusName, const Vec3D &position) { addBonus(bonusName, position); });
|
|
|
|
|
client->setRemoveBonusCallBack([this](const ObjectNameTag &bonusName) { removeBonus(bonusName); });
|
|
|
|
|
client->setChangeEnemyWeaponCallBack(
|
|
|
|
|
[this](const std::string &weaponName, sf::Uint16 id) { changeEnemyWeapon(weaponName, id); });
|
2022-07-22 22:52:54 +03:00
|
|
|
|
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::start() {
|
|
|
|
|
// This code executed once in the beginning:
|
|
|
|
|
setUpdateWorld(false);
|
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
|
screen->setMouseCursorVisible(true);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-17 20:52:21 +03:00
|
|
|
|
world->loadMap(ShooterConsts::MAP_OBJ, Vec3D{5, 5, 5});
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-17 20:52:21 +03:00
|
|
|
|
// TODO: encapsulate call backs inside Player
|
2021-10-31 11:39:08 +03:00
|
|
|
|
player->setAddTraceCallBack([this](const Vec3D &from, const Vec3D &to) {
|
|
|
|
|
client->addTrace(from, to);
|
|
|
|
|
addFireTrace(from, to);
|
|
|
|
|
});
|
|
|
|
|
player->setDamagePlayerCallBack(
|
|
|
|
|
[this](sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); });
|
|
|
|
|
player->setRayCastFunction(
|
2022-07-07 13:14:00 +03:00
|
|
|
|
[this](const Vec3D &from, const Vec3D &to) { return world->rayCast(from, to, "Player Weapon fireTrace bulletHole"); });
|
2021-10-31 11:39:08 +03:00
|
|
|
|
player->setTakeBonusCallBack([this](const string &bonusName) { client->takeBonus(bonusName); });
|
|
|
|
|
player->setAddWeaponCallBack([this](std::shared_ptr<Weapon> weapon) { addWeapon(std::move(weapon)); });
|
|
|
|
|
player->setRemoveWeaponCallBack([this](std::shared_ptr<Weapon> weapon) { removeWeapon(std::move(weapon)); });
|
2021-10-12 17:12:47 +03:00
|
|
|
|
|
2021-10-31 19:01:06 +03:00
|
|
|
|
player->reInitWeapons();
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
|
camera->translateToPoint(player->position() + Vec3D{0, 1.8, 0});
|
2021-10-28 16:58:02 +03:00
|
|
|
|
player->attach(camera);
|
|
|
|
|
world->addBody(player);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
|
|
// connecting to the server
|
2021-11-13 18:30:12 +03:00
|
|
|
|
initNetwork();
|
2021-10-02 20:36:07 +03:00
|
|
|
|
// Waiting for connect and updating server if it's same window
|
2021-10-28 16:58:02 +03:00
|
|
|
|
while (client->isWorking() && !client->connected()) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
client->update();
|
|
|
|
|
server->update();
|
|
|
|
|
Time::update();
|
|
|
|
|
}
|
|
|
|
|
// If connect fail - return to menu
|
2021-10-28 16:58:02 +03:00
|
|
|
|
if (!client->isWorking()) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
inGame = false;
|
|
|
|
|
server->stop();
|
|
|
|
|
}
|
2021-10-25 22:32:55 +03:00
|
|
|
|
|
|
|
|
|
// windows init:
|
2021-10-28 16:58:02 +03:00
|
|
|
|
mainMenu.setTitle("Main menu");
|
2021-10-25 22:32:55 +03:00
|
|
|
|
mainMenu.setBackgroundTexture(ShooterConsts::MAIN_MENU_BACK, 1.1, 1.1, screen->width(), screen->height());
|
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
mainMenu.addButton(screen->width() / 2, 200, 200, 20, [this]() {
|
|
|
|
|
this->play();
|
2022-02-23 17:29:42 +03:00
|
|
|
|
SoundController::loadAndPlay(SoundTag("click"), ShooterConsts::CLICK_SOUND);
|
2021-10-31 11:39:08 +03:00
|
|
|
|
}, "Server: " + client->serverIp().toString(), 5, 5, ShooterConsts::MAIN_MENU_GUI, {0, 66}, {0, 86}, {0, 46},
|
|
|
|
|
Consts::MEDIUM_FONT, {255, 255, 255});
|
|
|
|
|
mainMenu.addButton(screen->width() / 2, 350, 200, 20, [this]() {
|
|
|
|
|
this->player->translateToPoint(Vec3D{0, 0, 0});
|
|
|
|
|
this->player->setVelocity({});
|
|
|
|
|
this->play();
|
2022-02-23 17:29:42 +03:00
|
|
|
|
SoundController::loadAndPlay(SoundTag("click"), ShooterConsts::CLICK_SOUND);
|
2021-10-31 11:39:08 +03:00
|
|
|
|
}, "Respawn", 5, 5, ShooterConsts::MAIN_MENU_GUI, {0, 66}, {0, 86}, {0, 46}, Consts::MEDIUM_FONT, {255, 255, 255});
|
|
|
|
|
|
|
|
|
|
mainMenu.addButton(screen->width() / 2, 500, 200, 20, [this]() {
|
|
|
|
|
client->disconnect();
|
|
|
|
|
server->stop();
|
|
|
|
|
this->exit();
|
|
|
|
|
}, "Exit", 5, 5, ShooterConsts::MAIN_MENU_GUI, {0, 66}, {0, 86}, {0, 46}, Consts::MEDIUM_FONT, {255, 255, 255});
|
2022-07-22 22:52:54 +03:00
|
|
|
|
client->setChatManager(chat);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::update() {
|
|
|
|
|
// This code executed every time step:
|
|
|
|
|
server->update();
|
|
|
|
|
client->update();
|
|
|
|
|
|
|
|
|
|
// Check all input after this condition please
|
2021-10-28 16:58:02 +03:00
|
|
|
|
if (!screen->hasFocus()) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
return;
|
2021-10-28 16:58:02 +03:00
|
|
|
|
}
|
2022-07-22 22:52:54 +03:00
|
|
|
|
if (keyboard->isKeyTapped(sf::Keyboard::Enter)) {
|
|
|
|
|
if (isTypingMessage) {
|
|
|
|
|
client->sendMessage(message);
|
|
|
|
|
message = "";
|
|
|
|
|
}
|
|
|
|
|
isTypingMessage = !isTypingMessage;
|
|
|
|
|
}
|
2022-07-23 00:47:19 +03:00
|
|
|
|
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::Tab)) {
|
|
|
|
|
setDebugInfo(!showDebugInfo());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (keyboard->isKeyTapped(sf::Keyboard::P)) {
|
|
|
|
|
screen->startRender();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (keyboard->isKeyTapped(sf::Keyboard::L)) {
|
|
|
|
|
screen->stopRender();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-23 01:06:19 +03:00
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
if (inGame) {
|
2021-10-16 20:22:55 +03:00
|
|
|
|
screen->setTitle(ShooterConsts::PROJECT_NAME);
|
2022-07-24 15:30:14 +03:00
|
|
|
|
|
2022-07-22 22:52:54 +03:00
|
|
|
|
if (isTypingMessage) {
|
2022-07-23 00:47:19 +03:00
|
|
|
|
string symbols = screen->getInputSymbols();
|
|
|
|
|
for (char s : symbols) {
|
2022-07-24 20:01:17 +03:00
|
|
|
|
if (s == (char)8) {//backspace
|
2022-07-23 00:47:19 +03:00
|
|
|
|
message = message.substr(0, message.size() - 1);
|
|
|
|
|
}
|
2022-07-24 20:01:17 +03:00
|
|
|
|
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
|
2022-07-23 00:47:19 +03:00
|
|
|
|
message += s;
|
2022-07-24 20:01:17 +03:00
|
|
|
|
}
|
2022-07-23 00:47:19 +03:00
|
|
|
|
}
|
2022-07-22 22:52:54 +03:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
playerController->update();
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-02 20:36:07 +03:00
|
|
|
|
} else {
|
|
|
|
|
mainMenu.update();
|
|
|
|
|
}
|
2022-07-23 01:06:19 +03:00
|
|
|
|
|
2021-10-02 20:36:07 +03:00
|
|
|
|
setUpdateWorld(inGame);
|
|
|
|
|
|
|
|
|
|
// background sounds and music control
|
2021-10-31 11:39:08 +03:00
|
|
|
|
if (SoundController::getStatus(SoundTag("background")) != sf::Sound::Status::Playing) {
|
2022-02-23 17:29:42 +03:00
|
|
|
|
SoundController::loadAndPlay(SoundTag("background"), ShooterConsts::BACK_NOISE);
|
2021-10-28 16:58:02 +03:00
|
|
|
|
}
|
2022-07-23 01:06:19 +03:00
|
|
|
|
|
|
|
|
|
|
2022-07-22 22:52:54 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::drawChat() {
|
2022-07-24 20:22:47 +03:00
|
|
|
|
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();
|
2022-07-24 15:30:14 +03:00
|
|
|
|
|
|
|
|
|
screen->drawText(chatText, Vec2D{ 0, (double)screen->height()*0.25 }, 20, chatColor);
|
|
|
|
|
|
|
|
|
|
if (isTypingMessage){
|
2022-07-24 20:01:17 +03:00
|
|
|
|
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));
|
2022-07-23 00:47:19 +03:00
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::gui() {
|
|
|
|
|
sf::Sprite sprite;
|
2021-10-16 20:22:55 +03:00
|
|
|
|
sprite.setTexture(*ResourceManager::loadTexture(ShooterConsts::MAIN_MENU_GUI));
|
2021-10-02 20:36:07 +03:00
|
|
|
|
sprite.setTextureRect(sf::IntRect(243, 3, 9, 9));
|
|
|
|
|
sprite.scale(3, 3);
|
2021-10-31 11:39:08 +03:00
|
|
|
|
sprite.setPosition(static_cast<float>(screen->width()) / 2.0f - 27.0f / 2.0f,
|
|
|
|
|
static_cast<float>(screen->height()) / 2.0f - 27.0f / 2.0f);
|
2021-10-26 09:40:35 +03:00
|
|
|
|
sprite.setColor(sf::Color(0, 0, 0, 250));
|
2021-10-02 20:36:07 +03:00
|
|
|
|
screen->drawSprite(sprite);
|
|
|
|
|
|
|
|
|
|
// health player stats
|
|
|
|
|
drawPlayerStats();
|
2021-10-26 09:40:35 +03:00
|
|
|
|
drawStatsTable();
|
2022-07-23 01:06:19 +03:00
|
|
|
|
drawChat();
|
2021-10-26 09:40:35 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::drawStatsTable() {
|
2021-11-13 18:30:12 +03:00
|
|
|
|
|
2021-10-26 09:50:59 +03:00
|
|
|
|
int i = 1;
|
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
screen->drawText(client->lastEvent(), Vec2D{10, 10}, 25, sf::Color(0, 0, 0, 100));
|
2021-10-26 09:40:35 +03:00
|
|
|
|
|
2021-11-09 22:54:20 +03:00
|
|
|
|
vector<shared_ptr < Player>>
|
|
|
|
|
allPlayers;
|
2021-10-26 09:40:35 +03:00
|
|
|
|
allPlayers.push_back(player);
|
2021-10-31 11:39:08 +03:00
|
|
|
|
for (auto&[playerId, player] : client->players())
|
2021-10-26 09:40:35 +03:00
|
|
|
|
allPlayers.push_back(player);
|
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
std::sort(allPlayers.begin(), allPlayers.end(), [](std::shared_ptr<Player> p1, std::shared_ptr<Player> p2) {
|
2021-10-26 09:40:35 +03:00
|
|
|
|
return p1->kills() - p1->deaths() > p2->kills() - p2->deaths();
|
2021-10-31 11:39:08 +03:00
|
|
|
|
});
|
2021-10-26 09:40:35 +03:00
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
for (auto &p : allPlayers) {
|
|
|
|
|
screen->drawText(std::to_string(i) + "\t" + p->playerNickName() + "\t" + std::to_string(p->kills()) + " / " +
|
|
|
|
|
std::to_string(p->deaths()),
|
2022-07-22 18:38:05 +03:00
|
|
|
|
Vec2D{10, 15 + 35.0 * i}, 25, p->color());
|
2021-10-26 09:40:35 +03:00
|
|
|
|
i++;
|
|
|
|
|
}
|
2021-11-13 18:30:12 +03:00
|
|
|
|
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::drawPlayerStats() {
|
|
|
|
|
// health bar
|
|
|
|
|
double xPos = 10;
|
2021-10-09 13:41:12 +03:00
|
|
|
|
double yPos = screen->height() - 20;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
int width = screen->width() / 2 - 20;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
int height = 10;
|
|
|
|
|
|
2021-10-12 20:19:02 +03:00
|
|
|
|
screen->drawTetragon(Vec2D{xPos, yPos},
|
2021-10-16 20:22:55 +03:00
|
|
|
|
Vec2D{xPos + width * player->health() / ShooterConsts::HEALTH_MAX, yPos},
|
|
|
|
|
Vec2D{xPos + width * player->health() / ShooterConsts::HEALTH_MAX, yPos + height},
|
2021-10-12 20:19:02 +03:00
|
|
|
|
Vec2D{xPos, yPos + height},
|
2021-10-31 11:39:08 +03:00
|
|
|
|
{static_cast<sf::Uint8>((ShooterConsts::HEALTH_MAX - player->health()) /
|
|
|
|
|
ShooterConsts::HEALTH_MAX * 255),
|
|
|
|
|
static_cast<sf::Uint8>(player->health() * 255 / ShooterConsts::HEALTH_MAX), 0, 100});
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-12 20:19:02 +03:00
|
|
|
|
screen->drawTetragon(Vec2D{xPos, yPos - 15},
|
2021-10-16 20:22:55 +03:00
|
|
|
|
Vec2D{xPos + width * player->ability() / ShooterConsts::ABILITY_MAX, yPos - 15},
|
|
|
|
|
Vec2D{xPos + width * player->ability() / ShooterConsts::ABILITY_MAX, yPos - 15 + height},
|
2021-10-12 20:19:02 +03:00
|
|
|
|
Vec2D{xPos, yPos - 15 + height},
|
2021-10-31 11:39:08 +03:00
|
|
|
|
{255, 168, 168, 100});
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-31 19:01:06 +03:00
|
|
|
|
auto balance = player->weapon()->balance();
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
screen->drawText(std::to_string((int) balance.first), Vec2D{150, static_cast<double>(screen->height() - 150)}, 100,
|
|
|
|
|
sf::Color(0, 0, 0, 100));
|
|
|
|
|
screen->drawText(std::to_string((int) balance.second), Vec2D{50, static_cast<double>(screen->height() - 100)}, 50,
|
|
|
|
|
sf::Color(0, 0, 0, 70));
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::play() {
|
|
|
|
|
inGame = true;
|
2021-10-28 16:58:02 +03:00
|
|
|
|
screen->setMouseCursorVisible(false);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::spawnPlayer(sf::Uint16 id) {
|
2021-10-09 14:38:24 +03:00
|
|
|
|
std::string name = "Enemy_" + std::to_string(id);
|
2021-10-28 16:58:02 +03:00
|
|
|
|
|
2022-07-11 16:58:05 +03:00
|
|
|
|
std::shared_ptr<Player> newPlayer = std::make_shared<Player>(ObjectNameTag(name), ShooterConsts::BODY_OBJ, Vec3D{0.4, 0.4, 0.4});
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
|
|
client->addPlayer(id, newPlayer);
|
2021-10-28 16:58:02 +03:00
|
|
|
|
world->addBody(newPlayer);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
newPlayer->setVisible(true);
|
2021-11-06 22:11:06 +03:00
|
|
|
|
newPlayer->setCollision(false);
|
2021-10-12 17:12:47 +03:00
|
|
|
|
newPlayer->setAcceleration(Vec3D{0, 0, 0});
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
|
|
// add head and other stuff:
|
2021-11-06 22:11:06 +03:00
|
|
|
|
world->loadBody(ObjectNameTag(name + "_head"), ShooterConsts::HEAD_OBJ, Vec3D{0.4, 0.4, 0.4});
|
|
|
|
|
world->body(ObjectNameTag(name + "_head"))->translate(Vec3D{0, 2.2, 0});
|
2021-10-28 16:58:02 +03:00
|
|
|
|
newPlayer->attach(world->body(ObjectNameTag(name + "_head")));
|
2021-10-17 10:21:10 +03:00
|
|
|
|
|
2021-11-06 22:11:06 +03:00
|
|
|
|
world->loadBody(ObjectNameTag(name + "_foot_1"), ShooterConsts::FOOT_OBJ, Vec3D{0.4, 0.4, 0.4});
|
|
|
|
|
world->body(ObjectNameTag(name + "_foot_1"))->translate(Vec3D{-0.25, 0, 0});
|
|
|
|
|
newPlayer->attach(world->body(ObjectNameTag(name + "_foot_1")));
|
2021-10-17 10:21:10 +03:00
|
|
|
|
|
2021-11-06 22:11:06 +03:00
|
|
|
|
world->loadBody(ObjectNameTag(name + "_foot_2"), ShooterConsts::FOOT_OBJ, Vec3D{0.4, 0.4, 0.4});
|
|
|
|
|
world->body(ObjectNameTag(name + "_foot_2"))->translate(Vec3D{0.25, 0, 0});
|
|
|
|
|
newPlayer->attach(world->body(ObjectNameTag(name + "_foot_2")));
|
|
|
|
|
|
2021-11-09 22:54:20 +03:00
|
|
|
|
int colorBodyNum = static_cast<int> (static_cast<double>((rand() - 1)) / RAND_MAX * 5.0);
|
|
|
|
|
int colorFootNum = static_cast<int> (static_cast<double>((rand() - 1)) / RAND_MAX * 5.0);
|
2021-11-07 10:47:24 +03:00
|
|
|
|
|
2022-02-23 17:29:42 +03:00
|
|
|
|
newPlayer->setColor(Consts::WHITE_COLORS[colorBodyNum]);
|
|
|
|
|
world->body(ObjectNameTag(name + "_foot_1"))->setColor(Consts::DARK_COLORS[colorFootNum]);
|
|
|
|
|
world->body(ObjectNameTag(name + "_foot_2"))->setColor(Consts::DARK_COLORS[colorFootNum]);
|
2021-10-18 18:30:02 +03:00
|
|
|
|
|
|
|
|
|
changeEnemyWeapon("gun", id);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::removePlayer(sf::Uint16 id) {
|
2021-10-17 10:38:15 +03:00
|
|
|
|
std::string name = "Enemy_" + std::to_string(id);
|
2021-11-06 22:11:06 +03:00
|
|
|
|
|
2021-11-10 14:14:10 +03:00
|
|
|
|
auto playerToRemove = world->body(ObjectNameTag(name));
|
|
|
|
|
|
|
|
|
|
Timeline::addAnimation<AScale>(AnimationListTag(name + "_remove"), playerToRemove, Vec3D(0.01, 0.01, 0.01));
|
|
|
|
|
Timeline::addAnimation<AFunction>(AnimationListTag(name + "_remove"), [this, name](){
|
|
|
|
|
world->removeBody(ObjectNameTag(name));
|
|
|
|
|
world->removeBody(ObjectNameTag(name + "_head"));
|
|
|
|
|
world->removeBody(ObjectNameTag(name + "_weapon"));
|
|
|
|
|
world->removeBody(ObjectNameTag(name + "_foot_1"));
|
|
|
|
|
world->removeBody(ObjectNameTag(name + "_foot_2"));
|
|
|
|
|
});
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
|
void Shooter::addFireTrace(const Vec3D &from, const Vec3D &to) {
|
2022-07-07 13:14:00 +03:00
|
|
|
|
std::string traceName = "Client_fireTrace_" + std::to_string(fireTraces++);
|
2021-10-28 16:58:02 +03:00
|
|
|
|
world->addBody(std::make_shared<RigidBody>(Mesh::LineTo(ObjectNameTag(traceName), from, to, 0.05)));
|
2021-10-17 10:21:10 +03:00
|
|
|
|
world->body(ObjectNameTag(traceName))->setCollider(false);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
2021-11-09 22:54:20 +03:00
|
|
|
|
Timeline::addAnimation<AColor>(AnimationListTag(traceName + "_fadeOut"), world->body(ObjectNameTag(traceName)),
|
|
|
|
|
sf::Color{150, 150, 150, 0});
|
|
|
|
|
Timeline::addAnimation<AFunction>(AnimationListTag(traceName + "_delete"),
|
|
|
|
|
[this, traceName]() { removeFireTrace(ObjectNameTag(traceName)); }, 1,
|
|
|
|
|
1);
|
2022-07-07 13:14:00 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string bulletHoleName = "Client_bulletHole_" + std::to_string(fireTraces++);
|
|
|
|
|
auto bulletHole = Mesh::Cube(ObjectNameTag(bulletHoleName), 0.2, sf::Color(70, 70, 70));
|
|
|
|
|
bulletHole.translate(to);
|
|
|
|
|
world->addBody(std::make_shared<RigidBody>(bulletHole));
|
|
|
|
|
world->body(ObjectNameTag(bulletHoleName))->setCollider(false);
|
|
|
|
|
|
|
|
|
|
Timeline::addAnimation<AFunction>(AnimationListTag(bulletHoleName + "_delete"),
|
|
|
|
|
[this, bulletHoleName]() { removeFireTrace(ObjectNameTag(bulletHoleName)); }, 1,
|
|
|
|
|
7);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
void Shooter::removeFireTrace(const ObjectNameTag &traceName) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
world->removeBody(traceName);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
|
void Shooter::addBonus(const string &bonusName, const Vec3D &position) {
|
2022-02-23 07:51:53 +03:00
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
std::string name = bonusName.substr(6, bonusName.size() - 3 - 5);
|
2021-10-28 16:58:02 +03:00
|
|
|
|
|
|
|
|
|
ObjectNameTag nameTag(bonusName);
|
|
|
|
|
|
2022-07-19 12:57:09 +03:00
|
|
|
|
world->addBody(std::make_shared<RigidBody>(ObjectNameTag(bonusName), "obj/items/" + name + ".obj", Vec3D{3, 3, 3}));
|
2021-11-10 14:14:10 +03:00
|
|
|
|
|
|
|
|
|
auto bonus = world->body(ObjectNameTag(bonusName));
|
|
|
|
|
|
|
|
|
|
bonus->translateToPoint(position);
|
|
|
|
|
bonus->setCollider(false);
|
|
|
|
|
bonus->setTrigger(true);
|
|
|
|
|
bonus->scale(Vec3D(0.01, 0.01, 0.01));
|
|
|
|
|
Timeline::addAnimation<AScale>(AnimationListTag(bonusName + "_creation"), bonus, Vec3D(100, 100, 100));
|
2021-11-09 22:54:20 +03:00
|
|
|
|
Timeline::addAnimation<ARotate>(AnimationListTag(bonusName + "_rotation"),
|
2021-11-10 14:14:10 +03:00
|
|
|
|
bonus, Vec3D{0, 2 * Consts::PI, 0}, 4,
|
2021-11-09 22:54:20 +03:00
|
|
|
|
Animation::LoopOut::Continue,
|
|
|
|
|
Animation::InterpolationType::Linear);
|
2022-02-23 07:51:53 +03:00
|
|
|
|
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-17 10:21:10 +03:00
|
|
|
|
void Shooter::removeBonus(const ObjectNameTag &bonusName) {
|
2021-10-02 20:36:07 +03:00
|
|
|
|
world->removeBody(bonusName);
|
2021-10-26 09:40:35 +03:00
|
|
|
|
Timeline::deleteAnimationList(AnimationListTag(bonusName.str() + "_rotation"));
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::addWeapon(std::shared_ptr<Weapon> weapon) {
|
2021-10-28 16:58:02 +03:00
|
|
|
|
world->addBody(weapon);
|
2021-10-18 18:30:02 +03:00
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
if (client != nullptr) {
|
2021-10-18 18:30:02 +03:00
|
|
|
|
client->changeWeapon(weapon->name().str());
|
2021-10-28 16:58:02 +03:00
|
|
|
|
}
|
2021-10-18 18:30:02 +03:00
|
|
|
|
}
|
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
|
void Shooter::changeEnemyWeapon(const std::string &weaponName, sf::Uint16 enemyId) {
|
2021-10-28 16:58:02 +03:00
|
|
|
|
ObjectNameTag weaponTag("Enemy_" + std::to_string(enemyId) + "_weapon");
|
2021-10-18 18:30:02 +03:00
|
|
|
|
auto head = world->body(ObjectNameTag("Enemy_" + std::to_string(enemyId) + "_head"));
|
|
|
|
|
auto enemy = world->body(ObjectNameTag("Enemy_" + std::to_string(enemyId)));
|
2021-11-10 14:14:10 +03:00
|
|
|
|
auto weapon = world->body(weaponTag);
|
2021-10-18 18:30:02 +03:00
|
|
|
|
|
|
|
|
|
// remove old weapon:
|
|
|
|
|
world->removeBody(weaponTag);
|
2021-10-29 18:19:30 +03:00
|
|
|
|
enemy->unattach(weaponTag);
|
2021-10-18 18:30:02 +03:00
|
|
|
|
|
2022-07-19 14:02:13 +03:00
|
|
|
|
world->loadBody(weaponTag, "obj/items/" + weaponName + ".obj");
|
2021-10-18 18:30:02 +03:00
|
|
|
|
world->body(weaponTag)->setCollider(false);
|
|
|
|
|
world->body(weaponTag)->scale(Vec3D(3, 3, 3));
|
|
|
|
|
|
2022-07-07 13:14:00 +03:00
|
|
|
|
world->body(weaponTag)->translateToPoint(head->position() - enemy->left() * 1.0 - enemy->up() * 1.0 + enemy->lookAt());
|
2021-10-18 18:30:02 +03:00
|
|
|
|
|
2021-11-06 22:11:06 +03:00
|
|
|
|
world->body(weaponTag)->rotate(Vec3D(0, enemy->angle().y(), 0));
|
|
|
|
|
world->body(weaponTag)->rotateLeft(head->angleLeftUpLookAt().x());
|
2021-10-28 16:58:02 +03:00
|
|
|
|
enemy->attach(world->body(weaponTag));
|
2022-07-07 13:14:00 +03:00
|
|
|
|
|
|
|
|
|
Timeline::addAnimation<ARotateLeft>(AnimationListTag("select_weapon_" + std::to_string(enemyId)),
|
|
|
|
|
world->body(weaponTag),
|
|
|
|
|
-2 * Consts::PI,
|
|
|
|
|
0.3,
|
|
|
|
|
Animation::LoopOut::None,
|
|
|
|
|
Animation::InterpolationType::Cos);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Shooter::removeWeapon(std::shared_ptr<Weapon> weapon) {
|
2021-10-28 16:58:02 +03:00
|
|
|
|
world->removeBody(weapon->name());
|
2021-10-02 20:36:07 +03:00
|
|
|
|
}
|