Search code examples
pythonpython-3.xkivykivy-language

Kivy Screenmanager Issues -


I am currently struggling with Kivy's screenmanager function. While it works in the menus it just won't show the character. I didn't find any helpful Information in the Documentation.

This works just fine so that class isn't the problem:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.image import Image
from kivy.core.window import Window


class Character(Widget):
    pass


class Basic(Image):


    def __init__(self, **kwargs):
        super(Basic, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(None, self)
        if not self._keyboard:
            return
        self._keyboard.bind(on_key_down=self.on_keyboard_down)
        print('Basic initialised')

    def on_keyboard_down(self, keyboard, keycode, text, modifiers):
        if keycode[1] == 'left':
            self.x -= 10
            print('pressed left')
        elif keycode[1] == 'right':
            self.x += 10
            print('pressed right')
        elif keycode[1] == 'up':
            self.y += 10
            print('pressed up')
        elif keycode[1] == 'down':
            self.y -= 10
            print('pressed down')
        else:
            return False
        return True


class HemeApp(App):

    def build(self):
        wimg = Basic(source='sprite.png')
        m = Character()
        m.add_widget(wimg)
        return m


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

But when I want to display that on my GameScreen from ScreenManager it's just a Blackscreen.

This is the code:

from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.config import Config
from kivy.vector import Vector
from kivy.uix.label import Label
from kivy.uix.popup import Popup
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.animation import Animation
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.screenmanager import ScreenManager, Screen

Builder.load_file('heme.kv')

##############################################################################################################################


class HemeApp(App):

    title = 'geme'
    icon = 'custoicon.png'

    def build(self):

        sm = ScreenManager()
        sm.add_widget(MenuScreen(name='menu'))
        sm.add_widget(SettingsScreen(name='settings'))
        sm.add_widget(CharacterCreationScreen(name='creationscreen'))
        sm.add_widget(GameScreen(name='gameplay'))

        return sm

    def save(self, plrname):
        fob = open('stats.txt', 'w+')
        fob.write(plrname + "\n")
        fob.close()


class MenuScreen(Screen):
    pass

class SettingsScreen(Screen):
    pass

class CharacterCreationScreen(Screen):
    pass

class Character(Widget):
    pass

class GameScreen(Screen):
    def playy(self):
        print ('playy fired')
        wimg = Basic(source='sprite.png')
        m = Character()
        m.add_widget(wimg)
        return m

    def on_enter(self):
        print ("on_enter fired")
        self.playy()



class MyButton(ButtonBehavior, Image):
    def __init__(self, **kwargs):
        super(MyButton, self).__init__(**kwargs)
        self.source = 'button.png'

    def on_press(self):
        self.source = 'button_pressed.png'

    def on_release(self):
        self.source = 'button.png'



class Basic(Image):


    def __init__(self, **kwargs):
        super(Basic, self).__init__(**kwargs)
        self._keyboard = Window.request_keyboard(None, self)
        if not self._keyboard:
            return
        self._keyboard.bind(on_key_down=self.on_keyboard_down)
        print('Basic initialised')

    def on_keyboard_down(self, keyboard, keycode, text, modifiers):
        print ('on_keyboard_down active')
        if keycode[1] == 'left':
            self.x -= 10
        elif keycode[1] == 'right':
            self.x += 10
        else:
            return False
        return True




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

Plus the Kivy code:

#; kivy 1.10.0
#:import Factory kivy.factory.Factory

<MenuScreen>:
    FloatLayout:
        canvas.before:
            Rectangle:
                pos: self.pos
                size: self.size
                source: 'bg.png'

        MyButton:
            pos: (330, 400)
            allow_stretch: True
            background_color: (0,1,0,1)
            size_hint: (.2,.2)
            text: 'Play'
            on_release:
                root.manager.transition.direction = 'right'
                root.manager.current = 'creationscreen'
        Label:
            pos: (330, 450)
            text: 'Play'
            color: (1,0,0)

        MyButton:
            pos: (330, 300)
            size_hint: (.2,.2)
            text: 'Goto settings'
            on_release:
                root.manager.transition.direction = 'right'
                root.manager.current = 'settings'
        MyButton:
            pos: (330, 200)
            background_color: (1,0,0,1)
            size_hint: (.2,.2)
            text: 'Quit'
            on_release: exit()

<SettingsScreen>:
    FloatLayout:
        MyButton:
            pos: (330, 400)
            size_hint: (.2,.2)
            text: 'My settings button'
        MyButton:
            pos: (330, 300)
            size_hint: (.2,.2)
            text: 'Back to menu'
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'menu'

<CharacterCreationScreen>:
    name: name_input
    FloatLayout:
        MyButton:
            pos: (330, 400)
            name: name_input
            size_hint: (.2,.2)
            text: 'Start game'
            on_release:
                root.manager.transition.direction = 'right'
                root.manager.current = 'gameplay'

        MyButton:
            pos: (430, 300)
            text: 'Save'
            on_release: app.save(name_input.text)
            size_hint: (.2,.2)

        TextInput:
            pos: (230, 300)
            id: name_input
            font_size: 20
            multiline: False
            size_hint: (.2,.2)

        MyButton:
            pos: (330, 200)
            size_hint: (.2,.2)
            text: 'Back to menu'
            on_release:
                root.manager.transition.direction = 'left'
                root.manager.current = 'menu'

<GameScreen>:
    game: game
    Character:
        id: game
        pos: self.pos

Solution

  • Problem

    The character was not displayed because no location was given to add the character.

    Solution

    1. Replaced return m with self.add_widget(m)

    Snippet

    class GameScreen(Screen):
        def playy(self):
            print('playy fired')
            wimg = Basic(source='sprite.png')
            m = Character()
            m.add_widget(wimg)
            self.add_widget(m)
    

    Output

    Img01