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
相关产品推荐
相关产品推荐

