SFML/C++ 为什么我的将敌人移向玩家的方法在玩家移动时停止工作?

问题描述 投票:0回答:1

在其他地方使用的唯一其他代码是 Player::getPosition(),它只是返回playerSprite.getPosition() 和 Game::update 将 Player::getPosition() 传递给此函数

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>

我预计敌人会沿直线向玩家移动,如果玩家静止不动,这种情况就会发生 如果玩家沿对角线远离敌人移动,这也有效,但如果玩家向任何其他方向移动,敌人会绕圈(有时是螺旋形)旋转,直到玩家停止移动或开始沿对角线远离敌人移动,或者有时移动沿着完全错误的方向走一条直线。 我试过了:

  • 将 attemptsMove() 分配给 Game::update 中的变量并将其传递给 Enemy::move()
  • 包括α角和β角并通过正弦规则计算角度的比率
  • 包括断点来验证角度是否正确(似乎总是如此)
  • 删除与玩家“排队”的检查并始终运行计算
  • 将 if (movement.x/y == 0.f) 更改为 if (abs(movement.x/y) < 0.01f) and < epsilon
  • 更改函数的调用位置以及传递给函数的参数
  • 还有一些其他变化,但似乎都没有任何希望
  • 重写所示块之外的大部分代码,这自然没有效果
  • 清理我的代码,(这实际上比我实际项目中的代码更干净,尽管我在发布它之前运行了它以确保它肯定不起作用)

似乎没有任何效果,而且很多事情让问题变得更糟或更严重,我真的不知道还能做什么

编辑:下面是工作代码

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
}
c++ sfml trigonometry
1个回答
0
投票

再次感谢用户@trojanfoe,他说 “你想太多了。要以给定的速度将

A
移向
B
,你只需要做
auto dir = normalize(B - A); A += dir * (speed * deltaTime);

下面是我修改后的代码,以合并这个更简单的解决方案(此代码在其他地方已经有一个 deltaTime 函数,可以修复帧渲染之间的间隔。)

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
}
© www.soinside.com 2019 - 2024. All rights reserved.