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/UDPSocket.cpp
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)
include_directories(/usr/local/include)

View File

@ -3,17 +3,19 @@
//
#include "Player.h"
#include <utility>
#include "engine/Screen.h"
#include "engine/utils/Log.h"
#include "engine/animation/Timeline.h"
#include "engine/animation/ARotateLeft.h"
Player::Player(ObjectNameTag name) : RigidBody(name) {
loadObj(ShooterConsts::CUBE_OBJ, Vec3D{0.5, 1.9, 0.5});
Player::Player(ObjectNameTag name) : RigidBody(std::move(name), ShooterConsts::CUBE_OBJ,Vec3D{0.5, 1.9, 0.5}) {
setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0});
setCollision(true);
setVisible(false);
setSimpleHitBox(true);
Vec3D randColor = Vec3D::Random();
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}));
Timeline::animate(AnimationListTag(traceName + "_delete"),
std::make_shared<AFunction>([this, traceName]() { removeFireTrace(ObjectNameTag(traceName)); }, 1,
2));
1));
}
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->body(ObjectNameTag(bonusName))->translateToPoint(position);
world->body(ObjectNameTag(bonusName))->setCollider(false);
world->body(ObjectNameTag(bonusName))->setSimpleHitBox(true);
world->body(ObjectNameTag(bonusName))->setTrigger(true);
Timeline::animate(AnimationListTag(bonusName + "_rotation"),
std::make_shared<ARotate>(world->body(ObjectNameTag(bonusName)), Vec3D{0, 2 * Consts::PI, 0}, 4,
Animation::LoopOut::Continue, Animation::InterpolationType::Linear));
@ -346,7 +348,7 @@ void Shooter::changeEnemyWeapon(const std::string &weaponName, sf::Uint16 enemyI
world->body(weaponTag)->setCollider(false);
world->body(weaponTag)->scale(Vec3D(3, 3, 3));
world->body(weaponTag)->translateToPoint(head->position() - enemy->left()*2 - enemy->up()*0.5);
world->body(weaponTag)->translateToPoint(head->position() - enemy->left() * 2 - enemy->up() * 0.5);
world->body(weaponTag)->rotate(Vec3D(0, Consts::PI + enemy->angle().y(), 0));
world->body(weaponTag)->rotateLeft(-head->angleLeftUpLookAt().x());

View File

@ -17,7 +17,7 @@
class Shooter final : public Engine {
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);
Window mainMenu;

View File

@ -38,7 +38,7 @@ namespace ShooterConsts {
const std::string SHOTGUN_RELOAD_SOUND = "sound/weapons/reload_shotgun.ogg";
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_GUI = "textures/gui.png";

View File

@ -13,7 +13,7 @@ int main() {
game.create(1280, 720, ShooterConsts::PROJECT_NAME);
//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);
return 0;

View File

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

View File

@ -16,7 +16,7 @@ private:
const std::function<void()> _callBack;
void update() override {
if (_allCalls != 0 && progress() > (double) _callsCounter / _allCalls) {
if (_allCalls != 0 && progress() >= (double) (_callsCounter + 1) / _allCalls) {
_callsCounter++;
_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"
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) {
@ -21,6 +22,7 @@ Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) {
Vec3D transformedDirection = (view() * direction).normalized();
/*
for (auto &tri : triangles()) {
for (int i = 0; i < 3; i++) {
Vec3D point = Vec3D(tri[i]);
@ -32,8 +34,19 @@ Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) {
}
}
}
*/
return model()*maxPoint + position();
for(auto & it : _hitBox) {
auto point = Vec3D(it);
double distance = point.dot(transformedDirection);
if (distance > maxDistance) {
maxDistance = distance;
maxPoint = point;
}
}
return model() * maxPoint + position();
}
Vec3D RigidBody::_support(std::shared_ptr<RigidBody> obj, const Vec3D &direction) {
@ -346,5 +359,14 @@ void RigidBody::setAcceleration(const Vec3D &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 "Simplex.h"
#include "../Mesh.h"
#include "HitBox.h"
struct CollisionPoint final {
const Vec3D normal;
@ -35,8 +36,12 @@ private:
Vec3D _velocity{0, 0, 0};
Vec3D _acceleration{0, 0, 0};
bool _collision = false;
bool _hasCollision = false;
bool _isCollider = true;
bool _isTrigger = false;
HitBox _hitBox{};
bool _simpleHitBox = false;
bool _inCollision = false;
Vec3D _collisionNormal{0, 0, 0};
@ -78,18 +83,24 @@ public:
[[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 isCollider() const { return _isCollider; }
[[nodiscard]] bool isTrigger() const { return _isTrigger; }
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 setSimpleHitBox(bool b);
void setTrigger(bool t) { _isTrigger = t; }
void updatePhysicsState();
void setVelocity(const Vec3D &velocity);