1) Create PlayerController

2) Split Screen.cpp into (Screen.cpp & Keyboard.cpp & Mouse.cpp)
master
Vectozavr 2021-09-19 19:44:31 +07:00
parent be42d4d9bc
commit 5a1c9d8f67
20 changed files with 497 additions and 368 deletions

View File

@ -85,7 +85,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)
if(APPLE OR UNIX)
include_directories(/usr/local/include)

View File

@ -128,7 +128,7 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) {
p2 = Point4D(dbuff[3], dbuff[4], dbuff[5]);
tmp = "Client_fireTraces_" + std::to_string(fireTraces++);
_world->addBody(std::make_shared<RigidBody>(RigidBody(Mesh::LineTo(p1, p2, 0.05))), tmp);
_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);

View File

@ -9,161 +9,6 @@
void Player::update() {
// friction
if(inCollision())
_velocity = _velocity - _velocity * Time::deltaTime() * 2;
if(_isInSlowMo) {
if(_ability > 0)
_ability -= Time::deltaTime();
else {
_ability = 0;
_isInSlowMo = false;
setVelocity(velocity() * _slowMoCoefficient);
setAcceleration(_acceleration * _slowMoCoefficient * _slowMoCoefficient);
_slowMoSound.stop();
_unSlowMoSound.play();
}
}
double coeff = _isInSlowMo ? 1.0 / _slowMoCoefficient : 1.0;
bool inRunning_old = _inRunning;
_inRunning = _screen != nullptr && (Screen::isKeyPressed(sf::Keyboard::A) || Screen::isKeyPressed(sf::Keyboard::D) || Screen::isKeyPressed(sf::Keyboard::W) || Screen::isKeyPressed(sf::Keyboard::S));
// in case when the camera is attached we make some animation during running
if(_camera != nullptr && _inRunning && !_camera->isInAnim()) {
_camera->a_translate("hor_oscil", -_camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_wait("hor_oscil", 0);
_camera->a_translate("hor_oscil", _camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_translate("vert_oscil", -Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_wait("vert_oscil", 0);
_camera->a_translate("vert_oscil", Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_wait("vert_oscil", 0);
_camera->a_translate("vert_oscil", -Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_wait("vert_oscil", 0);
_camera->a_translate("vert_oscil", Point4D{0, 1, 0}/24, 0.15/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.3/coeff, Animation::None, Animation::cos);
} else if(_camera != nullptr && inRunning_old && !_inRunning) {
_camera->a_stopAllAnimations();
_camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.15/coeff, Animation::None, Animation::cos);
}
auto rayToFloor = (*_world).rayCast(position(), position() + Point4D{0, -5, 0});
if(_world != nullptr && _screen != nullptr && _camera != nullptr) {
// Left and right
if (Screen::isKeyPressed(sf::Keyboard::A)) {
translate(_camera->left() * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision())
setVelocity(Point4D{0,0,0});
}
if (Screen::isKeyPressed(sf::Keyboard::D)) {
translate(-_camera->left() * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision())
setVelocity(Point4D{0,0,0});
}
// Forward and backward
if (Screen::isKeyPressed(sf::Keyboard::W)) {
translate(_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision())
setVelocity(Point4D{0,0,0});
}
if (Screen::isKeyPressed(sf::Keyboard::S)) {
translate(-_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision())
setVelocity(Point4D{0,0,0});
}
if (_ability > 0 && !_isInSlowMo && Screen::isKeyPressed(sf::Keyboard::LShift)) {
// slow mo
_isInSlowMo = true;
setVelocity(velocity() / _slowMoCoefficient);
setAcceleration(_acceleration / (_slowMoCoefficient * _slowMoCoefficient));
_unSlowMoSound.stop();
_slowMoSound.play();
} else if (_isInSlowMo && !Screen::isKeyPressed(sf::Keyboard::LShift)) {
_isInSlowMo = false;
setVelocity(velocity() * _slowMoCoefficient);
setAcceleration(_acceleration * _slowMoCoefficient * _slowMoCoefficient);
_slowMoSound.stop();
_unSlowMoSound.play();
}
if (Screen::isKeyPressed(sf::Keyboard::Space) && inCollision()) {
addVelocity(Point4D{0, std::abs(_collisionNormal.y()) * sqrt(2 * _g * _jumpHeight) * coeff, 0});
translate(Point4D{0, Time::deltaTime() * _walkSpeed * 2 * coeff, 0});
}
// Mouse movement
Point4D disp = _screen->getMouseDisplacement();
rotate(Point4D{0, -disp.x() / 1000.0, 0});
_velocity = Matrix4x4::RotationY(-disp.x() / 1000.0) * _velocity;
double rotationLeft = disp.y() / 1000.0;
// You can only see in range [-90 : 90] grad
if (_camera->angleLeftUpLookAt().x() + rotationLeft > M_PI / 2)
rotationLeft = M_PI / 2 - _camera->angleLeftUpLookAt().x();
if (_camera->angleLeftUpLookAt().x() + rotationLeft < -M_PI / 2)
rotationLeft = -M_PI / 2 - _camera->angleLeftUpLookAt().x();
_camera->rotateLeft(rotationLeft);
rotateWeaponsRelativePoint(position() + Point4D{0, 1.8, 0}, _camera->left(), rotationLeft);
if (_screen->isKeyTapped(sf::Keyboard::Right) || _screen->isKeyTapped(sf::Keyboard::E)) {
if(_weapons.size() > 1) {
// change '_selectedWeapon'
_weapons[_selectedWeapon]->removeFromWorld(_world);
_selectedWeapon = (_selectedWeapon + 1) % _weapons.size();
_weapons[_selectedWeapon]->addToWorld(_world);
Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon));
_changeWeaponSound.play();
}
}
if (_screen->isKeyTapped(sf::Keyboard::Left) || _screen->isKeyTapped(sf::Keyboard::Q)) {
if(_weapons.size() > 1) {
// change '_selectedWeapon'
_weapons[_selectedWeapon]->removeFromWorld(_world);
if (_selectedWeapon > 0)
_selectedWeapon = (_selectedWeapon - 1) % _weapons.size();
else
_selectedWeapon = _weapons.size() - 1;
_weapons[_selectedWeapon]->addToWorld(_world);
Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon));
_changeWeaponSound.play();
}
}
if (_screen->isButtonPressed(sf::Mouse::Button::Left)) {
auto damagedPlayers = _weapons[_selectedWeapon]->fire(_world, _camera);
for(auto& damagedPlayer : damagedPlayers) {
sf::Uint16 targetId = std::stoi(damagedPlayer.first.substr(7));
_damagePlayerCallBack(targetId, damagedPlayer.second);
}
}
if(Screen::isKeyPressed(sf::Keyboard::R)) {
_weapons[_selectedWeapon]->reload();
}
if (_inRunning && inCollision() && _walkSound.getStatus() != sf::Sound::Status::Playing) {
if ((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();
}
}
}
}
void Player::rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v, double val) {
@ -172,98 +17,35 @@ void Player::rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v
}
void Player::drawStats() {
if(_screen == nullptr)
return;
// health bar
int xPos = 10;
int yPos = _screen->height() - 10 - 10;
double xPos = 10;
double yPos = _screen->height() - 10 - 10;
int width = _screen->width()/2 - 20;
int height = 10;
double width = _screen->width()/2 - 20;
double height = 10;
sf::ConvexShape polygon1;
polygon1.setPointCount(4);
sf::ConvexShape polygon2;
polygon2.setPointCount(4);
_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 });
polygon1.setPoint(0, sf::Vector2f((float)xPos, (float)yPos));
polygon1.setPoint(1, sf::Vector2f((float)(xPos + width), (float)yPos));
polygon1.setPoint(2, sf::Vector2f((float)(xPos + width), (float)(yPos + height)));
polygon1.setPoint(3, sf::Vector2f((float)xPos, (float)(yPos + height)));
polygon2.setPoint(0, sf::Vector2f((float)xPos, (float)yPos));
polygon2.setPoint(1, sf::Vector2f((float)xPos + width * _health / _healthMax, (float)yPos));
polygon2.setPoint(2, sf::Vector2f((float)xPos + width * _health / _healthMax, (float)(yPos + height)));
polygon2.setPoint(3, sf::Vector2f((float)xPos, (float)(yPos + height)));
polygon1.setFillColor({ 255, 174, 174, 100 });
polygon2.setFillColor({ static_cast<sf::Uint8>((_healthMax - _health)/_healthMax * 255), static_cast<sf::Uint8>(_health * 255 / _healthMax), 0, 100 });
polygon1.setOutlineThickness(3);
_screen->window.draw(polygon2);
// ability bar
sf::ConvexShape polygon3;
polygon3.setPointCount(4);
polygon3.setPoint(0, sf::Vector2f((float)xPos, (float)yPos - 15));
polygon3.setPoint(1, sf::Vector2f((float)xPos + width * _ability / _abilityMax, (float)yPos - 15));
polygon3.setPoint(2, sf::Vector2f((float)xPos + width * _ability / _abilityMax, (float)(yPos - 15 + height)));
polygon3.setPoint(3, sf::Vector2f((float)xPos, (float)(yPos - 15 + height)));
polygon3.setFillColor({ 255, 168, 168, 100 });
_screen->window.draw(polygon3);
// ammo
sf::Text text_health;
text_health.setFont(*ResourceManager::loadFont("../engine/fonts/Roboto-Medium.ttf"));
// text health
text_health.setCharacterSize(20);
text_health.setFillColor(sf::Color::White);
text_health.setStyle(sf::Text::Italic);
text_health.setPosition(0, 0);
text_health.setString(std::to_string((int)_health));
// text ammo
sf::Text text_ammo1(text_health);
sf::Text text_ammo2(text_health);
int ammo1Size = 100;
int ammo2Size = 50;
_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();
text_ammo1.setCharacterSize(ammo1Size);
text_ammo1.setString(std::to_string((int)balance.first));
text_ammo1.setPosition(150, _screen->height() - 50 - ammo1Size);
text_ammo1.setFillColor(sf::Color(0, 0, 0, 100));
_screen->window.draw(text_ammo1);
_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));
text_ammo2.setCharacterSize(ammo2Size);
text_ammo2.setString(std::to_string((int)balance.second));
text_ammo2.setPosition(50, _screen->height() - 50 - ammo2Size);
text_ammo2.setFillColor(sf::Color(0, 0, 0, 70));
_screen->window.draw(text_ammo2);
// text _killSound/_deathSound stats
sf::Text text_kills(text_health);
text_kills.setStyle(sf::Text::Bold);
text_kills.setString("KILLS: " + std::to_string((int)_kills) + " | " + "DEATHS: " + std::to_string((int)_deaths));
text_kills.setFillColor(sf::Color(0, 0, 0, 100));
text_kills.setCharacterSize(ammo2Size/2);
text_kills.setPosition(10, 10);
_screen->window.draw(text_kills);
sf::Text text_deaths(text_health);
text_deaths.setString(std::to_string((int)_deaths));
text_deaths.setFillColor(sf::Color(100, 0, 0, 100));
text_deaths.setCharacterSize(ammo2Size);
text_deaths.setPosition(10, ammo2Size + 10);
_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() {
@ -339,3 +121,40 @@ void Player::initWeapons() {
_weapons[_selectedWeapon]->addToWorld(_world);
}
void Player::nextWeapon() {
if(_weapons.size() > 1) {
// change '_selectedWeapon'
_weapons[_selectedWeapon]->removeFromWorld(_world);
_selectedWeapon = (_selectedWeapon + 1) % _weapons.size();
_weapons[_selectedWeapon]->addToWorld(_world);
Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon));
_changeWeaponSound.play();
}
}
void Player::previousWeapon() {
if(_weapons.size() > 1) {
// change '_selectedWeapon'
_weapons[_selectedWeapon]->removeFromWorld(_world);
if (_selectedWeapon > 0)
_selectedWeapon = (_selectedWeapon - 1) % _weapons.size();
else
_selectedWeapon = _weapons.size() - 1;
_weapons[_selectedWeapon]->addToWorld(_world);
Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon));
_changeWeaponSound.play();
}
}
void Player::fire() {
auto damagedPlayers = _weapons[_selectedWeapon]->fire(_world, _camera);
for(auto& damagedPlayer : damagedPlayers) {
sf::Uint16 targetId = std::stoi(damagedPlayer.first.substr(7));
_damagePlayerCallBack(targetId, damagedPlayer.second);
}
}
void Player::reload() {
_weapons[_selectedWeapon]->reload();
}

