OpenGL 2D项目中敌人无法朝向玩家移动的技术求助
我正在开发一个2D游戏项目,需要实现敌人追踪玩家的功能。目前敌人已经能正确朝向玩家,但移动逻辑出了问题——敌人会朝着远离玩家的方向移动,而不是靠近。
以下是我的相关代码:
玩家绘制代码
//Body modelMatrix = visMatrix; modelMatrix *= transform2D::Translate(translateX, translateY); modelMatrix *= transform2D::Scale(1, 1); modelMatrix *= transform2D::Rotate(playerAngle); modelMatrix *= transform2D::Translate(-50, -50); RenderMesh2D(meshes["square3"], shaders["VertexColor"], modelMatrix); //Eye1 modelMatrix = visMatrix; modelMatrix *= transform2D::Translate(translateX, translateY); modelMatrix *= transform2D::Scale(0.25f, 0.25f); modelMatrix *= transform2D::Rotate(playerAngle); modelMatrix *= transform2D::Translate(150, 200); modelMatrix *= transform2D::Rotate(0); modelMatrix *= transform2D::Translate(-50, -50); RenderMesh2D(meshes["square1"], shaders["VertexColor"], modelMatrix); //Eye2 modelMatrix = visMatrix; modelMatrix *= transform2D::Translate(translateX, translateY); modelMatrix *= transform2D::Scale(0.25f, 0.25f); modelMatrix *= transform2D::Rotate(playerAngle); modelMatrix *= transform2D::Translate(-150, 200); modelMatrix *= transform2D::Rotate(0); modelMatrix *= transform2D::Translate(-50, -50); RenderMesh2D(meshes["square1"], shaders["VertexColor"], modelMatrix);
敌人绘制代码
//Body modelMatrix = visMatrix; modelMatrix *= transform2D::Translate(translateEnemyX, translateEnemyY); modelMatrix *= transform2D::Scale(1, 1); modelMatrix *= transform2D::Rotate(enemyAngle); modelMatrix *= transform2D::Translate(-50, -50); RenderMesh2D(meshes["border"], shaders["VertexColor"], modelMatrix); //Eye1 modelMatrix = visMatrix; modelMatrix *= transform2D::Translate(translateEnemyX, translateEnemyY); modelMatrix *= transform2D::Scale(0.25f, 0.25f); modelMatrix *= transform2D::Rotate(enemyAngle); modelMatrix *= transform2D::Translate(150, 200); modelMatrix *= transform2D::Rotate(0); modelMatrix *= transform2D::Translate(-50, -50); RenderMesh2D(meshes["square2"], shaders["VertexColor"], modelMatrix); //Eye2 modelMatrix = visMatrix; modelMatrix *= transform2D::Translate(translateEnemyX, translateEnemyY); modelMatrix *= transform2D::Scale(0.25f, 0.25f); modelMatrix *= transform2D::Rotate(enemyAngle); modelMatrix *= transform2D::Translate(-150, 200); modelMatrix *= transform2D::Rotate(0); modelMatrix *= transform2D::Translate(-50, -50); RenderMesh2D(meshes["square2"], shaders["VertexColor"], modelMatrix);
当前角度计算(朝向正常)
enemyAngle = atan2(translateX - translateEnemyX, translateY - translateEnemyY);
移动逻辑(问题所在)
enemySpeed = 10; translateEnemyX += enemySpeed * cos(enemyAngle); translateEnemyY += enemySpeed * sin(enemyAngle);
现在的问题是,敌人朝向玩家是对的,但移动时会远离玩家。请问该如何修正移动逻辑,让敌人正确向玩家移动?
这个问题的核心是**atan2的参数顺序和三角函数对应关系不匹配**,导致移动方向搞反了。我们一步步来解决:
1. 理解atan2的参数顺序
标准的atan2函数定义是atan2(y, x),它计算的是从原点到点(x,y)的向量与x轴正方向的夹角。你当前计算角度时把**x方向的差值(玩家X - 敌人X)**放在了y参数的位置,**y方向的差值(玩家Y - 敌人Y)**放在了x参数的位置,这刚好搞反了。不过因为这个角度适配了你渲染坐标系的旋转规则,所以敌人朝向显示正常,但移动时用cos和sin对应这个角度就会出错。
2. 修正移动逻辑的两种方案
方案一:调整三角函数的对应关系
既然角度计算是适配渲染的,那我们可以直接调整移动时的三角函数使用,交换cos和sin的位置并修正符号:
enemySpeed = 10; // 交换cos和sin,匹配当前角度的坐标系规则 translateEnemyX += enemySpeed * sin(enemyAngle); translateEnemyY += enemySpeed * cos(enemyAngle);
方案二:基于向量的移动(更直观推荐)
其实不用纠结三角函数,直接计算敌人到玩家的方向向量,归一化后乘以速度移动,这种方法完全绕开坐标系差异问题,逻辑更清晰:
enemySpeed = 10; // 计算敌人指向玩家的方向向量 float dirX = translateX - translateEnemyX; float dirY = translateY - translateEnemyY; // 计算向量长度(避免除以0的情况) float distance = sqrt(dirX * dirX + dirY * dirY); if (distance > 0) { // 归一化向量(方向不变,长度变为1) dirX /= distance; dirY /= distance; // 按速度移动敌人 translateEnemyX += enemySpeed * dirX; translateEnemyY += enemySpeed * dirY; }
这种向量式的移动在2D游戏里非常常用,后续扩展(比如添加障碍物躲避、平滑追踪)也更容易实现。
3. 为什么之前的移动会反向?
你用反序参数计算的enemyAngle,对应的向量和实际需要的追踪方向是错位的,导致cos(enemyAngle)和sin(enemyAngle)给出的移动方向刚好与玩家所在方向相反,所以敌人会越跑越远。
建议优先试试方案二,这种方法出错概率更低,也更符合现代游戏开发的常规思路。
内容的提问来源于stack exchange,提问作者Catalin Ursu

