【问题标题】:Why is collide_widget not working here?为什么 collide_widget 在这里不起作用?
【发布时间】:2014-03-21 03:07:04
【问题描述】:

我想知道为什么我的“collide_with_hero”方法似乎不起作用?我的 Npcs 课程有问题吗?

我只是想检测小部件何时发生碰撞(英雄和树小部件),我删除了方法中的所有附加代码,现在我只是试图检测碰撞并打印如果真的话。当我运行游戏并将我的英雄角色带入树中时,什么也没有打印,什么也没有发生。

我在构建中调用 self.tree.collide_with_widget。关于我在这里做错了什么有什么建议吗?

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.behaviors import ButtonBehavior
from kivy.core.audio import SoundLoader
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import FallOutTransition


gamelayout = RelativeLayout(size=(300, 300))
bglayout = RelativeLayout()

class Game(Screen):
    pass    

class Bg(Image):

    def __init__(self, **kwargs):
        super(Bg, self).__init__(**kwargs)
        self.allow_stretch = True
        self.size_hint = (None, None)
        self.size = (1440, 1440)

class Npcs(Image):
    def __init__(self, **kwargs):
        super(Npcs, self).__init__(**kwargs)

    def collide_with_hero(self, hero):
        if self.collide_widget(hero):
            print "you ran into a tree"

            #dir1 = self.hero.x - self.x
            #if self.x < self.hero.x:
            #    self.hero.x = self.x + dir1


class MoveableImage(Image):

    def __init__(self, **kwargs):
        super(MoveableImage, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(None, self)
        if not self._keyboard:
            return
        self._keyboard.bind(on_key_down=self.on_keyboard_down)
        self._keyboard.bind(on_key_up=self.on_keyboard_up)
        self.size_hint = (.11, .11)
        self.y = (Window.height/2.1)
        self.app = App.get_running_app()


    def on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'left':
            self.source = 'selectionscreen/left.zip'
            self.anim_delay=.20
            if self.x < (Window.width * .25):
                bglayout.x += 4
            else:
                self.x -= 6
        elif keycode[1] == 'right':
            self.source ='selectionscreen/right.zip'
            self.anim_delay=.20
            if self.x > (Window.width * .70):
                bglayout.x -= 4
            else:
                self.x += 6
        elif keycode[1] == 'down':
            self.source ='selectionscreen/right.zip'
            self.anim_delay=.20
            if self.y < (Window.height * .25):
                bglayout.y += 4
            else:
                self.y -= 6
        elif keycode[1] == 'up':
            self.source = 'selectionscreen/back.zip'
            self.anim_delay=.1
            if self.y > (Window.height * .70):
                bglayout.y -= 4
            else:
                self.y += 6
        else:
            return False
        return True

    def on_keyboard_up(self, keyboard, keycode):
        if keycode[1] == 'left':
            self.source = 'selectionscreen/left1.png'
        elif keycode[1] == 'right':
            self.source ='selectionscreen/right1.png'
        elif keycode[1] == 'down':
            self.source ='selectionscreen/right1.png'
        elif keycode[1] == 'up':
            self.source ='selectionscreen/back2.png'
        else:
            return False
        return True


class gameApp(App):
    def build(self):
        global sm
        sm = ScreenManager()
        game = Game(name='game')
        sm.add_widget(game)
        hero = MoveableImage(source='selectionscreen/right1.png', pos=(75, 40))
        self.tree = Npcs(source='selectionscreen/tree.zip', pos=(100, 200))
        self.tree.collide_with_hero(hero)
        self.background=Bg(source='selectionscreen/background9.png')

        #add widgets to bglayout
        bglayout.add_widget(self.background)
        bglayout.add_widget(self.tree)

        #add bglayout and moveable hero to gamelayout
        gamelayout.add_widget(bglayout)
        gamelayout.add_widget(hero)
        game.add_widget(gamelayout)

        return sm



if __name__ == '__main__':
    gameApp().run()

【问题讨论】:

  • 您没有将 hero 参数发送到您的 collide_with_hero 方法。你只是在做self.tree.collide_with_hero,这可能只是在 Python 中创建一个属性(如果没有失败)。通常人们对collide_widget 有疑问,因为您在屏幕上看到的内容并不能反映小部件的确切位置和大小属性。
  • 例如,树的图像可能比小部件大得多。所以你看到英雄坐在树上,但树小部件可能在一个小角落。检查this question和(这篇文章)[robertour.com/2013/10/02/easy-way-debugging-kivy-interfaces/]
  • 我已经修复了您和 Inclement 告诉我的内容并更新了我上面的代码,但仍然没有运气。我会阅读你发布的链接。我想知道问题是否是因为“英雄”和“树”的布局大小不同。

标签: collision-detection kivy


【解决方案1】:

您需要一个主游戏循环来在某个时间间隔或按键事件后检查碰撞。您可以在此处查看 Pong 示例:http://kivy.org/docs/tutorials/pong.html 以了解如何实现这一目标。

更具体地说,从本节开始阅读:http://kivy.org/docs/tutorials/pong.html#adding-ball-animation

    Clock.schedule_interval(game.update, 1.0/60.0)

它使用 Clock.schedule_interval 来调度一个名为“update”的主循环函数。

    def update(self, dt):
        self.ball.move()

        #bounce off top and bottom
        if (self.ball.y < 0) or (self.ball.top > self.height):
            self.ball.velocity_y *= -1

        #bounce off left and right
        if (self.ball.x < 0) or (self.ball.right > self.width):
            self.ball.velocity_x *= -1

您需要在这样的函数中编写碰撞检测代码。如果您的游戏涉及更复杂的物理模拟,那么您可以考虑使用像 http://box2d.org/ 这样的库。它会为你管理所有的碰撞和东西。

【讨论】:

    【解决方案2】:

    首先,您将self.tree 设为图像,但它没有collide_with_hero 方法。您需要使其成为您定义的新类 Npcs 的实例。

    其次,你没有调用collide_with_hero 方法。您需要执行self.tree.collide_with_hero(hero) 才能实际调用它,包括将您的英雄作为参数传递给函数。

    【讨论】:

      猜你喜欢
      • 2013-05-16
      • 2019-02-10
      • 2017-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多