HitBox added. acceleration of collision detection in 20 times.

master
Vectozavr 2021-11-04 02:57:48 +07:00
parent 747f294ec9
commit 6bc5c7dd1f
12 changed files with 168 additions and 26 deletions

View File

@ -91,7 +91,7 @@ add_executable(shooter
engine/network/UDPConnection.h engine/network/UDPConnection.h
engine/network/UDPSocket.cpp engine/network/UDPSocket.cpp
engine/network/UDPSocket.h engine/network/UDPSocket.h
engine/SoundController.cpp engine/SoundController.h ShooterMsgType.h ShooterMsgType.cpp engine/animation/AAttractToPoint.h engine/animation/ARotateRelativePoint.h engine/animation/ARotateLeft.h engine/utils/Timer.cpp engine/utils/Timer.h) engine/SoundController.cpp engine/SoundController.h ShooterMsgType.h ShooterMsgType.cpp engine/animation/AAttractToPoint.h engine/animation/ARotateRelativePoint.h engine/animation/ARotateLeft.h engine/utils/Timer.cpp engine/utils/Timer.h engine/physics/HitBox.cpp engine/physics/HitBox.h)
if(APPLE OR UNIX) if(APPLE OR UNIX)
include_directories(/usr/local/include) include_directories(/usr/local/include)

View File

