Triangle physics seemingly done
This commit is contained in:
@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"activeFile": "map.tmj",
|
"activeFile": "overworld.tsx",
|
||||||
"expandedProjectPaths": [
|
"expandedProjectPaths": [
|
||||||
"templates",
|
".",
|
||||||
"."
|
"templates"
|
||||||
],
|
],
|
||||||
"fileStates": {
|
"fileStates": {
|
||||||
":/automap-tiles.tsx": {
|
":/automap-tiles.tsx": {
|
||||||
@ -13,11 +13,11 @@
|
|||||||
"scaleInEditor": 1
|
"scaleInEditor": 1
|
||||||
},
|
},
|
||||||
"map.tmj": {
|
"map.tmj": {
|
||||||
"scale": 4,
|
"scale": 3,
|
||||||
"selectedLayer": 2,
|
"selectedLayer": 0,
|
||||||
"viewCenter": {
|
"viewCenter": {
|
||||||
"x": 6599.375,
|
"x": 6520.166666666666,
|
||||||
"y": 6795.125
|
"y": 6836.833333333333
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"overworld.tsx": {
|
"overworld.tsx": {
|
||||||
@ -35,8 +35,8 @@
|
|||||||
"project": "map project.tiled-project",
|
"project": "map project.tiled-project",
|
||||||
"property.type": "int",
|
"property.type": "int",
|
||||||
"recentFiles": [
|
"recentFiles": [
|
||||||
"overworld.tsx",
|
|
||||||
"map.tmj",
|
"map.tmj",
|
||||||
|
"overworld.tsx",
|
||||||
"entities.tsx"
|
"entities.tsx"
|
||||||
],
|
],
|
||||||
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
|
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
|
||||||
|
@ -101,9 +101,8 @@ void entityUpdate(entity_t *entity) {
|
|||||||
switch(TILE_META_DATA[tile].solidType) {
|
switch(TILE_META_DATA[tile].solidType) {
|
||||||
case TILE_SOLID_FULL:
|
case TILE_SOLID_FULL:
|
||||||
collision = physicsCheckCircleAABB(
|
collision = physicsCheckCircleAABB(
|
||||||
newX, newY, selfCircR,
|
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||||
fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
lx, ty,
|
||||||
fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
|
||||||
FIXED248(TILE_WIDTH_HEIGHT, 0),
|
FIXED248(TILE_WIDTH_HEIGHT, 0),
|
||||||
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:
|
case TILE_SOLID_TRIANGLE_TOP_RIGHT:
|
||||||
collision = physicsCheckCircleTriangle(
|
collision = physicsCheckCircleTriangle(
|
||||||
newX, newY, selfCircR,
|
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||||
lx, ty,
|
rx, by,
|
||||||
rx, ty,
|
rx, ty,
|
||||||
rx, by
|
lx, ty
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case TILE_SOLID_TRIANGLE_TOP_LEFT:
|
case TILE_SOLID_TRIANGLE_TOP_LEFT:
|
||||||
// collision = physicsCheckCircleTriangle(
|
collision = physicsCheckCircleTriangle(
|
||||||
// newX, newY, selfCircR,
|
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||||
// lx, ty,
|
lx, by,
|
||||||
// rx, ty,
|
lx, ty,
|
||||||
// lx, by
|
rx, ty
|
||||||
// );
|
);
|
||||||
// break;
|
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_BOTTOM_LEFT:
|
case TILE_SOLID_TRIANGLE_BOTTOM_RIGHT:
|
||||||
// collision = physicsCheckCircleTriangle(
|
collision = physicsCheckCircleTriangle(
|
||||||
// newX, newY, selfCircR,
|
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||||
// fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
rx, ty,
|
||||||
// fx248Addfx248(fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
rx, by,
|
||||||
// fx248Addfx248(fx248Mulfx248(x, FIXED248(TILE_WIDTH_HEIGHT, 0)), FIXED248(TILE_WIDTH_HEIGHT, 0)),
|
lx, by
|
||||||
// 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)),
|
break;
|
||||||
// fx248Mulfx248(y, FIXED248(TILE_WIDTH_HEIGHT, 0))
|
case TILE_SOLID_TRIANGLE_BOTTOM_LEFT:
|
||||||
// );
|
collision = physicsCheckCircleTriangle(
|
||||||
// break;
|
fx248Addfx248(newX, halfTileWH), fx248Addfx248(newY, halfTileWH), selfCircR,
|
||||||
|
lx, ty,
|
||||||
|
lx, by,
|
||||||
|
rx, by
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
|
@ -99,13 +99,155 @@ collisionresult_t physicsCheckCircleAABB(
|
|||||||
return result;
|
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(
|
collisionresult_t physicsCheckCircleTriangle(
|
||||||
fixed248_t circleX, fixed248_t circleY, fixed248_t circleR,
|
fixed248_t circleX, fixed248_t circleY, fixed248_t circleR,
|
||||||
fixed248_t triX0, fixed248_t triY0,
|
fixed248_t triX0, fixed248_t triY0,
|
||||||
fixed248_t triX1, fixed248_t triY1,
|
fixed248_t triX1, fixed248_t triY1,
|
||||||
fixed248_t triX2, fixed248_t triY2
|
fixed248_t triX2, fixed248_t triY2
|
||||||
) {
|
) {
|
||||||
collisionresult_t result;
|
collisionresult_t result = { .hit = false };
|
||||||
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,45 @@ collisionresult_t physicsCheckCircleAABB(
|
|||||||
fixed248_t aabbWidth, fixed248_t aabbHeight
|
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.
|
* Check for collision between a circle and a triangle.
|
||||||
*
|
*
|
||||||
|
@ -19,6 +19,7 @@ typedef int32_t fixed248_t;
|
|||||||
(((f) * FIXED248_HIGH_MULTIPLIER) / 100) \
|
(((f) * FIXED248_HIGH_MULTIPLIER) / 100) \
|
||||||
))
|
))
|
||||||
#define FIXED248_ONE (FIXED248(1, 0))
|
#define FIXED248_ONE (FIXED248(1, 0))
|
||||||
|
#define FIXED248_ZERO (FIXED248(0, 0))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an int32_t value to a fixed248_t value.
|
* Convert an int32_t value to a fixed248_t value.
|
||||||
|
Reference in New Issue
Block a user