View File

@ -33,23 +33,15 @@ private:
double _g = 35;
double _slowMoCoefficient = 5;
bool _isInSlowMo = false;
std::shared_ptr<Camera> _camera;
std::shared_ptr<Screen> _screen;
std::shared_ptr<World> _world;
bool _inRunning = false;
// sounds
sf::Sound _killSound;
sf::Sound _deathSound;
sf::Sound _walkSound;
sf::Sound _changeWeaponSound;
sf::Sound _slowMoSound;
sf::Sound _unSlowMoSound;
sf::Sound _fullHealthSound;
sf::Sound _fullAbilitySound;
@ -62,7 +54,6 @@ private:
std::function<void(const Point4D&, const Point4D&)> _addTraceCallBack;
std::function<void(const std::string&)> _takeBonusCallBack;
public:
Player() {
loadObj("../obj/cube.obj", "", Point4D{0.5, 1.9, 0.5});
@ -73,9 +64,6 @@ public:
_changeWeaponSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/change_weapon.ogg"));
_slowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/slow_mo.ogg"));
_unSlowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/unslow_mo.ogg"));
_fullHealthSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/fullHealth.ogg"));
_fullAbilitySound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/fullAbility.ogg"));
@ -107,6 +95,13 @@ public:
_ability = a;
}
void nextWeapon();
void previousWeapon();
void fire();
void reload();
[[nodiscard]] double ability() const { return _ability; }
void setFullHealth() {
_health = _healthMax;
_fullHealthSound.play();
@ -141,7 +136,6 @@ public:
void rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v, double val);
void drawStats();
void addKill() { _kills++; }

