int crashTestPlayers(int i, const segment2 *movement) { int j, k; int crash = 0; Data *data = game->player[i].data; segment2 *current = data->trails + data->trailOffset; // debug: only test player0 against himself // j = 0; // if(i == 0) { for(j = 0; j < game->players; j++) { int crash = 0; if(game->player[j].data->trail_height < TRAIL_HEIGHT) continue; for(k = 0; k < game->player[j].data->trailOffset + 1; k++) { segment2 *wall; vec2 v; float t1, t2; if(j == i && k >= game->player[j].data->trailOffset - 1) break; wall = game->player[j].data->trails + k; if(segment2_Intersect(&v, &t1, &t2, movement, wall)) { #if 0 printf("(%.2f, %.2f), (%.2f, %.2f), %.2f, %.2f\n", data->posx, data->posy, v.v[0], v.v[1], t1, t2); #endif if(t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) { current->vDirection.v[0] = v.v[0] - current->vStart.v[0]; current->vDirection.v[1] = v.v[1] - current->vStart.v[1]; createEvent(i, EVENT_CRASH); crash = 1; break; } } } if(crash) break; } return crash; }
int crashTestWalls(int i, const segment2 *movement) { int j; vec2 v; float t1, t2; int crash = 0; Data *data = game->player[i].data; segment2 *current = data->trails + data->trailOffset; for(j = 0; j < 4; j++) { if(segment2_Intersect(&v, &t1, &t2, current, walls + j)) { if(t1 >= 0 && t1 < 1 && t2 >= 0 && t2 < 1) { current->vDirection.v[0] = v.v[0] - current->vStart.v[0]; current->vDirection.v[1] = v.v[1] - current->vStart.v[1]; createEvent(i, EVENT_CRASH); crash = 1; break; } } } return crash; }
int applyWallAcceleration(int player, int dt) { // find distance to enemy walls left & right enum { eLeft, eRight, eMax }; segment2 segments[eMax]; Data *data = game->player[player].data; int dirLeft = (data->dir + 3) % 4; int dirRight = (data->dir + 1) % 4; float left, right; float x, y; vec2 vPos; int i, j; getPositionFromIndex(&x, &y, player); vPos.v[0] = x; vPos.v[1] = y; for(i = 0; i < eMax; i++) { vec2Copy(&segments[i].vStart, &vPos); } segments[eLeft].vDirection.v[0] = dirsX[dirLeft]; segments[eLeft].vDirection.v[1] = dirsY[dirLeft]; segments[eRight].vDirection.v[0] = dirsX[dirRight]; segments[eRight].vDirection.v[1] = dirsY[dirRight]; left = FLT_MAX; right = FLT_MAX; for(i = 0; i < game->players; i++) { segment2 *wall = game->player[i].data->trails; if(i == player) continue; if(game->player[i].data->trail_height < TRAIL_HEIGHT) continue; for(j = 0; j < game->player[i].data->trailOffset + 1; j++) { float t1, t2; vec2 v; if(segment2_Intersect(&v, &t1, &t2, segments + eLeft, wall) && t1 > 0 && t1 < left && t2 >= 0 && t2 <= 1) left = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eRight, wall) && t1 > 0 && t1 < right && t2 >= 0 && t2 <= 1) right = t1; wall++; } } { float accell_limit = getSettingf("wall_accel_limit"); if(left < accell_limit || right < accell_limit) { float boost = getSettingf("wall_accel_use") * dt / 1000.0f; data->speed += boost; return 1; } else { return 0; } } }
void ai_getDistances(int player, AI_Distances *distances) { enum { eFront = 0, eLeft, eRight, eBackleft, eMax }; segment2 segments[eMax]; vec2 v, vPos; Data *data = game->player[player].data; int dirLeft = (data->dir + 3) % 4; int dirRight = (data->dir + 1) % 4; int i, j; float *front = &distances->front; float *right = &distances->right; float *left = &distances->left; float *backleft = &distances->backleft; getPositionFromIndex(vPos.v + 0, vPos.v + 1, player); for(i = 0; i < eMax; i++) { vec2_Copy(&segments[i].vStart, &vPos); } segments[eFront].vDirection.v[0] = (float) dirsX[data->dir]; segments[eFront].vDirection.v[1] = (float) dirsY[data->dir]; segments[eLeft].vDirection.v[0] = (float) dirsX[dirLeft]; segments[eLeft].vDirection.v[1] = (float) dirsY[dirLeft]; segments[eRight].vDirection.v[0] = (float) dirsX[dirRight]; segments[eRight].vDirection.v[1] = (float) dirsY[dirRight]; segments[eBackleft].vDirection.v[0] = (float) dirsX[dirLeft] - dirsX[data->dir]; segments[eBackleft].vDirection.v[1] = (float) dirsY[dirLeft] - dirsY[data->dir]; vec2_Normalize(&segments[eBackleft].vDirection, &segments[eBackleft].vDirection); *front = FLT_MAX; *left = FLT_MAX; *right = FLT_MAX; *backleft = FLT_MAX; // loop over all segment for(i = 0; i < game->players; i++) { segment2 *wall = game->player[i].data->trails; if(game->player[i].data->trail_height < TRAIL_HEIGHT) continue; for(j = 0; j < game->player[i].data->trailOffset + 1; j++) { float t1, t2; if(i == player && j == game->player[i].data->trailOffset) break; if(segment2_Intersect(&v, &t1, &t2, segments + eFront, wall) && t1 > 0 && t1 < *front && t2 >= 0 && t2 <= 1) *front = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eLeft, wall) && t1 > 0 && t1 < *left && t2 >= 0 && t2 <= 1) *left = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eRight, wall) && t1 > 0 && t1 < *right && t2 >= 0 && t2 <= 1) *right = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eBackleft, wall) && t1 > 0 && t1 < *backleft && t2 >= 0 && t2 <= 1) *backleft = t1; wall++; } } for(i = 0; i < game2->level->nBoundaries; i++) { float t1, t2; segment2* wall = game2->level->boundaries + i; if(segment2_Intersect(&v, &t1, &t2, segments + eFront, wall) && t1 > 0 && t1 < *front && t2 >= 0 && t2 <= 1) *front = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eLeft, wall) && t1 > 0 && t1 < *left && t2 >= 0 && t2 <= 1) *left = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eRight, wall) && t1 > 0 && t1 < *right && t2 >= 0 && t2 <= 1) *right = t1; if(segment2_Intersect(&v, &t1, &t2, segments + eBackleft, wall) && t1 > 0 && t1 < *backleft && t2 >= 0 && t2 <= 1) *backleft = t1; } // update debug render segments { AI *ai = game->player[player].ai; vec2_Copy(&ai->front.vStart, &vPos); vec2_Copy(&ai->left.vStart, &vPos); vec2_Copy(&ai->right.vStart, &vPos); vec2_Copy(&ai->backleft.vStart, &vPos); ai->front.vDirection.v[0] = *front * dirsX[data->dir]; ai->front.vDirection.v[1] = *front * dirsY[data->dir]; ai->left.vDirection.v[0] = *left * dirsX[dirLeft]; ai->left.vDirection.v[1] = *left * dirsY[dirLeft]; ai->right.vDirection.v[0] = *right * dirsX[dirRight]; ai->right.vDirection.v[1] = *right * dirsY[dirRight]; ai->backleft.vDirection.v[0] = (float) (dirsX[dirLeft] - dirsX[data->dir]); ai->backleft.vDirection.v[1] = (float) (dirsY[dirLeft] - dirsY[data->dir]); vec2_Normalize(&ai->backleft.vDirection, &ai->backleft.vDirection); vec2_Scale(&ai->backleft.vDirection, &ai->backleft.vDirection, *backleft); } // printf("%.2f, %.2f, %.2f\n", *front, *right, *left); return; }
void ai_getConfig(int player, int target, AI_Configuration *config) { Data *data; getPositionFromIndex(config->player.vStart.v + 0, config->player.vStart.v + 1, player); getPositionFromIndex(config->opponent.vStart.v + 0, config->opponent.vStart.v + 1, target); data = game->player[player].data; config->player.vDirection.v[0] = dirsX[ data->dir ] * data->speed; config->player.vDirection.v[1] = dirsY[ data->dir ] * data->speed; data = game->player[target].data; config->opponent.vDirection.v[0] = dirsX[ data->dir ] * data->speed; config->opponent.vDirection.v[1] = dirsY[ data->dir ] * data->speed; // compute sector { vec2 diff; vec3 v1, v2, v3; vec3 up = { { 0, 0, 1 } }; float cosphi; float phi; int i; vec2_Sub(&diff, &config->player.vStart, &config->opponent.vStart); v1.v[0] = diff.v[0]; v1.v[1] = diff.v[1]; v1.v[2] = 0; v2.v[0] = config->opponent.vDirection.v[0]; v2.v[1] = config->opponent.vDirection.v[1]; v2.v[2] = 0; vec3_Normalize(&v1, &v1); vec3_Normalize(&v2, &v2); vec3_Cross(&v3, &v1, &v2); vec3_Normalize(&v3, &v3); cosphi = vec3_Dot(&v1, &v2); nebu_Clamp(&cosphi, -1, 1); phi = (float) acos(cosphi); if(vec3_Dot(&v3, &up) > 0) phi = 2 * (float) M_PI - phi; for(i = 0; i < 8; i++) { phi -= (float) M_PI / 4; if(phi < 0) { config->location = i; break; } } } // compute intersection { segment2 seg1; segment2 seg2; seg1.vStart = config->opponent.vStart; seg1.vDirection = config->opponent.vDirection; seg2.vStart = config->player.vStart; vec2_Orthogonal( &seg2.vDirection, &config->opponent.vDirection ); vec2_Normalize( &seg2.vDirection, &seg2.vDirection ); vec2_Scale( &seg2.vDirection, &seg2.vDirection, vec2_Length( &config->player.vDirection ) ); segment2_Intersect( &config->intersection, &config->t_opponent, &config->t_player, &seg1, &seg2 ); if(config->t_player < 0) config->t_player *= -1; } }