Roman
Roman

Reputation: 687

kivy: after remove_widget it disappears from the screen but stays in ids

I am making an arkanoid game and having a problem: after collision I am using remove_widget method to remove a widget from layout. So it disappears from the screen but it is still in there, it is available by ids and if the ball enters that point again it still collides with a widget.

Here is some code:

gemsgrid.kv

<Brick@Widget>:
    canvas:
        Rectangle:
            size: self.size
            pos: self.pos

<GemsGrid@FloatLayout>:
    size_hint: None, None
    Brick:
        pos: 300, 100
        id: 1
    Brick:
        pos: 300,200
        id: 2

main.py

from kivy.app import App
from kivy.clock import Clock
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import NumericProperty


Builder.load_file('paddle.kv')
Builder.load_file('ball.kv')
Builder.load_file('gemsgrid.kv')


class Game(RelativeLayout):
    lives = NumericProperty(5)

    def __init__(self, **kwargs):
        super(Game, self).__init__(**kwargs)
        self.game_started = False

    def on_touch_move(self, touch):
        if touch.y < self.height / 3:
            self.ids.paddle_widget.center_x = touch.x
            if not self.game_started:
                self.ids.ball_widget.serve_ball()
                self.game_started = True

    def update(self, dt):
        if self.game_started:
            self.ids.ball_widget.move()
            self.ids.paddle_widget.bounce_ball(self.ids.ball_widget)
            for id, gem in self.gemsgrid.ids.iteritems():
                if self.ids.ball_widget.collide_widget(gem):
                    self.gemsgrid.remove_widget(gem)
                    self.right_left_collissioned(self.ids.ball_widget, gem)
                    self.top_bottom_collissioned(self.ids.ball_widget, gem)

        # bounce off top and bottom
        if (self.ids.ball_widget.top > self.height):
            self.ids.ball_widget.velocity_y *= -1

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

        # subtract one life if hit the bottom but not the paddle
        if (self.ids.ball_widget.y < self.y):
            self.lives -= 1
            self.ids.ball_widget.reset()
            self.game_started = False

    def right_left_collissioned(self, ball, gem):
        if ball.y > gem.y and ball.y < (gem.y + gem.height):
            ball.velocity_x *= -1

    def top_bottom_collissioned(self, ball, gem):
            if ball.x > gem.x and ball.x < gem.x + gem.width:
                ball.velocity_y *= -1


class MainApp(App):
    def on_pause(self):
        return True

    def build(self):
        game = Game()
        Clock.schedule_interval(game.update, 1/60)
        return game


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

What am I missing?

Upvotes: 0

Views: 264

Answers (2)

Albert Gao
Albert Gao

Reputation: 3769

The ids is generated when the .kv has been parsed. So it will stay that way.

Use self.children instead to check if it is still there.

Upvotes: 1

inclement
inclement

Reputation: 29458

The ids dict is static and is not intended to update like this (although I don't see why it couldn't be changed if people really want the feature). It sounds like it just isn't a good fit for your problem, I would manage the object references manually.

Upvotes: 1

Related Questions