title: How to use a variable/function from a class instance in a differrent class with kivy?
body: <p>first, I'm new here, so don't hesitate to correct me if I act innapropriatly !</p>
  <p>I'm making a sudo turn based RPG combat to train with kivy tools and I've come in contact with a big problem, I'm having a lot of troubles making a kivy classe use variables and function from another kivy class instance, for some case I used <code>self.parent.parent.parent</code> etc but It is very frail and unsatisfying, and it does not work everywhere, I know that in theory I should use <code>id</code> and/or <code>app</code> but I just can't make it work, I guess I'm missing something with how they work, here is my python file :</p>
  <pre><code>import kivy
  from kivy.app import App
  from kivy.clock import Clock
  from kivy.lang import Builder
  from kivy.uix.boxlayout import BoxLayout
  from kivy.uix.button import Button
  from kivy.uix.floatlayout import FloatLayout
  from kivy.uix.relativelayout import RelativeLayout
  from kivy.uix.widget import Widget
  from kivy.uix.tabbedpanel import TabbedPanel
  from kivy.uix.screenmanager import ScreenManager, Screen, SlideTransition, NoTransition, CardTransition, SwapTransition, \
      FadeTransition, WipeTransition, FallOutTransition, RiseInTransition
  from kivy.properties import StringProperty, NumericProperty, ObjectProperty, BooleanProperty
  from kivy.core.audio import SoundLoader
  import time
  
  game_won = False
  game_over = False
  disabled_time = 1.5
  
  
  class MainWidget(BoxLayout):
      Ennemy_img = StringProperty(&quot;images/slime.png&quot;)
      Effect_img = StringProperty(&quot;images/void.png&quot;)
      menu_widget = ObjectProperty()
      menu_size = NumericProperty(1)
      menu_size_x = NumericProperty(1)
      monster_hp_lost = NumericProperty(0)
      monster_hp = NumericProperty(100)
      monster_hp_left_ratio = NumericProperty(1)
      monster_xp_gain = NumericProperty(20)
      hero_hp_lost = NumericProperty(0)
      hero_hp = NumericProperty(100)
      hero_mp_lost = NumericProperty(0)
      hero_mp = NumericProperty(100)
      hero_xp = NumericProperty(0)
      hero_lvl = NumericProperty(1)
      next_level = NumericProperty(100)
      hp_left_ratio = NumericProperty(1)
      monster_attack_effect = StringProperty(&quot;images/void.png&quot;)
      ennemy_turn = NumericProperty(0)
      object_1_qty = NumericProperty(3)
      object_2_qty = NumericProperty(3)
      object_3_qty = NumericProperty(3)
  
  
  
      spit_sound = None
      lvl_up_sound = None
      fizzle_sound = None
      game_over_sound = None
      sword_sound = None
      fire_sound = None
      wind_sound = None
      heal_sound = None
      victory_sound = None
  
      def __init__(self, **kwargs):
          super().__init__(**kwargs)
          self.init_audio()
  
      def init_audio(self):
          self.spit_sound = SoundLoader.load(&quot;audio/spit.wav&quot;)
          self.lvl_up_sound = SoundLoader.load(&quot;audio/lvlup.wav&quot;)
          self.fizzle_sound = SoundLoader.load(&quot;audio/Fizzle.wav&quot;)
          self.sword_sound = SoundLoader.load(&quot;audio/sword.wav&quot;)
          self.fire_sound = SoundLoader.load(&quot;audio/fireball.wav&quot;)
          self.wind_sound = SoundLoader.load(&quot;audio/tornado.wav&quot;)
          self.heal_sound = SoundLoader.load(&quot;audio/healing.wav&quot;)
          self.victory_sound = SoundLoader.load(&quot;audio/victory.wav&quot;)
          self.game_over_sound = SoundLoader.load(&quot;audio/Game_over.wav&quot;)
  
          self.spit_sound.volume = 3
          self.lvl_up_sound.volume = 3
          self.sword_sound.volume = 5
          self.fire_sound.volume = 3
          self.wind_sound.volume = 3
          self.heal_sound.volume = 5
          self.victory_sound.volume = 1
          self.game_over_sound.volume = 5
  
      def reset_all(self):
          self.Ennemy_img = &quot;images/slime.png&quot;
          self.Effect_img = &quot;images/void.png&quot;
          self.ids.Effect_spell.source = &quot;images/void.png&quot;
          self.monster_attack_effect = &quot;images/void.png&quot;
          self.menu_size = 1
          self.menu_size_x = 1
          self.monster_hp_lost = 0
          self.monster_hp = 100
          self.monster_hp_left_ratio = 1
          self.hero_hp_lost = 0
          self.hero_hp = 100
          self.hero_mp = 100
          self.hero_mp_lost = 0
          self.hp_left_ratio = 1
          self.ennemy_turn = 0
  
      def spell_effect_reset(self):
          self.ids.Effect_spell.source = &quot;images/void.png&quot;
          self.monster_attack_effect = &quot;images/void.png&quot;
  
      def check_lifes_totals(self):
          global game_won
          global game_over
          if self.monster_hp_lost &gt;= self.monster_hp:
              self.victory_sound.play()
              game_won = True
              self.hero_xp += self.monster_xp_gain
              if self.hero_xp &gt;= self.next_level:
                  self.hero_lvl += 1
                  self.hero_xp = 0
                  self.lvl_up_sound.play()
              self.reset_all()
          elif self.hero_hp_lost &gt;= self.hero_hp:
              game_over = True
              self.reset_all()
  
      def monster_turn(self, dt):
          self.ids.Effect_spell.source = &quot;images/void.png&quot;
          self.hero_hp_lost += 10
          self.spit_sound.play()
          self.monster_attack_effect = &quot;images/slime_spit.png&quot;
          self.ennemy_turn = 0
  
      def on_attack(self):
          self.ennemy_turn = 1
          self.spell_effect_reset()
          self.sword_sound.play()
          self.ids.Effect_spell.source = &quot;images/slash.png&quot;
          self.monster_hp_lost += 10
          self.check_lifes_totals()
          Clock.schedule_once(self.monster_turn, disabled_time)
  
      def on_spell_fire_pressed(self):
          self.spell_effect_reset()
          mp_cost = 35
          if self.hero_mp - self.hero_mp_lost &gt;= mp_cost:
              self.ennemy_turn = 1
              self.fire_sound.play()
              self.ids.Effect_spell.source = &quot;images/fireball.png&quot;
              self.monster_hp_lost += 30
              self.hero_mp_lost += 30
              self.check_lifes_totals()
              # self.monster_hp_left_ratio = (self.monster_hp - self.hp_lost) / self.monster_hp
              Clock.schedule_once(self.monster_turn, disabled_time)
  
          else:
              self.fizzle_sound.play()
  
      def on_spell_wind_pressed(self):
          self.spell_effect_reset()
          mp_cost = 20
          if self.hero_mp - self.hero_mp_lost &gt;= mp_cost:
              self.ennemy_turn = 1
              self.wind_sound.play()
              self.ids.Effect_spell.source = &quot;images/tornado.png&quot;
              self.hero_hp_lost += 20
              self.hero_mp_lost += 20
              self.check_lifes_totals()
              Clock.schedule_once(self.monster_turn, disabled_time)
          else:
              self.fizzle_sound.play()
  
      def on_spell_heal_pressed(self):
          self.spell_effect_reset()
          mp_cost = 20
          if self.hero_mp - self.hero_mp_lost &gt;= mp_cost:
              self.ennemy_turn = 1
              self.heal_sound.play()
              self.monster_attack_effect = &quot;images/heal.png&quot;
              self.hero_hp_lost -= 20
              self.hero_mp_lost += mp_cost
              self.check_lifes_totals()
              Clock.schedule_once(self.monster_turn, disabled_time)
          else:
              self.fizzle_sound.play()
  
      def on_object_1_pressed(self):
          self.spell_effect_reset()
          if self.object_1_qty &gt; 0:
              self.ennemy_turn = 1
              self.heal_sound.play()
              self.monster_attack_effect = &quot;images/heal_potion.png&quot;
              self.hero_hp_lost -= 30
              self.object_1_qty -= 1
              self.check_lifes_totals()
              Clock.schedule_once(self.monster_turn, disabled_time)
          else:
              self.fizzle_sound.play()
  
      def on_object_2_pressed(self):
          self.spell_effect_reset()
          if self.object_2_qty &gt; 0:
              self.ennemy_turn = 1
              self.heal_sound.play()
              self.monster_attack_effect = &quot;images/mana_potion.png&quot;
              self.hero_mp_lost -= 20
              self.object_2_qty -= 1
              self.check_lifes_totals()
              Clock.schedule_once(self.monster_turn, disabled_time)
          else:
              self.fizzle_sound.play()
  
      def on_object_3_pressed(self):
          self.spell_effect_reset()
          if self.object_3_qty &gt; 0:
              self.ennemy_turn = 1
              self.fire_sound.play()
              self.ids.Effect_spell.source = &quot;images/explosion.png&quot;
              self.monster_hp_lost += 35
              self.object_3_qty -= 1
              self.check_lifes_totals()
              Clock.schedule_once(self.monster_turn, disabled_time)
          else:
              self.fizzle_sound.play()
  
      def some_method_to_change_object_button_text(self):
          app = kivy.app.App.get_running_app()
          app.root.ids.menu_full.ids.object_menu.ids.object_3.text = 'new'
  
  
  class AllScreen(Screen):
  
      def ennemy_killed(self):
          self.ids.Ennemy_img.source = &quot;images/void.png&quot;
  
      def change_screen(self, screen_to_go):
          self.manager.current = screen_to_go
  
  
  class MenuFull(TabbedPanel):
      ennemy_turn = BooleanProperty(False)
  
      def ennemy_turn_on(self):
          self.ennemy_turn = 1
          Clock.schedule_once(self.ennemy_turn_off, 1.5)
  
      def ennemy_turn_off(self, dt):
          self.ennemy_turn = 0
  
  
  
  class PlayerInfo(BoxLayout):
      pass
  
  
  class MagicMenu(BoxLayout):
      pass
  
  
  class ObjectMenu(BoxLayout):
      object_1_qty = NumericProperty(3)
      object_2_qty = NumericProperty(3)
      object_3_qty = NumericProperty(3)
  
      def on_object_3_pressed(self):
          if self.object_3_qty &gt; 0:
              self.object_3_qty -= 1
  
      def on_object_2_pressed(self):
          if self.object_2_qty &gt; 0:
              self.object_2_qty -= 1
  
      def on_object_1_pressed(self):
          if self.object_1_qty &gt; 0:
              self.object_1_qty -= 1
  
  
  class MenuScreen(AllScreen):
      def reset_game_won(self):
          global game_won
          global game_over
  
          game_won = False
          game_over = False
  
  
  class GameOverScreen(AllScreen):
      game_over_sound = None
  
      def __init__(self, **kwargs):
          super().__init__(**kwargs)
          self.init_audio()
  
      def init_audio(self):
          self.game_over_sound = SoundLoader.load(&quot;audio/Game_over.wav&quot;)
  
          self.game_over_sound.volume = 5
  
      def reset_game_over(self):
          global game_won
          global game_over
  
          game_won = False
          game_over = False
  
  
  class FightScreen(AllScreen):
  
      def check_game_end(self):
          if game_won:
              self.manager.current = 'menu'
          elif game_over:
              self.manager.current = 'game_over'
  
  
  class TryAgainButton(Button):
      pass
  
  
  class ActionButton(Button):
      pass
  
  
  class MagicButton(Button):
      text = &quot;Magie&quot;
  
      def on_press(self):
          print(&quot;Liste des Sorts&quot;)
  
  
  class ObjectButton(Button):
      text = &quot;Objets&quot;
  
      def on_press(self):
          print(&quot;Liste des Objets&quot;)
  
  
  class FleeButton(Button):
      text = &quot;Fuite&quot;
  
  
  class MonsterFightApp(App):
      pass
  
      def build(self):
          # Create the screen manager
          sm = ScreenManager(transition=NoTransition())
          sm.add_widget(MenuScreen(name='menu'))
          sm.add_widget(FightScreen(name='combat'))
          sm.add_widget(GameOverScreen(name='game_over'))
  
          return sm
  
  
  MonsterFightApp().run()
  </code></pre>
  <p>and here is my kv file :</p>
  <pre><code>MenuScreen:
  
  
  &lt;MenuScreen&gt;:
      on_pre_enter: root.reset_game_won()
      Button:
          text: &quot;FIGHT ! &quot;
          on_press: root.manager.current = 'combat'
  
  
  &lt;FightScreen&gt;:
      MainWidget:
  
  &lt;GameOverScreen&gt;:
      on_pre_enter: root.game_over_sound.play(), root.reset_game_over()
      on_leave: root.game_over_sound.stop()
      RelativeLayout:
          Label:
              text: &quot;GAME OVER&quot;
              color: 1, 0, 0
              font_size: dp(100)
              font_name: &quot;fonts/Dragon_Fire.otf&quot;
          Button:
              size_hint: 0.2, 0.1
              pos_hint: {'center_x': 0.5, 'center_y': 0.3}
              text: &quot;TRY AGAIN&quot;
              on_release: root.manager.current = 'menu'
  
  &lt;MainWidget&gt;:
      BoxLayout:
          orientation : &quot;vertical&quot;
          BoxLayout:
              size_hint: 1, 0.1
              ProgressBar:
                  value: root.hero_xp
          RelativeLayout:
              Image:
                  id: Ennemy_img
                  source: root.Ennemy_img
              Image:
                  id: Effect_spell
                  source: root.Effect_img
          ProgressBar:
              size_hint: (root.monster_hp - root.monster_hp_lost) / root.monster_hp, 0.1
              canvas:
                  BorderImage:
                      border: (12, 12, 12, 12)
                      pos: self.x, self.center_y - 12
                      size: self.width, 24
                      source: 'images/red.png'
          BoxLayout:
              orientation: &quot;horizontal&quot;
              RelativeLayout:
                  MenuFull:
                      id: menu_full
                  Button:
                      size_hint: root.ennemy_turn, root.ennemy_turn
                      text: &quot;ENNEMY TURN&quot;
                      size: 0, 0
                      opacity: 0
                      disabled: True
              PlayerInfo:
                  orientation : &quot;horizontal&quot;
                  RelativeLayout:
                      Image:
                          source : 'images/mage.png'
                      Image:
                          source : root.monster_attack_effect
                  BoxLayout:
                      orientation: &quot;vertical&quot;
                      Label :
                          text : &quot;NAME&quot;
                      Label :
                          text : &quot;HP : &quot;
                      ProgressBar:
                          size_hint: (root.hero_hp - root.hero_hp_lost) / root.hero_hp, 0.1
                          canvas:
                              BorderImage:
                                  border: (12, 12, 12, 12)
                                  pos: self.x, self.center_y - 12
                                  size: self.width, 24
                                  source: 'images/red.png'
                      Label :
                          text : &quot; MP : &quot;
                      ProgressBar:
                          size_hint: (root.hero_mp - root.hero_mp_lost) / root.hero_mp, 0.1
                          canvas:
                              BorderImage:
                                  border: (12, 12, 12, 12)
                                  pos: self.x, self.center_y - 12
                                  size: self.width, 24
                                  source: 'images/blue.png'
                      Label :
                          text : &quot;LVL : &quot; + str(root.hero_lvl)
  
  
  
  &lt;MenuFull&gt;:
      do_default_tab: False
      TabbedPanelItem:
          text: &quot;Attaque&quot;
          Button:
              text: &quot;Attack&quot;
              disabled: True if root.ennemy_turn == True else False
              on_press: root.ennemy_turn_on(), self.parent.parent.parent.parent.parent.parent.on_attack(), self.parent.parent.parent.parent.parent.parent.parent.check_game_end()
      TabbedPanelItem
          text: &quot;Magic&quot;
          MagicMenu:
      TabbedPanelItem
          text: &quot;Objets&quot;
          ObjectMenu:
              id: object_menu
      TabbedPanelItem
          text: &quot;Fuite&quot;
          MagicMenu:
  
  
  &lt;MagicMenu&gt;:
      orientation : &quot;vertical&quot;
      Button:
          text: &quot;Fireball&quot;
          on_press: self.parent.parent.parent.parent.parent.parent.parent.on_spell_fire_pressed(), self.parent.parent.parent.parent.parent.parent.parent.parent.check_game_end()
      Button:
          text: &quot;Healing&quot;
          on_press: self.parent.parent.parent.parent.parent.parent.parent.on_spell_heal_pressed(), self.parent.parent.parent.parent.parent.parent.parent.parent.check_game_end()
      Button:
          text: &quot;tornado&quot;
          on_press: self.parent.parent.parent.parent.parent.parent.parent.on_spell_wind_pressed(), self.parent.parent.parent.parent.parent.parent.parent.parent.check_game_end()
  
  
  &lt;ObjectMenu&gt;:
      orientation : &quot;vertical&quot;
      BoxLayout:
          Button:
              text: &quot;Healing Potion&quot;
              on_press: self.parent.parent.parent.parent.parent.parent.parent.parent.on_object_1_pressed(), self.parent.parent.parent.parent.parent.parent.parent.parent.parent.check_game_end(), root.on_object_1_pressed()
          Button:
              disabled: True
              disabled_color: 1, 1, 1, 1
              size_hint: 0.2, 1
              text: &quot;x&quot; + str(root.object_1_qty)
      BoxLayout:
          Button:
              text: &quot;Mana Potion&quot;
              on_press: self.parent.parent.parent.parent.parent.parent.parent.parent.on_object_2_pressed(), self.parent.parent.parent.parent.parent.parent.parent.parent.parent.check_game_end(), root.on_object_2_pressed()
          Button:
              disabled: True
              disabled_color: 1, 1, 1, 1
              size_hint: 0.2, 1
              text: &quot;x&quot; + str(root.object_2_qty)
      BoxLayout:
          Button:
              text: &quot;Explosive Potion&quot;
              on_press: self.parent.parent.parent.parent.parent.parent.parent.parent.on_object_3_pressed(), self.parent.parent.parent.parent.parent.parent.parent.parent.parent.check_game_end(), root.on_object_3_pressed()
          Button:
              id : object_3
              disabled: True
              disabled_color: 1, 1, 1, 1
              size_hint: 0.2, 1
              text: &quot;x&quot; + str(root.object_3_qty)
  </code></pre>
  <p>here I want to make <code>ObjectMenu</code> use <code>object_1/2/3_qty</code> From <code>MainWidget</code> but they just won't communicate.</p>
  <p>so if anyone has an idea of what to do to achieve that I would love it !</p>