'How to use a variable/function from a class instance in a differrent class with kivy?
first, I'm new here, so don't hesitate to correct me if I act innapropriatly !
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 self.parent.parent.parent
etc but It is very frail and unsatisfying, and it does not work everywhere, I know that in theory I should use id
and/or app
but I just can't make it work, I guess I'm missing something with how they work, here is my python file :
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("images/slime.png")
Effect_img = StringProperty("images/void.png")
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("images/void.png")
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("audio/spit.wav")
self.lvl_up_sound = SoundLoader.load("audio/lvlup.wav")
self.fizzle_sound = SoundLoader.load("audio/Fizzle.wav")
self.sword_sound = SoundLoader.load("audio/sword.wav")
self.fire_sound = SoundLoader.load("audio/fireball.wav")
self.wind_sound = SoundLoader.load("audio/tornado.wav")
self.heal_sound = SoundLoader.load("audio/healing.wav")
self.victory_sound = SoundLoader.load("audio/victory.wav")
self.game_over_sound = SoundLoader.load("audio/Game_over.wav")
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 = "images/slime.png"
self.Effect_img = "images/void.png"
self.ids.Effect_spell.source = "images/void.png"
self.monster_attack_effect = "images/void.png"
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 = "images/void.png"
self.monster_attack_effect = "images/void.png"
def check_lifes_totals(self):
global game_won
global game_over
if self.monster_hp_lost >= self.monster_hp:
self.victory_sound.play()
game_won = True
self.hero_xp += self.monster_xp_gain
if self.hero_xp >= self.next_level:
self.hero_lvl += 1
self.hero_xp = 0
self.lvl_up_sound.play()
self.reset_all()
elif self.hero_hp_lost >= self.hero_hp:
game_over = True
self.reset_all()
def monster_turn(self, dt):
self.ids.Effect_spell.source = "images/void.png"
self.hero_hp_lost += 10
self.spit_sound.play()
self.monster_attack_effect = "images/slime_spit.png"
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 = "images/slash.png"
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 >= mp_cost:
self.ennemy_turn = 1
self.fire_sound.play()
self.ids.Effect_spell.source = "images/fireball.png"
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 >= mp_cost:
self.ennemy_turn = 1
self.wind_sound.play()
self.ids.Effect_spell.source = "images/tornado.png"
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 >= mp_cost:
self.ennemy_turn = 1
self.heal_sound.play()
self.monster_attack_effect = "images/heal.png"
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 > 0:
self.ennemy_turn = 1
self.heal_sound.play()
self.monster_attack_effect = "images/heal_potion.png"
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 > 0:
self.ennemy_turn = 1
self.heal_sound.play()
self.monster_attack_effect = "images/mana_potion.png"
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 > 0:
self.ennemy_turn = 1
self.fire_sound.play()
self.ids.Effect_spell.source = "images/explosion.png"
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 = "images/void.png"
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 > 0:
self.object_3_qty -= 1
def on_object_2_pressed(self):
if self.object_2_qty > 0:
self.object_2_qty -= 1
def on_object_1_pressed(self):
if self.object_1_qty > 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("audio/Game_over.wav")
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 = "Magie"
def on_press(self):
print("Liste des Sorts")
class ObjectButton(Button):
text = "Objets"
def on_press(self):
print("Liste des Objets")
class FleeButton(Button):
text = "Fuite"
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()
and here is my kv file :
MenuScreen:
<MenuScreen>:
on_pre_enter: root.reset_game_won()
Button:
text: "FIGHT ! "
on_press: root.manager.current = 'combat'
<FightScreen>:
MainWidget:
<GameOverScreen>:
on_pre_enter: root.game_over_sound.play(), root.reset_game_over()
on_leave: root.game_over_sound.stop()
RelativeLayout:
Label:
text: "GAME OVER"
color: 1, 0, 0
font_size: dp(100)
font_name: "fonts/Dragon_Fire.otf"
Button:
size_hint: 0.2, 0.1
pos_hint: {'center_x': 0.5, 'center_y': 0.3}
text: "TRY AGAIN"
on_release: root.manager.current = 'menu'
<MainWidget>:
BoxLayout:
orientation : "vertical"
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: "horizontal"
RelativeLayout:
MenuFull:
id: menu_full
Button:
size_hint: root.ennemy_turn, root.ennemy_turn
text: "ENNEMY TURN"
size: 0, 0
opacity: 0
disabled: True
PlayerInfo:
orientation : "horizontal"
RelativeLayout:
Image:
source : 'images/mage.png'
Image:
source : root.monster_attack_effect
BoxLayout:
orientation: "vertical"
Label :
text : "NAME"
Label :
text : "HP : "
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 : " MP : "
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 : "LVL : " + str(root.hero_lvl)
<MenuFull>:
do_default_tab: False
TabbedPanelItem:
text: "Attaque"
Button:
text: "Attack"
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: "Magic"
MagicMenu:
TabbedPanelItem
text: "Objets"
ObjectMenu:
id: object_menu
TabbedPanelItem
text: "Fuite"
MagicMenu:
<MagicMenu>:
orientation : "vertical"
Button:
text: "Fireball"
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: "Healing"
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: "tornado"
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()
<ObjectMenu>:
orientation : "vertical"
BoxLayout:
Button:
text: "Healing Potion"
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: "x" + str(root.object_1_qty)
BoxLayout:
Button:
text: "Mana Potion"
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: "x" + str(root.object_2_qty)
BoxLayout:
Button:
text: "Explosive Potion"
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: "x" + str(root.object_3_qty)
here I want to make ObjectMenu
use object_1/2/3_qty
From MainWidget
but they just won't communicate.
so if anyone has an idea of what to do to achieve that I would love it !
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|