Why is collide_widget not working here?

Question:

I am wondering why my ‘collide_with_hero’ method does not seem to be working? Is there something wrong with my Npcs class?

I am just trying to detect when widgets collide (the hero and the tree widget), I stripped out all the additional code in the method, and I am at the point now where I am just simply trying to detect collision and print something if True. When I run the game and walk my hero character into the tree, nothing prints, nothing happens.

I call self.tree.collide_with_widget in the build. Any advice on what I am doing wrong here?

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()
Asked By: david

||

Answers:

First, you made self.tree an Image, but this doesn’t have a collide_with_hero method. You need to make it an instance of the new class you defined, Npcs.

Second, you didn’t call the collide_with_hero method. You need to do self.tree.collide_with_hero(hero) to actually call it including passing your hero as an argument to the function.

Answered By: inclement

You need a main game loop to check for collision after some interval in time or on a keypress event. You can take a look at the Pong example here: http://kivy.org/docs/tutorials/pong.html to get an idea about how to achieve that.

More specifically start reading from this section: http://kivy.org/docs/tutorials/pong.html#adding-ball-animation.

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

It uses Clock.schedule_interval to schedule a main loop function called “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

You will need to write the collision detection code in a function like that. If your game involves more complex Physics simulation then you may consider using a library like http://box2d.org/. It will manage all the collisions and stuff for you.

Answered By: gat
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.