乒乓球:球拍如何知道击球的位置?

时间:2011-01-02 09:19:02

标签: algorithm artificial-intelligence pong

在实施Pacman和Snake后,我正在实施下一个非常经典的游戏:Pong。

实现非常简单,但我只剩下一个小问题。当其中一个桨(我不确定它是否被称为桨)由计算机控制时,我无法将其定位在正确的位置。

球具有当前位置,速度(现在是恒定的)和方向角。所以我可以计算它将撞到计算机控制桨的一侧的位置。所以我可以把桨放在那里。但是在真实游戏中,计算机的球拍有可能会错过球。我该如何实现这个概率?

如果我只使用0.5的概率说计算机的球拍会击球,问题就解决了,但我认为这并不是那么简单。

从原始游戏开始,我认为概率取决于当前球拍位置与球将撞到边界的位置之间的距离。

是否有人有任何提示如何计算?

7 个答案:

答案 0 :(得分:29)

从非常有趣的书“赛车梁”(Google Books:http://books.google.co.uk/books?id=DqePfdz_x6gC&lpg=PP1&dq=racing%20the%20beam&pg=PA40#v=onepage&q&f=false)中引用原始技术:

  

为了帮助模拟精确划桨定位中固有的人为错误,AI桨每八帧跳过一次调整。由此产生的行为明显不明显,但它允许计算机玩家的目标漂移到足以偶尔错过球。实现技术上也是微不足道的,只需要单个掩码和二进制AND操作,对此存在相应的6502指令。程序员可以使用另一个操作码测试结果是否为零,如果需要,可以跳过移动划线的指令。

     

即使是这种行为也必须稍加修改才能使游戏完全正常工作。如果AI玩家每隔8帧就停止跟踪一次球,那么在几秒钟之内它将无可救药地失去同步。为了防止这种情况,AI在球场的顶部和底部附近遵循二次球跟踪方案。如果球与其中一个墙碰撞而桨也与其对齐,则桨重新调整,从球最后撞击墙壁后累积的任何漂移中恢复。结果是计算机桨和球的随机错位和重新对准。

答案 1 :(得分:20)

我们为高中CS班制作了一个(伪)3D乒乓球比赛。我们做的是,我们让计算机始终将球拍向球移动,但是以最大速度 - 这样,如果球太远,它可能会错过球,但它仍然很聪明。这有帮助吗?

答案 2 :(得分:5)

我认为你应该让球拍始终从当前位置移动到特定点,这将是球与球拍垂直对齐的位置。然后你可能有50%的几率将球拍移动到这个精确的位置并使球偏转,25%的可能性它将超过,可能是一些X像素,并且有25%的可能性它会下冲。更好的方法可能是让它在钟形曲线上移动到那个位置,这样每次都会错过不同的数量。

答案 3 :(得分:4)

我不确定“官方”的做法是什么,但我一直只是使用(伪代码)

if (ball is above paddle) {
    move paddle up
}
if (ball is below paddle) {
    move paddle down
}

然后我给了球拍略微变化的速度,这个速度足够慢,以至于无法始终跟上球。有点粗糙,但它确实有效。

此主题还有一些您可能想要查看的有趣想法:http://www.gamedev.net/community/forums/topic.asp?topic_id=439576

答案 4 :(得分:4)

其他答案讨论如何确定在不同情况下进入的正确方向。您还可以在计算机播放器“反应”之前添加延迟时间,方法是开始向这个方向移动 - 这反映了人类玩家的典型反应。

答案 5 :(得分:4)

就是这样,我前几天写了一个pong克隆,只是为了好玩。

您可以播放here并查看源代码here

AI获取球的当前速度并将x距离与墙壁相乘。然后它以上限速度朝着该计算位置移动。它没有考虑垂直反弹,但这是有意的(使AI可以击败)。

以下是相关摘录:

/* Update enemy based on simple AI */
enemy.update = function (delta) {
    var impactDistance, impactTime, targetY, speed;
    speed = .25; // a little slower than the human player

    if (ball.vx < 0) {
        // Ball is moving away, AI takes a nap ..
        return;
    }

    // Figure out linear trajectory ..
    impactDistance = width - ball.width - ball.x;
    impactTime = impactDistance / (ball.vx * .25 * 1000);
    targetY = ball.y + (ball.vy * .25 * 1000) * impactTime;

    if (Math.abs(targetY - (this.y + this.height/2)) < 10) {
        // AI doesn't need to move
        return;
    }

    if (targetY < this.y + (this.height / 2)) {
        // Move up if ball is going above paddle
        speed = -speed;
    }

    this.y += speed * delta;
    this.keepInBounds();
};

答案 6 :(得分:2)

经过多次迭代,如果您的桨(根据您的视角,是您的桨或AI)太靠近屏幕的顶部或底部,则根本无法覆盖所需的距离。桨可以很容易地跟随球的y值。如果你太过分,你会错过。

或者,您可以在每次击球后将AI重置为中心,或者只要球移开(即朝向对手),就可以向中心移动

或者更简单地说:
  - 当球移开时向中心移动   - 在球接近时模仿球的y坐标。

从这里你可以通过使y-coord模仿机制比球更慢来更改难度(更一致,可能是原始实现的样子;因为困难被抽象为简单的速度系数),或者添加随机错误每次运动或其他。