You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SFML/C++ 敌人追踪移动玩家时功能失效的问题求助

SFML/C++ 敌人追踪移动玩家时功能失效的问题求助

大家好,我现在遇到一个SFML开发中的棘手问题:敌人追踪玩家时,只有玩家静止或者斜着远离敌人的情况下,追踪是正常的;只要玩家往其他方向移动,敌人就会原地转圈(有时候是螺旋状),甚至往完全错误的方向移动,实在搞不懂哪里出问题了。

先给大家说明下相关的代码背景:

  • 这里用到的外部代码只有Player::getPosition()(本质就是返回playerSprite.getPosition()),以及Game::update(),它会把玩家位置传给下面的敌人移动函数。
  • 调试时enemyLocation的初始值是:
sf::Vector2f enemyLocation{0.f, 0.f};

下面是我当前的敌人移动相关核心代码:

///<summary>
/// gets the amount enemy should move
/// called from Game.update()
///</summary>
/// <param name="t_playerPos"> player window position </param>
/// <returns> enemy move amount per frame (normalised) </returns>
sf::Vector2f Enemy::attemptMove(sf::Vector2f t_playerPos)
{
    sf::Vector2f movement = { 0.f, 0.f }; // movement towards player each frame
    sf::Vector2f direction = t_playerPos - enemyLocation; // delta playerPos and enemyPos
    float angle = atan2f(direction.y, direction.x); // angle to player (rad)
    angle = angle * 180.f / M_PI; // convert angle to degrees
    float hyp = 1.f; // length of line to player (used for normalisation of vector)

        // check if enemy is horizontally in line with player
    if (direction.x == 0.f) { 
        if (direction.y > 0.f) { movement.y = hyp; } // move straight down
        else { movement = -hyp; } // move straight up
    }
        // check if enemy is vertically in line with player
    else if (direction.y == 0.f) {
        if (direction.x > 0.f) { movement.x = hyp; } // move right
        else { movement.x = -hyp; } // move left
    }
        // if enemy is not in line with player
    else {
                // ratio of sides y:x = opp:adj
        movement.y = sinf(angle);
        movement.x = cosf(angle); 

                // normalising the vector
        hyp = sqrtf(abs(movement.x * movement.x) + abs(movement.y * movement.y));
        hyp = abs(1.f / hyp); // inverse of pythagoras theorem hypothenuse

        movement.x = hyp * movement.x;
        movement.y = hyp * movement.y; // sqrt(x^2 + y^2) should equal 1
        move(movement);
    }
    return movement; // return to Game::update() (not currently assigned to anything there)
}

///<summary>
/// moves the enemy by the amount it should each frame
/// in final code will be called from Game.update()
/// for now only called from Enemy::attemptMove()
///</summary>
///<param name="t_movement"> amount to move each frame towards player </param>
void Enemy::move(sf::Vector2f t_movement)
{
    enemyLocation += t_movement; // update enemy location
    enemySprite.setPosition(enemyLocation); // set enemy position to updated location
}

我的头文件包含如下:

#include <SFML/Graphics.hpp>
#include <iostream>
#define _USE_MATH_DEFINES
#include <math.h>

我已经尝试了一堆方法,但都没解决问题,有些甚至让情况更糟:

  • 在Game::update()里把attemptMove()的返回值赋值给变量,再传给Enemy::move()
  • 尝试用正弦定理计算alpha和beta角度的比例
  • 加断点验证角度值,看起来都是正确的
  • 移除了判断敌人和玩家是否在同一直线的代码,直接运行计算逻辑
  • 把if (movement.x/y == 0.f)改成if (abs(movement.x/y) < 0.01f)或者用epsilon值做判断
  • 改变函数的调用位置和传递的参数
  • 重写了这段代码之外的大量逻辑,当然这没什么效果
  • 清理了代码(现在贴的版本比我项目里的更简洁,而且我运行过确认问题依然存在)

实在没辙了,有没有大佬能帮我看看问题出在哪?


EDIT:修复后的可用代码

void Enemy::attemptMove(sf::Vector2f t_playerPos)
{
    sf::Vector2f direction = t_playerPos - enemyLocation; // playerPos-enemyPos (direction to player)
    float hyp;
     // normalising the vector
    hyp = sqrtf(abs(direction.x * direction.x) + abs(direction.y * direction.y));
    hyp = abs(1.f / hyp); // inverse of pythagoras theorem hypothenuse
    direction.x = hyp * direction.x;
    direction.y = hyp * direction.y; // sqrt(x^2 + y^2) should equal 1
    
move(direction);
}

void Enemy::move(sf::Vector2f t_movement)
{
    enemyLocation += t_movement; // update enemy location
    enemySprite.setPosition(enemyLocation); // set enemy position to updated location
}

备注:内容来源于stack exchange,提问作者Amp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 12:52:59