So I have this example:
#include <numbers>
#include <vector>
#include <chipmunk/chipmunk.h>
constexpr float SPRITE_SIZE{64};
constexpr double MAX_SEE_AHEAD{2 * SPRITE_SIZE};
constexpr int STEP_COUNT{4};
constexpr double OBSTACLE_AVOIDANCE_ANGLE{60 * (std::numbers::pi / 180)};
cpVect raycast(const cpVect ¤tPosition, const cpVect ¤tVelocity, cpSpace *space, const float angle = 0) {
const auto rotated_velocity{cpvnormalize(cpvrotate(currentVelocity, cpvforangle(angle)))};
cpShapeFilter wallFilter = cpShapeFilterNew(CP_NO_GROUP, 2, CP_ALL_CATEGORIES);
for (int step = 1; step <= STEP_COUNT; step++) {
const cpVect position{currentPosition + (rotated_velocity * step * (MAX_SEE_AHEAD / STEP_COUNT))};
if (cpSpacePointQueryNearest(space, position, SPRITE_SIZE / 2, wallFilter, nullptr)) {
return position;
}
}
return {-1, -1};
}
inline cpVect convertPos(const int x, const int y) {
return {static_cast<float>(x) * SPRITE_SIZE + SPRITE_SIZE / 2, static_cast<float>(y) * SPRITE_SIZE + SPRITE_SIZE / 2};
}
int main() {
// Create the space
cpSpace *space{cpSpaceNew()};
// Create the player
const std::vector vertices{convertPos(1, 2), convertPos(2, 2), convertPos(1, 3), convertPos(2, 3)};
cpBody *playerBody{cpBodyNewKinematic()};
cpShape *playerShape{cpPolyShapeNew(playerBody, 4, vertices.data(), cpTransformIdentity, 0.0)};
cpSpaceAddBody(space, playerBody);
cpShapeSetBody(playerShape, playerBody);
cpSpaceAddShape(space, playerShape);
cpBodySetPosition(playerBody, {128, 192});
cpBodySetVelocity(playerBody, {0, 100});
cpShapeSetCollisionType(playerShape, 1);
cpShapeSetFilter(playerShape, cpShapeFilterNew(CP_NO_GROUP, 1, 2));
// Add a wall to the space
cpBody *wallBody{cpBodyNewStatic()};
cpShape *wallShape{cpBoxShapeNew(wallBody, SPRITE_SIZE, SPRITE_SIZE, 0.0)};
cpSpaceAddBody(space, wallBody);
cpShapeSetBody(wallShape, wallBody);
cpSpaceAddShape(space, wallShape);
cpBodySetPosition(wallBody, {128, 320});
cpShapeSetCollisionType(wallShape, 2);
cpShapeSetFilter(wallShape, cpShapeFilterNew(CP_NO_GROUP, 2, CP_ALL_CATEGORIES));
// Do the raycast using cpSpacePointQueryNearest
const cpVect currentPosition{cpBodyGetPosition(playerBody)};
const cpVect currentVelocity{cpBodyGetVelocityAtWorldPoint(playerBody, cpvzero)};
const cpVect forward_ray{raycast(currentPosition, currentVelocity, space)};
const cpVect left_ray{raycast(currentPosition, currentVelocity, space, OBSTACLE_AVOIDANCE_ANGLE)};
const cpVect right_ray{raycast(currentPosition, currentVelocity, space, -OBSTACLE_AVOIDANCE_ANGLE)};
return 0;
}
However, I don't think the filters are setup correctly since the left, forward, and right rays all return the first step position (which is within the player's bbox). What should happen is the left and right rays return cpVect(-1, -1) while the forward ray returns cpVect(128, 288) (the first point to intersect the wall's bbox.