152
PlayerController.cpp Normal file
View File

@ -0,0 +1,152 @@
//
// Created by Иван Ильин on 19.09.2021.
//
#include "PlayerController.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) {
_slowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/slow_mo.ogg"));
_unSlowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/unslow_mo.ogg"));
_changeWeaponSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/change_weapon.ogg"));
}
void PlayerController::update() {
// friction
if(_player->inCollision())
_player->setVelocity(_player->velocity()*(1.0 - Time::deltaTime() * 2));
if(_isInSlowMo) {
if(_player->ability() > 0)
_player->setAbility(_player->ability() - Time::deltaTime());
else {
_player->setAbility(0);
_isInSlowMo = false;
_player->setVelocity(_player->velocity() * _slowMoCoefficient);
_player->setAcceleration(_player->acceleration() * _slowMoCoefficient * _slowMoCoefficient);
_slowMoSound.stop();
_unSlowMoSound.play();
}
}
double coeff = _isInSlowMo ? 1.0 / _slowMoCoefficient : 1.0;
bool inRunning_old = _inRunning;
_inRunning = ( Keyboard::isKeyPressed(sf::Keyboard::A) ||
Keyboard::isKeyPressed(sf::Keyboard::D) ||
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);
_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);
} 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);
}
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);
if(_player->inCollision())
_player->setVelocity(Point4D{0,0,0});
}
if (Keyboard::isKeyPressed(sf::Keyboard::D)) {
_player->translate(-_player->camera()->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);
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);
if(_player->inCollision())
_player->setVelocity(Point4D{0,0,0});
}
if (_player->ability() > 0 && !_isInSlowMo && Keyboard::isKeyPressed(sf::Keyboard::LShift)) {
// slow mo
_isInSlowMo = true;
_player->setVelocity(_player->velocity() / _slowMoCoefficient);
_player->setAcceleration(_player->acceleration() / (_slowMoCoefficient * _slowMoCoefficient));
_unSlowMoSound.stop();
_slowMoSound.play();
} else if (_isInSlowMo && !Keyboard::isKeyPressed(sf::Keyboard::LShift)) {
_isInSlowMo = false;
_player->setVelocity(_player->velocity() * _slowMoCoefficient);
_player->setAcceleration(_player->acceleration() * _slowMoCoefficient * _slowMoCoefficient);
_slowMoSound.stop();
_unSlowMoSound.play();
}
if (Keyboard::isKeyPressed(sf::Keyboard::Space) && _player->inCollision()) {
_player->addVelocity(Point4D{0, std::abs(_player->collisionNormal().y()) * sqrt(2 * _g * _jumpHeight) * coeff, 0});
_player->translate(Point4D{0, Time::deltaTime() * _walkSpeed * 2 * coeff, 0});
}
// Mouse movement
Point4D disp = _mouse->getMouseDisplacement();
_player->rotate(Point4D{0, -disp.x() / 1000.0, 0});
_player->setVelocity(Matrix4x4::RotationY(-disp.x() / 1000.0) * _player->velocity());
double rotationLeft = disp.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();
_player->camera()->rotateLeft(rotationLeft);
_player->rotateWeaponsRelativePoint(_player->position() + Point4D{0, 1.8, 0}, _player->camera()->left(), rotationLeft);
if (_keyboard->isKeyTapped(sf::Keyboard::Right) || _keyboard->isKeyTapped(sf::Keyboard::E)) {
_player->nextWeapon();
}
if (_keyboard->isKeyTapped(sf::Keyboard::Left) || _keyboard->isKeyTapped(sf::Keyboard::Q)) {
_player->previousWeapon();
}
if (Mouse::isButtonPressed(sf::Mouse::Button::Left)) {
_player->fire();
}
if(Keyboard::isKeyPressed(sf::Keyboard::R)) {
_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();
}
}
}

