【问题标题】:Drawing Line From an Angle in Java在Java中从一个角度画线
【发布时间】:2016-03-28 01:48:24
【问题描述】:

首先,我必须说这是一个转发。我之前的帖子被标记为重复,尽管我在编辑中非常清楚地说明了为什么这与另一篇完全不同,但似乎没有人会访问它。这个问题仍然完全有效并且完全没有答案,所以请不要仅仅因为其他人也在使用 Pacman 制作游戏而将其标记为重复。如果我纠正这个问题的方法是错误的,请原谅我并告诉我解决这个问题的正确方法,因为我对这个网站的运作方式仍然知之甚少。

我之前的帖子如下:

我正在创建一个以吃豆人为主题的乒乓球游戏。为了增加主题,我想在 Pacman 面对的角度画两条线,一条在球的两侧。我将所有内容都放在一个 JPanel 中,因为我在我的教育中还没有达到使用组件的程度。我试图创建一个从我的 Pacman 中获取参数的走廊对象,但我不知道如何进行触发。我的框架是 1000 x 1000,顶部 40 像素高的条用于显示数据。我的 Pacman 以度数提供信息,因此请在答案中说明这一点。谢谢你,我会尽力回答任何问题。

更新:我已经完成了一些工作,并且我有一些代码可以分享这个主题。如下:

import java.awt.*;
public class Corridor
{
public Corridor()
{

}
public void drawLines(Graphics myBuffer, BallPacman pm)
{
double x1 = pm.getX();
double y1 = pm.getY() + 150;
double ix = pm.getdx();
double iy = pm.getdy();
double x2 = pm.getX();
double y2 = pm.getY() + 150;
    if (iy < 0) {
        while (x1 > 0 && y1 > 40) {
            x1 -= 0.1;
            y1 -= 0.1 * (iy / ix);
        }
        if (x1 <= 0)
        {
            y1 += (0 - x1) * (iy / ix);
            x1 = 0;
        }
        else {
            x1 += (40 - y1) * (iy / ix);
            y1 = 40;
        }
        while (x2 < 1000 && y2 < 1000) {
            x2 += 0.1;
            y2 += 0.1 * (iy / ix);
        }
        if (x2 >= 1000) {
            y2 -= (x1 - 1000) * (iy / ix);
            x2 = 1000;
        }
        else {
            x2 -= (1000 - y2) * (iy / ix);
            y2 = 1000;
        }
    }
    else {
        while (x1 > 0 && y1 > 40) {
            x1 -= 0.1;
            y1 -= 0.1 * -(iy / ix);
        }
        if (x1 <= 0)
        {
            y1 += (0 - x1) * -(iy / ix);
            x1 = 0;
        }
        else {
            x1 += (40 - y1) * -(iy / ix);
            y1 = 40;
        }
        while (x2 < 1000 && y2 < 1000) {
            x2 += 0.1;
            y2 += 0.1 * -(iy / ix);
        }
        if (x2 >= 1000) {
            y2 -= (x2 - 1000) * -(iy / ix);
            x2 = 1000;
        }
        else {
            x2 -= (y2 - 1000) * -(iy / ix);
            y2 = 1000;
        }
    }
    myBuffer.setColor (Color.BLUE);
    myBuffer.drawLine ((int)x1, (int)y1, (int)x2, (int)y2);
}
}

不幸的是,这会产生奇怪的结果,例如移动和垂直线。我意识到它只产生一条线,但它是一种测试。 BallPacman 有一个 move 方法,每次调用计时器时它都会移动 dx 和 dy。 dx 和 dy 可能是正数或负数。

更新:我问了我的一个朋友,他说基本上,我想要两条线平行于 Ballpacman 所遵循的线。不幸的是,我不知道如何实现这个结果。

更新:我想发布一些新的和附加的代码: 我用来获取角度的方法(输入dx和dy):

public double getFAngle (double x, double y)
{
    return Math.toDegrees(Math.atan2(x, y));
}

我尝试用来获取线条的新策略(存在于 drawLines 方法中):

