Fixed and expanded coordinate system, and some more physics WIP

This commit is contained in:
Maximilian Giller 2023-06-29 21:26:30 +02:00
parent ad5a6731a3
commit b5d7dfede9
25 changed files with 367 additions and 51 deletions

View file

@ -116,20 +116,35 @@ set(SOURCES
src/game/physics/holes/collectable_simulation.cpp src/game/physics/holes/collectable_simulation.cpp
src/game/physics/holes/collectable_simulation.hpp src/game/physics/holes/collectable_simulation.hpp
src/game/physics/holes/holes_simulation.cpp src/game/physics/holes/holes_simulation.cpp
src/game/physics/holes/holes_simulation.hpp src/game/physics/holes/layouts/hole_description.hpp src/game/physics/holes/layouts/hole_layout.cpp src/game/physics/holes/layouts/hole_layout.hpp src/game/physics/holes/layouts/depth_hole_layout.hpp src/game/physics/holes/layouts/depth_hole_description.hpp) src/game/physics/holes/holes_simulation.hpp
src/game/physics/holes/layouts/hole_description.hpp
src/game/physics/holes/layouts/hole_layout.cpp
src/game/physics/holes/layouts/hole_layout.hpp
src/game/physics/holes/layouts/depth_hole_layout.hpp
src/game/physics/holes/layouts/depth_hole_description.hpp)
set(PHYSICS_00_SOURCES set(PHYSICS_00_SOURCES
src/prototypes/physics_00.cpp) src/prototypes/physics_00.cpp)
set(MATH_00_SOURCES set(MATH_00_SOURCES
src/prototypes/math_00.cpp) src/prototypes/math_00.cpp)
set(COORDINATES_00_SOURCES
src/prototypes/coordinates_00.cpp
src/coordinates/coordinates.h
src/coordinates/coordinate_transformer.h
src/coordinates/coordinate_transformer.cpp
src/coordinates/translated_coordinates.h
src/coordinates/translated_coordinates.cpp)
# Add an executable target # Add an executable target
add_executable(Holesome ${SOURCES}) add_executable(Holesome ${SOURCES})
add_executable(Physics_00 ${PHYSICS_00_SOURCES}) add_executable(Physics_00 ${PHYSICS_00_SOURCES})
add_executable(Math_00 ${MATH_00_SOURCES}) add_executable(Math_00 ${MATH_00_SOURCES})
add_executable(Coordinates_00 ${COORDINATES_00_SOURCES})
# Link SFML and other libraries to your executable target # Link SFML and other libraries to your executable target
target_link_libraries(Holesome sfml-graphics sfml-audio) target_link_libraries(Holesome sfml-graphics sfml-audio)
target_link_libraries(Holesome Eigen3::Eigen) target_link_libraries(Holesome Eigen3::Eigen)
@ -139,6 +154,8 @@ target_link_libraries(Physics_00 box2d::box2d)
target_link_libraries(Math_00 Eigen3::Eigen) target_link_libraries(Math_00 Eigen3::Eigen)
target_link_libraries(Coordinates_00 Eigen3::Eigen)
# Assets # Assets
add_custom_target(copy_assets add_custom_target(copy_assets
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets

View file

@ -6,7 +6,6 @@
## Bugs ## Bugs
- Player spawns initially at (0,0) and almost fails to jump to target spawn
- Player disconnect in multiplayer sometimes targeting disconnected player or something like that - Player disconnect in multiplayer sometimes targeting disconnected player or something like that
## High priority ## High priority
@ -14,6 +13,7 @@
- Physics - Physics
- Players-join-screen before the game starts - Players-join-screen before the game starts
- Short input delay when a new identity connects, to avoid accidental inputs at beginning
- Procedural points generation - Procedural points generation
- Game over screen - Game over screen
- Proper player graphics - Proper player graphics

View file

@ -13,7 +13,7 @@
#define PLAYER_RADIUS_PER_LEVEL 0.25f #define PLAYER_RADIUS_PER_LEVEL 0.25f
// World // World
#define WORLD_GRAVITY b2Vec2(0.f, -9.8f) #define WORLD_GRAVITY b2Vec2(0.f, 0.f)
#define SKY_HEIGHT_SCALE 2.f #define SKY_HEIGHT_SCALE 2.f
// FPS // FPS
@ -49,9 +49,10 @@
#define COLLECTABLES_SIM_LINEAR_DAMPING 0.5f #define COLLECTABLES_SIM_LINEAR_DAMPING 0.5f
#define COLLECTABLES_SIM_ANGULAR_DAMPING 0.5f #define COLLECTABLES_SIM_ANGULAR_DAMPING 0.5f
#define COLLECTABLES_SIM_DENSITY 1.f #define COLLECTABLES_SIM_DENSITY 1.f
#define COLLECTABLES_SIM_FRICTION 0.3f #define COLLECTABLES_SIM_FRICTION 0.0f
#define COLLECTABLES_SIM_RESTITUTION 0.5f #define COLLECTABLES_SIM_RESTITUTION 0.5f
#define COLLECTABLES_SIM_SLEEPING true #define COLLECTABLES_SIM_SLEEPING true
#define COLLECTABLES_SIM_GROUND_THICKNESS 0.1f
// Directions // Directions
#define DIRECTION_HARD_ACTIVATION_THRESHOLD 0.1f #define DIRECTION_HARD_ACTIVATION_THRESHOLD 0.1f

View file

@ -1,11 +1,12 @@
#include "coordinate_transformer.h" #include "coordinate_transformer.h"
#include "../config.h" #include "../config.h"
#include "../logging/easylogging++.h" #include "../logging/easylogging++.h"
#include "../utilities/vector_utils.hpp"
// Initialize matrix // Initialize matrix
const Eigen::Matrix<float, 3, 3> CoordinateTransformer::worldToIsometricMatrix = const Eigen::Matrix<float, 3, 3> CoordinateTransformer::worldToIsometricMatrix =
(Eigen::Matrix<float, 3, 3>() << (Eigen::Matrix<float, 3, 3>() <<
1, -1, 0, 1, -1, 0,
-ISOMETRIC_SKEW, -ISOMETRIC_SKEW, -1, -ISOMETRIC_SKEW, -ISOMETRIC_SKEW, -1,
1, 1, 0 1, 1, 0
).finished(); ).finished();
@ -17,19 +18,21 @@ IsometricCoordinates CoordinateTransformer::worldToIsometric(WorldCoordinates wo
Eigen::Vector3f isoCoordinatesVector = worldToIsometricMatrix * worldCoordinatesVector; Eigen::Vector3f isoCoordinatesVector = worldToIsometricMatrix * worldCoordinatesVector;
return IsometricCoordinates( return {
isoCoordinatesVector.x() * WORLD_TO_ISO_SCALE, // x isoCoordinatesVector.x() * WORLD_TO_ISO_SCALE, // x
isoCoordinatesVector.y() * WORLD_TO_ISO_SCALE, // y isoCoordinatesVector.y() * WORLD_TO_ISO_SCALE, // y
isoCoordinatesVector.z() // depth isoCoordinatesVector.z() // depth
); };
} }
WorldCoordinates CoordinateTransformer::isometricToWorld(IsometricCoordinates isometricCoordinates) WorldCoordinates CoordinateTransformer::isometricToWorld(IsometricCoordinates isometricCoordinates)
{ {
Eigen::Vector3f isoCoordinatesVector; Eigen::Vector3f isoCoordinatesVector;
isoCoordinatesVector << isometricCoordinates.x, isometricCoordinates.y, isometricCoordinates.depth; isoCoordinatesVector << isometricCoordinates.x / WORLD_TO_ISO_SCALE,
isometricCoordinates.y / WORLD_TO_ISO_SCALE,
isometricCoordinates.depth;
Eigen::Vector3f worldCoordinatesVector = worldToIsometricMatrix.inverse() * isoCoordinatesVector / WORLD_TO_ISO_SCALE; Eigen::Vector3f worldCoordinatesVector = worldToIsometricMatrix.inverse() * isoCoordinatesVector;
return { return {
worldCoordinatesVector.x(), // x worldCoordinatesVector.x(), // x
@ -37,3 +40,41 @@ Eigen::Vector3f isoCoordinatesVector;
worldCoordinatesVector.z() // z worldCoordinatesVector.z() // z
}; };
} }
float CoordinateTransformer::worldToDepth(sf::Vector2f worldGroundCoordinates)
{
return CoordinateTransformer::worldToIsometric({worldGroundCoordinates.x, worldGroundCoordinates.y, 0}).depth;
}
sf::Vector2f CoordinateTransformer::closestWorldPointAtDepth(float depth, sf::Vector2f referenceWorldPoint)
{
float depthAtReferencePoint = worldToDepth(referenceWorldPoint);
float depthDifference = depth - depthAtReferencePoint;
float stepSizePerAxis = depthDifference / 2.f;
return referenceWorldPoint + sf::Vector2f(stepSizePerAxis, stepSizePerAxis);
}
DiagonalWorldCoordinates CoordinateTransformer::worldToDiagonal(WorldCoordinates worldCoordinates)
{
auto depth = CoordinateTransformer::worldToDepth(worldCoordinates.toGroundCoordinates());
auto depthCenterCoordinates = CoordinateTransformer::closestWorldPointAtDepth(depth, {0, 0});
auto horizontal = length(worldCoordinates.toGroundCoordinates() - depthCenterCoordinates);
return {horizontal, worldCoordinates.z, depth};
}
WorldCoordinates CoordinateTransformer::diagonalToWorld(DiagonalWorldCoordinates diagonalWorldCoordinates)
{
auto depthCenterCoordinates = CoordinateTransformer::closestWorldPointAtDepth(diagonalWorldCoordinates.depth,
{0, 0});
auto const horizontalAxis = sf::Vector2f(1, -1);
auto worldGroundCoordinates = depthCenterCoordinates + horizontalAxis * diagonalWorldCoordinates.horizontal;
return {
worldGroundCoordinates.x,
worldGroundCoordinates.y,
diagonalWorldCoordinates.vertical
};
}

View file

@ -12,6 +12,10 @@ private:
public: public:
static IsometricCoordinates worldToIsometric(WorldCoordinates worldCoordinates); static IsometricCoordinates worldToIsometric(WorldCoordinates worldCoordinates);
static WorldCoordinates isometricToWorld(IsometricCoordinates isometricCoordinates); static WorldCoordinates isometricToWorld(IsometricCoordinates isometricCoordinates);
static DiagonalWorldCoordinates worldToDiagonal(WorldCoordinates worldCoordinates);
static WorldCoordinates diagonalToWorld(DiagonalWorldCoordinates diagonalWorldCoordinates);
static float worldToDepth(sf::Vector2f worldGroundCoordinates);
static sf::Vector2f closestWorldPointAtDepth(float depth, sf::Vector2f referenceWorldPoint);
}; };