@ -3,17 +3,19 @@
// //
#include "Player.h" #include "Player.h"
#include <utility>
#include "engine/Screen.h" #include "engine/Screen.h"
#include "engine/utils/Log.h" #include "engine/utils/Log.h"
#include "engine/animation/Timeline.h" #include "engine/animation/Timeline.h"
#include "engine/animation/ARotateLeft.h" #include "engine/animation/ARotateLeft.h"
Player::Player(ObjectNameTag name) : RigidBody(name) { Player::Player(ObjectNameTag name) : RigidBody(std::move(name), ShooterConsts::CUBE_OBJ,Vec3D{0.5, 1.9, 0.5}) {
loadObj(ShooterConsts::CUBE_OBJ, Vec3D{0.5, 1.9, 0.5});
setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0}); setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0});
setCollision(true); setCollision(true);
setVisible(false); setVisible(false);
setSimpleHitBox(true);
Vec3D randColor = Vec3D::Random(); Vec3D randColor = Vec3D::Random();
setColor({static_cast<sf::Uint8>(randColor.x() * 255), static_cast<sf::Uint8>(randColor.y() * 255), setColor({static_cast<sf::Uint8>(randColor.x() * 255), static_cast<sf::Uint8>(randColor.y() * 255),

View File

@ -300,7 +300,7 @@ void Shooter::addFireTrace(const Vec3D &from, const Vec3D &to) {
std::make_shared<AColor>(world->body(ObjectNameTag(traceName)), sf::Color{150, 150, 150, 0})); std::make_shared<AColor>(world->body(ObjectNameTag(traceName)), sf::Color{150, 150, 150, 0}));
Timeline::animate(AnimationListTag(traceName + "_delete"), Timeline::animate(AnimationListTag(traceName + "_delete"),
std::make_shared<AFunction>([this, traceName]() { removeFireTrace(ObjectNameTag(traceName)); }, 1, std::make_shared<AFunction>([this, traceName]() { removeFireTrace(ObjectNameTag(traceName)); }, 1,
2)); 1));
} }
void Shooter::removeFireTrace(const ObjectNameTag &traceName) { void Shooter::removeFireTrace(const ObjectNameTag &traceName) {
@ -315,6 +315,8 @@ void Shooter::addBonus(const string &bonusName, const Vec3D &position) {
world->addBody(std::make_shared<RigidBody>(ObjectNameTag(bonusName), "obj/" + name + ".obj", Vec3D{3, 3, 3})); world->addBody(std::make_shared<RigidBody>(ObjectNameTag(bonusName), "obj/" + name + ".obj", Vec3D{3, 3, 3}));
world->body(ObjectNameTag(bonusName))->translateToPoint(position); world->body(ObjectNameTag(bonusName))->translateToPoint(position);
world->body(ObjectNameTag(bonusName))->setCollider(false); world->body(ObjectNameTag(bonusName))->setCollider(false);
world->body(ObjectNameTag(bonusName))->setSimpleHitBox(true);
world->body(ObjectNameTag(bonusName))->setTrigger(true);
Timeline::animate(AnimationListTag(bonusName + "_rotation"), Timeline::animate(AnimationListTag(bonusName + "_rotation"),
std::make_shared<ARotate>(world->body(ObjectNameTag(bonusName)), Vec3D{0, 2 * Consts::PI, 0}, 4, std::make_shared<ARotate>(world->body(ObjectNameTag(bonusName)), Vec3D{0, 2 * Consts::PI, 0}, 4,
Animation::LoopOut::Continue, Animation::InterpolationType::Linear)); Animation::LoopOut::Continue, Animation::InterpolationType::Linear));

View File

@ -17,7 +17,7 @@
class Shooter final : public Engine { class Shooter final : public Engine {
private: private:
std::shared_ptr<Player> player = std::make_shared<Player>(ObjectNameTag("Player"));; std::shared_ptr<Player> player = std::make_shared<Player>(ObjectNameTag("Player"));
std::shared_ptr<PlayerController> playerController = std::make_shared<PlayerController>(player, keyboard, mouse); std::shared_ptr<PlayerController> playerController = std::make_shared<PlayerController>(player, keyboard, mouse);
Window mainMenu; Window mainMenu;

View File

@ -38,7 +38,7 @@ namespace ShooterConsts {
const std::string SHOTGUN_RELOAD_SOUND = "sound/weapons/reload_shotgun.ogg"; const std::string SHOTGUN_RELOAD_SOUND = "sound/weapons/reload_shotgun.ogg";
const std::string CUBE_OBJ = "obj/cube.obj"; const std::string CUBE_OBJ = "obj/cube.obj";
const std::string MAP_OBJ = "maps/map2.obj"; const std::string MAP_OBJ = "maps/map1.obj";
const std::string MAIN_MENU_BACK = "textures/back.png"; const std::string MAIN_MENU_BACK = "textures/back.png";
const std::string MAIN_MENU_GUI = "textures/gui.png"; const std::string MAIN_MENU_GUI = "textures/gui.png";

View File

@ -13,7 +13,7 @@ int main() {
game.create(1280, 720, ShooterConsts::PROJECT_NAME); game.create(1280, 720, ShooterConsts::PROJECT_NAME);
//game.create(1920, 1080, ShooterConsts::PROJECT_NAME, true, Consts::BACKGROUND_COLOR, sf::Style::Fullscreen); //game.create(1920, 1080, ShooterConsts::PROJECT_NAME, true, Consts::BACKGROUND_COLOR, sf::Style::Fullscreen);
//game.create(2048, 1152, ShooterConsts::PROJECT_NAME, true); //game.create(2048, 1152, ShooterConsts::PROJECT_NAME, false);
//game.create(3072, 1920, ShooterConsts::PROJECT_NAME, true, Consts::BACKGROUND_COLOR, sf::Style::Fullscreen); //game.create(3072, 1920, ShooterConsts::PROJECT_NAME, true, Consts::BACKGROUND_COLOR, sf::Style::Fullscreen);
return 0; return 0;

View File

@ -93,7 +93,7 @@ void World::removeBody(const ObjectNameTag &tag) {
} }
void World::checkCollision(const ObjectNameTag &tag) { void World::checkCollision(const ObjectNameTag &tag) {
if (_objects[tag]->isCollision()) { if (_objects[tag]->hasCollision()) {
_objects[tag]->setInCollision(false); _objects[tag]->setInCollision(false);
@ -102,7 +102,10 @@ void World::checkCollision(const ObjectNameTag &tag) {
ObjectNameTag name = it->first; ObjectNameTag name = it->first;
it++; it++;
if (name != tag) { if ((name == tag) || !(obj->isCollider() || obj->isTrigger())) {
continue;
}
std::pair<bool, Simplex> gjk = _objects[tag]->checkGJKCollision(obj); std::pair<bool, Simplex> gjk = _objects[tag]->checkGJKCollision(obj);
if (gjk.first) { if (gjk.first) {
if (obj->isCollider()) { if (obj->isCollider()) {
@ -113,7 +116,7 @@ void World::checkCollision(const ObjectNameTag &tag) {
_objects[tag]->collisionCallBack()(name, obj); _objects[tag]->collisionCallBack()(name, obj);
} }
} }
}
} }
} }
} }

View File

@ -16,7 +16,7 @@ private:
const std::function<void()> _callBack; const std::function<void()> _callBack;
void update() override { void update() override {
if (_allCalls != 0 && progress() > (double) _callsCounter / _allCalls) { if (_allCalls != 0 && progress() >= (double) (_callsCounter + 1) / _allCalls) {
_callsCounter++; _callsCounter++;
_callBack(); _callBack();
} }

76
engine/physics/HitBox.cpp Normal file
View File

@ -0,0 +1,76 @@
//
// Created by Иван Ильин on 04.11.2021.
//
#include "HitBox.h"
#include "../Consts.h"
HitBox::HitBox(const Mesh &mesh) {
for(const auto& t : mesh.triangles()) {
for(int i = 0; i < 3; i++) {
// we dont need to add the same points in hit box
_addIfUnique(Vec3D(t[i]));
}
}
}
void HitBox::_addIfUnique(const Vec3D &point) {
bool addPoint = true;
for(const auto& p : _hitBox) {
if((p - point).sqrAbs() < Consts::EPS) {
addPoint = false;
}
}
if(addPoint) {
_hitBox.push_back(point);
}
}
HitBox HitBox::Box(const Mesh &mesh) {
HitBox result;
double maxX = -std::numeric_limits<double>::max();
double maxY = -std::numeric_limits<double>::max();
double maxZ = -std::numeric_limits<double>::max();
double minX = std::numeric_limits<double>::max();
double minY = std::numeric_limits<double>::max();
double minZ = std::numeric_limits<double>::max();
for(const auto& t : mesh.triangles()) {
for(int i = 0; i < 3; i++) {
Vec3D point = Vec3D(t[i]);
if(point.x() > maxX) {
maxX = point.x();
}
if(point.y() > maxY) {
maxY = point.y();
}
if(point.z() > maxZ) {
maxZ = point.z();
}
if(point.x() < minX) {
minX = point.x();
}
if(point.y() < minY) {
minY = point.y();
}
if(point.z() < minZ) {
minZ = point.z();
}
}
}
result._hitBox.emplace_back(minX, minY, minZ);
result._hitBox.emplace_back(minX, maxY, minZ);
result._hitBox.emplace_back(maxX, minY, minZ);
result._hitBox.emplace_back(maxX, maxY, minZ);
result._hitBox.emplace_back(minX, minY, maxZ);
result._hitBox.emplace_back(minX, maxY, maxZ);
result._hitBox.emplace_back(maxX, minY, maxZ);
result._hitBox.emplace_back(maxX, maxY, maxZ);
return result;
}

26
engine/physics/HitBox.h Normal file
View File

@ -0,0 +1,26 @@
//
// Created by Иван Ильин on 04.11.2021.
//
#ifndef SHOOTER_HITBOX_H
#define SHOOTER_HITBOX_H
#include "../Mesh.h"
class HitBox {
private:
std::vector<Vec3D> _hitBox;
void _addIfUnique(const Vec3D& point);
public:
HitBox() = default;
explicit HitBox(const Mesh& mesh);
std::vector<Vec3D>::iterator begin() { return _hitBox.begin(); }
std::vector<Vec3D>::iterator end() { return _hitBox.end(); }
HitBox static Box(const Mesh& mesh);
};
#endif //SHOOTER_HITBOX_H

View File

@ -11,7 +11,8 @@
#include "../Consts.h" #include "../Consts.h"
RigidBody::RigidBody(ObjectNameTag nameTag, const std::string &filename, const Vec3D &scale) : Mesh(std::move(nameTag), RigidBody::RigidBody(ObjectNameTag nameTag, const std::string &filename, const Vec3D &scale) : Mesh(std::move(nameTag),
filename, scale) { filename, scale),
_hitBox(*this) {
} }
Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) { Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) {
@ -21,6 +22,7 @@ Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) {
Vec3D transformedDirection = (view() * direction).normalized(); Vec3D transformedDirection = (view() * direction).normalized();
/*
for (auto &tri : triangles()) { for (auto &tri : triangles()) {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
Vec3D point = Vec3D(tri[i]); Vec3D point = Vec3D(tri[i]);
@ -32,6 +34,17 @@ Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) {
} }
} }
} }
*/
for(auto & it : _hitBox) {
auto point = Vec3D(it);
double distance = point.dot(transformedDirection);
if (distance > maxDistance) {
maxDistance = distance;
maxPoint = point;
}
}
return model() * maxPoint + position(); return model() * maxPoint + position();
} }
@ -346,5 +359,14 @@ void RigidBody::setAcceleration(const Vec3D &acceleration) {
_acceleration = acceleration; _acceleration = acceleration;
} }
RigidBody::RigidBody(const Mesh &mesh) : Mesh(mesh) { RigidBody::RigidBody(const Mesh &mesh) : Mesh(mesh), _hitBox(mesh) {
}
void RigidBody::setSimpleHitBox(bool b) {
_simpleHitBox = b;
if (_simpleHitBox) {
_hitBox = HitBox::Box(*this);
} else {
_hitBox = HitBox(*this);
}
} }

View File

@ -13,6 +13,7 @@
#include "../Triangle.h" #include "../Triangle.h"
#include "Simplex.h" #include "Simplex.h"
#include "../Mesh.h" #include "../Mesh.h"
#include "HitBox.h"
struct CollisionPoint final { struct CollisionPoint final {
const Vec3D normal; const Vec3D normal;
@ -35,8 +36,12 @@ private:
Vec3D _velocity{0, 0, 0}; Vec3D _velocity{0, 0, 0};
Vec3D _acceleration{0, 0, 0}; Vec3D _acceleration{0, 0, 0};
bool _collision = false; bool _hasCollision = false;
bool _isCollider = true; bool _isCollider = true;
bool _isTrigger = false;
HitBox _hitBox{};
bool _simpleHitBox = false;
bool _inCollision = false; bool _inCollision = false;
Vec3D _collisionNormal{0, 0, 0}; Vec3D _collisionNormal{0, 0, 0};
@ -78,18 +83,24 @@ public:
[[nodiscard]] Vec3D collisionNormal() const { return _collisionNormal; } [[nodiscard]] Vec3D collisionNormal() const { return _collisionNormal; }
[[nodiscard]] bool isCollision() const { return _collision; } [[nodiscard]] bool hasCollision() const { return _hasCollision; }
[[nodiscard]] bool inCollision() const { return _inCollision; } [[nodiscard]] bool inCollision() const { return _inCollision; }
[[nodiscard]] bool isCollider() const { return _isCollider; } [[nodiscard]] bool isCollider() const { return _isCollider; }
[[nodiscard]] bool isTrigger() const { return _isTrigger; }
void setInCollision(bool c) { _inCollision = c; } void setInCollision(bool c) { _inCollision = c; }
void setCollision(bool c) { _collision = c; } void setCollision(bool c) { _hasCollision = c; }
void setCollider(bool c) { _isCollider = c; } void setCollider(bool c) { _isCollider = c; }
void setSimpleHitBox(bool b);
void setTrigger(bool t) { _isTrigger = t; }
void updatePhysicsState(); void updatePhysicsState();
void setVelocity(const Vec3D &velocity); void setVelocity(const Vec3D &velocity);