OpenGL graphics acceleration support!
parent
22c18968f6
commit
e471795290
|
@ -113,3 +113,19 @@ if (SFML_FOUND)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(shooter sfml-audio sfml-network sfml-graphics sfml-window sfml-system)
|
target_link_libraries(shooter sfml-audio sfml-network sfml-graphics sfml-window sfml-system)
|
||||||
|
|
||||||
|
# OpenGL part
|
||||||
|
if (APPLE OR UNIX)
|
||||||
|
set(GLEW_H /usr/local/Cellar/glew/2.1.0/include/GL)
|
||||||
|
set(GLFW_H /usr/local/Cellar/glfw/3.2.1/include/GLFW)
|
||||||
|
include_directories(${GLEW_H} ${GLFW_H})
|
||||||
|
|
||||||
|
set(GLEW_LINK /usr/local/Cellar/glew/2.1.0/lib/libGLEW.2.1.dylib)
|
||||||
|
set(GLFW_LINK /usr/local/Cellar/glfw/3.2.1/lib/libglfw.3.dylib)
|
||||||
|
link_libraries(${OPENGL} ${GLEW_LINK} ${GLFW_LINK})
|
||||||
|
|
||||||
|
target_link_libraries(shooter "-framework OpenGL")
|
||||||
|
target_link_libraries(shooter "-framework GLUT")
|
||||||
|
else()
|
||||||
|
|
||||||
|
endif()
|
10
Player.cpp
10
Player.cpp
|
@ -8,7 +8,7 @@
|
||||||
#include "engine/utils/Log.h"
|
#include "engine/utils/Log.h"
|
||||||
|
|
||||||
Player::Player() {
|
Player::Player() {
|
||||||
loadObj(ShooterConsts::CUBE_OBJ, Vec3D{0.5, 1.9, 0.5});
|
loadObj(ShooterConsts::CUBE_OBJ, Vec3D{1.5, 1.9, 1.5});
|
||||||
setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0});
|
setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0});
|
||||||
setCollision(true);
|
setCollision(true);
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
@ -109,15 +109,17 @@ void Player::previousWeapon() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::fire() {
|
bool Player::fire() {
|
||||||
auto camera = attached(ObjectNameTag("Camera"));
|
auto camera = attached(ObjectNameTag("Camera"));
|
||||||
if(camera != nullptr) {
|
if(camera != nullptr) {
|
||||||
auto damagedPlayers = _weapons[_selectedWeapon]->fire(_rayCastFunction, camera->position(), camera->lookAt());
|
auto fireInfo = _weapons[_selectedWeapon]->fire(_rayCastFunction, camera->position(), camera->lookAt());
|
||||||
for(auto& [damagedPlayerName, damage] : damagedPlayers) {
|
for(auto& [damagedPlayerName, damage] : fireInfo.damagedPlayers) {
|
||||||
sf::Uint16 targetId = std::stoi(damagedPlayerName.str().substr(6));
|
sf::Uint16 targetId = std::stoi(damagedPlayerName.str().substr(6));
|
||||||
_damagePlayerCallBack(targetId, damage);
|
_damagePlayerCallBack(targetId, damage);
|
||||||
}
|
}
|
||||||
|
return fireInfo.shot;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::reload() {
|
void Player::reload() {
|
||||||
|
|
8
Player.h
8
Player.h
|
@ -37,7 +37,7 @@ private:
|
||||||
std::function<void(std::shared_ptr<Weapon>)> _addWeaponCallBack;
|
std::function<void(std::shared_ptr<Weapon>)> _addWeaponCallBack;
|
||||||
std::function<void(std::shared_ptr<Weapon>)> _removeWeaponCallBack;
|
std::function<void(std::shared_ptr<Weapon>)> _removeWeaponCallBack;
|
||||||
|
|
||||||
std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> _rayCastFunction;
|
std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> _rayCastFunction;
|
||||||
public:
|
public:
|
||||||
Player();
|
Player();
|
||||||
|
|
||||||
|
@ -57,8 +57,10 @@ public:
|
||||||
|
|
||||||
void nextWeapon();
|
void nextWeapon();
|
||||||
void previousWeapon();
|
void previousWeapon();
|
||||||
void fire();
|
bool fire();
|
||||||
void reload();
|
void reload();
|
||||||
|
[[nodiscard]] ObjectNameTag weaponName() const { return _weapons[_selectedWeapon]->name(); }
|
||||||
|
std::shared_ptr<Weapon> weapon() { return _weapons[_selectedWeapon]; }
|
||||||
|
|
||||||
void rotateWeaponsRelativePoint(const Vec3D& point, const Vec3D& v, double val);
|
void rotateWeaponsRelativePoint(const Vec3D& point, const Vec3D& v, double val);
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ public:
|
||||||
void setRemoveWeaponCallBack(std::function<void(std::shared_ptr<Weapon>)> removeWeapon) {
|
void setRemoveWeaponCallBack(std::function<void(std::shared_ptr<Weapon>)> removeWeapon) {
|
||||||
_removeWeaponCallBack = std::move(removeWeapon);
|
_removeWeaponCallBack = std::move(removeWeapon);
|
||||||
}
|
}
|
||||||
void setRayCastFunction(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction) {
|
void setRayCastFunction(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction) {
|
||||||
_rayCastFunction = std::move(rayCastFunction);
|
_rayCastFunction = std::move(rayCastFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "engine/animation/ATranslate.h"
|
#include "engine/animation/ATranslate.h"
|
||||||
#include "engine/animation/ATranslateToPoint.h"
|
#include "engine/animation/ATranslateToPoint.h"
|
||||||
#include "engine/animation/Timeline.h"
|
#include "engine/animation/Timeline.h"
|
||||||
|
#include "engine/animation/ARotate.h"
|
||||||
#include "ShooterConsts.h"
|
#include "ShooterConsts.h"
|
||||||
|
|
||||||
PlayerController::PlayerController(std::shared_ptr<Player> player,
|
PlayerController::PlayerController(std::shared_ptr<Player> player,
|
||||||
|
@ -107,15 +108,24 @@ void PlayerController::update() {
|
||||||
SoundController::playSound(SoundTag("unSlowMo"), ShooterConsts::UN_SLOW_MO_SOUND);
|
SoundController::playSound(SoundTag("unSlowMo"), ShooterConsts::UN_SLOW_MO_SOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Mouse::isButtonPressed(sf::Mouse::Button::Left)) {
|
||||||
|
bool shot = _player->fire();
|
||||||
|
|
||||||
|
if(shot) {
|
||||||
|
if(!_player->inCollision() && (_player->weaponName() == ObjectNameTag("shotgun")))
|
||||||
|
_player->addVelocity(-camera->lookAt() * 30 * coeff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Keyboard::isKeyPressed(sf::Keyboard::Space) && _player->inCollision()) {
|
if (Keyboard::isKeyPressed(sf::Keyboard::Space) && _player->inCollision()) {
|
||||||
// if we just want to jump, we have to add particular speed
|
// if we just want to jump, we have to add particular speed
|
||||||
if (!_isSliding)
|
if (!_isSliding)
|
||||||
_player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff, 0 });
|
_player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff, 0 });
|
||||||
// if we want to slide, we have to add speed * 60/fps to make it independent on frame rate
|
// if we want to slide, we have to add speed * 60/fps to make it independent on frame rate
|
||||||
else
|
else
|
||||||
_player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff * 60.0 / Time::fps(), 0 });
|
_player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff * Time::deltaTime() * 60, 0 });
|
||||||
|
|
||||||
_player->translate(Vec3D{ 0, Time::deltaTime() * ShooterConsts::WALK_SPEED * 2 * coeff * 60.0 / Time::fps(), 0 });
|
_player->translate(Vec3D{ 0, Time::deltaTime() * ShooterConsts::WALK_SPEED * 2 * coeff, 0 });
|
||||||
_isSliding = true;
|
_isSliding = true;
|
||||||
} else {
|
} else {
|
||||||
_isSliding = false;
|
_isSliding = false;
|
||||||
|
@ -149,10 +159,6 @@ void PlayerController::update() {
|
||||||
_player->previousWeapon();
|
_player->previousWeapon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Mouse::isButtonPressed(sf::Mouse::Button::Left)) {
|
|
||||||
_player->fire();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Keyboard::isKeyPressed(sf::Keyboard::R)) {
|
if(Keyboard::isKeyPressed(sf::Keyboard::R)) {
|
||||||
_player->reload();
|
_player->reload();
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,3 +59,4 @@ GamePlay:
|
||||||
![Project demonstration](img/gamePlay5.png)
|
![Project demonstration](img/gamePlay5.png)
|
||||||
![Project demonstration](img/gamePlay6.png)
|
![Project demonstration](img/gamePlay6.png)
|
||||||
![Project demonstration](img/gamePlay7.png)
|
![Project demonstration](img/gamePlay7.png)
|
||||||
|
![Project demonstration](img/opengl.png)
|
||||||
|
|
|
@ -81,7 +81,7 @@ void Shooter::start() {
|
||||||
// TODO: encapsulate call backs inside Player
|
// TODO: encapsulate call backs inside Player
|
||||||
player->setAddTraceCallBack([this](const Vec3D& from, const Vec3D& to){ client->addTrace(from, to); addFireTrace(from, to); });
|
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->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); });
|
||||||
player->setRayCastFunction([this](const Vec3D& from, const Vec3D& to) { return world->rayCast(from, to, "Enemy"); });
|
player->setRayCastFunction([this](const Vec3D& from, const Vec3D& to) { return world->rayCast(from, to, "weapon Player"); });
|
||||||
player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); });
|
player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); });
|
||||||
player->setAddWeaponCallBack([this](std::shared_ptr<Weapon> weapon){ addWeapon(std::move(weapon)); });
|
player->setAddWeaponCallBack([this](std::shared_ptr<Weapon> weapon){ addWeapon(std::move(weapon)); });
|
||||||
player->setRemoveWeaponCallBack([this](std::shared_ptr<Weapon> weapon){ removeWeapon(std::move(weapon)); });
|
player->setRemoveWeaponCallBack([this](std::shared_ptr<Weapon> weapon){ removeWeapon(std::move(weapon)); });
|
||||||
|
@ -246,7 +246,7 @@ void Shooter::addFireTrace(const Vec3D &from, const Vec3D &to) {
|
||||||
world->addBody(std::make_shared<RigidBody>(Mesh::LineTo(from, to, 0.05)), ObjectNameTag(traceName));
|
world->addBody(std::make_shared<RigidBody>(Mesh::LineTo(from, to, 0.05)), ObjectNameTag(traceName));
|
||||||
world->body(ObjectNameTag(traceName))->setCollider(false);
|
world->body(ObjectNameTag(traceName))->setCollider(false);
|
||||||
|
|
||||||
Timeline::animate(AnimationListTag(traceName + "_fadeOut"), new AColor(world->body(ObjectNameTag(traceName)), {255, 255, 255, 0}));
|
Timeline::animate(AnimationListTag(traceName + "_fadeOut"), new AColor(world->body(ObjectNameTag(traceName)), {150, 150, 150, 0}));
|
||||||
Timeline::animate(AnimationListTag(traceName + "_delete"), new AFunction([this, traceName](){ removeFireTrace(ObjectNameTag(traceName)); }, 1, 2));
|
Timeline::animate(AnimationListTag(traceName + "_delete"), new AFunction([this, traceName](){ removeFireTrace(ObjectNameTag(traceName)); }, 1, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ void Shooter::removeBonus(const ObjectNameTag &bonusName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shooter::addWeapon(std::shared_ptr<Weapon> weapon) {
|
void Shooter::addWeapon(std::shared_ptr<Weapon> weapon) {
|
||||||
world->addBody(weapon, weapon->name());
|
world->addBody(weapon, ObjectNameTag("weapon_" + weapon->name().str()));
|
||||||
|
|
||||||
if(client != nullptr)
|
if(client != nullptr)
|
||||||
client->changeWeapon(weapon->name().str());
|
client->changeWeapon(weapon->name().str());
|
||||||
|
@ -294,5 +294,5 @@ void Shooter::changeEnemyWeapon(const std::string& weaponName, sf::Uint16 enemyI
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shooter::removeWeapon(std::shared_ptr<Weapon> weapon) {
|
void Shooter::removeWeapon(std::shared_ptr<Weapon> weapon) {
|
||||||
world->removeBody(ObjectNameTag(weapon->name()));
|
world->removeBody(ObjectNameTag("weapon_" + weapon->name().str()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "utils/Log.h"
|
#include "utils/Log.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "Consts.h"
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Triangle>> Camera::project(std::shared_ptr<Mesh> mesh) {
|
std::vector<std::shared_ptr<Triangle>> Camera::project(std::shared_ptr<Mesh> mesh) {
|
||||||
|
|
||||||
|
@ -128,3 +127,30 @@ void Camera::clear() {
|
||||||
_triangles.clear();
|
_triangles.clear();
|
||||||
_V = Matrix4x4::View(left(), up(), lookAt(), position());
|
_V = Matrix4x4::View(left(), up(), lookAt(), position());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenGL function
|
||||||
|
GLfloat *Camera::view() const {
|
||||||
|
auto* v = (GLfloat*)malloc(4*4*sizeof(GLfloat));
|
||||||
|
|
||||||
|
v[0] = -(GLfloat)left().x();
|
||||||
|
v[4] = -(GLfloat)left().y();
|
||||||
|
v[8] = -(GLfloat)left().z();
|
||||||
|
v[12] = (GLfloat)position().dot(left());
|
||||||
|
|
||||||
|
v[1] = (GLfloat)up().x();
|
||||||
|
v[5] = (GLfloat)up().y();
|
||||||
|
v[9] = (GLfloat)up().z();
|
||||||
|
v[13] = -(GLfloat)position().dot(up());
|
||||||
|
|
||||||
|
v[2] = -(GLfloat)lookAt().x();
|
||||||
|
v[6] = -(GLfloat)lookAt().y();
|
||||||
|
v[10] = -(GLfloat)lookAt().z();
|
||||||
|
v[14] = (GLfloat)position().dot(lookAt());
|
||||||
|
|
||||||
|
v[3] = (GLfloat)0.0f;
|
||||||
|
v[7] = (GLfloat)0.0f;
|
||||||
|
v[11] = (GLfloat)0.0f;
|
||||||
|
v[15] = (GLfloat)1.0f;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
#define ENGINE_CAMERA_H
|
#define ENGINE_CAMERA_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Screen.h"
|
|
||||||
#include "Plane.h"
|
#include "Plane.h"
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
|
#include <SFML/OpenGL.hpp>
|
||||||
|
|
||||||
class Camera final : public Object{
|
class Camera final : public Object{
|
||||||
private:
|
private:
|
||||||
|
@ -24,6 +24,7 @@ private:
|
||||||
|
|
||||||
bool _ready = false;
|
bool _ready = false;
|
||||||
double _aspect = 0;
|
double _aspect = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Camera() = default;
|
Camera() = default;
|
||||||
Camera(const Camera& camera) = delete;
|
Camera(const Camera& camera) = delete;
|
||||||
|
@ -36,6 +37,9 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] int buffSize() const { return _triangles.size(); }
|
[[nodiscard]] int buffSize() const { return _triangles.size(); }
|
||||||
std::vector<std::shared_ptr<Triangle>> sorted();
|
std::vector<std::shared_ptr<Triangle>> sorted();
|
||||||
|
|
||||||
|
// OpenGL function
|
||||||
|
[[nodiscard]] GLfloat* view() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Consts {
|
||||||
const sf::Color BACKGROUND_COLOR = sf::Color(255, 255, 255);
|
const sf::Color BACKGROUND_COLOR = sf::Color(255, 255, 255);
|
||||||
const std::string PROJECT_NAME = "engine";
|
const std::string PROJECT_NAME = "engine";
|
||||||
const bool USE_LOG_FILE = true;
|
const bool USE_LOG_FILE = true;
|
||||||
|
const bool USE_OPEN_GL = true;
|
||||||
|
|
||||||
const double PI = 3.14159265358979323846264338327950288;
|
const double PI = 3.14159265358979323846264338327950288;
|
||||||
const double EPS = 0.000001;
|
const double EPS = 0.000001;
|
||||||
|
|
|
@ -42,11 +42,6 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name,
|
||||||
Time::update();
|
Time::update();
|
||||||
update();
|
update();
|
||||||
|
|
||||||
/* Project all mesh
|
|
||||||
* Here we project all _tris for each body from world._objects.
|
|
||||||
* When we call camera.project(m.second),
|
|
||||||
*/
|
|
||||||
|
|
||||||
// sometimes we dont need to update physics world
|
// sometimes we dont need to update physics world
|
||||||
// (for example in menu or while pause)
|
// (for example in menu or while pause)
|
||||||
// hence we can set '_updateWorld' equal to false in setUpdateWorld(bool):
|
// hence we can set '_updateWorld' equal to false in setUpdateWorld(bool):
|
||||||
|
@ -54,15 +49,30 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name,
|
||||||
|
|
||||||
Timeline::update();
|
Timeline::update();
|
||||||
|
|
||||||
camera->clear();
|
|
||||||
world->update();
|
world->update();
|
||||||
world->projectObjectsInCamera(camera);
|
|
||||||
|
|
||||||
// draw projected body
|
if(_useOpenGL) {
|
||||||
|
GLfloat* view = camera->view();
|
||||||
|
for(auto & it : *world) {
|
||||||
|
if (it.second->isVisible()) {
|
||||||
|
GLfloat* geometry = Screen::glMeshToGLfloatArray(it.second, camera->position());
|
||||||
|
screen->glDrawMesh(geometry, view, 3 * it.second->triangles().size());
|
||||||
|
free(geometry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(view);
|
||||||
|
} else {
|
||||||
|
// clear triangles from previous frame
|
||||||
|
camera->clear();
|
||||||
|
// project triangles to the camera plane
|
||||||
|
for(auto & it : *world)
|
||||||
|
camera->project(it.second);
|
||||||
|
// draw triangles on the screen
|
||||||
for (auto &t : camera->sorted())
|
for (auto &t : camera->sorted())
|
||||||
screen->drawTriangle(*t);
|
screen->drawTriangle(*t);
|
||||||
|
|
||||||
_triPerSec = camera->buffSize() * Time::fps();
|
_triPerSec = camera->buffSize() * Time::fps();
|
||||||
|
}
|
||||||
|
|
||||||
printDebugText();
|
printDebugText();
|
||||||
gui();
|
gui();
|
||||||
|
@ -87,13 +97,18 @@ void Engine::exit() {
|
||||||
|
|
||||||
void Engine::printDebugText() const {
|
void Engine::printDebugText() const {
|
||||||
if (_debugText) {
|
if (_debugText) {
|
||||||
screen->debugText(_name + "\n\n X: " +
|
std::string str = _name + "\n\n X: " +
|
||||||
std::to_string((camera->position().x())) + "\n Y: " +
|
std::to_string((camera->position().x())) + "\n Y: " +
|
||||||
std::to_string((camera->position().y())) + "\n Z: " +
|
std::to_string((camera->position().y())) + "\n Z: " +
|
||||||
std::to_string((camera->position().z())) + "\n\n" +
|
std::to_string((camera->position().z())) + "\n\n" +
|
||||||
std::to_string(screen->width()) + "x" +
|
std::to_string(screen->width()) + "x" +
|
||||||
std::to_string(screen->height()) + "\n" +
|
std::to_string(screen->height()) + "\t" +
|
||||||
std::to_string(Time::fps()) +
|
std::to_string(Time::fps()) + " fps";
|
||||||
" fps \n" + std::to_string((int) _triPerSec) + " tris/s");
|
if(_useOpenGL) {
|
||||||
|
str += "\n Using OpenGL acceleration";
|
||||||
|
} else {
|
||||||
|
str += "\n" + std::to_string((int) _triPerSec) + " tris/s";
|
||||||
|
}
|
||||||
|
screen->debugText(str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ private:
|
||||||
double _triPerSec = 0;
|
double _triPerSec = 0;
|
||||||
bool _debugText = true;
|
bool _debugText = true;
|
||||||
bool _updateWorld = true;
|
bool _updateWorld = true;
|
||||||
|
bool _useOpenGL = Consts::USE_OPEN_GL;
|
||||||
|
|
||||||
void printDebugText() const;
|
void printDebugText() const;
|
||||||
protected:
|
protected:
|
||||||
|
@ -35,6 +36,7 @@ protected:
|
||||||
|
|
||||||
void setDebugText(bool value) { _debugText = value; }
|
void setDebugText(bool value) { _debugText = value; }
|
||||||
void setUpdateWorld(bool value) { _updateWorld = value; }
|
void setUpdateWorld(bool value) { _updateWorld = value; }
|
||||||
|
void setGlEnable(bool value) { _useOpenGL = value; }
|
||||||
|
|
||||||
virtual void gui(){}
|
virtual void gui(){}
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -52,7 +52,7 @@ public:
|
||||||
~Mesh() override;
|
~Mesh() override;
|
||||||
|
|
||||||
Mesh static Obj(const std::string& filename);
|
Mesh static Obj(const std::string& filename);
|
||||||
Mesh static LineTo(const Vec3D& from, const Vec3D& to, double line_width = 0.1, const sf::Color& color = {150, 150, 150, 255});
|
Mesh static LineTo(const Vec3D& from, const Vec3D& to, double line_width = 0.1, const sf::Color& color = {150, 150, 150, 100});
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //INC_3DZAVR_MESH_H
|
#endif //INC_3DZAVR_MESH_H
|
||||||
|
|
|
@ -7,6 +7,9 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "utils/Log.h"
|
#include "utils/Log.h"
|
||||||
#include "ResourceManager.h"
|
#include "ResourceManager.h"
|
||||||
|
#include <SFML/OpenGL.hpp>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
void Screen::open(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) {
|
void Screen::open(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) {
|
||||||
_title = name;
|
_title = name;
|
||||||
|
@ -15,6 +18,7 @@ void Screen::open(int screenWidth, int screenHeight, const std::string &name, bo
|
||||||
_background = background;
|
_background = background;
|
||||||
|
|
||||||
sf::ContextSettings settings;
|
sf::ContextSettings settings;
|
||||||
|
settings.depthBits = 24;
|
||||||
settings.antialiasingLevel = 8;
|
settings.antialiasingLevel = 8;
|
||||||
|
|
||||||
_window = std::make_shared<sf::RenderWindow>();
|
_window = std::make_shared<sf::RenderWindow>();
|
||||||
|
@ -37,6 +41,9 @@ void Screen::display() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::clear() {
|
void Screen::clear() {
|
||||||
|
// Clear the depth buffer
|
||||||
|
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
_window->clear(_background);
|
_window->clear(_background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +55,10 @@ void Screen::drawTriangle(const Triangle& triangle)
|
||||||
sf::Vertex(sf::Vector2f((float)triangle[1].x(), (float)triangle[1].y()), triangle.color()),
|
sf::Vertex(sf::Vector2f((float)triangle[1].x(), (float)triangle[1].y()), triangle.color()),
|
||||||
sf::Vertex(sf::Vector2f((float)triangle[2].x(), (float)triangle[2].y()), triangle.color())
|
sf::Vertex(sf::Vector2f((float)triangle[2].x(), (float)triangle[2].y()), triangle.color())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_window->pushGLStates();
|
||||||
_window->draw(tris, 3, sf::Triangles);
|
_window->draw(tris, 3, sf::Triangles);
|
||||||
|
_window->popGLStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::setTitle(const std::string& title) {
|
void Screen::setTitle(const std::string& title) {
|
||||||
|
@ -71,9 +81,11 @@ void Screen::debugText(const std::string& text) {
|
||||||
t.setString(text);
|
t.setString(text);
|
||||||
t.setCharacterSize(30);
|
t.setCharacterSize(30);
|
||||||
t.setFillColor(sf::Color::Black);
|
t.setFillColor(sf::Color::Black);
|
||||||
t.setPosition(10, 10);
|
t.setPosition(10, 50);
|
||||||
|
|
||||||
|
_window->pushGLStates();
|
||||||
_window->draw(t);
|
_window->draw(t);
|
||||||
|
_window->popGLStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::drawTetragon(const Vec2D &p1, const Vec2D &p2, const Vec2D &p3, const Vec2D &p4, sf::Color color) {
|
void Screen::drawTetragon(const Vec2D &p1, const Vec2D &p2, const Vec2D &p3, const Vec2D &p4, sf::Color color) {
|
||||||
|
@ -84,7 +96,10 @@ void Screen::drawTetragon(const Vec2D &p1, const Vec2D &p2, const Vec2D &p3, con
|
||||||
polygon.setPoint(2, sf::Vector2f((float)p3.x(), (float)p3.y()));
|
polygon.setPoint(2, sf::Vector2f((float)p3.x(), (float)p3.y()));
|
||||||
polygon.setPoint(3, sf::Vector2f((float)p4.x(), (float)p4.y()));
|
polygon.setPoint(3, sf::Vector2f((float)p4.x(), (float)p4.y()));
|
||||||
polygon.setFillColor(color);
|
polygon.setFillColor(color);
|
||||||
|
|
||||||
|
_window->pushGLStates();
|
||||||
_window->draw(polygon);
|
_window->draw(polygon);
|
||||||
|
_window->popGLStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::drawText(const std::string& string, const Vec2D &position, int size, sf::Color color) {
|
void Screen::drawText(const std::string& string, const Vec2D &position, int size, sf::Color color) {
|
||||||
|
@ -98,17 +113,125 @@ void Screen::drawText(const std::string& string, const Vec2D &position, int size
|
||||||
text.setPosition((float)position.x(), (float)position.y());
|
text.setPosition((float)position.x(), (float)position.y());
|
||||||
|
|
||||||
text.setString(string);
|
text.setString(string);
|
||||||
|
|
||||||
|
_window->pushGLStates();
|
||||||
_window->draw(text);
|
_window->draw(text);
|
||||||
|
_window->popGLStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::drawSprite(const sf::Sprite &sprite) {
|
void Screen::drawSprite(const sf::Sprite &sprite) {
|
||||||
|
_window->pushGLStates();
|
||||||
_window->draw(sprite);
|
_window->draw(sprite);
|
||||||
|
_window->popGLStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::drawText(const sf::Text &text) {
|
void Screen::drawText(const sf::Text &text) {
|
||||||
|
_window->pushGLStates();
|
||||||
_window->draw(text);
|
_window->draw(text);
|
||||||
|
_window->popGLStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::attachMouse(std::shared_ptr<Mouse> mouse) {
|
void Screen::attachMouse(std::shared_ptr<Mouse> mouse) {
|
||||||
mouse->setWindow(_window);
|
mouse->setWindow(_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenGL functions
|
||||||
|
void Screen::glDrawMesh(GLfloat* geometry, GLfloat* view, size_t count) {
|
||||||
|
// OpenGL:
|
||||||
|
// Make the window the active window for OpenGL calls
|
||||||
|
_window->setActive(true);
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE); // enable culling face
|
||||||
|
glCullFace(GL_BACK); // cull faces from back
|
||||||
|
glFrontFace(GL_CCW); // vertex order (counter clock wise)
|
||||||
|
|
||||||
|
// Enable Z-buffer read and write
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glClearDepth(1.f);
|
||||||
|
|
||||||
|
// Disable lighting
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
// enable alpha channel:
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
// Configure the viewport (the same size as the window)
|
||||||
|
glViewport(0, 0, _window->getSize().x, _window->getSize().y);
|
||||||
|
|
||||||
|
// Setup a perspective projection
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
GLfloat ratio = static_cast<float>(_window->getSize().x) / _window->getSize().y;
|
||||||
|
glFrustum(-ratio, ratio, -1.f, 1.f, 1.0f, 500.f);
|
||||||
|
|
||||||
|
// Enable position and texture coordinates vertex components
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glVertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), geometry);
|
||||||
|
glColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat), geometry + 3);
|
||||||
|
|
||||||
|
// Disable normal and color vertex components
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
// Apply some transformations
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glLoadMatrixf(view);
|
||||||
|
|
||||||
|
// Draw the mesh
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, count);
|
||||||
|
|
||||||
|
// Make the window no longer the active window for OpenGL calls
|
||||||
|
_window->setActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLfloat* Screen::glMeshToGLfloatArray(std::shared_ptr<Mesh> mesh, const Vec3D& cameraPosition) {
|
||||||
|
Vec3D pos = mesh->position();
|
||||||
|
std::vector<Triangle>& triangles = mesh->triangles();
|
||||||
|
|
||||||
|
auto* geometry = (GLfloat*)malloc(7*3*triangles.size()*sizeof(GLfloat));
|
||||||
|
|
||||||
|
for(int i = 0; i < triangles.size(); i++) {
|
||||||
|
int stride = 21*i;
|
||||||
|
|
||||||
|
double dot = triangles[i].norm().dot((pos + Vec3D(triangles[i][0]) - cameraPosition).normalized());
|
||||||
|
sf::Color color = triangles[i].color();
|
||||||
|
sf::Color ambientColor = sf::Color((sf::Uint8)(color.r * (0.3 * std::abs(dot) + 0.7)),
|
||||||
|
(sf::Uint8)(color.g * (0.3 * std::abs(dot) + 0.7)),
|
||||||
|
(sf::Uint8)(color.b * (0.3 * std::abs(dot) + 0.7)),
|
||||||
|
(sf::Uint8)color.a);
|
||||||
|
|
||||||
|
|
||||||
|
geometry[stride + 0] = (GLfloat)triangles[i][0].x() + pos.x();
|
||||||
|
geometry[stride + 1] = (GLfloat)triangles[i][0].y() + pos.y();
|
||||||
|
geometry[stride + 2] = (GLfloat)triangles[i][0].z() + pos.z();
|
||||||
|
|
||||||
|
geometry[stride + 3] = (GLfloat)ambientColor.r/255.0f;
|
||||||
|
geometry[stride + 4] = (GLfloat)ambientColor.g/255.0f;
|
||||||
|
geometry[stride + 5] = (GLfloat)ambientColor.b/255.0f;
|
||||||
|
geometry[stride + 6] = (GLfloat)ambientColor.a/255.0f;
|
||||||
|
|
||||||
|
geometry[stride + 7] = (GLfloat)triangles[i][1].x() + pos.x();
|
||||||
|
geometry[stride + 8] = (GLfloat)triangles[i][1].y() + pos.y();
|
||||||
|
geometry[stride + 9] = (GLfloat)triangles[i][1].z() + pos.z();
|
||||||
|
|
||||||
|
geometry[stride + 10] = (GLfloat)ambientColor.r/255.0f;
|
||||||
|
geometry[stride + 11] = (GLfloat)ambientColor.g/255.0f;
|
||||||
|
geometry[stride + 12] = (GLfloat)ambientColor.b/255.0f;
|
||||||
|
geometry[stride + 13] = (GLfloat)ambientColor.a/255.0f;
|
||||||
|
|
||||||
|
geometry[stride + 14] = (GLfloat)triangles[i][2].x() + pos.x();
|
||||||
|
geometry[stride + 15] = (GLfloat)triangles[i][2].y() + pos.y();
|
||||||
|
geometry[stride + 16] = (GLfloat)triangles[i][2].z() + pos.z();
|
||||||
|
|
||||||
|
geometry[stride + 17] = (GLfloat)ambientColor.r/255.0f;
|
||||||
|
geometry[stride + 18] = (GLfloat)ambientColor.g/255.0f;
|
||||||
|
geometry[stride + 19] = (GLfloat)ambientColor.b/255.0f;
|
||||||
|
geometry[stride + 20] = (GLfloat)ambientColor.a/255.0f;
|
||||||
|
}
|
||||||
|
return geometry;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "utils/Time.h"
|
#include "utils/Time.h"
|
||||||
#include "Mouse.h"
|
#include "Mouse.h"
|
||||||
#include "Consts.h"
|
#include "Consts.h"
|
||||||
|
#include "Mesh.h"
|
||||||
|
#include "Camera.h"
|
||||||
|
|
||||||
class Screen final {
|
class Screen final {
|
||||||
private:
|
private:
|
||||||
|
@ -29,7 +31,7 @@ public:
|
||||||
|
|
||||||
void display();
|
void display();
|
||||||
void clear();
|
void clear();
|
||||||
bool hasFocus() const { return _window->hasFocus(); }
|
[[nodiscard]] bool hasFocus() const { return _window->hasFocus(); }
|
||||||
|
|
||||||
void drawTriangle(const Triangle& triangle);
|
void drawTriangle(const Triangle& triangle);
|
||||||
void drawTetragon(const Vec2D& p1, const Vec2D& p2, const Vec2D& p3, const Vec2D& p4, sf::Color color);
|
void drawTetragon(const Vec2D& p1, const Vec2D& p2, const Vec2D& p3, const Vec2D& p4, sf::Color color);
|
||||||
|
@ -50,6 +52,10 @@ public:
|
||||||
void debugText(const std::string& text);
|
void debugText(const std::string& text);
|
||||||
|
|
||||||
void attachMouse(std::shared_ptr<Mouse> mouse);
|
void attachMouse(std::shared_ptr<Mouse> mouse);
|
||||||
|
|
||||||
|
// OpenGL functions
|
||||||
|
void glDrawMesh(GLfloat* geometry, GLfloat* view, size_t count);
|
||||||
|
static GLfloat* glMeshToGLfloatArray(std::shared_ptr<Mesh> mesh, const Vec3D& cameraPosition);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "utils/Log.h"
|
#include "utils/Log.h"
|
||||||
#include "Plane.h"
|
#include "Plane.h"
|
||||||
#include "ResourceManager.h"
|
#include "ResourceManager.h"
|
||||||
|
#include <sstream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -19,15 +21,28 @@ void World::loadBody(const ObjectNameTag& tag, const string &filename, const Vec
|
||||||
Log::log("World::loadBody(): inserted body from " + filename + " with title '" + tag.str() + "' with " + std::to_string(_objects[tag]->triangles().size()) + " tris.");
|
Log::log("World::loadBody(): inserted body from " + filename + " with title '" + tag.str() + "' with " + std::to_string(_objects[tag]->triangles().size()) + " tris.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Vec3D, ObjectNameTag> World::rayCast(const Vec3D& from, const Vec3D& to, const std::string& tag) {
|
IntersectionInformation World::rayCast(const Vec3D& from, const Vec3D& to, const std::string& skipTags) {
|
||||||
|
|
||||||
std::pair<Vec3D, string> result;
|
// make vector of tags, that we are going to escape
|
||||||
|
vector <string> tagsToSkip;
|
||||||
|
stringstream s(skipTags);
|
||||||
|
std::string t;
|
||||||
|
while (s >> t) tagsToSkip.push_back(t);
|
||||||
|
|
||||||
|
bool intersected = false;
|
||||||
std::unique_ptr<Vec3D> point = std::make_unique<Vec3D>();
|
std::unique_ptr<Vec3D> point = std::make_unique<Vec3D>();
|
||||||
|
std::unique_ptr<Triangle> triangle = std::make_unique<Triangle>();
|
||||||
std::string bodyName;
|
std::string bodyName;
|
||||||
double minDistance = Consts::RAY_CAST_MAX_DISTANCE;
|
double minDistance = Consts::RAY_CAST_MAX_DISTANCE;
|
||||||
|
std::shared_ptr<RigidBody> intersectedBody = nullptr;
|
||||||
|
|
||||||
for(auto& [name, body] : _objects) {
|
for(auto& [name, body] : _objects) {
|
||||||
if(!tag.empty() && name.str().find(tag) == std::string::npos)
|
|
||||||
|
//for (auto& escapeTag : tagsToSkip)
|
||||||
|
// if(name.str().find(escapeTag) != std::string::npos)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
if(name.str().find("Player") != std::string::npos || name.str().find("weapon") != std::string::npos)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for(auto& tri : body->triangles()) {
|
for(auto& tri : body->triangles()) {
|
||||||
|
@ -39,11 +54,14 @@ std::pair<Vec3D, ObjectNameTag> World::rayCast(const Vec3D& from, const Vec3D& t
|
||||||
if(intersection.second > 0 && distance < minDistance && tri_translated.isPointInside(intersection.first)) {
|
if(intersection.second > 0 && distance < minDistance && tri_translated.isPointInside(intersection.first)) {
|
||||||
minDistance = distance;
|
minDistance = distance;
|
||||||
point = std::make_unique<Vec3D>(intersection.first);
|
point = std::make_unique<Vec3D>(intersection.first);
|
||||||
|
triangle = std::make_unique<Triangle>(tri_translated);
|
||||||
bodyName = name.str();
|
bodyName = name.str();
|
||||||
|
intersected = true;
|
||||||
|
intersectedBody = body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {*point, ObjectNameTag(bodyName)};
|
return IntersectionInformation{*point, sqrt(minDistance), *triangle, ObjectNameTag(bodyName), intersectedBody, intersected};
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::loadMap(const std::string& filename, const Vec3D& scale) {
|
void World::loadMap(const std::string& filename, const Vec3D& scale) {
|
||||||
|
@ -53,6 +71,8 @@ void World::loadMap(const std::string& filename, const Vec3D& scale) {
|
||||||
addBody(std::make_shared<RigidBody>(*objs[i]), meshName);
|
addBody(std::make_shared<RigidBody>(*objs[i]), meshName);
|
||||||
body(meshName)->scale(scale);
|
body(meshName)->scale(scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto it = _objects.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::removeBody(const ObjectNameTag& tag) {
|
void World::removeBody(const ObjectNameTag& tag) {
|
||||||
|
@ -95,11 +115,6 @@ void World::update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::projectObjectsInCamera(std::shared_ptr<Camera> camera) {
|
|
||||||
for (auto &[name, body] : _objects)
|
|
||||||
camera->project(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<RigidBody> World::body(const ObjectNameTag& tag) {
|
std::shared_ptr<RigidBody> World::body(const ObjectNameTag& tag) {
|
||||||
if(_objects.count(tag) == 0)
|
if(_objects.count(tag) == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -7,8 +7,18 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
|
#include "Screen.h"
|
||||||
#include "physics/RigidBody.h"
|
#include "physics/RigidBody.h"
|
||||||
|
|
||||||
|
struct IntersectionInformation final {
|
||||||
|
const Vec3D pointOfIntersection;
|
||||||
|
const double distanceToObject;
|
||||||
|
const Triangle intersectedTriangle;
|
||||||
|
const ObjectNameTag objectName;
|
||||||
|
const std::shared_ptr<RigidBody> obj;
|
||||||
|
const bool intersected;
|
||||||
|
};
|
||||||
|
|
||||||
class World final {
|
class World final {
|
||||||
private:
|
private:
|
||||||
std::map<ObjectNameTag, std::shared_ptr<RigidBody>> _objects;
|
std::map<ObjectNameTag, std::shared_ptr<RigidBody>> _objects;
|
||||||
|
@ -17,19 +27,19 @@ public:
|
||||||
|
|
||||||
void checkCollision(const ObjectNameTag& tag);
|
void checkCollision(const ObjectNameTag& tag);
|
||||||
void update();
|
void update();
|
||||||
void projectObjectsInCamera(std::shared_ptr<Camera> camera);
|
|
||||||
|
|
||||||
void addBody(std::shared_ptr<RigidBody> mesh, const ObjectNameTag& tag);
|
void addBody(std::shared_ptr<RigidBody> mesh, const ObjectNameTag& tag);
|
||||||
std::shared_ptr<RigidBody> body(const ObjectNameTag& tag);
|
std::shared_ptr<RigidBody> body(const ObjectNameTag& tag);
|
||||||
void removeBody(const ObjectNameTag& tag);
|
void removeBody(const ObjectNameTag& tag);
|
||||||
void loadBody(const ObjectNameTag& tag, const std::string &filename, const Vec3D& scale = Vec3D{1, 1, 1});
|
void loadBody(const ObjectNameTag& tag, const std::string &filename, const Vec3D& scale = Vec3D{1, 1, 1});
|
||||||
|
|
||||||
// rayCast returns pair of Point4D and std::string:
|
// std::string skipTags is a string that consist of all objects we want to skip in ray casting
|
||||||
// 1) Point4D is point of collision
|
IntersectionInformation rayCast(const Vec3D& from, const Vec3D& to, const std::string& skipTags = "");
|
||||||
// 2) std::string - title of the object
|
|
||||||
std::pair<Vec3D, ObjectNameTag> rayCast(const Vec3D& from, const Vec3D& to, const std::string& tag = "");
|
|
||||||
|
|
||||||
void loadMap(const std::string& filename, const Vec3D & scale = Vec3D{1, 1, 1});
|
void loadMap(const std::string& filename, const Vec3D & scale = Vec3D{1, 1, 1});
|
||||||
|
|
||||||
|
std::map<ObjectNameTag, std::shared_ptr<RigidBody>>::iterator begin() { return _objects.begin(); }
|
||||||
|
std::map<ObjectNameTag, std::shared_ptr<RigidBody>>::iterator end() { return _objects.end(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Ak47::Ak47(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) {
|
Ak47::Ak47(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-2.2, 1.0, 1.3}, Vec3D{0, Consts::PI, 0}) {
|
||||||
fireSound = ShooterConsts::AK47_FIRE_SOUND;
|
fireSound = ShooterConsts::AK47_FIRE_SOUND;
|
||||||
reloadSound = ShooterConsts::AK47_RELOAD_SOUND;
|
reloadSound = ShooterConsts::AK47_RELOAD_SOUND;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
class Gold_Ak47 final : public Weapon {
|
class Gold_Ak47 final : public Weapon {
|
||||||
public:
|
public:
|
||||||
explicit Gold_Ak47(int ammo = 200, const std::string& weaponName = "gold_ak47") : Weapon(weaponName, ShooterConsts::GOLD_AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) {
|
explicit Gold_Ak47(int ammo = 200, const std::string& weaponName = "gold_ak47") : Weapon(weaponName, ShooterConsts::GOLD_AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-2.2, 1.0, 1.3}, Vec3D{0, Consts::PI, 0}) {
|
||||||
fireSound = ShooterConsts::GOLD_AK47_FIRE_SOUND;
|
fireSound = ShooterConsts::GOLD_AK47_FIRE_SOUND;
|
||||||
reloadSound = ShooterConsts::GOLD_AK47_RELOAD_SOUND;
|
reloadSound = ShooterConsts::GOLD_AK47_RELOAD_SOUND;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Gun::Gun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::GUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) {
|
Gun::Gun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::GUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-1.8, 1.3, 1.8}, Vec3D{0, Consts::PI, 0}) {
|
||||||
fireSound = ShooterConsts::GUN_FIRE_SOUND;
|
fireSound = ShooterConsts::GUN_FIRE_SOUND;
|
||||||
reloadSound = ShooterConsts::GUN_RELOAD_SOUND;
|
reloadSound = ShooterConsts::GUN_RELOAD_SOUND;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include "Rifle.h"
|
#include "Rifle.h"
|
||||||
#include "../ShooterConsts.h"
|
#include "../ShooterConsts.h"
|
||||||
|
|
||||||
Rifle::Rifle(int ammo, const std::string &weaponName) : Weapon(weaponName, ShooterConsts::RIFLE_OBJ, Vec3D{3, 3, 3}, Vec3D{-1.2, 1, 0.3}, Vec3D{0, Consts::PI, 0}) {
|
Rifle::Rifle(int ammo, const std::string &weaponName) : Weapon(weaponName, ShooterConsts::RIFLE_OBJ, Vec3D{3, 3, 3}, Vec3D{-2.3, 1, 1.3}, Vec3D{0, Consts::PI, 0}) {
|
||||||
fireSound = ShooterConsts::RIFLE_FIRE_SOUND;
|
fireSound = ShooterConsts::RIFLE_FIRE_SOUND;
|
||||||
reloadSound = ShooterConsts::RIFLE_RELOAD_SOUND;
|
reloadSound = ShooterConsts::RIFLE_RELOAD_SOUND;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::SHOTGUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.95, 1.3, -0.6}, Vec3D{0, Consts::PI, 0}) {
|
Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::SHOTGUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-1.95, 0.8, 1.5}, Vec3D{0, Consts::PI, 0}) {
|
||||||
fireSound = ShooterConsts::SHOTGUN_FIRE_SOUND;
|
fireSound = ShooterConsts::SHOTGUN_FIRE_SOUND;
|
||||||
reloadSound = ShooterConsts::SHOTGUN_RELOAD_SOUND;
|
reloadSound = ShooterConsts::SHOTGUN_RELOAD_SOUND;
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, S
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<ObjectNameTag, double>
|
std::map<ObjectNameTag, double>
|
||||||
Shotgun::processFire(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) {
|
Shotgun::processFire(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) {
|
||||||
std::map<ObjectNameTag, double> damagedPlayers;
|
std::map<ObjectNameTag, double> damagedPlayers;
|
||||||
|
|
||||||
for(int i = 0; i < 15; i++) {
|
for(int i = 0; i < 15; i++) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
class Shotgun final : public Weapon {
|
class Shotgun final : public Weapon {
|
||||||
public:
|
public:
|
||||||
explicit Shotgun(int ammo = 15, const std::string& weaponName = "shotgun");
|
explicit Shotgun(int ammo = 15, const std::string& weaponName = "shotgun");
|
||||||
std::map<ObjectNameTag, double> processFire(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) override;
|
std::map<ObjectNameTag, double> processFire(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, co
|
||||||
translate(t);
|
translate(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<ObjectNameTag, double> Weapon::fire(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) {
|
FireInformation Weapon::fire(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) {
|
||||||
if(_clipAmmo == 0) {
|
if(_clipAmmo == 0) {
|
||||||
reload();
|
reload();
|
||||||
if(_clipAmmo == 0)
|
if(_clipAmmo == 0)
|
||||||
|
@ -29,7 +29,7 @@ std::map<ObjectNameTag, double> Weapon::fire(std::function<std::pair<Vec3D, Obje
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_clipAmmo <= 0 || std::abs(Time::time() - _lastFireTime) < _fireDelay || std::abs(Time::time() - _lastReloadTime) < _reloadTime)
|
if(_clipAmmo <= 0 || std::abs(Time::time() - _lastFireTime) < _fireDelay || std::abs(Time::time() - _lastReloadTime) < _reloadTime)
|
||||||
return std::map<ObjectNameTag, double>();
|
return FireInformation{std::map<ObjectNameTag, double>(), false};
|
||||||
|
|
||||||
_lastFireTime = Time::time();
|
_lastFireTime = Time::time();
|
||||||
_clipAmmo--;
|
_clipAmmo--;
|
||||||
|
@ -37,7 +37,7 @@ std::map<ObjectNameTag, double> Weapon::fire(std::function<std::pair<Vec3D, Obje
|
||||||
SoundController::playSound(SoundTag("fire"), fireSound);
|
SoundController::playSound(SoundTag("fire"), fireSound);
|
||||||
Log::log("Weapon::fire (" + std::to_string(_stockAmmo) + " : " + std::to_string(_clipAmmo) + ")");
|
Log::log("Weapon::fire (" + std::to_string(_stockAmmo) + " : " + std::to_string(_clipAmmo) + ")");
|
||||||
|
|
||||||
return processFire(std::move(rayCastFunction), position, direction);
|
return FireInformation{processFire(std::move(rayCastFunction), position, direction), true};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::reload() {
|
void Weapon::reload() {
|
||||||
|
@ -56,11 +56,11 @@ void Weapon::reload() {
|
||||||
_lastReloadTime = Time::time();
|
_lastReloadTime = Time::time();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<ObjectNameTag, double> Weapon::processFire(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) {
|
std::map<ObjectNameTag, double> Weapon::processFire(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) {
|
||||||
return addTrace(std::move(rayCastFunction), position, direction);
|
return addTrace(std::move(rayCastFunction), position, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<ObjectNameTag, double> Weapon::addTrace(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& from, const Vec3D& directionTo) {
|
std::map<ObjectNameTag, double> Weapon::addTrace(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& from, const Vec3D& directionTo) {
|
||||||
std::map<ObjectNameTag, double> damagedPlayers;
|
std::map<ObjectNameTag, double> damagedPlayers;
|
||||||
|
|
||||||
double spreading = _spreading*ShooterConsts::FIRE_DISTANCE/100;
|
double spreading = _spreading*ShooterConsts::FIRE_DISTANCE/100;
|
||||||
|
@ -70,13 +70,12 @@ std::map<ObjectNameTag, double> Weapon::addTrace(std::function<std::pair<Vec3D,
|
||||||
|
|
||||||
// damage player
|
// damage player
|
||||||
auto rayCast = rayCastFunction(from, from + directionTo * ShooterConsts::FIRE_DISTANCE + randV);
|
auto rayCast = rayCastFunction(from, from + directionTo * ShooterConsts::FIRE_DISTANCE + randV);
|
||||||
if(rayCast.second.str().find("Enemy") != std::string::npos) {
|
if(rayCast.objectName.str().find("Enemy") != std::string::npos)
|
||||||
damagedPlayers[rayCast.second] += _damage/(1.0 + (from - rayCast.first).abs());
|
damagedPlayers[rayCast.objectName] += _damage/(1.0 + rayCast.distanceToObject);
|
||||||
}
|
|
||||||
|
|
||||||
// add trace line
|
// add trace line
|
||||||
Vec3D lineFrom = position() + Vec3D(triangles().back()[0]);
|
Vec3D lineFrom = position() + Vec3D(triangles().back()[0]);
|
||||||
Vec3D lineTo = rayCast.first == Vec3D(0) ? position() + -lookAt() * ShooterConsts::FIRE_DISTANCE + randV: rayCast.first;
|
Vec3D lineTo = rayCast.intersected ? rayCast.pointOfIntersection : position() + -lookAt() * ShooterConsts::FIRE_DISTANCE + randV;
|
||||||
_addTraceCallBack(lineFrom, lineTo);
|
_addTraceCallBack(lineFrom, lineTo);
|
||||||
|
|
||||||
return damagedPlayers;
|
return damagedPlayers;
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
#include "../engine/SoundController.h"
|
#include "../engine/SoundController.h"
|
||||||
#include "../engine/Consts.h"
|
#include "../engine/Consts.h"
|
||||||
|
|
||||||
|
struct FireInformation {
|
||||||
|
const std::map<ObjectNameTag, double> damagedPlayers;
|
||||||
|
const bool shot;
|
||||||
|
};
|
||||||
|
|
||||||
class Weapon : public RigidBody {
|
class Weapon : public RigidBody {
|
||||||
protected:
|
protected:
|
||||||
int _initialPack = 100; // how much ammo do you have when you find the weapon
|
int _initialPack = 100; // how much ammo do you have when you find the weapon
|
||||||
|
@ -39,14 +44,14 @@ protected:
|
||||||
|
|
||||||
std::function<void(const Vec3D&, const Vec3D&)> _addTraceCallBack;
|
std::function<void(const Vec3D&, const Vec3D&)> _addTraceCallBack;
|
||||||
|
|
||||||
std::map<ObjectNameTag, double> addTrace(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction);
|
std::map<ObjectNameTag, double> addTrace(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction);
|
||||||
|
|
||||||
virtual std::map<ObjectNameTag, double> processFire(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction);
|
virtual std::map<ObjectNameTag, double> processFire(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Weapon(const std::string& weaponName, const std::string& objFileName, const Vec3D& scale, const Vec3D& translate, const Vec3D& rotate);
|
Weapon(const std::string& weaponName, const std::string& objFileName, const Vec3D& scale, const Vec3D& translate, const Vec3D& rotate);
|
||||||
|
|
||||||
std::map<ObjectNameTag, double> fire(std::function<std::pair<Vec3D, ObjectNameTag>(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction);
|
FireInformation fire(std::function<IntersectionInformation(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction);
|
||||||
void reload();
|
void reload();
|
||||||
|
|
||||||
[[nodiscard]] std::pair<double, double> balance() const{ return std::make_pair(_clipAmmo, _stockAmmo); }
|
[[nodiscard]] std::pair<double, double> balance() const{ return std::make_pair(_clipAmmo, _stockAmmo); }
|
||||||
|
|
Loading…
Reference in New Issue