mirror of https://github.com/axmolengine/axmol.git
190 lines
5.9 KiB
C++
190 lines
5.9 KiB
C++
// MIT License
|
|
|
|
// Copyright (c) 2019 Erin Catto
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
// The above copyright notice and this permission notice shall be included in all
|
|
// copies or substantial portions of the Software.
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
// SOFTWARE.
|
|
|
|
#include "test.h"
|
|
|
|
#include <algorithm>
|
|
|
|
// This test shows collision processing and tests
|
|
// deferred body destruction.
|
|
class CollisionProcessing : public Test
|
|
{
|
|
public:
|
|
CollisionProcessing()
|
|
{
|
|
// Ground body
|
|
{
|
|
b2EdgeShape shape;
|
|
shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f));
|
|
|
|
b2FixtureDef sd;
|
|
sd.shape = &shape;
|
|
;
|
|
|
|
b2BodyDef bd;
|
|
b2Body* ground = m_world->CreateBody(&bd);
|
|
ground->CreateFixture(&sd);
|
|
}
|
|
|
|
float xLo = -5.0f, xHi = 5.0f;
|
|
float yLo = 2.0f, yHi = 35.0f;
|
|
|
|
// Small triangle
|
|
b2Vec2 vertices[3];
|
|
vertices[0].Set(-1.0f, 0.0f);
|
|
vertices[1].Set(1.0f, 0.0f);
|
|
vertices[2].Set(0.0f, 2.0f);
|
|
|
|
b2PolygonShape polygon;
|
|
polygon.Set(vertices, 3);
|
|
|
|
b2FixtureDef triangleShapeDef;
|
|
triangleShapeDef.shape = &polygon;
|
|
triangleShapeDef.density = 1.0f;
|
|
|
|
b2BodyDef triangleBodyDef;
|
|
triangleBodyDef.type = b2_dynamicBody;
|
|
triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
|
|
|
|
b2Body* body1 = m_world->CreateBody(&triangleBodyDef);
|
|
body1->CreateFixture(&triangleShapeDef);
|
|
|
|
// Large triangle (recycle definitions)
|
|
vertices[0] *= 2.0f;
|
|
vertices[1] *= 2.0f;
|
|
vertices[2] *= 2.0f;
|
|
polygon.Set(vertices, 3);
|
|
|
|
triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
|
|
|
|
b2Body* body2 = m_world->CreateBody(&triangleBodyDef);
|
|
body2->CreateFixture(&triangleShapeDef);
|
|
|
|
// Small box
|
|
polygon.SetAsBox(1.0f, 0.5f);
|
|
|
|
b2FixtureDef boxShapeDef;
|
|
boxShapeDef.shape = &polygon;
|
|
boxShapeDef.density = 1.0f;
|
|
|
|
b2BodyDef boxBodyDef;
|
|
boxBodyDef.type = b2_dynamicBody;
|
|
boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
|
|
|
|
b2Body* body3 = m_world->CreateBody(&boxBodyDef);
|
|
body3->CreateFixture(&boxShapeDef);
|
|
|
|
// Large box (recycle definitions)
|
|
polygon.SetAsBox(2.0f, 1.0f);
|
|
boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
|
|
|
|
b2Body* body4 = m_world->CreateBody(&boxBodyDef);
|
|
body4->CreateFixture(&boxShapeDef);
|
|
|
|
// Small circle
|
|
b2CircleShape circle;
|
|
circle.m_radius = 1.0f;
|
|
|
|
b2FixtureDef circleShapeDef;
|
|
circleShapeDef.shape = &circle;
|
|
circleShapeDef.density = 1.0f;
|
|
|
|
b2BodyDef circleBodyDef;
|
|
circleBodyDef.type = b2_dynamicBody;
|
|
circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
|
|
|
|
b2Body* body5 = m_world->CreateBody(&circleBodyDef);
|
|
body5->CreateFixture(&circleShapeDef);
|
|
|
|
// Large circle
|
|
circle.m_radius *= 2.0f;
|
|
circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi));
|
|
|
|
b2Body* body6 = m_world->CreateBody(&circleBodyDef);
|
|
body6->CreateFixture(&circleShapeDef);
|
|
}
|
|
|
|
void Step(Settings& settings) override
|
|
{
|
|
Test::Step(settings);
|
|
|
|
// We are going to destroy some bodies according to contact
|
|
// points. We must buffer the bodies that should be destroyed
|
|
// because they may belong to multiple contact points.
|
|
const int32 k_maxNuke = 6;
|
|
b2Body* nuke[k_maxNuke];
|
|
int32 nukeCount = 0;
|
|
|
|
// Traverse the contact results. Destroy bodies that
|
|
// are touching heavier bodies.
|
|
for (int32 i = 0; i < m_pointCount; ++i)
|
|
{
|
|
ContactPoint* point = m_points + i;
|
|
|
|
b2Body* body1 = point->fixtureA->GetBody();
|
|
b2Body* body2 = point->fixtureB->GetBody();
|
|
float mass1 = body1->GetMass();
|
|
float mass2 = body2->GetMass();
|
|
|
|
if (mass1 > 0.0f && mass2 > 0.0f)
|
|
{
|
|
if (mass2 > mass1)
|
|
{
|
|
nuke[nukeCount++] = body1;
|
|
}
|
|
else
|
|
{
|
|
nuke[nukeCount++] = body2;
|
|
}
|
|
|
|
if (nukeCount == k_maxNuke)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sort the nuke array to group duplicates.
|
|
std::sort(nuke, nuke + nukeCount);
|
|
|
|
// Destroy the bodies, skipping duplicates.
|
|
int32 i = 0;
|
|
while (i < nukeCount)
|
|
{
|
|
b2Body* b = nuke[i++];
|
|
while (i < nukeCount && nuke[i] == b)
|
|
{
|
|
++i;
|
|
}
|
|
|
|
if (b != m_bomb)
|
|
{
|
|
m_world->DestroyBody(b);
|
|
}
|
|
}
|
|
}
|
|
|
|
static Test* Create() { return new CollisionProcessing; }
|
|
};
|
|
|
|
static int testIndex = RegisterTest("Examples", "Collision Processing", CollisionProcessing::Create);
|