增加精灵位置非常快,没有滞后 - Python

时间:2012-07-30 09:32:36

标签: python kivy game-physics pong game-ai

我正在使用Python中的Kivy为一个学校项目制作一个PONG游戏。到目前为止,由于这个论坛,我已经为NPC桨做了一些人工智能。 这是代码:

    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

这是一个名为ArtificialIntelligence()的PongGame()类方法。

我用它来称呼它:

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

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

它的工作方式是它相对于球位置增加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

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

有谁知道我怎么能基本上让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) 

但这看起来真的很难看,真的很低效......我更喜欢更清洁的方式。

3 个答案:

答案 0 :(得分:1)

每秒300帧,问题不在于更新率,因为你超出了人眼感知移动50倍或更多的能力。

生涩的动作之所以出现,是因为当你的球拍刚刚跳到球现在的位置时,球正沿着线性轨迹行进。理想情况下,您的计算机播放器可以计算当它击中计算机板的平面时球的位置,然后以每秒30帧或更少的速度对该位置采取非常平滑的路线。当然,预测数学需要少量的三角函数,但这是一种“正确”的方式,通过预期,这就是一个优秀的玩家将如何发挥作用。

增加计算机桨的大小会容易得多,这也会给人类玩家一个视觉指示,说明游戏的难度。当计算机的球拍成为墙壁时,玩家将看到没有胜利可以完成。较大的桨具有不那么生涩的副作用,但这是否是一种“好”的方式是你的决定。

答案 1 :(得分:1)

我的建议是使用触发器来确定球的位置,然后让桨移动到那里进行拦截。

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

制作游戏时AI现在非常重要,玩家不会看到它“作弊”并给它一个更大的划桨,或传送能力,这将是明显的迹象。它应该以与人类相同的方式发挥,只是更好 - 不使用玩家无法访问的某种机制。 “这个游戏很糟糕,因为CPU作弊”是对视频游戏论坛的一个非常普遍的负面评论。

因此,如果您需要计算机错过,请确保其随机因素关闭其三角计算,因此玩家无法将其游戏与人类区分开来。

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

答案 2 :(得分:1)

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

他开发了这个算法(tbh他做得太快了,以至于我真的无法理解它!)但这实际上使用了trig来生成桨将去的地方(注意,我不使用角度,因为我有其他值可以使用)

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位置对其进行缩小,计算到屏幕最右边的距离,并将其除以速度。这给了我一个可以用来迭代的数字。

现在我迭代这个,并创建一个名为wantedPos的变量,这是我想要我的桨去的地方。这使用桨叶y位置,添加(球将在 - 桨的位置),这给了我球和桨之间的距离,除以迭代次数,这给了我桨的位置在球的同一位置。随着每次调用中numcterations减少,wantedPos也减少,这意味着间隙变小。然后我使用9作为速度迭代球更接近球,这允许我增加或减少难度。

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