View file

@ -2,6 +2,9 @@
#define HOLESOME_COORDINATES_H #define HOLESOME_COORDINATES_H
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include "../utilities/vector_utils.hpp"
class DiagonalWorldCoordinates;
struct WorldCoordinates struct WorldCoordinates
{ {
@ -54,6 +57,11 @@ struct WorldCoordinates
{ {
return !(*this == other); return !(*this == other);
} }
[[nodiscard]] sf::Vector2f toGroundCoordinates() const
{
return {x, y};
}
}; };
struct IsometricCoordinates struct IsometricCoordinates
@ -76,6 +84,19 @@ struct IsometricCoordinates
{} {}
}; };
struct DiagonalWorldCoordinates
{
float horizontal;
float vertical;
float depth; // Bigger means further back. Can be used for accurate rendering order.
const sf::Vector2f horizontalAxis = {1, -1};
DiagonalWorldCoordinates(float horizontal, float vertical, float depth) : horizontal(horizontal),
vertical(vertical), depth(depth)
{}
};
struct GridCoordinates struct GridCoordinates
{ {
float x; float x;

View file

@ -2,7 +2,8 @@
#include <utility> #include <utility>
WorldCoordinates TranslatedCoordinates::world() const { WorldCoordinates TranslatedCoordinates::world() const
{
auto coordinates = worldCoordinates; auto coordinates = worldCoordinates;
if (parent != nullptr) if (parent != nullptr)
{ {
@ -12,35 +13,42 @@ WorldCoordinates TranslatedCoordinates::world() const {
return coordinates; return coordinates;
} }
IsometricCoordinates TranslatedCoordinates::isometric() const { IsometricCoordinates TranslatedCoordinates::isometric() const
{
return CoordinateTransformer::worldToIsometric(world()); return CoordinateTransformer::worldToIsometric(world());
} }
GridCoordinates TranslatedCoordinates::grid() const { GridCoordinates TranslatedCoordinates::grid() const
{
auto referenceWordCoordinates = world(); auto referenceWordCoordinates = world();
// Grid coords are just camera coords without height, and scaled differently // Grid coords are just camera coords without height, and scaled differently
return {referenceWordCoordinates.x - 0.5f, referenceWordCoordinates.y - 0.5f}; return {referenceWordCoordinates.x - 0.5f, referenceWordCoordinates.y - 0.5f};
} }
void TranslatedCoordinates::setWorld(WorldCoordinates newWorldCoordinates) { void TranslatedCoordinates::setWorld(WorldCoordinates newWorldCoordinates)
{
this->worldCoordinates = newWorldCoordinates; this->worldCoordinates = newWorldCoordinates;
} }
void TranslatedCoordinates::setIsometric(IsometricCoordinates newIsometricCoordinates) { void TranslatedCoordinates::setIsometric(IsometricCoordinates newIsometricCoordinates)
{
this->worldCoordinates = CoordinateTransformer::isometricToWorld(newIsometricCoordinates); this->worldCoordinates = CoordinateTransformer::isometricToWorld(newIsometricCoordinates);
} }
void TranslatedCoordinates::setTranslated(const TranslatedCoordinates& newCoordinates) { void TranslatedCoordinates::setTranslated(const TranslatedCoordinates &newCoordinates)
{
this->worldCoordinates = newCoordinates.world(); this->worldCoordinates = newCoordinates.world();
} }
void TranslatedCoordinates::move(WorldCoordinates deltaWorldCoordinates) { void TranslatedCoordinates::move(WorldCoordinates deltaWorldCoordinates)
{
this->worldCoordinates = this->worldCoordinates + deltaWorldCoordinates; this->worldCoordinates = this->worldCoordinates + deltaWorldCoordinates;
} }
TranslatedCoordinates::TranslatedCoordinates(WorldCoordinates worldCoordinates) TranslatedCoordinates::TranslatedCoordinates(WorldCoordinates worldCoordinates)
: worldCoordinates(worldCoordinates) { : worldCoordinates(worldCoordinates)
{
} }
void TranslatedCoordinates::move(sf::Vector2f deltaWorldCoordinates) void TranslatedCoordinates::move(sf::Vector2f deltaWorldCoordinates)
@ -73,3 +81,18 @@ TranslatedCoordinates::TranslatedCoordinates(GridCoordinates gridCoordinates)
{ {
setGrid(gridCoordinates); setGrid(gridCoordinates);
} }
DiagonalWorldCoordinates TranslatedCoordinates::diagonalWorld() const
{
return CoordinateTransformer::worldToDiagonal(world());
}
void TranslatedCoordinates::setDiagonal(DiagonalWorldCoordinates newDiagonalWorldCoordinates)
{
this->worldCoordinates = CoordinateTransformer::diagonalToWorld(newDiagonalWorldCoordinates);
}
TranslatedCoordinates::TranslatedCoordinates(DiagonalWorldCoordinates diagonalWorldCoordinates)
{
setDiagonal(diagonalWorldCoordinates);
}

View file

@ -9,6 +9,7 @@ class TranslatedCoordinates
{ {
public: public:
explicit TranslatedCoordinates(WorldCoordinates worldCoordinates); explicit TranslatedCoordinates(WorldCoordinates worldCoordinates);
explicit TranslatedCoordinates(DiagonalWorldCoordinates diagonalWorldCoordinates);
explicit TranslatedCoordinates(GridCoordinates gridCoordinates); explicit TranslatedCoordinates(GridCoordinates gridCoordinates);
[[nodiscard]] WorldCoordinates world() const; [[nodiscard]] WorldCoordinates world() const;
@ -17,12 +18,16 @@ public:
[[nodiscard]] GridCoordinates grid() const; [[nodiscard]] GridCoordinates grid() const;
[[nodiscard]] DiagonalWorldCoordinates diagonalWorld() const;
void setWorld(WorldCoordinates newWorldCoordinates); void setWorld(WorldCoordinates newWorldCoordinates);
void setTranslated(const TranslatedCoordinates& newCoordinates); void setTranslated(const TranslatedCoordinates& newCoordinates);
void setIsometric(IsometricCoordinates newIsometricCoordinates); void setIsometric(IsometricCoordinates newIsometricCoordinates);
void setDiagonal(DiagonalWorldCoordinates newDiagonalWorldCoordinates);
void setGrid(GridCoordinates newGridCoordinates); void setGrid(GridCoordinates newGridCoordinates);
void move(WorldCoordinates deltaWorldCoordinates); void move(WorldCoordinates deltaWorldCoordinates);

View file

@ -13,9 +13,9 @@ void Collectable::setRotation(float angle)
} }
int Collectable::getDepth() const float Collectable::getDepth() const
{ {
return static_cast<int>(coordinates->isometric().depth); return coordinates->isometric().depth;
} }
void Collectable::setSprite(const std::string &spriteName) void Collectable::setSprite(const std::string &spriteName)
@ -24,5 +24,8 @@ void Collectable::setSprite(const std::string &spriteName)
float sizeWidth = 1.f * WORLD_TO_ISO_SCALE; float sizeWidth = 1.f * WORLD_TO_ISO_SCALE;
auto size = sf::Vector2f{sizeWidth, sizeWidth}; auto size = sf::Vector2f{sizeWidth, sizeWidth};
auto sprite = std::make_shared<VersatileSprite>(spriteName, size); auto sprite = std::make_shared<VersatileSprite>(spriteName, size);
addChildScreenOffset(sprite, IsometricCoordinates(-sizeWidth / 2.f, -sizeWidth)); addChildScreenOffset(sprite, IsometricCoordinates(-size / 2.f));
// Set half size offset of coordinates
coordinates->move(WorldCoordinates(0, 0, sizeWidth / 2.f));
} }

View file

@ -13,7 +13,7 @@ public:
void setRotation(float angle); void setRotation(float angle);
int getDepth() const; float getDepth() const;
int getId() const int getId() const
{ {

View file

@ -1,4 +1,6 @@
#include "collectables_collection.hpp" #include "collectables_collection.hpp"
#include <cmath>
#include "collectables_depth_collection.hpp" #include "collectables_depth_collection.hpp"
#include "../../../logging/easylogging++.h" #include "../../../logging/easylogging++.h"
@ -51,10 +53,11 @@ void CollectablesCollection::update()
// Then, move collectables to new depth collections // Then, move collectables to new depth collections
for (auto &[depth, depthCollection]: depthCollections) for (auto &[depth, depthCollection]: depthCollections)
{ {
for (auto &collectable: depthCollection->collectables) auto collectables = depthCollection->collectables;
for (auto &collectable: collectables)
{ {
auto newDepth = collectable->getDepth(); int newDepth = std::floor(collectable->getDepth());
if (newDepth != depth) if (newDepth != depth && newDepth < depthCollections.size())
{ {
depthCollection->remove(collectable); depthCollection->remove(collectable);
depthCollections[newDepth]->add(collectable); depthCollections[newDepth]->add(collectable);

View file

@ -39,6 +39,6 @@ sf::ContextSettings GameFactory::getAdditionalSettings() {
} }
void GameFactory::applyAdditionalWindowConfig(sf::RenderWindow *window) { void GameFactory::applyAdditionalWindowConfig(sf::RenderWindow *window) {
window->setFramerateLimit(FRAME_RATE); // window->setFramerateLimit(FRAME_RATE);
window->setKeyRepeatEnabled(KEY_REPEAT_ENABLED); window->setKeyRepeatEnabled(KEY_REPEAT_ENABLED);
} }

View file

@ -79,3 +79,8 @@ void GameObject::physicsUpdate()
child->physicsUpdate(); child->physicsUpdate();
} }
} }
void GameObject::addDetachedChild(const std::shared_ptr<GameObject> &child)
{
children.push_back(child);
}

View file

@ -26,6 +26,7 @@ public:
void addChildScreenOffset(const std::shared_ptr<GameObject> &child, IsometricCoordinates offset = {0, 0}); void addChildScreenOffset(const std::shared_ptr<GameObject> &child, IsometricCoordinates offset = {0, 0});
void addChildWorldOffset(const std::shared_ptr<GameObject> &child, WorldCoordinates offset); void addChildWorldOffset(const std::shared_ptr<GameObject> &child, WorldCoordinates offset);
void addChild(const std::shared_ptr<GameObject> &child); void addChild(const std::shared_ptr<GameObject> &child);
void addDetachedChild(const std::shared_ptr<GameObject> &child);
void removeChild(const std::shared_ptr<GameObject> &child); void removeChild(const std::shared_ptr<GameObject> &child);
void clearChildren(); void clearChildren();
[[nodiscard]] std::vector<std::shared_ptr<GameObject>> getChildren() const { return children; } [[nodiscard]] std::vector<std::shared_ptr<GameObject>> getChildren() const { return children; }

View file

@ -61,6 +61,13 @@ void LevelLoader::loadLevel(const LevelConfig &levelConfig)
} }
for (int i = 0; i <= 25; i++)
{
auto debugImage = SpriteFactory::createSingleSprite("edge");
debugImage->coordinates->setWorld({0, 0, (float) i});
levelRenderer->addDetachedChild(debugImage);
}
LOG(INFO) << "Finished loading level '" << levelConfig.name << "'."; LOG(INFO) << "Finished loading level '" << levelConfig.name << "'.";
} }
@ -81,7 +88,7 @@ void LevelLoader::spawnCollectable(const CollectableInLevel &collectableInfo)
{ {
LOG(INFO) << "Spawning collectable '" << collectableInfo.name << "' ..."; LOG(INFO) << "Spawning collectable '" << collectableInfo.name << "' ...";
auto collectable = CollectableFactory::createFromInLevelConfig(collectableInfo); auto collectable = CollectableFactory::createFromInLevelConfig(collectableInfo);
LOG(DEBUG) << "Has depth " << collectable->getDepth() << "."; LOG(INFO) << "Has depth " << collectable->getDepth() << ".";
CollectablesCollection::getInstance()->add(collectable); CollectablesCollection::getInstance()->add(collectable);
HolesSimulation::getInstance()->addCollectable(collectable); HolesSimulation::getInstance()->addCollectable(collectable);
} }

View file

@ -1,7 +1,8 @@
#include "collectable_simulation.hpp" #include "collectable_simulation.hpp"
#include <utility> #include "../../../logging/easylogging++.h"
#include "../../../config.h" #include "../../../config.h"
#include "layouts/hole_layout.hpp"
CollectableSimulation::CollectableSimulation(const std::shared_ptr<Collectable> &collectable) CollectableSimulation::CollectableSimulation(const std::shared_ptr<Collectable> &collectable)
: collectable(collectable) : collectable(collectable)
@ -11,24 +12,8 @@ CollectableSimulation::CollectableSimulation(const std::shared_ptr<Collectable>
world->SetAllowSleeping(COLLECTABLES_SIM_SLEEPING); world->SetAllowSleeping(COLLECTABLES_SIM_SLEEPING);
// Create body // Create body
b2BodyDef bodyDef; auto coordinates = collectable->coordinates->diagonalWorld();
bodyDef.type = b2_dynamicBody; body = addSquareBody(b2_dynamicBody, {coordinates.horizontal, coordinates.vertical}, sf::Vector2f(1, 1));
bodyDef.angularDamping = COLLECTABLES_SIM_ANGULAR_DAMPING;
bodyDef.linearDamping = COLLECTABLES_SIM_LINEAR_DAMPING;
// bodyDef.position.Set(collectable->getPosition().x, collectable->getPosition().y);
body = world->CreateBody(&bodyDef);
// Create shape
b2CircleShape shape;
// shape.m_radius = collectable->getRadius();
// Create fixture
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape;
fixtureDef.friction = COLLECTABLES_SIM_FRICTION;
fixtureDef.restitution = COLLECTABLES_SIM_RESTITUTION;
fixtureDef.density = COLLECTABLES_SIM_DENSITY;
body->CreateFixture(&fixtureDef);
} }
void CollectableSimulation::physicsUpdate() void CollectableSimulation::physicsUpdate()
@ -36,6 +21,30 @@ void CollectableSimulation::physicsUpdate()
updateGroundHole(); updateGroundHole();
world->Step(FRAME_TIME.asSeconds(), COLLECTABLES_SIM_VELOCITY_ITERATIONS, COLLECTABLES_SIM_POSITION_ITERATIONS); world->Step(FRAME_TIME.asSeconds(), COLLECTABLES_SIM_VELOCITY_ITERATIONS, COLLECTABLES_SIM_POSITION_ITERATIONS);
updateCollectable();
}
b2Body *CollectableSimulation::addSquareBody(b2BodyType type, sf::Vector2f center, sf::Vector2f size)
{
b2BodyDef bodyDef;
bodyDef.type = type;
bodyDef.angularDamping = COLLECTABLES_SIM_ANGULAR_DAMPING;
bodyDef.linearDamping = COLLECTABLES_SIM_LINEAR_DAMPING;
bodyDef.position.Set(center.x, center.y);
b2Body *body = world->CreateBody(&bodyDef);
b2PolygonShape shape;
shape.SetAsBox(size.x / 2.f, size.y / 2.f);
b2FixtureDef fixtureDef;
fixtureDef.shape = &shape;
fixtureDef.friction = COLLECTABLES_SIM_FRICTION;
fixtureDef.restitution = COLLECTABLES_SIM_RESTITUTION;
fixtureDef.density = COLLECTABLES_SIM_DENSITY;
body->CreateFixture(&fixtureDef);
return body;
} }
std::shared_ptr<Collectable> CollectableSimulation::getCollectable() const std::shared_ptr<Collectable> CollectableSimulation::getCollectable() const
@ -45,5 +54,12 @@ std::shared_ptr<Collectable> CollectableSimulation::getCollectable() const
void CollectableSimulation::updateGroundHole() void CollectableSimulation::updateGroundHole()
{ {
auto holeLayout = HoleLayout::getInstance()->atDepth(collectable->getDepth());
}
void CollectableSimulation::updateCollectable()
{
auto bodyPosition = body->GetPosition();
collectable->coordinates->setDiagonal({bodyPosition.x, bodyPosition.y, collectable->getDepth()});
collectable->setRotation(body->GetAngle());
} }