double angle = pm.getFAngle (pm.getdx(), pm.getdy());
int x1 = (int) (pm.getX() + 5000 * Math.cos (angle * Math.PI / 180));
int x2 = (int) (pm.getX() - 5000 * Math.cos (angle * Math.PI / 180));
int y1 = (int) (pm.getY() + 5000 * Math.sin (angle * Math.PI / 180));
int y2 = (int) (pm.getY() - 5000 * Math.sin (angle * Math.PI / 180));
myBuffer.setColor (Color.BLUE);
myBuffer.drawLine (x1, y1, x2, y2);`

这种方法是尝试制作一条直线穿过 Pacman 的路径。我的想法是,如果我能做到这一点,我可以通过分别增加和减少第 1 行和第 2 行的 y 点来实现墙壁。它似乎在每个 90 的倍数(包括 0)上都完美地工作。但是,它在所有其他角度上都以一种非常奇怪的方式工作。我可以为此提供的唯一具体内容是它在 45 度处垂直。此外,线路在移动,这至少是不可取的。这段代码也破坏了我将端点直接放在墙上的愿望。请允许我详细说明我的计划的目标:

  1. 感应吃豆人的正确角度
  2. 画两条平行于 Pacman 路径的线,这样 Pacman 就不会 随时拦截他们。优选地,这些线将具有 以下四行中的至少两行的端点:x = 0, x = 1000, y = 40, y = 1000
  3. 无论 Pacman 的 X 和 Y 方向如何,都绘制相同的线。换句话说,这些线不应因 Pacman 沿路径的任何变化而改变。
  4. 当 Pacman 的角度发生变化时,线条会发生变化以反映该变化。是否每次调用都运行计算并不重要,只要存在正确的结果、具有正确角度的静态(非移动)线即可。

谢谢。

更新(重新发布): 自上次更新以来,我最好的代码没有改变。然而,我已经思考了为什么它不起作用,并提出了以下假设:它在 90 度倍数上的工作与在其他所有角度上一样可怕。但是,角度的性质使我无法看到线在移动。因此,我必须猜测代码有缺陷,因为它无法忽略 Pacman 的移动。

更新: 为了响应我多次收到的图片请求,我从 VGR 优秀代码的少数几个角度之一收到了这个rendering。 正如我所说,代码以 90 度的倍数工作,例如上面的那个,但不能正确渲染所有其他角度。并且针对 VGR 的评论,当 Pacman 的 x 和 y 变化时,它们永远不会移动(因为它们不应该这样做),但会随着 Pacman 角度的变化而移动。将线条想象成Corridor 的墙壁,它总是移动到吃豆人需要去的地方。当吃豆人沿着走廊走时,他们永远不会移动,但一旦他走到死胡同,走廊就会改变以适应他的新方向。我真诚地希望这会有所帮助。

【问题讨论】:

    标签: java swing awt


    【解决方案1】:

    你的想法是对的:

    Shape originalClip = myBuffer.getClip();
    myBuffer.clipRect(0, 40, 1000, 1000 - 40);
    
    double x = pm.getX();
    double y = pm.getY();
    double angle = Math.atan2(pm.getdy(), pm.getdx());
    double dx = PACMAN_RADIUS * Math.sin(angle);
    double dy = PACMAN_RADIUS * Math.cos(angle);
    
    double x1 = x - dx;
    double x2 = x + dx;
    double y1 = y - dy;
    double y2 = y + dy;
    
    myBuffer.setColor(Color.BLUE);
    
    myBuffer.drawLine((int) (x1 - 5000 * dy),
                      (int) (y1 + 5000 * dx),
                      (int) (x1 + 5000 * dy),
                      (int) (y1 - 5000 * dx));
    
    myBuffer.drawLine((int) (x2 - 5000 * dy),
                      (int) (y2 + 5000 * dx),
                      (int) (x2 + 5000 * dy),
                      (int) (y2 - 5000 * dx));
    
    myBuffer.setClip(originalClip);
    

    一些注意事项:

    • clipRect 用于确保线条不会画在 y=40 以上。
    • 仅将度数转换为弧度是没有意义的。
    • atan2 期望 dy 作为第一个参数,dx 作为第二个参数。

    【讨论】:

    • 几点:首先:谢谢!这是迄今为止我在这个社区得到的最有帮助的回应。其次,我试图实现您的注释,即 atan2 在我的代码中接受 dy 作为第一个,dx 作为第二个,但似乎没有任何效果。当我将 dx 作为第一个参数时,我必须在 fillArc 方法中偏移 90,但这是完全可靠的。无论我尝试什么变体,作为第一个参数的 dy 都会产生不合时宜的结果。
    • 在主焦的话题上,这两行渲染得非常好,完美地满足了代码目标#4的要求,也部分满足了#2的要求。很可能,#1 也很合适,但没有视觉上确凿的方法来推断这一点。问题是:1)线条在视觉上是移动的,2)线条肯定不是根据吃豆人的角度量身定制的。虽然 Pacman 肯定不会触及线(因此部分实现了#2),但这是因为线不断地在运动,以试图超出他的范围。这可能是什么原因?
    • 很难理解你的目标。如果线条从不移动,您希望它们的端点在哪里?如果他们从不移动,当吃豆人改变方向时,他们怎么能平行于它呢?也许您可以创建一个图像来展示所需行为的示例?
    • 如果更新没有回答您的问题,请告诉我需要什么。
    • 您说“当 Pacman 的 x 和 y 发生变化时,它们永远不会移动(因为它们不应该这样做)”,但我不明白这怎么可能。如果走廊总是围绕着吃豆人,那么当吃豆人移动时,它怎么移动呢?如果吃豆人水平移动一段时间,然后向上移动十个像素,然后再次开始水平移动,现在水平走廊不是需要比以前画高十个像素吗?
    猜你喜欢
    • 2011-04-01
    • 1970-01-01
    • 2016-02-06
    • 1970-01-01
    • 2017-09-07
    • 2015-08-13
    • 2020-02-25
    • 2016-03-19
    • 1970-01-01
    相关资源
    最近更新 更多