pythonkivytext-based

Text-Based adventure in Kivy, Python


I'm very new to programming, just have an introductory seminar in university, and I'm supposed to program a little app in Python. For that, I want to use Kivy, but I got stuck. I have a text file which should include the question, the possible answers and where it's supposed to go considering which answer the user chose:

0|"Will you rather do A or B?"|"A"|"B"|1|2
1|"Congrats, you chose A. Now go to B."|"Go to B"|"Go to B"|2|2
2|"That's B. Incredible. Want to discover C?"|"Yes."|"Stay here."|3|6
3|Wow, C is so cool, isn't it? There's also a D.|D? Crazy!|Boring. Go back.|4|0
4|Welcome to the depths of D. You are curious, aren't you?|Yep.|Nope.|5|0
5|Cool. There's nothing else here.|There must be.|Knew it.|4|0
6|Surprise! You should really discover C.|Alright.|Is there a D?|3|4

Now I want the game to go to the according line, replace the displayed text and go on. In theory, this is kind of working with my Code (I'm sorry if it's messed up, as I said, I'm new to this topic):

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button

with open('try.txt') as t:
    Lines = t.readlines()
first_line = Lines[0].strip()
x = first_line.split("|")
answer_b = int(x[5])

class MyGrid(GridLayout): 
    def __init__(self, **kwargs):
        super(MyGrid, self).__init__(**kwargs)
        self.cols = 1

        self.inside = GridLayout()
        self.inside.cols = 2

        self.btna = Button(text=x[2])
        self.btna.bind(on_press=self.a)
        self.inside.add_widget(self.btna)

        self.btnb = Button(text=x[3])
        self.btnb.bind(on_press=self.b)
        self.inside.add_widget(self.btnb)

        self.main_text = Label(text=x[1])
        self.add_widget(self.main_text)

        self.add_widget(self.inside)

    def a(self, instance):
        answer_a = int(x[4])
        next_line_a = Lines[answer_a].strip()
        print(next_line_a)
        print(answer_a)
        x = next_line_a.split("|")
        self.main_text.text = x[1]
        self.btna.text = x[2]
        self.btnb.text = x[3]
        self.btna.bind(on_press=self.a)

    def b(self, instance):
        next_line_b = Lines[answer_b].strip()
        print(next_line_b)
        print(answer_b)
        x = next_line_b.split("|")
        self.main_text.text = x[1]
        self.btna.text = x[2]
        self.btnb.text = x[3]

class Game(App):
    def build(self):
        return MyGrid()

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

The problem is that it stays with the first line I defined and I don't really know how to go around that problem. I would imagine that I first define x with the first line, and after that x gets redefined with the according new line. But the next_line and x variable are both dependent on each other - I tried two different ways with answer a and b, but both don't really work. B will just continuously take the first_line-x, A tells me that x is referenced before assignment. It would be great if someone could help me out of my confusion, because everything I tried just didn't work out... Thanks!


Solution

  • I changed it so you pass items into the object that you create. It's challenging to get the inheritance correct.

    I also added an initializer to the Games object. I think this works but to be honest I am not expert in the workings of Kivy and have gotten this pattern to work but I don't know for sure if it is best practice.

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    import kivy
    from kivy.app import App
    from kivy.uix.label import Label
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.button import Button
    
    with open('try.txt') as t:
        Lines = t.readlines()
    
    
    class MyGrid(GridLayout):
        def __init__(self, Lines: list):
            super(MyGrid, self).__init__()
            self.first_line = Lines[0].strip()
            self.xx = self.first_line.split("|")
            self.answer_b = int(self.xx[5])
            self.cols = 1
    
            self.inside = GridLayout()
            self.inside.cols = 2
    
            self.btna = Button(text=self.xx[2])
            self.btna.bind(on_press=self.a)
            self.inside.add_widget(self.btna)
    
            self.btnb = Button(text=self.xx[3])
            self.btnb.bind(on_press=self.b)
            self.inside.add_widget(self.btnb)
    
            self.main_text = Label(text=self.xx[1])
            self.add_widget(self.main_text)
    
            self.add_widget(self.inside)
    
        def a(self, instance):
            answer_a = int(self.xx[4])
            next_line_a = Lines[answer_a].strip()
            print(next_line_a)
            print(answer_a)
            self.xx = next_line_a.split("|")
            self.main_text.text = self.xx[1]
            self.btna.text = self.xx[2]
            self.btnb.text = self.xx[3]
            self.btna.bind(on_press=self.a)
    
        def b(self, instance):
            next_line_b = Lines[self.answer_b].strip()
            print(next_line_b)
            print(self.answer_b)
            self.xx = next_line_b.split("|")
            self.main_text.text = self.xx[1]
            self.btna.text = self.xx[2]
            self.btnb.text = self.xx[3]
    
    
    class Game(App):
        def __init__(self, **kwargs):
            self._arguments_to_pass_through = kwargs
            super().__init__()
    
        def build(self):
            return MyGrid(**self._arguments_to_pass_through)
    
    
    if __name__ == '__main__':
        Game(Lines=Lines).run()