View file

@ -22,6 +22,10 @@ private:
std::shared_ptr<Collectable> collectable; std::shared_ptr<Collectable> collectable;
void updateGroundHole(); void updateGroundHole();
void updateCollectable();
b2Body *addSquareBody(b2BodyType type, sf::Vector2f center, sf::Vector2f size);
}; };

View file

@ -6,6 +6,10 @@ struct DepthHoleDescription
int playerId; int playerId;
float x; float x;
float width; float width;
DepthHoleDescription(int playerId, float x, float width)
: playerId(playerId), x(x), width(width)
{}
}; };
#endif //HOLESOME_DEPTH_HOLE_DESCRIPTION_HPP #endif //HOLESOME_DEPTH_HOLE_DESCRIPTION_HPP

View file

@ -8,6 +8,10 @@ struct DepthHoleLayout
{ {
float depth; float depth;
std::vector<DepthHoleDescription> holes; std::vector<DepthHoleDescription> holes;
DepthHoleLayout(float depth, std::vector<DepthHoleDescription> holes)
: depth(depth), holes(std::move(holes))
{}
}; };
#endif //HOLESOME_DEPTH_HOLE_LAYOUT_HPP #endif //HOLESOME_DEPTH_HOLE_LAYOUT_HPP

View file

@ -4,6 +4,8 @@
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include "../../../player/player.hpp" #include "../../../player/player.hpp"
#include "../../../../utilities/vector_utils.hpp"
#include "depth_hole_description.hpp"
struct HoleDescription struct HoleDescription
{ {
@ -19,6 +21,21 @@ struct HoleDescription
auto world3d = player->coordinates->world(); auto world3d = player->coordinates->world();
worldPosition = sf::Vector2f(world3d.x, world3d.y); worldPosition = sf::Vector2f(world3d.x, world3d.y);
} }
[[nodiscard]] DepthHoleDescription atDepth(float depth) const
{
auto closestPointAtDepth = CoordinateTransformer::closestWorldPointAtDepth(depth, worldPosition);
auto distance = length(worldPosition - closestPointAtDepth);
if (distance > radius)
{
// No hole at this depth
return DepthHoleDescription(playerId, 0.f, 0.f);
}
float chordLength = 2.f * std::sqrt(radius * radius - distance * distance);
return DepthHoleDescription(playerId, closestPointAtDepth.x, chordLength);
}
}; };

