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

Lazarus/FreePascal中移动角色与行星碰撞接触点求解

解决行星跳跃游戏的着陆定位问题

我来帮你梳理下着陆逻辑的问题,结合你的代码和变量说明,给你一套可行的解决方案:

核心问题分析

你的代码里存在两个关键问题:

  1. 弧度与度数/自定义单位的转换混淆:FreePascal的三角函数(cos/sin/arccos)都是基于弧度计算的,但你用了自定义的1130单位一圈,转换逻辑没对应上;
  2. 角度计算的象限缺失:arccos只能返回0~π的角度,无法区分上下/左右象限,导致着陆位置偏移。

具体修正方案

1. 统一角度转换逻辑

先明确单位对应关系:

  • 标准圆周:2π弧度 = 360度 = 你的1130自定义旋转单位
  • 转换公式:自定义单位 = 弧度值 * (1130 / (2 * Pi))

2. 修正着陆角度与位置计算

当玩家需要着陆到目标行星(notplanump1对应的行星)时,用ArcTan2计算向量角度(能覆盖所有象限),再定位到行星圆周上:

var
  dx, dy: Integer;
  targetAngleRad: Double;
  targetPlanetRadius: Integer;
  targetPlanetX, targetPlanetY: Integer;
begin
  // 获取目标行星的核心参数
  targetPlanetX := xorigins[notplanump1];
  targetPlanetY := yorigins[notplanump1];
  targetPlanetRadius := rs[notplanump1];

  // 计算玩家当前位置到目标行星中心的向量
  dx := GTR.Left - targetPlanetX;
  dy := GTR.Top - targetPlanetY;

  // 计算向量对应的弧度角度(ArcTan2处理所有象限,比arccos可靠)
  targetAngleRad := ArcTan2(dy, dx);

  // 将弧度转换为你的自定义1130单位旋转值
  currotp1 := Round(targetAngleRad * (1130 / (2 * Pi)));

  // 将玩家定位到目标行星的圆周上
  GTR.Left := targetPlanetX + Round(Cos(targetAngleRad) * targetPlanetRadius);
  GTR.Top := targetPlanetY + Round(Sin(targetAngleRad) * targetPlanetRadius);

  // 维持自定义旋转单位的循环范围(0~1130)
  while currotp1 > 1130 do
    currotp1 := currotp1 - 1130;
  while currotp1 < 0 do
    currotp1 := currotp1 + 1130;
end;

3. 优化原移动代码的角度计算

你的原移动代码里的角度转坐标逻辑可以简化,避免冗余的符号运算:

// 原代码的坐标计算可以简化为:
GTR.Left := curplaxp1 + Round(Cos(DegToRad(currotp1 * (360 / 1130))) * r);
GTR.Top := curplayp1 + Round(Sin(DegToRad(currotp1 * (360 / 1130))) * r);

这里先把自定义1130单位转成度数,再转成弧度,逻辑更清晰。


为什么之前的尝试失败?

  • 你用DegToRad时,可能错误地将已经是弧度的数值再次转换,导致角度完全混乱;
  • arccos无法区分象限,比如相同的y值会对应左右两个不同的点,导致着陆位置错误;
  • 自定义旋转单位和标准弧度的转换关系没明确,计算时的比例系数错误。

内容的提问来源于stack exchange,提问作者Zekeste42

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:01:06