2

我正在使用 Python 中的 Kivy 为学校项目制作 PONG 游戏。到目前为止,感谢这个论坛,我已经为 NPC 桨制作了一些 AI。这是代码:

    if self.ball.y < self.player2.center_y:
        self.player2.center_y = self.player2.center_y - 4
    if self.ball.y > self.player2.center_y:
        self.player2.center_y = self.player2.center_y + 4

这是在 PongGame() 类的一个方法中,称为ArtificialIntelligence()。

我用这个来称呼它:

Clock.schedule_interval(game.ArtificialIntelligence, 1/300)     

这允许我每 1/300 秒调用一次。但是,任何超过1/300的东西,我似乎都没有区别。即 1/9001 不会每 1/9001 秒调用一次。

它的工作方式是相对于球的位置将 y 坐标增加 4 个像素,并且每 1/300 秒执行一次,因此它不会以这种速度“滞后”。这对玩家来说基本上是一个“简单”的模式。如果我想做一个“硬”模式,我需要让NPC更准确。我可以这样做

self.player2.center_y = self.player2.center_y + 20

像这样的东西。这将是非常准确的。但是,它看起来并不“流畅”,它看起来“滞后”。我假设我可以通过更频繁地调用该方法来获得相同的移动量,而不是通过改变像素移动来改变它的移动量。但是,我不知道如何做到这一点,因为正如我所说,从 1/300 以上的任何位置更改它似乎没有任何区别。

这就是我使用桨的方式:

if touch.x < self.width/3:
    self.player1.center_y = touch.y

我可以随心所欲地移动它,因为它会随着我移动鼠标而更新。它看起来很流畅,因为它会根据需要更新。我不知道如何用我的 AI 做到这一点。

有谁知道我怎样才能基本上使 NPC 桨更准确,让我做 Easy-Normal-Hard 等,同时保持流动性和没有滞后?我只看到一种方法可以做到:增加调用方法的数量。

但是我打赌有更好的方法,我不知道该怎么做。有谁知道我怎么能做到这一点?谢谢。

编辑:看起来我可以这样做:

Clock.schedule_interval(game.ArtificialIntelligence, 1/300)     
Clock.schedule_interval(game.ArtificialIntelligence, 1/300) 
Clock.schedule_interval(game.ArtificialIntelligence, 1/300) 
Clock.schedule_interval(game.ArtificialIntelligence, 1/300)         
Clock.schedule_interval(game.ArtificialIntelligence, 1/300) 

但这看起来真的很丑陋而且效率很低......我更喜欢更清洁的方式。

4

3 回答 3

1

在每秒 300 帧的情况下,问题不在于更新速率,因为您已经超过了人眼感知运动的能力 50 倍或更多。

突然运动的出现是因为球沿着直线轨迹移动,而您的桨只是跳到球现在的位置。理想情况下,您的计算机玩家可以计算出球撞击计算机桨的平面时的位置,然后以每秒 30 帧或更低的速度以非常平滑的路线到达该位置。当然,预测数学需要少量的三角函数,但它是“正确”的方法,因为这是一个好的球员会如何打球,通过预测。

仅仅增加计算机桨的大小会容易得多,这也会向人类玩家提供视觉指示游戏的难度。当计算机的桨变成一堵墙时,玩家会看到没有获胜的机会。较大的桨会产生不那么生涩的副作用,但这是否是“好”的方式是你的决定。

于 2012-07-30T11:01:11.380 回答
1

我的建议是使用三角来计算球的位置,然后让桨移动到那里拦截它。

动画将以每秒 30 帧的速度流畅。

如今,当制作游戏时,AI 非常重要,玩家不会看到它“作弊”,并赋予它更大的桨或传送能力,这将是明显的迹象。它应该以与人类相同的方式进行游戏,只是更好 - 不使用玩家无法访问的某些机制。“这个游戏很烂,因为 CPU 作弊”是电子游戏论坛上非常普遍的负面评论。

因此,如果您需要计算机错过,请确保它的三角计算因随机因素而偏离,这样玩家就无法将其游戏与人类的游戏区分开来。

编辑:例如:如果随机(X)<=球的速度,则正确拦截,否则随机(Y)单位错过。

于 2012-07-30T13:08:50.320 回答
1

感谢您的帮助,我能够根据您和他的帮助与老师一起解决问题。

他开发了这个算法(他做的太快了,我真的无法理解它!)但这本质上是使用三角来生成桨的去向(注意,我不使用角度,因为我有其他值可以使用)

def AIController(self, *args):      
    ballsFuturePos = self.ball.center_y + ((self.width - self.ball.center_x) / self.ball.velocity_x) * self.ball.velocity_y
    numIterations = ((self.width - self.ball.center_x) / self.ball.velocity_x)
    #print ballsFuturePos
    #print numIterations
    if numIterations > 0:
        self.wantedPos = self.player2.center_y +(ballsFuturePos - self.player2.center_y) / numIterations        
        #print wantedPos
        #self.player2.center_y = wantedPos + (error / wantedPos) * 100


    if self.player2.center_y < self.wantedPos:
        self.player2.center_y = self.player2.center_y + 9
    if self.player2.center_y > self.wantedPos:
        self.player2.center_y = self.player2.center_y - 9

因此,我通过获取球的 y 位置,添加(宽度 - 球的 x 位置)来生成球将要击中屏幕最右侧部分的位置(这让我知道屏幕最右侧部分的距离) x 像素),然后我用 x 速度计算,然后用 y 速度乘以整个事物,这给了我斜率(我认为),因此现在计算斜率也意味着它具有轨迹和因此可以预测球将在哪里击中屏幕。

我通过获取屏幕宽度并减去球 x 位置来计算到达球所需的迭代次数,该位置计算距离屏幕最右侧部分的距离,然后除以速度。这给了我一个可以用来迭代的数字。

现在我用它进行迭代,并创建一个名为 WantPos 的变量,这是我想要我的桨去的地方。这使用桨的 y 位置,加上(球将在哪里 - 桨在哪里),这给了我球和桨之间的距离,除以迭代次数,这给了我桨的位置在球的同一位置。随着每次调用的 numIterations 减少,wantedPos 也会减少,这意味着差距会变小。然后,我使用 9 作为速度迭代桨靠近球,这允许我增加或减少难度。

谢谢。如果我在试图描述他的行为时搞砸了我的逻辑,请告诉我!我想我明白了,但确认会很好:)

于 2012-07-31T04:24:28.540 回答