Repulsion Vector [SFML C++]

Started by
0 comments, last by Edward Owen 6 years, 1 month ago

Hi there!
I am trying to implement a basic AI for a Turrets game in SFML and C++ and I have some problems.
This AI follows some waypoints stablished in a Bezier Courve. 
In first place, this path was followed only by one enemy. For this purpose, the enemy has to calculate his distance between his actual position
to the next waypoint he has to pick.
If the distance is less than a specific value we stablish, then, we get to the next point. This will repeat until the final destination is reached. (in the submitting code, forget about the var m_go)

Okay, our problem gets when we spawn several enemies and all have to follow the same path, because it produces a bad visual effect (everyone gets upside another).
In order to solve this visual problem, we have decided to use a repulsion vector. The calculus gets like this:

5aaad7410a92d_Capturadepantallade2018-03-1521-22-27.png.4a1e4884df3ffa52a7e0b701162c665e.png


As you can see, we calculate the repulsion vector with the inverse of the distance between the enemy and his nearest neighbor.
Then, we get it applying this to the "theorical" direction, by adding it, and we get a resultant, which is the direction that
our enemy has to follow to not "collide" with it's neighbors. But, our issue comes here: 


The enemys get sepparated in the middle of the curve and, as we spawn more enemys, the speed of all of them increases dramatically (including the enemies that don't calculate the repuslion vector).
1 - Is it usual that this sepparation occours in the middle of the trajectory?
2 - Is it there a way to control this direction without the speed getting affected?
3 - Is it there any alternative to this theory?

I submit the code below (There is a variable in Spanish [resultante] which it means resultant in English):
 


            if (!m_pathCompleted) {
                if (m_currentWP == 14 && m_cambio == true) {
                    m_currentWP = 0;
                    m_path = m_pathA;
                    m_cambio = false;
                }

                if (m_neighbors.size() > 1) {
                    for (int i = 0; i < m_neighbors.size(); i++) {
                        if (m_enemyId != m_neighbors[i]->GetId()) {

                            float l_nvx = m_neighbors[i]->GetSprite().getPosition().x - m_enemySprite.getPosition().x;
                            float l_nvy = m_neighbors[i]->GetSprite().getPosition().y - m_enemySprite.getPosition().y;
                            float distance = std::sqrt(l_nvx * l_nvx + l_nvy * l_nvy);

                            if (distance < MINIMUM_NEIGHBOR_DISTANCE) {
                                l_nvx *= -1;
                                l_nvy *= -1;

                                float l_vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
                                float l_vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;

                                float l_resultanteX = l_nvx + l_vx;
                                float l_resultanteY = l_nvy + l_vy;

                                float l_waypointDistance = std::sqrt(l_resultanteX * l_resultanteX + l_resultanteY * l_resultanteY);

                                if (l_waypointDistance < MINIMUM_WAYPOINT_DISTANCE) {
                                    if (m_currentWP == m_path.size() - 1) {
                                        std::cout << "\n";
                                        std::cout << "[GAME OVER]" << std::endl;
                                        m_go = false;
                                        m_pathCompleted = true;
                                    } else {
                                        m_currentWP++;
                                    }
                                }

                                if (l_waypointDistance > MINIMUM_WAYPOINT_DISTANCE) {
                                    l_resultanteX = l_resultanteX / l_waypointDistance;
                                    l_resultanteY = l_resultanteY / l_waypointDistance;
                                    m_enemySprite.move(ENEMY_SPEED * l_resultanteX * dt, ENEMY_SPEED * l_resultanteY * dt);
                                }

                            } else {

                                float vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
                                float vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;
                                float len = std::sqrt(vx * vx + vy * vy);

                                if (len < MINIMUM_WAYPOINT_DISTANCE) {
                                    if (m_currentWP == m_path.size() - 1) {
                                        std::cout << "\n";
                                        std::cout << "[GAME OVER]" << std::endl;
                                        m_go = false;
                                        m_pathCompleted = true;
                                    } else {
                                        m_currentWP++;
                                    }
                                }

                                if (len > MINIMUM_WAYPOINT_DISTANCE) {
                                    vx = vx / len;
                                    vy = vy / len;
                                    m_enemySprite.move(ENEMY_SPEED * vx * dt, ENEMY_SPEED * vy * dt);
                                }
                            }
                        }
                    }
                } else {
                    float vx = m_path[m_currentWP].x - m_enemySprite.getPosition().x;
                    float vy = m_path[m_currentWP].y - m_enemySprite.getPosition().y;

                    float len = std::sqrt(vx * vx + vy * vy);

                    if (len < MINIMUM_WAYPOINT_DISTANCE) {
                        if (m_currentWP == m_path.size() - 1) {
                            std::cout << "\n";
                            std::cout << "[GAME OVER]" << std::endl;
                            m_go = false;
                            m_pathCompleted = true;
                        } else {
                            m_currentWP++;
                        }
                    }

                    if (len > MINIMUM_WAYPOINT_DISTANCE) {

                        vx = vx / len;
                        vy = vy / len;

                        m_enemySprite.move(ENEMY_SPEED * vx * dt, ENEMY_SPEED * vy * dt);
                    }
                }
            }


¡¡Thank you very much in advance!! 

This topic is closed to new replies.

Advertisement