39
PlayerController.h Normal file
View File

@ -0,0 +1,39 @@
//
// Created by Иван Ильин on 19.09.2021.
//
#ifndef SHOOTER_PLAYERCONTROLLER_H
#define SHOOTER_PLAYERCONTROLLER_H
#include "Player.h"
#include "Keyboard.h"
#include "Mouse.h"
class PlayerController {
private:
std::shared_ptr<Player> _player;
std::shared_ptr<World> _world;
std::shared_ptr<Keyboard> _keyboard;
std::shared_ptr<Mouse> _mouse;
bool _inRunning = false;
double _slowMoCoefficient = 5;
bool _isInSlowMo = false;
double _g = 35;
sf::Sound _slowMoSound;
sf::Sound _unSlowMoSound;
sf::Sound _changeWeaponSound;
sf::Sound _walkSound;
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);
void update();
};
#endif //SHOOTER_PLAYERCONTROLLER_H

View File

@ -10,6 +10,9 @@
Engine::Engine() {
screen = std::make_shared<Screen>();
keyboard = std::make_shared<Keyboard>();
mouse = std::make_shared<Mouse>();
world = std::make_shared<World>();
camera = std::make_shared<Camera>();
}
@ -18,13 +21,14 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name,
_name = name;
screen->open(screenWidth, screenHeight, name, verticalSync, background, style);
screen->attachMouse(mouse);
Log::log("Engine::create(): started engine (" + std::to_string(screenWidth) + " x " + std::to_string(screenHeight) + ") with name '" + name + "'.");
Log::log("Engine::create(): started engine (" + std::to_string(screenWidth) + " x " + std::to_string(screenHeight) + ") with title '" + name + "'.");
Time::update();
start();
camera->init(screenWidth, screenHeight);
screen->getMouseDisplacement(); // We do it to set mouse position in the center (see how getMouseDisplacement() works)
mouse->setMouseInCenter();
while (screen->isOpen()) {
screen->clear();
@ -69,7 +73,8 @@ void Engine::exit() {
screen->close();
}
ResourceManager::unloadAllResources();
Log::log("Engine::exit(): exit engine (" + std::to_string(screen->width()) + " x " + std::to_string(screen->height()) + ") with name '" + screen->name() + "'.");
Log::log("Engine::exit(): exit engine (" + std::to_string(screen->width()) + " x " + std::to_string(screen->height()) + ") with title '" +
screen->title() + "'.");
}
void Engine::printDebugText() const {

View File

@ -6,6 +6,9 @@
#define ENGINE_ENGINE_H
#include "Screen.h"
#include "Keyboard.h"
#include "Mouse.h"
#include "World.h"
#include "Camera.h"
#include "utils/Log.h"
@ -21,6 +24,9 @@ private:
protected:
std::shared_ptr<Screen> screen;
std::shared_ptr<Keyboard> keyboard;
std::shared_ptr<Mouse> mouse;
std::shared_ptr<World> world;
std::shared_ptr<Camera> camera;

24
engine/Keyboard.cpp Normal file
View File

@ -0,0 +1,24 @@
//
// Created by Иван Ильин on 19.09.2021.
//
#include "Keyboard.h"
#include "utils/Time.h"
bool Keyboard::isKeyPressed(sf::Keyboard::Key key) {
return sf::Keyboard::isKeyPressed(key);
}
bool Keyboard::isKeyTapped(sf::Keyboard::Key key) {
if (!Keyboard::isKeyPressed(key))
return false;
if(_tappedKeys.count(key) == 0) {
_tappedKeys.emplace(key, Time::time());
return true;
} else if((Time::time() - _tappedKeys[key]) > 0.2) {
_tappedKeys[key] = Time::time();
return true;
}
return false;
}

21
engine/Keyboard.h Normal file
View File

@ -0,0 +1,21 @@
//
// Created by Иван Ильин on 19.09.2021.
//
#ifndef SHOOTER_KEYBOARD_H
#define SHOOTER_KEYBOARD_H
#include <SFML/Graphics.hpp>
class Keyboard {
private:
std::map<sf::Keyboard::Key, double> _tappedKeys;
public:
Keyboard() = default;
static bool isKeyPressed(sf::Keyboard::Key key); // returns true if this key is pressed
bool isKeyTapped(sf::Keyboard::Key key); // returns true if this key is tapped and 1/5 sec passed (button bouncing problem solved)
};
#endif //SHOOTER_KEYBOARD_H

50
engine/Mouse.cpp Normal file
View File

@ -0,0 +1,50 @@
//
// Created by Иван Ильин on 19.09.2021.
//
#include "Mouse.h"
#include "utils/Time.h"
Point4D Mouse::getMousePosition() const {
sf::Vector2<int> pos = sf::Mouse::getPosition(*_window);
return Point4D(pos.x, pos.y, 0, 0);
}
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;
//setMouseInCenter();
return Point4D(disp.x, disp.y, 0, 0);
}
void Mouse::setMouseInCenter() const {
sf::Mouse::setPosition({ static_cast<int>(_window->getSize().x / 2), static_cast<int>(_window->getSize().y / 2) }, *_window);
}
bool Mouse::isButtonPressed(sf::Mouse::Button button) {
return sf::Mouse::isButtonPressed(button);
}
bool Mouse::isButtonTapped(sf::Mouse::Button button) {
if (!Mouse::isButtonPressed(button))
return false;
if(_tappedButtons.count(button) == 0) {
_tappedButtons.emplace(button, Time::time());
return true;
} else if((Time::time() - _tappedButtons[button]) > 0.2) {
_tappedButtons[button] = Time::time();
return true;
}
return false;
}
void Mouse::setWindow(std::shared_ptr<sf::RenderWindow> window) {
_window = window;
}
void Mouse::setMouseCursorVisible(bool visible) {
_window->setMouseCursorVisible(visible);
}

