Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions MSTests/MSTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,80 @@ namespace MSTests
}
}

/// <summary>
/// Spawns two balls and platforms, each on different layers. One of the balls cannot interact with one of the platforms.
/// </summary>
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));
Expand Down
2 changes: 1 addition & 1 deletion SFPhysics/CircleBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
12 changes: 11 additions & 1 deletion SFPhysics/PhysicsBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
}

Expand Down Expand Up @@ -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;
}




Expand Down
2 changes: 2 additions & 0 deletions SFPhysics/PhysicsLayer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "pch.h"
#include "PhysicsLayer.h"
2 changes: 2 additions & 0 deletions SFPhysics/SFPhysics.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
<ClInclude Include="include\SFPhysics\PhysicsBodyT.h" />
<ClInclude Include="include\SFPhysics\PhysicsCircle.h" />
<ClInclude Include="include\SFPhysics\PhysicsConvexPolygon.h" />
<ClInclude Include="include\SFPhysics\PhysicsLayer.h" />
<ClInclude Include="include\SFPhysics\PhysicsRectangle.h" />
<ClInclude Include="include\SFPhysics\PhysicsShape.h" />
<ClInclude Include="include\SFPhysics\PhysicsShapeList.h" />
Expand Down Expand Up @@ -209,6 +210,7 @@
<ClCompile Include="PhysicsBodyCollisionResult.cpp" />
<ClCompile Include="PhysicsCircle.cpp" />
<ClCompile Include="PhysicsConvexPolygon.cpp" />
<ClCompile Include="PhysicsLayer.cpp" />
<ClCompile Include="PhysicsRectangle.cpp" />
<ClCompile Include="PhysicsShape.cpp" />
<ClCompile Include="PhysicsShapeList.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions SFPhysics/SFPhysics.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@
<ClInclude Include="include\SFPhysics\PhysicsConvexPolygon.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="include\SFPhysics\PhysicsLayer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="SFPhysics.cpp">
Expand Down Expand Up @@ -152,6 +155,9 @@
<ClCompile Include="PhysicsShapeList.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PhysicsLayer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
Expand Down
53 changes: 52 additions & 1 deletion SFPhysics/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
14 changes: 12 additions & 2 deletions SFPhysics/include/SFPhysics/PhysicsBody.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -39,6 +39,16 @@ namespace sfp {
PhysicsBodyCollisionResult collideWith(PhysicsBody& other);
void setMoved(bool moved = false);
bool hasMoved();
/// <summary>
/// Sets the collision layer to be set to this object. Default is 0.
/// </summary>
/// <param name="layer">The layer to use.</param>
void setLayer(unsigned int layer);
/// <summary>
/// Gets the current layer associated with this object. Default is 0.
/// </summary>
/// <returns>The layer this object is associated with.</returns>
unsigned int getLayer();

bool operator == (const PhysicsBody& other) {
return this == &other;
Expand Down
43 changes: 43 additions & 0 deletions SFPhysics/include/SFPhysics/PhysicsLayer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#pragma once

#include <list>

/// <summary>
/// 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.
/// </summary>
struct PhysicsLayer
{
public:
unsigned Layer;
std::list<unsigned> 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);
}
};

21 changes: 21 additions & 0 deletions SFPhysics/include/SFPhysics/World.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <SFML/Graphics.hpp>
#include <list>
#include "PhysicsBody.h"
#include "PhysicsLayer.h"

using namespace sf;
using namespace std;
Expand All @@ -15,6 +16,7 @@ namespace sfp {
bool ignoreMovement;
list<PhysicsBody*> removalList;
long unsigned deltaAccumulator = 0;
list<PhysicsLayer> layers;
public:
World(Vector2f gravity);

Expand All @@ -23,6 +25,25 @@ namespace sfp {
void UpdatePhysics(unsigned long deltaMilliseconds, unsigned long msPerTick = 0);
void VisualizeAllBounds(RenderWindow& window);
void setIgnoreMovement(bool ignore = true);
/// <summary>
/// Prevents a layer from interacting with another layer.
/// </summary>
/// <param name="layer1">The first layer to compare</param>
/// <param name="layer2">The second layer to compare</param>
void ExcludeCollision(unsigned int layer1, unsigned int layer2);
/// <summary>
/// Allows a layer to interact with another layer. Note that layers can interact with other layers by default.
/// </summary>
/// <param name="layer1">The first layer to compare</param>
/// <param name="layer2">The second layer to compare</param>
void IncludeCollision(unsigned int layer1, unsigned int layer2);
/// <summary>
/// Check if a layer is allowed to collide with another layer.
/// </summary>
/// <param name="layer1">The first layer to compare</param>
/// <param name="layer2">The second layer to compare</param>
/// <returns></returns>
bool HasCollision(unsigned int layer1, unsigned int layer2);
};
}

Expand Down