Triangle physics seemingly done
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
{
|
||||
"activeFile": "map.tmj",
|
||||
"activeFile": "overworld.tsx",
|
||||
"expandedProjectPaths": [
|
||||
"templates",
|
||||
"."
|
||||
".",
|
||||
"templates"
|
||||
],
|
||||
"fileStates": {
|
||||
":/automap-tiles.tsx": {
|
||||
@ -13,11 +13,11 @@
|
||||
"scaleInEditor": 1
|
||||
},
|
||||
"map.tmj": {
|
||||
"scale": 4,
|
||||
"selectedLayer": 2,
|
||||
"scale": 3,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 6599.375,
|
||||
"y": 6795.125
|
||||
"x": 6520.166666666666,
|
||||
"y": 6836.833333333333
|
||||
}
|
||||
},
|
||||
"overworld.tsx": {
|
||||
@ -35,8 +35,8 @@
|
||||
"project": "map project.tiled-project",
|
||||
"property.type": "int",
|
||||
"recentFiles": [
|
||||
"overworld.tsx",
|
||||
"map.tmj",
|
||||
"overworld.tsx",
|
||||
"entities.tsx"
|
||||
],
|
||||
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
|
||||
|
@ -101,9 +101,8 @@ void entityUpdate(entity_t *entity) {
|
||||
switch(TILE_META_DATA[tile].solidType) {
|
||||
case TILE_SOLID_FULL:
|
||||
collision = physicsCheckCircleAABB(
|
||||
newX, newY, selfCircR,
|
||||
fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||
lx, ty,
|
||||
FIXED248(TILE_WIDTH_HEIGHT, 0),
|
||||
FIXED248(TILE_WIDTH_HEIGHT, 0)
|
||||
);
|
||||
@ -111,44 +110,38 @@ void entityUpdate(entity_t *entity) {
|
||||
|
||||
case TILE_SOLID_TRIANGLE_TOP_RIGHT:
|
||||
collision = physicsCheckCircleTriangle(
|
||||
newX, newY, selfCircR,
|
||||
lx, ty,
|
||||
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||
rx, by,
|
||||
rx, ty,
|
||||
rx, by
|
||||
lx, ty
|
||||
);
|
||||
break;
|
||||
|
||||
// case TILE_SOLID_TRIANGLE_TOP_LEFT:
|
||||
// collision = physicsCheckCircleTriangle(
|
||||
// newX, newY, selfCircR,
|
||||
// lx, ty,
|
||||
// rx, ty,
|
||||
// lx, by
|
||||
// );
|
||||
// break;
|
||||
// case TILE_SOLID_TRIANGLE_BOTTOM_RIGHT:
|
||||
// collision = physicsCheckCircleTriangle(
|
||||
// newX, newY, selfCircR,
|
||||
// fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0))
|
||||
// );
|
||||
// break;
|
||||
case TILE_SOLID_TRIANGLE_TOP_LEFT:
|
||||
collision = physicsCheckCircleTriangle(
|
||||
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||
lx, by,
|
||||
lx, ty,
|
||||
rx, ty
|
||||
);
|
||||
break;
|
||||
|
||||
// case TILE_SOLID_TRIANGLE_BOTTOM_LEFT:
|
||||
// collision = physicsCheckCircleTriangle(
|
||||
// newX, newY, selfCircR,
|
||||
// fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Addfx248(fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
||||
// fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0))
|
||||
// );
|
||||
// break;
|
||||
case TILE_SOLID_TRIANGLE_BOTTOM_RIGHT:
|
||||
collision = physicsCheckCircleTriangle(
|
||||
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||
rx, ty,
|
||||
rx, by,
|
||||
lx, by
|
||||
);
|
||||
break;
|
||||
case TILE_SOLID_TRIANGLE_BOTTOM_LEFT:
|
||||
collision = physicsCheckCircleTriangle(
|
||||
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||
lx, ty,
|
||||
lx, by,
|
||||
rx, by
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
|
@ -99,13 +99,155 @@ collisionresult_t physicsCheckCircleAABB(
|
||||
return result;
|
||||
}
|
||||
|
||||
void physicsClosestPointOnSegment(
|
||||
fixed248_t ax, fixed248_t ay,
|
||||
fixed248_t bx, fixed248_t by,
|
||||
fixed248_t px, fixed248_t py,
|
||||
fixed248_t *outX, fixed248_t *outY
|
||||
) {
|
||||
fixed248_t abx = fx248Subfx248(bx, ax);
|
||||
fixed248_t aby = fx248Subfx248(by, ay);
|
||||
fixed248_t apx = fx248Subfx248(px, ax);
|
||||
fixed248_t apy = fx248Subfx248(py, ay);
|
||||
|
||||
fixed248_t abLenSq = fx248Addfx248(
|
||||
fx248Mulfx248(abx, abx),
|
||||
fx248Mulfx248(aby, aby)
|
||||
);
|
||||
|
||||
if(abLenSq == FIXED248_ZERO) {
|
||||
*outX = ax;
|
||||
*outY = ay;
|
||||
return;
|
||||
}
|
||||
|
||||
fixed248_t t = fx248Divfx248(
|
||||
fx248Addfx248(fx248Mulfx248(apx, abx), fx248Mulfx248(apy, aby)),
|
||||
abLenSq
|
||||
);
|
||||
|
||||
if(t < FIXED248_ZERO) t = FIXED248_ZERO;
|
||||
if(t > FIXED248_ONE) t = FIXED248_ONE;
|
||||
|
||||
*outX = fx248Addfx248(ax, fx248Mulfx248(abx, t));
|
||||
*outY = fx248Addfx248(ay, fx248Mulfx248(aby, t));
|
||||
}
|
||||
|
||||
bool_t physicsIsPointInTriangle(
|
||||
fixed248_t px, fixed248_t py,
|
||||
fixed248_t ax, fixed248_t ay,
|
||||
fixed248_t bx, fixed248_t by,
|
||||
fixed248_t cx, fixed248_t cy
|
||||
) {
|
||||
fixed248_t abx = fx248Subfx248(bx, ax);
|
||||
fixed248_t aby = fx248Subfx248(by, ay);
|
||||
fixed248_t bcx = fx248Subfx248(cx, bx);
|
||||
fixed248_t bcy = fx248Subfx248(cy, by);
|
||||
fixed248_t cax = fx248Subfx248(ax, cx);
|
||||
fixed248_t cay = fx248Subfx248(ay, cy);
|
||||
|
||||
fixed248_t apx = fx248Subfx248(px, ax);
|
||||
fixed248_t apy = fx248Subfx248(py, ay);
|
||||
fixed248_t bpx = fx248Subfx248(px, bx);
|
||||
fixed248_t bpy = fx248Subfx248(py, by);
|
||||
fixed248_t cpx = fx248Subfx248(px, cx);
|
||||
fixed248_t cpy = fx248Subfx248(py, cy);
|
||||
|
||||
fixed248_t cross1 = fx248Subfx248(
|
||||
fx248Mulfx248(abx, apy),
|
||||
fx248Mulfx248(aby, apx)
|
||||
);
|
||||
fixed248_t cross2 = fx248Subfx248(
|
||||
fx248Mulfx248(bcx, bpy),
|
||||
fx248Mulfx248(bcy, bpx)
|
||||
);
|
||||
fixed248_t cross3 = fx248Subfx248(
|
||||
fx248Mulfx248(cax, cpy),
|
||||
fx248Mulfx248(cay, cpx)
|
||||
);
|
||||
|
||||
bool_t hasNeg = (
|
||||
(cross1 < FIXED248_ZERO) ||
|
||||
(cross2 < FIXED248_ZERO) ||
|
||||
(cross3 < FIXED248_ZERO)
|
||||
);
|
||||
|
||||
bool_t hasPos = (
|
||||
(cross1 > FIXED248_ZERO) ||
|
||||
(cross2 > FIXED248_ZERO) ||
|
||||
(cross3 > FIXED248_ZERO)
|
||||
);
|
||||
|
||||
return !(hasNeg && hasPos);
|
||||
}
|
||||
|
||||
collisionresult_t physicsCheckCircleTriangle(
|
||||
fixed248_t circleX, fixed248_t circleY, fixed248_t circleR,
|
||||
fixed248_t triX0, fixed248_t triY0,
|
||||
fixed248_t triX1, fixed248_t triY1,
|
||||
fixed248_t triX2, fixed248_t triY2
|
||||
) {
|
||||
collisionresult_t result;
|
||||
result.hit = false;
|
||||
collisionresult_t result = { .hit = false };
|
||||
fixed248_t vx[3] = { triX0, triX1, triX2 };
|
||||
fixed248_t vy[3] = { triY0, triY1, triY2 };
|
||||
|
||||
fixed248_t closestX = FIXED248_ZERO;
|
||||
fixed248_t closestY = FIXED248_ZERO;
|
||||
fixed248_t normalX = FIXED248_ZERO;
|
||||
fixed248_t normalY = FIXED248_ZERO;
|
||||
fixed248_t minDistSq = FIXED248_MAX;
|
||||
|
||||
for(uint8_t i = 0; i < 3; ++i) {
|
||||
uint8_t j = (i + 1) % 3;
|
||||
|
||||
fixed248_t testX, testY;
|
||||
physicsClosestPointOnSegment(
|
||||
vx[i], vy[i], vx[j], vy[j],
|
||||
circleX, circleY, &testX, &testY
|
||||
);
|
||||
|
||||
fixed248_t dx = fx248Subfx248(circleX, testX);
|
||||
fixed248_t dy = fx248Subfx248(circleY, testY);
|
||||
fixed248_t distSq = fx248Addfx248(
|
||||
fx248Mulfx248(dx, dx),
|
||||
fx248Mulfx248(dy, dy)
|
||||
);
|
||||
|
||||
if(distSq < minDistSq) {
|
||||
minDistSq = distSq;
|
||||
closestX = testX;
|
||||
closestY = testY;
|
||||
normalX = dx;
|
||||
normalY = dy;
|
||||
}
|
||||
}
|
||||
|
||||
fixed248_t dist = fx248Sqrt(minDistSq);
|
||||
fixed248_t invDist = (
|
||||
(dist != FIXED248_ZERO) ?
|
||||
fx248Divfx248(FIXED248_ONE, dist) :
|
||||
FIXED248_ONE
|
||||
);
|
||||
|
||||
fixed248_t nx = fx248Mulfx248(-normalX, invDist);
|
||||
fixed248_t ny = fx248Mulfx248(-normalY, invDist);
|
||||
|
||||
if(physicsIsPointInTriangle(
|
||||
circleX, circleY, vx[0], vy[0], vx[1], vy[1], vx[2], vy[2]
|
||||
)) {
|
||||
result.hit = true;
|
||||
result.depth = fx248Subfx248(circleR, dist);
|
||||
result.normalX = nx;
|
||||
result.normalY = ny;
|
||||
return result;
|
||||
}
|
||||
|
||||
if(dist < circleR) {
|
||||
result.hit = true;
|
||||
result.depth = fx248Subfx248(circleR, dist);
|
||||
result.normalX = nx;
|
||||
result.normalY = ny;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -48,6 +48,45 @@ collisionresult_t physicsCheckCircleAABB(
|
||||
fixed248_t aabbWidth, fixed248_t aabbHeight
|
||||
);
|
||||
|
||||
/**
|
||||
* Calculate the closest point on a line segment to a point.
|
||||
*
|
||||
* @param ax X coordinate of the first endpoint of the segment.
|
||||
* @param ay Y coordinate of the first endpoint of the segment.
|
||||
* @param bx X coordinate of the second endpoint of the segment.
|
||||
* @param by Y coordinate of the second endpoint of the segment.
|
||||
* @param px X coordinate of the point.
|
||||
* @param py Y coordinate of the point.
|
||||
* @param outX Pointer to store the X coordinate of the closest point.
|
||||
* @param outY Pointer to store the Y coordinate of the closest point.
|
||||
*/
|
||||
void physicsClosestPointOnSegment(
|
||||
fixed248_t ax, fixed248_t ay,
|
||||
fixed248_t bx, fixed248_t by,
|
||||
fixed248_t px, fixed248_t py,
|
||||
fixed248_t *outX, fixed248_t *outY
|
||||
);
|
||||
|
||||
/**
|
||||
* Check if a point is inside a triangle defined by three vertices.
|
||||
*
|
||||
* @param px X coordinate of the point.
|
||||
* @param py Y coordinate of the point.
|
||||
* @param x0 X coordinate of the first vertex of the triangle.
|
||||
* @param y0 Y coordinate of the first vertex of the triangle.
|
||||
* @param x1 X coordinate of the second vertex of the triangle.
|
||||
* @param y1 Y coordinate of the second vertex of the triangle.
|
||||
* @param x2 X coordinate of the third vertex of the triangle.
|
||||
* @param y2 Y coordinate of the third vertex of the triangle.
|
||||
* @return true if the point is inside the triangle, false otherwise.
|
||||
*/
|
||||
bool_t physicsIsPointInTriangle(
|
||||
fixed248_t px, fixed248_t py,
|
||||
fixed248_t x0, fixed248_t y0,
|
||||
fixed248_t x1, fixed248_t y1,
|
||||
fixed248_t x2, fixed248_t y2
|
||||
);
|
||||
|
||||
/**
|
||||
* Check for collision between a circle and a triangle.
|
||||
*
|
||||
|
@ -19,6 +19,7 @@ typedef int32_t fixed248_t;
|
||||
(((f) * FIXED248_HIGH_MULTIPLIER) / 100) \
|
||||
))
|
||||
#define FIXED248_ONE (FIXED248(1, 0))
|
||||
#define FIXED248_ZERO (FIXED248(0, 0))
|
||||
|
||||
/**
|
||||
* Convert an int32_t value to a fixed248_t value.
|
||||
|
Reference in New Issue
Block a user