31
engine/Mouse.h Normal file
View File

@ -0,0 +1,31 @@
//
// Created by Иван Ильин on 19.09.2021.
//
#ifndef SHOOTER_MOUSE_H
#define SHOOTER_MOUSE_H
#include <SFML/Graphics.hpp>
#include "utils/Point4D.h"
class Mouse {
private:
std::shared_ptr<sf::RenderWindow> _window;
std::map<sf::Mouse::Button, double> _tappedButtons;
public:
Mouse() = default;
void setWindow(std::shared_ptr<sf::RenderWindow> window);
static bool isButtonPressed(sf::Mouse::Button button); // returns true if this button is pressed
bool isButtonTapped(sf::Mouse::Button button); // returns true if this button is tapped and 1/5 sec passed (button bouncing problem solved)
[[nodiscard]] Point4D getMousePosition() const;
[[nodiscard]] Point4D getMouseDisplacement() const;
void setMouseInCenter() const;
void setMouseCursorVisible(bool visible);
};
#endif //SHOOTER_MOUSE_H

View File

@ -11,7 +11,7 @@
void Screen::open(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) {
_name = name;
_title = name;
_w = screenWidth;
_h = screenHeight;
_background = background;
@ -19,26 +19,27 @@ void Screen::open(int screenWidth, int screenHeight, const std::string &name, bo
sf::ContextSettings settings;
settings.antialiasingLevel = 8;
window.create(sf::VideoMode(_w, _h), name, style, settings);
window.setVerticalSyncEnabled(verticalSync);
_window = std::make_shared<sf::RenderWindow>();
_window->create(sf::VideoMode(_w, _h), name, style, settings);
_window->setVerticalSyncEnabled(verticalSync);
}
void Screen::display() {
sf::Event event{};
while (window.pollEvent(event)) {
while (_window->pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
_window->close();
}
}
std::string title = _name + " (" + std::to_string(Time::fps()) + " fps)";
window.setTitle(title);
std::string title = _title + " (" + std::to_string(Time::fps()) + " fps)";
_window->setTitle(title);
window.display();
_window->display();
}
void Screen::clear() {
window.clear(_background);
_window->clear(_background);
}
void Screen::drawTriangle(const Triangle& triangle)
@ -49,74 +50,19 @@ void Screen::drawTriangle(const Triangle& triangle)
sf::Vertex(sf::Vector2f(triangle[1].x(), triangle[1].y()), triangle.color()),
sf::Vertex(sf::Vector2f(triangle[2].x(), triangle[2].y()), triangle.color())
};
window.draw(tris, 3, sf::Triangles);
_window->draw(tris, 3, sf::Triangles);
}
void Screen::setName(const std::string& title) {
_name = title;
void Screen::setTitle(const std::string& title) {
_title = title;
}
bool Screen::isOpen() {
return window.isOpen();
return _window->isOpen();
}
void Screen::close() {
window.close();
}
bool Screen::isKeyPressed(sf::Keyboard::Key key) {
return sf::Keyboard::isKeyPressed(key);
}
Point4D Screen::getMousePosition() const {
sf::Vector2<int> pos = sf::Mouse::getPosition(window);
return Point4D(pos.x, pos.y, 0, 0);
}
Point4D Screen::getMouseDisplacement() const {
sf::Vector2<int> disp = sf::Mouse::getPosition(window) - sf::Vector2<int>(_w/2, _h/2);
setMouseInCenter();
return Point4D(disp.x, disp.y, 0, 0);
}
void Screen::setMouseInCenter() const {
sf::Mouse::setPosition({ _w / 2, _h / 2 }, window);
}
void Screen::setMouseCursorVisible(bool visible) {
window.setMouseCursorVisible(visible);
}
bool Screen::isKeyTapped(sf::Keyboard::Key key) {
if (!Screen::isKeyPressed(key))
return false;
if(_tappedKeys.count(key) == 0) {
_tappedKeys.emplace(key, Time::time());
return true;
} else if((Time::time() - _tappedKeys[key]) > 0.2) {
_tappedKeys[key] = Time::time();
return true;
}
return false;
}
bool Screen::isButtonPressed(sf::Mouse::Button button) {
return sf::Mouse::isButtonPressed(button);
}
bool Screen::isButtonTapped(sf::Mouse::Button button) {
if (!Screen::isButtonPressed(button))
return false;
if(_tappedButtons.count(button) == 0) {
_tappedButtons.emplace(button, Time::time());
return true;
} else if((Time::time() - _tappedButtons[button]) > 0.2) {
_tappedButtons[button] = Time::time();
return true;
}
return false;
_window->close();
}
@ -129,5 +75,42 @@ void Screen::debugText(const std::string& text) {
t.setFillColor(sf::Color::Black);
t.setPosition(10, 10);
window.draw(t);
_window->draw(t);
}
void Screen::drawTetragon(const Point4D &p1, const Point4D &p2, const Point4D &p3, const Point4D &p4, sf::Color color) {
sf::ConvexShape polygon;
polygon.setPointCount(4);
polygon.setPoint(0, sf::Vector2f((float)p1.x(), (float)p1.y()));
polygon.setPoint(1, sf::Vector2f((float)p2.x(), (float)p2.y()));
polygon.setPoint(2, sf::Vector2f((float)p3.x(), (float)p3.y()));
polygon.setPoint(3, sf::Vector2f((float)p4.x(), (float)p4.y()));
polygon.setFillColor(color);
_window->draw(polygon);
}
void Screen::drawText(const std::string& string, const Point4D &position, int size, sf::Color color) {
sf::Text text;
text.setFont(*ResourceManager::loadFont("../engine/fonts/Roboto-Medium.ttf"));
text.setCharacterSize(size);
text.setFillColor(color);
text.setStyle(sf::Text::Italic);
text.setPosition((float)position.x(), (float)position.y());
text.setString(string);
_window->draw(text);
}
void Screen::drawSprite(const sf::Sprite &sprite) {
_window->draw(sprite);
}
void Screen::drawText(const sf::Text &text) {
_window->draw(text);
}
void Screen::attachMouse(std::shared_ptr<Mouse> mouse) {
mouse->setWindow(_window);
}

View File

@ -11,53 +11,46 @@
#include <SFML/Graphics.hpp>
#include <map>
#include "utils/Time.h"
#include "Mouse.h"
class Screen {
private:
int _w = 1920;
int _h = 1080;
std::string _name;
std::string _title;
sf::Color _background;
std::map<sf::Keyboard::Key, double> _tappedKeys;
std::map<sf::Mouse::Button, double> _tappedButtons;
std::string _font = "../engine/fonts/Roboto-Thin.ttf";
std::shared_ptr<sf::RenderWindow> _window;
public:
sf::RenderWindow window;
void open(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);
void display();
void clear();
bool hasFocus() const { return _window->hasFocus(); }
void drawTriangle(const Triangle& triangle);
void drawTetragon(const Point4D& p1, const Point4D& p2, const Point4D& p3, const Point4D& p4, sf::Color color);
void drawText(const std::string& string, const Point4D& position, int size, sf::Color color);
void drawText(const sf::Text& text);
void drawSprite(const sf::Sprite& sprite);
void setName(const std::string& title);
std::string name() const { return _name; };
void setTitle(const std::string& title);
[[nodiscard]] std::string title() const { return _title; };
bool isOpen();
int width() const {return window.getSize().x;}
int height() const {return window.getSize().y;}
[[nodiscard]] int width() const {return _window->getSize().x;}
[[nodiscard]] int height() const {return _window->getSize().y;}
void close();
static bool isKeyPressed(sf::Keyboard::Key key); // returns true if this key is pressed
bool isKeyTapped(sf::Keyboard::Key key); // returns true if this key is tapped and 1/5 sec passed (button bouncing problem solved)
static bool isButtonPressed(sf::Mouse::Button button); // returns true if this button is pressed
bool isButtonTapped(sf::Mouse::Button button); // returns true if this button is tapped and 1/5 sec passed (button bouncing problem solved)
Point4D getMousePosition() const;
Point4D getMouseDisplacement() const;
void setMouseInCenter() const;
void setMouseCursorVisible(bool visible);
void debugText(const std::string& text);
void attachMouse(std::shared_ptr<Mouse> mouse);
};

View File

@ -16,7 +16,7 @@ void World::addBody(std::shared_ptr<RigidBody> body, const string &name) {
void World::loadBody(const string &name, const string &filename, const std::string &materials, const Point4D& scale) {
_objects.emplace(name, std::make_shared<RigidBody>(Mesh(filename, materials, scale)));
Log::log("World::loadBody(): inserted body from " + filename + " with name '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " _tris.");
Log::log("World::loadBody(): inserted body from " + filename + " with title '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " _tris.");
}
void World::removeBody(const string &name) {

View File

@ -29,7 +29,7 @@ public:
// rayCast returns pair of Point4D and std::string:
// 1) Point4D is point of collision (the last coordinate is -1 if there are no collisions)
// 2) std::string - name of the object
// 2) std::string - title of the object
std::pair<Point4D, std::string> rayCast(const Point4D& from, const Point4D& to);
void loadMap(const std::string& filename, const std::string& name = "", const Point4D& scale = Point4D{1, 1, 1}, const std::string &materials = "../maps/materials.txt");

View File

@ -14,15 +14,15 @@ void Window::addButton(int x, int y, int w, int h, std::function<void()> click,
buttons.back().init();
}
void Window::update(std::shared_ptr<Screen> screen) {
void Window::update() {
screen->setName(s_name);
screen->window.draw(back);
_screen->setTitle(s_name);
_screen->drawSprite(back);
Point4D mousePos = screen->getMousePosition();
Point4D mousePos = _mouse->getMousePosition();
Point4D dMousePos = mousePos - prevMousePosition;
back.setPosition(back.getPosition() - sf::Vector2f(dMousePos.x()/30, dMousePos.y()/30));
bool isPressed = screen->isButtonTapped(sf::Mouse::Left);
bool isPressed = _mouse->isButtonTapped(sf::Mouse::Left);
for(auto& button : buttons) {
if( mousePos.x() > button.x - button.w*button.sx/2 && mousePos.y() > button.y - button.h*button.sy/2 &&
@ -34,9 +34,9 @@ void Window::update(std::shared_ptr<Screen> screen) {
button.unSelect();
}
if(screen->isOpen()) {
screen->window.draw(button.button);
screen->window.draw(button.text);
if(_screen->isOpen()) {
_screen->drawSprite(button.button);
_screen->drawText(button.text);
}
}

View File

@ -10,6 +10,7 @@
#include "Button.h"
#include "Screen.h"
#include "Mouse.h"
class Window {
private:
@ -20,8 +21,11 @@ private:
sf::Sprite back;
Point4D prevMousePosition;
std::shared_ptr<Screen> _screen;
std::shared_ptr<Mouse> _mouse;
public:
explicit Window(std::string name = "Menu", std::string backTexture = "") : s_name(std::move(name)), s_backTexture(std::move(backTexture)){}
explicit Window(std::shared_ptr<Screen> screen, std::shared_ptr<Mouse> mouse, std::string name = "Menu", std::string backTexture = "") : _screen(screen), _mouse(mouse), s_name(std::move(name)), s_backTexture(std::move(backTexture)){}
void addButton(int x, int y, int w, int h,
std::function<void()> click,
@ -34,7 +38,7 @@ public:
void setBackgroundTexture(const std::string& texture, double sx = 1, double sy = 1, int w = 1920, int h = 1080);
void update(std::shared_ptr<Screen> screen);
void update();
};

View File

@ -52,6 +52,8 @@ public:
std::pair<bool, Simplex> checkGJKCollision(std::shared_ptr<RigidBody> obj);
CollisionPoint EPA(const Simplex& simplex, std::shared_ptr<RigidBody> obj);
[[nodiscard]] Point4D collisionNormal() const { return _collisionNormal; }
[[nodiscard]] bool isCollision() const { return _collision; }
[[nodiscard]] bool inCollision() const {return _inCollision; }
[[nodiscard]] bool isCollider() const {return _isCollider; }
@ -67,6 +69,7 @@ public:
void setAcceleration(const Point4D& acceleration);
[[nodiscard]] Point4D velocity() const { return _velocity; }
[[nodiscard]] Point4D acceleration() const { return _acceleration; }
[[nodiscard]] const std::function<void(const std::string&, std::shared_ptr<RigidBody>)>& collisionCallBack() const { return _collisionCallBack; }
void setCollisionCallBack(const std::function<void(const std::string&, std::shared_ptr<RigidBody>)>& f) { _collisionCallBack = f; }

View File

@ -7,6 +7,7 @@
#include "Player.h"
#include "ResourceManager.h"
#include "gui/Window.h"
#include "PlayerController.h"
#include "Client.h"
#include "Server.h"
@ -61,6 +62,7 @@ void InitNetwork(shared_ptr<Server> server, shared_ptr<Client> client)
class Shooter : public Engine {
private:
shared_ptr<Player> player;
shared_ptr<PlayerController> playerController;
sf::Sound backgroundNoise;
@ -72,7 +74,7 @@ private:
bool inGame = false;
public:
Shooter() = default;
Shooter() : mainMenu(screen, mouse) {};
void start() override;
void update() override;
@ -86,11 +88,13 @@ void Shooter::start() {
// This code executed once in the beginning:
setDebugText(false);
screen->setMouseCursorVisible(true);
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>();
@ -139,22 +143,23 @@ void Shooter::update() {
client->update();
// Check all input after this condition please
if (!screen->window.hasFocus())
if (!screen->hasFocus())
return;
if(screen->isKeyTapped(sf::Keyboard::Escape)) {
if(keyboard->isKeyTapped(sf::Keyboard::Escape)) {
inGame = !inGame;
screen->setMouseCursorVisible(!inGame);
mouse->setMouseCursorVisible(!inGame);
}
if(inGame) {
screen->setName("Shooter");
screen->setTitle("Shooter");
player->update();
playerController->update();
mouse->setMouseInCenter();
} else {
mainMenu.update(screen);
mainMenu.update();
}
setUpdateWorld(inGame);
// background sounds and music control
@ -172,7 +177,7 @@ void Shooter::gui() {
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->window.draw(sprite);
screen->drawSprite(sprite);
// health player stats
player->drawStats();
@ -181,10 +186,10 @@ void Shooter::gui() {
void Shooter::play() {
inGame = true;
screen->setMouseCursorVisible(!inGame);
mouse->setMouseCursorVisible(!inGame);
}
int main(int argc, char* argv[]) {
int main() {
Shooter game;
//game.create(1280, 720, "Shooter");