View file

@ -35,3 +35,13 @@ void HoleLayout::lateUpdate()
HoleLayout::HoleLayout() HoleLayout::HoleLayout()
: currentHoles(), previousHoles() : currentHoles(), previousHoles()
{} {}
DepthHoleLayout HoleLayout::atDepth(float depth) const
{
std::vector<DepthHoleDescription> depthHoles{};
for (const auto &hole: currentHoles)
{
depthHoles.push_back(hole.atDepth(depth));
}
return DepthHoleLayout(depth, depthHoles);
}

View file

@ -5,6 +5,7 @@
#include <memory> #include <memory>
#include "../../../game_object.h" #include "../../../game_object.h"
#include "hole_description.hpp" #include "hole_description.hpp"
#include "depth_hole_layout.hpp"
class HoleLayout : public GameObject class HoleLayout : public GameObject
{ {
@ -17,6 +18,8 @@ public:
void clear(); void clear();
DepthHoleLayout atDepth(float depth) const;
private: private:
static inline std::shared_ptr<HoleLayout> singletonInstance = nullptr; static inline std::shared_ptr<HoleLayout> singletonInstance = nullptr;

View file

@ -28,7 +28,7 @@ std::shared_ptr<PlayerCollection> PlayerCollection::getInstance()
void PlayerCollection::addPlayer(const std::shared_ptr<Player> &player) void PlayerCollection::addPlayer(const std::shared_ptr<Player> &player)
{ {
newPlayerBuffer.push_back(player); newPlayerBuffer.push_back(player);
addChild(player); addDetachedChild(player);
} }
void PlayerCollection::clear() void PlayerCollection::clear()
@ -102,7 +102,7 @@ void PlayerCollection::spawnPlayer(const std::shared_ptr<InputIdentity> &inputId
nextSpawnPointIndex = static_cast<int>((nextSpawnPointIndex + 1) % spawnPoints.size()); nextSpawnPointIndex = static_cast<int>((nextSpawnPointIndex + 1) % spawnPoints.size());
auto player = std::make_shared<Player>(inputIdentity, PLAYER_SKIN, spawn); auto player = std::make_shared<Player>(inputIdentity, PLAYER_SKIN, spawn);
PlayerCollection::getInstance()->addPlayer(player); addPlayer(player);
} }
std::vector<std::shared_ptr<Player>> PlayerCollection::getPlayers() const std::vector<std::shared_ptr<Player>> PlayerCollection::getPlayers() const

View file

@ -0,0 +1,121 @@
#include <iostream>
#include <Eigen/Dense>
#include "../coordinates/translated_coordinates.h"
enum CoordinateSystem
{
NONE,
WORLD,
DIAGONAL,
ISOMETRIC
};
CoordinateSystem inputCoordinateSystem()
{
while (true)
{
try
{
std::cout << "Enter coordinate system (w/d/i) or x to close: ";
char coordinateSystemIndicator;
std::cin >> coordinateSystemIndicator;
switch (coordinateSystemIndicator)
{
case 'x':
std::cout << "Closing ..." << std::endl;
return NONE;
case 'w':
std::cout << "World coordinates" << std::endl;
return WORLD;
case 'd':
std::cout << "Diagonal world coordinates" << std::endl;
return DIAGONAL;
case 'i':
std::cout << "Isometric coordinates" << std::endl;
return ISOMETRIC;
default:
std::cout << "Invalid coordinate system. Try again ..." << std::endl;
continue;
}
} catch (...)
{
}
}
}
std::vector<float> input3values(std::string prompt = "Enter 3 values: ")
{
while (true)
{
try
{
std::vector<float> values(3);
std::cout << prompt;
std::cin >> values[0] >> values[1] >> values[2];
return values;
} catch (...)
{
}
}
}
TranslatedCoordinates worldToTranslated(std::vector<float> values)
{
return TranslatedCoordinates(WorldCoordinates{values[0], values[1], values[2]});
}
TranslatedCoordinates diagonalToTranslated(std::vector<float> values)
{
return TranslatedCoordinates(DiagonalWorldCoordinates{values[0], values[1], values[2]});
}
TranslatedCoordinates isometricToTranslated(std::vector<float> values)
{
auto world = CoordinateTransformer::isometricToWorld(IsometricCoordinates{values[0], values[1], values[2]});
return TranslatedCoordinates(world);
}
void printCoordinates(TranslatedCoordinates coordinates)
{
std::cout << "World coordinates (x, y, z): " << coordinates.world().x << ", " << coordinates.world().y << ", "
<< coordinates.world().z << std::endl;
std::cout << "Diagonal world coordinates (horizontal, vertical, depth): " << coordinates.diagonalWorld().horizontal << ", "
<< coordinates.diagonalWorld().vertical << ", " << coordinates.diagonalWorld().depth
<< std::endl;
std::cout << "Isometric coordinates (x, y, depth): " << coordinates.isometric().x << ", "
<< coordinates.isometric().y << ", " << coordinates.isometric().depth << std::endl;
}
int main()
{
while (true)
{
CoordinateSystem coordinateSystem = inputCoordinateSystem();
TranslatedCoordinates translatedCoordinates = TranslatedCoordinates(WorldCoordinates{0, 0, 0});
switch (coordinateSystem)
{
case NONE:
return 0;
case WORLD:
translatedCoordinates = worldToTranslated(input3values("Enter world coordinates (x, y, z): "));
break;
case DIAGONAL:
translatedCoordinates = diagonalToTranslated(
input3values("Enter diagonal world coordinates (horizontal, vertical, depth): "));
break;
case ISOMETRIC:
translatedCoordinates = isometricToTranslated(
input3values("Enter isometric coordinates (x, y, depth): "));
break;
}
printCoordinates(translatedCoordinates);
// Wait for enter, then clear screen
std::cin.ignore();
std::cin.get();
std::cout << "\033[2J\033[1;1H";
}
}

View file

@ -7,7 +7,7 @@
template<typename T> template<typename T>
float length(sf::Vector2<T> v) float length(sf::Vector2<T> v)
{ {
return std::sqrt(v.x * v.x + v.y * v.y); return std::sqrt(pow(v.x, 2) + pow(v.y, 2));
} }
template<typename T> template<typename T>
@ -29,4 +29,10 @@ sf::Vector2<T> abs(sf::Vector2<T> v)
return sf::Vector2<T>(std::abs(v.x), std::abs(v.y)); return sf::Vector2<T>(std::abs(v.x), std::abs(v.y));
} }
template<typename T>
T sum(sf::Vector2<T> v)
{
return v.x + v.y;
}
#endif //HOLESOME_VECTOR_UTILS_HPP #endif //HOLESOME_VECTOR_UTILS_HPP