diff --git a/MSTests/MSTests.cpp b/MSTests/MSTests.cpp
index dc3aeea..01bd8a1 100644
--- a/MSTests/MSTests.cpp
+++ b/MSTests/MSTests.cpp
@@ -309,6 +309,80 @@ namespace MSTests
}
}
+ ///
+ /// Spawns two balls and platforms, each on different layers. One of the balls cannot interact with one of the platforms.
+ ///
+ TEST_METHOD(LayerInteractionTest)
+ {
+ RenderWindow window(VideoMode(800, 600), "Set velocity test");
+ World world(Vector2f(0, 1));
+ PhysicsCircle circle1;
+ circle1.setCenter(Vector2f(300, 100));
+ circle1.setSize(Vector2f(50, 50));
+ circle1.setLayer(0);
+ circle1.setFillColor(sf::Color::Red);
+ world.AddPhysicsBody(circle1);
+
+ PhysicsCircle circle2;
+ circle2.setCenter(Vector2f(500, 100));
+ circle2.setSize(Vector2f(100, 100));
+ circle2.setLayer(1);
+ circle2.setFillColor(sf::Color::Green);
+ world.AddPhysicsBody(circle2);
+
+
+ PhysicsRectangle floor1;
+ floor1.setSize(Vector2f(800, 20));
+ floor1.setCenter(Vector2f(400, 590));
+ floor1.setStatic(true);
+ floor1.setLayer(0);
+ world.AddPhysicsBody(floor1);
+
+ PhysicsRectangle floor2;
+ floor2.setSize(Vector2f(800, 20));
+ floor2.setCenter(Vector2f(400, 400));
+ floor2.setStatic(true);
+ floor2.setLayer(2);
+ floor2.setFillColor(sf::Color::Green);
+ world.AddPhysicsBody(floor2);
+
+ world.ExcludeCollision(1, 2);
+
+ system_clock::time_point last = system_clock::now();
+
+ Clock clock;
+ Time lastTime(clock.getElapsedTime());
+ Time runTime = clock.getElapsedTime() + sf::seconds(10);
+ while (clock.getElapsedTime() < runTime) {
+
+ // calculate MS since last frame
+ Time currentTime(clock.getElapsedTime());
+ Time deltaTime(currentTime - lastTime);
+ int deltaTimeMS(deltaTime.asMilliseconds());
+ if (deltaTimeMS > 0) {
+ world.UpdatePhysics(deltaTimeMS, 1);
+ lastTime = currentTime;
+ }
+ window.clear(Color(0, 0, 0));
+
+ window.draw(circle1);
+ window.draw(circle2);
+ window.draw(floor1);
+ window.draw(floor2);
+ world.VisualizeAllBounds(window);
+ window.display();
+
+ Event ev;
+ if (window.pollEvent(ev))
+ {
+ if (ev.key.code == Keyboard::Space)
+ {
+ break;
+ }
+ }
+ }
+ }
+
TEST_METHOD(SFMLBinding)
{
World world(Vector2f(0, 1));
diff --git a/SFPhysics/CircleBounds.cpp b/SFPhysics/CircleBounds.cpp
index fa3cbb6..9035f71 100644
--- a/SFPhysics/CircleBounds.cpp
+++ b/SFPhysics/CircleBounds.cpp
@@ -107,7 +107,7 @@ float sfp::CircleBounds::getRadius()
void sfp::CircleBounds::setSize(Vector2f extents)
{
- setRadius(max(extents.x, extents.y)/2);
+ setRadius(max(extents.x, extents.y));
}
Vector2f sfp::CircleBounds::getSize()
diff --git a/SFPhysics/PhysicsBody.cpp b/SFPhysics/PhysicsBody.cpp
index 5c6d76b..d960d4e 100644
--- a/SFPhysics/PhysicsBody.cpp
+++ b/SFPhysics/PhysicsBody.cpp
@@ -10,7 +10,7 @@ using namespace sfp;
sfp::PhysicsBody::PhysicsBody():
restitution(1.0),mass(1.0),isStatic(false),
- velocity(Vector2f(0,0))
+ velocity(Vector2f(0,0)), layer(0)
{
}
@@ -124,6 +124,16 @@ bool sfp::PhysicsBody::hasMoved()
return moved;
}
+void sfp::PhysicsBody::setLayer(unsigned int layer)
+{
+ this->layer = layer;
+}
+
+unsigned int sfp::PhysicsBody::getLayer()
+{
+ return layer;
+}
+
diff --git a/SFPhysics/PhysicsLayer.cpp b/SFPhysics/PhysicsLayer.cpp
new file mode 100644
index 0000000..fbc7338
--- /dev/null
+++ b/SFPhysics/PhysicsLayer.cpp
@@ -0,0 +1,2 @@
+#include "pch.h"
+#include "PhysicsLayer.h"
diff --git a/SFPhysics/SFPhysics.vcxproj b/SFPhysics/SFPhysics.vcxproj
index f49824e..912382a 100644
--- a/SFPhysics/SFPhysics.vcxproj
+++ b/SFPhysics/SFPhysics.vcxproj
@@ -181,6 +181,7 @@
+
@@ -209,6 +210,7 @@
+
diff --git a/SFPhysics/SFPhysics.vcxproj.filters b/SFPhysics/SFPhysics.vcxproj.filters
index e80d770..ea6928a 100644
--- a/SFPhysics/SFPhysics.vcxproj.filters
+++ b/SFPhysics/SFPhysics.vcxproj.filters
@@ -90,6 +90,9 @@
Header Files
+
+ Header Files
+
@@ -152,6 +155,9 @@
Source Files
+
+ Source Files
+
diff --git a/SFPhysics/World.cpp b/SFPhysics/World.cpp
index 05b2a69..d76e564 100644
--- a/SFPhysics/World.cpp
+++ b/SFPhysics/World.cpp
@@ -81,7 +81,7 @@ void sfp::World::UpdatePhysics(unsigned long deltaMilliseconds,unsigned long msP
// do collision, very stupid right now. long run should not check
// objecst that havent moved
for (auto obj2 : objects) {
- if ((obj != obj2) && (ignoreMovement || obj->hasMoved() || obj2->hasMoved())) {
+ if ((obj != obj2) && (ignoreMovement || obj->hasMoved() || obj2->hasMoved()) && HasCollision(obj->getLayer(), obj2->getLayer())) {
PhysicsBodyCollisionResult collision =
obj->collideWith(*obj2);
if (collision.hasCollided) {
@@ -111,3 +111,54 @@ void sfp::World::setIgnoreMovement(bool ignore)
{
ignoreMovement = ignore;
}
+
+void sfp::World::ExcludeCollision(unsigned int layer1, unsigned int layer2)
+{
+ // Use the lower layer number. This is to prevent overlap.
+ int primaryLayer = layer1 < layer2 ? layer1 : layer2;
+ int otherLayer = layer1 < layer2 ? layer2 : layer1;
+
+ for (auto layer : layers)
+ {
+ if (layer.Layer == primaryLayer)
+ {
+ layer.AddExcludedLayer(otherLayer);
+ return;
+ }
+ }
+
+ PhysicsLayer layer;
+ layer.Layer = layer1;
+ layer.AddExcludedLayer(layer2);
+ layers.push_back(layer);
+}
+
+void sfp::World::IncludeCollision(unsigned int layer1, unsigned int layer2)
+{
+ // Use the lower layer number. This is to prevent overlap.
+ int primaryLayer = layer1 < layer2 ? layer1 : layer2;
+ int otherLayer = layer1 < layer2 ? layer2 : layer1;
+
+ for (auto layer : layers)
+ {
+ if (layer.Layer == primaryLayer)
+ {
+ layer.RemoveExcludedLayer(otherLayer);
+ return;
+ }
+ }
+}
+
+bool sfp::World::HasCollision(unsigned int layer1, unsigned int layer2)
+{
+ // Use the lower layer number. This is to prevent overlap.
+ int primaryLayer = layer1 < layer2 ? layer1 : layer2;
+ int otherLayer = layer1 < layer2 ? layer2 : layer1;
+
+ for (auto layer : layers)
+ {
+ if (layer.Layer == primaryLayer)
+ return !layer.ExcludesLayer(otherLayer);
+ }
+ return true;
+}
diff --git a/SFPhysics/include/SFPhysics/PhysicsBody.h b/SFPhysics/include/SFPhysics/PhysicsBody.h
index fd3e0a1..ca3b23e 100644
--- a/SFPhysics/include/SFPhysics/PhysicsBody.h
+++ b/SFPhysics/include/SFPhysics/PhysicsBody.h
@@ -16,11 +16,11 @@ namespace sfp {
bool isStatic;
Vector2f velocity;
bool moved;
-
+ unsigned int layer;
public:
PhysicsBody();
PhysicsBody(Bounds& bounds, bool isStatic = false,
- float restitution=1.0f,float mass=1.0f);
+ float restitution=1.0f,float mass=1.0f, int layer = 0);
void applyImpulse(Vector2f impulse);
void update(unsigned int deltaMillisconds);
void setPosition(Vector2f center);
@@ -39,6 +39,16 @@ namespace sfp {
PhysicsBodyCollisionResult collideWith(PhysicsBody& other);
void setMoved(bool moved = false);
bool hasMoved();
+ ///
+ /// Sets the collision layer to be set to this object. Default is 0.
+ ///
+ /// The layer to use.
+ void setLayer(unsigned int layer);
+ ///
+ /// Gets the current layer associated with this object. Default is 0.
+ ///
+ /// The layer this object is associated with.
+ unsigned int getLayer();
bool operator == (const PhysicsBody& other) {
return this == &other;
diff --git a/SFPhysics/include/SFPhysics/PhysicsLayer.h b/SFPhysics/include/SFPhysics/PhysicsLayer.h
new file mode 100644
index 0000000..8ed5fc0
--- /dev/null
+++ b/SFPhysics/include/SFPhysics/PhysicsLayer.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include
+
+///
+/// Struct that stores a Layer and a list of Exclusion layers.
+/// This struct is intended for internal use.
+///
+/// Notes: This isn't intended to be a very complex Physics Layer system. Instead, it tries to prioritize ease-of-use without concerning too much on bit flags.
+///
+struct PhysicsLayer
+{
+public:
+ unsigned Layer;
+ std::list ExclusionLayers;
+
+ bool ExcludesLayer(unsigned layer)
+ {
+ for (unsigned excludedLayer : ExclusionLayers)
+ {
+ if (excludedLayer == layer)
+ return true;
+ }
+ return false;
+ }
+
+ void AddExcludedLayer(unsigned layer)
+ {
+ for (unsigned excludedLayer : ExclusionLayers)
+ {
+ if (excludedLayer == layer)
+ return;
+ }
+
+ ExclusionLayers.push_back(layer);
+ }
+
+ void RemoveExcludedLayer(unsigned layer)
+ {
+ ExclusionLayers.remove(layer);
+ }
+};
+
diff --git a/SFPhysics/include/SFPhysics/World.h b/SFPhysics/include/SFPhysics/World.h
index faab82d..cd31561 100644
--- a/SFPhysics/include/SFPhysics/World.h
+++ b/SFPhysics/include/SFPhysics/World.h
@@ -2,6 +2,7 @@
#include
#include
#include "PhysicsBody.h"
+#include "PhysicsLayer.h"
using namespace sf;
using namespace std;
@@ -15,6 +16,7 @@ namespace sfp {
bool ignoreMovement;
list removalList;
long unsigned deltaAccumulator = 0;
+ list layers;
public:
World(Vector2f gravity);
@@ -23,6 +25,25 @@ namespace sfp {
void UpdatePhysics(unsigned long deltaMilliseconds, unsigned long msPerTick = 0);
void VisualizeAllBounds(RenderWindow& window);
void setIgnoreMovement(bool ignore = true);
+ ///
+ /// Prevents a layer from interacting with another layer.
+ ///
+ /// The first layer to compare
+ /// The second layer to compare
+ void ExcludeCollision(unsigned int layer1, unsigned int layer2);
+ ///
+ /// Allows a layer to interact with another layer. Note that layers can interact with other layers by default.
+ ///
+ /// The first layer to compare
+ /// The second layer to compare
+ void IncludeCollision(unsigned int layer1, unsigned int layer2);
+ ///
+ /// Check if a layer is allowed to collide with another layer.
+ ///
+ /// The first layer to compare
+ /// The second layer to compare
+ ///
+ bool HasCollision(unsigned int layer1, unsigned int layer2);
};
}