Add ant gravity, surface constraint, and collision displacement

- isObstacle() now blocks all non-air, non-home materials so ants treat sand/dirt/rock/food as walls
- gravity pulls ants down when no solid cell is below them, gating all steering logic while falling
- collision displacement pushes ants to nearest air cell when sand falls on top of them
This commit is contained in:
Jared Miller 2026-03-11 20:50:46 -04:00
parent d4e48af662
commit f41e464b4a
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C

View file

@ -33,12 +33,6 @@ vec2 roundUvToCellCenter(vec2 uv) {
return floor(uv * WORLD_SIZE) / WORLD_SIZE + cellSize * 0.5;
}
bool tryGetFood(vec2 pos) {
float materialId = texture(tWorld, roundUvToCellCenter(pos)).x;
return int(materialId) == MAT_FOOD;
}
bool tryDropFood(vec2 pos) {
float materialId = texture(tWorld, roundUvToCellCenter(pos)).x;
@ -47,8 +41,9 @@ bool tryDropFood(vec2 pos) {
bool isObstacle(vec2 pos) {
float materialId = texture(tWorld, roundUvToCellCenter(pos)).x;
return int(materialId) == MAT_ROCK;
int matInt = int(materialId);
// ants can only move through air and home cells
return matInt != MAT_AIR && matInt != MAT_HOME;
}
float smell(vec2 pos, float isCarrying) {
@ -123,6 +118,40 @@ void main() {
pathIntDy = 0.;
}
// --- GRAVITY AND SURFACE CHECK ---
vec2 cellCenter = roundUvToCellCenter(pos);
float belowMat = texture(tWorld, cellCenter - vec2(0., cellSize)).x;
float currentMat = texture(tWorld, cellCenter).x;
bool belowSolid = (int(belowMat) != MAT_AIR);
// collision displacement: if current cell is now solid (sand fell on us), push to nearest air
if (int(currentMat) != MAT_AIR && int(currentMat) != MAT_HOME) {
vec2 upPos = cellCenter + vec2(0., cellSize);
vec2 leftPos = cellCenter - vec2(cellSize, 0.);
vec2 rightPos = cellCenter + vec2(cellSize, 0.);
if (int(texture(tWorld, upPos).x) == MAT_AIR) {
pos = upPos;
} else if (int(texture(tWorld, leftPos).x) == MAT_AIR) {
pos = leftPos;
} else if (int(texture(tWorld, rightPos).x) == MAT_AIR) {
pos = rightPos;
}
cellCenter = roundUvToCellCenter(pos);
belowMat = texture(tWorld, cellCenter - vec2(0., cellSize)).x;
belowSolid = (int(belowMat) != MAT_AIR);
}
bool isFalling = false;
// GRAVITY: if nothing solid below and not at world bottom, fall
if (!belowSolid && pos.y > cellSize) {
pos.y -= cellSize;
isFalling = true;
}
if (!isFalling) {
if (isCarrying == 0.) {
if (noise < 0.33) {
vec2 offset = vec2(cos(angle), sin(angle)) * sampleDistance;
@ -198,8 +227,8 @@ void main() {
// check cell below for diggable material
vec2 belowUv = roundUvToCellCenter(pos - vec2(0., cellSize));
float belowMat = texture(tWorld, belowUv).x;
vec4 belowProps = texelFetch(uMaterialProps, ivec2(int(belowMat), 0), 0);
float belowDigMat = texture(tWorld, belowUv).x;
vec4 belowProps = texelFetch(uMaterialProps, ivec2(int(belowDigMat), 0), 0);
if (belowProps.r == BEHAVIOR_POWDER && belowProps.b <= ANT_CARRY_STRENGTH) {
// diggable material below — bias downward
@ -293,6 +322,8 @@ void main() {
}
}
} // end !isFalling
FragColor = vec4(
pos.x,
pos.y,