Initial commit
This commit is contained in:
223
engines/crab/collision.cpp
Normal file
223
engines/crab/collision.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is based on the CRAB engine
|
||||
*
|
||||
* Copyright (c) Arvind Raja Yadav
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crab/collision.h"
|
||||
|
||||
namespace Crab {
|
||||
|
||||
// Find if a line and a rectangle intersect
|
||||
bool collideLineRect(int p0X, int p0Y, int p1X, int p1Y, const Rect &rect) {
|
||||
int q0_x = rect.x;
|
||||
int q0_y = rect.y;
|
||||
int q1_x = rect.x + rect.w;
|
||||
int q1_y = rect.y;
|
||||
|
||||
if (collideLine<int>(p0X, p0Y, p1X, p1Y, q0_x, q0_y, q1_x, q1_y))
|
||||
return true;
|
||||
|
||||
q0_x = rect.x;
|
||||
q0_y = rect.y;
|
||||
q1_x = rect.x;
|
||||
q1_y = rect.y + rect.h;
|
||||
|
||||
if (collideLine<int>(p0X, p0Y, p1X, p1Y, q0_x, q0_y, q1_x, q1_y))
|
||||
return true;
|
||||
|
||||
q0_x = rect.x + rect.w;
|
||||
q0_y = rect.y;
|
||||
q1_x = rect.x + rect.w;
|
||||
q1_y = rect.y + rect.h;
|
||||
|
||||
if (collideLine<int>(p0X, p0Y, p1X, p1Y, q0_x, q0_y, q1_x, q1_y))
|
||||
return true;
|
||||
|
||||
q0_x = rect.x;
|
||||
q0_y = rect.y + rect.h;
|
||||
q1_x = rect.x + rect.w;
|
||||
q1_y = rect.y + rect.h;
|
||||
|
||||
if (collideLine<int>(p0X, p0Y, p1X, p1Y, q0_x, q0_y, q1_x, q1_y))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find if there is a clear line of sight between two rectangles
|
||||
bool lineOfSight(const Rect &a, const Rect &b, const Rect &obstacle) {
|
||||
int p0_x = a.x;
|
||||
int p0_y = a.y;
|
||||
int p1_x = b.x;
|
||||
int p1_y = b.y;
|
||||
|
||||
if (collideLineRect(p0_x, p0_y, p1_x, p1_y, obstacle))
|
||||
return false;
|
||||
|
||||
p0_x = a.x + a.w;
|
||||
p0_y = a.y;
|
||||
p1_x = b.x + b.w;
|
||||
p1_y = b.y;
|
||||
|
||||
if (collideLineRect(p0_x, p0_y, p1_x, p1_y, obstacle))
|
||||
return false;
|
||||
|
||||
p0_x = a.x;
|
||||
p0_y = a.y + a.h;
|
||||
p1_x = b.x;
|
||||
p1_y = b.y + b.h;
|
||||
|
||||
if (collideLineRect(p0_x, p0_y, p1_x, p1_y, obstacle))
|
||||
return false;
|
||||
|
||||
p0_x = a.x + a.w;
|
||||
p0_y = a.y + a.h;
|
||||
p1_x = b.x + b.w;
|
||||
p1_y = b.y + b.h;
|
||||
|
||||
if (collideLineRect(p0_x, p0_y, p1_x, p1_y, obstacle))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// float IntervalDistance(float minA, float maxA, float minB, float maxB)
|
||||
//{
|
||||
// if (minA < minB)
|
||||
// return minB - maxA;
|
||||
//
|
||||
// return minA - maxB;
|
||||
// }
|
||||
//
|
||||
//// Calculate the projection of a polygon on an axis and returns it as a [min, max] interval
|
||||
// void ProjectPolygon(const Vector2i &axis, const Polygon2D &poly, float &min, float &max)
|
||||
//{
|
||||
// // To project a point on an axis use the dot product
|
||||
// float d = axis.DotProduct(poly.point[0]);
|
||||
// min = d;
|
||||
// max = d;
|
||||
//
|
||||
// for(auto i = poly.point.begin(); i != poly.point.end(); ++i)
|
||||
// {
|
||||
// d = i->DotProduct(axis);
|
||||
//
|
||||
// if (d < min) min = d;
|
||||
// else if (d > max) max = d;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// PolygonCollisionResult Collide(const Polygon2D &polyA, const Polygon2D &polyB, const Vector2i &velocity)
|
||||
//{
|
||||
// PolygonCollisionResult result;
|
||||
//
|
||||
// int edgeCountA = polyA.edge.size();
|
||||
// int edgeCountB = polyB.edge.size();
|
||||
// float minIntervalDistance = std::numeric_limits<float>::max();
|
||||
// Vector2i translationAxis;
|
||||
// Vector2i edge;
|
||||
//
|
||||
// // Loop through all the edges of both polygons
|
||||
// for(int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++)
|
||||
// {
|
||||
// if (edgeIndex < edgeCountA)
|
||||
// edge = polyA.edge[edgeIndex];
|
||||
// else
|
||||
// edge = polyB.edge[edgeIndex - edgeCountA];
|
||||
//
|
||||
// // ===== 1. Find if the Polygon2Ds are currently intersecting =====
|
||||
//
|
||||
// // Find the axis perpendicular to the current edge
|
||||
// Vector2i axis(-edge.y, edge.x);
|
||||
// axis.Normalize();
|
||||
//
|
||||
// // Find the projection of the Polygon2D on the current axis
|
||||
// float minA = 0; float minB = 0; float maxA = 0; float maxB = 0;
|
||||
// ProjectPolygon(axis, polyA, minA, maxA);
|
||||
// ProjectPolygon(axis, polyB, minB, maxB);
|
||||
//
|
||||
// // Check if the Polygon2D projections are currently intersecting
|
||||
// if (IntervalDistance(minA, maxA, minB, maxB) > 0)
|
||||
// result.intersect = false;
|
||||
//
|
||||
// // ===== 2. Now find if the Polygon2Ds *will* intersect =====
|
||||
//
|
||||
// // Project the velocity on the current axis
|
||||
// float velocityProjection = axis.DotProduct(velocity);
|
||||
//
|
||||
// // Get the projection of Polygon2D A during the movement
|
||||
// if (velocityProjection < 0)
|
||||
// minA += velocityProjection;
|
||||
// else
|
||||
// maxA += velocityProjection;
|
||||
//
|
||||
// // Do the same test as above for the new projection
|
||||
// float intervalDistance = IntervalDistance(minA, maxA, minB, maxB);
|
||||
// if (intervalDistance > 0)
|
||||
// result.will_intersect = false;
|
||||
//
|
||||
// // If the Polygon2Ds are not intersecting and won't intersect, exit the loop
|
||||
// if (!result.intersect && !result.will_intersect)
|
||||
// break;
|
||||
//
|
||||
// // Check if the current interval distance is the minimum one. If so store
|
||||
// // the interval distance and the current distance.
|
||||
// // This will be used to calculate the minimum translation vector
|
||||
// intervalDistance = abs(intervalDistance);
|
||||
// if (intervalDistance < minIntervalDistance)
|
||||
// {
|
||||
// minIntervalDistance = intervalDistance;
|
||||
// translationAxis = axis;
|
||||
//
|
||||
// Vector2i d, ca, cb;
|
||||
// ca = polyA.Center();
|
||||
// cb = polyB.Center();
|
||||
//
|
||||
// d.x = ca.x - cb.x;
|
||||
// d.y = ca.y - cb.y;
|
||||
//
|
||||
// if (d.DotProduct(translationAxis) < 0)
|
||||
// {
|
||||
// translationAxis.x = -translationAxis.x;
|
||||
// translationAxis.y = -translationAxis.y;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // The minimum translation vector can be used to push the Polygon2Ds apart.
|
||||
// // First moves the Polygon2Ds by their velocity
|
||||
// // then move polyA by MinimumTranslationVector.
|
||||
// if (result.will_intersect)
|
||||
// {
|
||||
// result.mtv.x = translationAxis.x * minIntervalDistance;
|
||||
// result.mtv.y = translationAxis.y * minIntervalDistance;
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
|
||||
} // End of namespace Crab
|
||||
Reference in New Issue
Block a user