Как мы инициируем другие действия после переключения на второй экран в Python Kivy Screen Manager? - PullRequest
0 голосов
/ 14 января 2020

Я пытаюсь использовать ScreenManager в Kivy.

Как я и ожидал, приведенный ниже код должен вместить два разных экрана: первый экран ScreenOne представляет собой кнопку Play и второй экран ScreenTwo - это место, где игровой процесс должен начаться сразу же.

Проблема в том, что при переключении на ScreenTwo.

# ---------- Original file: kivytut2.py  ----------

# Importations
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.widget import Widget
from kivy.graphics import Rectangle
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.core.audio import SoundLoader

# Creating my kv code in the Python file
Builder.load_string("""
<ScreenOne>:
    BoxLayout:
        Button:
            text: "Play"
            background_normal: ''
            background_color: 0, 255, 255, .85
            on_press:
                # You can define the duration of the change
                # and the direction of the slide
                root.manager.transition.direction = 'up'
                root.manager.transition.duration = 0.5
                root.manager.current = 'screen_two'
""")

# Create a class for all screens in which you can include
# helpful methods specific to that screen
class ScreenOne(Screen):
    pass


class ScreenTwo(Screen):
    # Detect collision, to comment out
    def collides(rect1, rect2):
        r1x = rect1[0][0]
        r1y = rect1[0][1]
        r2x = rect2[0][0]
        r2y = rect2[0][1]
        r1w = rect1[1][0]
        r1h = rect1[1][1]
        r2w = rect2[1][0]
        r2h = rect2[1][1]

        if (r1x < r2x + r2w and r1x + r1w > r2x and r1y < r2y + r2h and r1y + r1h > r2y):
            return True
        else:
            return False

    def keyboard_events(self, **kwargs):
        super().keyboard_events(**kwargs)
        # Requesting keyboard event and setting its callbacks
        self._keyboard = Window.request_keyboard(self._on_keyboard_closed, self)
        self._keyboard.bind(on_key_down=self._on_key_down)
        self._keyboard.bind(on_key_up=self._on_key_up)

        # The Fly rectangle
        with self.canvas:
            self.enemy = Rectangle(source="assets/theenemy.png", pos=(350, 350), size=(100, 85))
            self.player = Rectangle(source="assets/theplayer.png", pos=(150, 150), size=(100, 85))

        self.keysPressed = set()

        # Refresh frame every "second argument" seconds
        Clock.schedule_interval(self.move_step, 0)

    # Background musics
    sound = SoundLoader.load("assets/gp.wav")
    if sound:
        print("Sound found at %s" % sound.source)
        print("Sound is %.3f seconds" % sound.length)
    sound.play()

    # The keyboard callback when closed?
    def _on_keyboard_closed(self):
        self.keyboard.unbind(on_key_down=self.on_key_down)
        self.keyboard.unbind(on_key_up=self.on_key_up)
        self.keyboard = None

    # The keyboard callback to change player position on key down
    def _on_key_down(self, keyboard, keycode, text, modifiers):
        self.keysPressed.add(text)

    def _on_key_up(self, keyboard, keycode):
        text = keycode[1]
        if text in self.keysPressed:
            self.keysPressed.remove(text)

    def move_step(self, dt):
        # Bottom left is origin, +x is right, -x is left, +y is up, -y is down
        currentx = self.player.pos[0]
        currenty = self.player.pos[1]

        # Move hundred pixels per second
        step_size = 100 * dt

        if "w" in self.keysPressed:
            currenty += step_size
        if "s" in self.keysPressed:
            currenty -= step_size
        if "a" in self.keysPressed:
            currentx -= step_size
        if "d" in self.keysPressed:
            currentx += step_size

        self.player.pos = (currentx, currenty)

        if collides((self.player.pos, self.player.size), (self.enemy.pos, self.player.size)):
            print("colliding, sire!")
        else:
            print("not colliding, sire.")


# The ScreenManager controls moving between screens
screen_manager = ScreenManager()

# Add the screens to the manager and then supply a name
# that is used to switch screens
screen_manager.add_widget(ScreenOne(name="screen_one"))
screen_manager.add_widget(ScreenTwo(name="screen_two"))

class KivyTut2App(App):

    def build(self):
        return screen_manager

sample_app = KivyTut2App()
sample_app.run()

возникает просто пустой черный экран.

В этом я использую файл примера Kivy с именем kivytut2.py, а также учебное пособие из YT https://www.youtube.com/watch?v=5t1VXHICv-Q&t=388s

Вся идея заключается в использовании ScreenManager в очень основное c главное меню.

Я ценю каждый комментарий и указания, чтобы решить это! Ура!

1 Ответ

0 голосов
/ 14 января 2020

Вы можете определить правило <ScreenTwo> так же, как вы сделали для ScreenOne в своем вызове Builder.load_string(). Просто добавьте <ScreenTwo>: в конец этой строки, а затем определите, что вы хотите видеть в ScreenTwo (как вы сделали для ScreenOne). Конечно, это полезно, только если вы хотите, чтобы что-то появилось в ScreenTwo.

. Я предлагаю начать с добавления on_enter() метода к ScreenTwo, например:

class ScreenTwo(Screen):
    def on_enter(self, *args):
        self.keyboard_events()

Это будет выполняться всякий раз, когда вы переключаетесь на ScreenTwo, и это вызывает ваш keyboard_events() метод ScreenTwo. Я думаю, что это начнет вашу игру (после того, как вы исправите некоторые ошибки в этом методе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...