Black screen on game launch - python

I'm trying to start a game when I click on "start game". Menu screen is removed and game launches (I can hear the sounds and then being killed by an enemy) but can't see a thing. All I get is a black screen. It's like the game is launched in the background.
What am I doing wrong ?
updated kv file:
<Game_Screen>:
name: 'game_screen'
on_enter: app.launch_game()
<Game_Menu>:
FloatLayout:
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint: None, None
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'SPACE SHOOTER'
font_size: 40
font_name: "fonts/Alexis Italic.ttf"
color: 0, 1, 0, 1
pos_hint: {'center_x': 0.5, 'center_y': 1.7}
BoxLayout:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
size: self.parent.size
pos: self.parent.pos
orientation: 'vertical'
Label:
text: 'menu'
font_name: "fonts/Alexis Bold.ttf"
font_size: 30
color: 0, 1, 0, 1
Button:
text: 'start game'
on_press: app.root.current = 'game_screen'
Button:
text: 'highest score'
on_release:
Button:
text: 'credits'
on_release: app.root.current = 'credits'
updated Python code:
class Game(Widget):
# works fine on its own
class Game_Menu(Screen):
pass
class Game_Screen(Screen):
pass
class Menu_UI(Widget):
pass
class Credits_Screen(Screen):
pass
class GameApp(App):
sm = ScreenManager()
sm.add_widget(Game_Menu(name='menu'))
sm.add_widget(Credits_Screen(name='credits'))
sm.add_widget(Game_Screen(name='game_screen'))
def launch_game(self):
game = Game()
Window.size = game.size
engines1.loop = True
engines1.play()
return game
def build(self):
return self.sm
if __name__ == '__main__':
GameApp().run()

Problem
Programming Guide » Events and Properties » Main loop
In Kivy applications, avoid long/infinite loops or sleeping. The
program will never exit your loop, preventing Kivy from doing all of
the other things that need doing. As a result, all you’ll see is a
black window which you won’t be able to interact with.
In your kv file, you have FloatLayout:, Kivy will consider that as a root widget.
Rule context
The root rule is declared by declaring the class of your root widget,
without any indentation, followed by : and will be set as the root
attribute of the App instance.
Solution
Use Clock schedule functions e.g. schedule_interval(), schedule_once(), or create_trigger() in replacement of long/infinite loops or sleeping.
Move codes for sm immediately after GameApp into the build method.
Indent all the codes after <Game_Menu>
Snippets - main.py
class GameApp(App):
def launch_game(self):
game = Game()
Window.size = game.size
engines1.loop = True
engines1.play()
return game
def build(self):
self.sm = ScreenManager()
self.sm.add_widget(Game_Menu(name='menu'))
self.sm.add_widget(Credits_Screen(name='credits'))
self.sm.add_widget(Game_Screen(name='game_screen'))
return self.sm
Snippets - game.kv
#:kivy 1.10.0
<Game_Screen>:
name: 'game_screen'
on_enter: app.launch_game()
<Game_Menu>:
FloatLayout:
pos_hint: {'center_x': 0.5, 'center_y': 0.5}
size_hint: None, None
canvas.before:
Color:
rgba: 1, 0, 0, 1
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'SPACE SHOOTER'
font_size: 40
font_name: "fonts/alexisv3ital.ttf" # "fonts/Alexis Italic.ttf"
color: 0, 1, 0, 1
pos_hint: {'center_x': 0.5, 'center_y': 1.7}
Output

Related

Reset previous screen upon changing screen or clicking on a button

For my game, I would like to to reset a screen when the user changes screen.
I have tried many things such as using the Clock and making a update function, but it never really work. The layout does not change even though I explicitly change it in python.
For example, if I have button that becomes disabled upon release, when I change screen, it should not be disabled anymore This something that has been on my mind for a long time and don't quite get it.
I have three small files for this main.py, screen_manager.kv and main.kv. Sorry for this noob question
main.py
from kivy.app import App
from kivy.clock import Clock
from kivy.config import Config
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.widget import Widget
# Setup the window
Config.set('graphics', 'resizable', False)
width = 550
height = 550
Window.size = (width, height)
class OptionWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class Quiz(Widget):
def __init__(self, **kwargs):
super(Quiz, self).__init__(**kwargs)
def update(self, dt):
pass
kv = Builder.load_file('screen_manager.kv')
class Application(App):
CATEGORY = ''
def build(self):
game = Quiz()
Clock.schedule_interval(game.update, 1.0 / 60.0)
return kv
if __name__ == '__main__':
Application().run()
screen_manager.kv
# File name: screen_manager.kv
#:include main.kv
WindowManager:
OptionWindow:
SecondWindow:
<OptionWindow>:
name: 'first'
Button:
text: "Reset SecondWindow"
on_release:
app.root.current = 'second'
root.manager.transition.direction = "right"
<SecondWindow>:
name: 'second'
Quiz:
FloatLayout:
size: root.width, root.height
pos: 0, 0
Button:
text: "Go back"
pos_hint: {'x': 0.4, 'y': 0.2}
size_hint: 0.6, 0.6
on_release:
app.root.current = 'first'
root.manager.transition.direction = "right"
main.kv
<Quiz>:
FloatLayout:
id: thelayout
size: root.width, root.height
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'press me'
pos_hint: {'x': 0.0, 'y': 0.2}
size_hint: 0.3, 0.3
on_release: self.disabled = True
Thanks for you help
Your code provides for disabling the Button, but there is nothing in your code to re-enable it. Once a Button is disabled, it stays that way until something changes changes it. You can add something to your SecondWindow to re-enable the button every time the SecondWindow is displayed. You can use on_enter or on_pre_enter to trigger something to happen whenever that Screen is displayed. like this:
<SecondWindow>:
name: 'second'
on_pre_enter: quiz.ids.butt.disabled = False
Quiz:
id: quiz
FloatLayout:
size: root.width, root.height
pos: 0, 0
Button:
text: "Go back"
pos_hint: {'x': 0.4, 'y': 0.2}
size_hint: 0.6, 0.6
on_release:
app.root.current = 'first'
root.manager.transition.direction = "right"
Note the added id for the Quiz and the added on_pre_enter:. Also needed is a way to reference the Button. I have done that by adding an id to that Button:
<Quiz>:
FloatLayout:
id: thelayout
size: root.width, root.height
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Button:
id: butt
text: 'press me'
pos_hint: {'x': 0.0, 'y': 0.2}
size_hint: 0.3, 0.3
on_release: self.disabled = True
Now, everytime before the SecondWindow is displayed, the on_pre_enter: is triggered, and the `Button`` is re-enabled.

Using entries from other kivy classes

I am a beginner in Language and I am trying to make a simple guessing game and I would like to know how I use the data entered in the Players Class in the Start_p1 Class. I want the name typed in the TextInput of the Players Class, to appear in the Label Text: of the Start_p1 Class.
Arquivo .py:
import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.uix.textinput import TextInput
from kivy.properties import StringProperty
class Home(Screen):
def next(self):
self.manager.current = "players"
class Players(Screen):
def start(self):
self.manager.current = 'st1'
class Start_p1(Screen):
def runn(self):
self.manager.current = 'st2'
class Start_p2(Screen):
def back(self):
self.manager.current = 'st1'
class Finish(Screen): pass
class Myapp(App):
sm = None
def build(self):
self.sm = ScreenManager()
self.sm.add_widget(Home(name = 'home'))
self.sm.add_widget(Players(name = 'players'))
self.sm.add_widget(Start_p1(name = 'st1'))
self.sm.add_widget(Start_p2(name = 'st2'))
self.sm.add_widget(Finish(name = 'finish'))
self.sm.current = 'home'
return self.sm
if __name__ == '__main__':
Myapp().run()
Arquivo.kv
#: import utils kivy.utils
<Home>:
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex('#2169af')
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'Iniciar'
pos_hint: {'center_x': .5, 'center_y': .5}
size_hint: 0.2, .1
background_color: utils.get_color_from_hex('#13447d')
on_release: root.next()
Button:
text: 'Configurações'
pos_hint: {'center_x': .5, 'center_y': .4}
size_hint: 0.2, .1
background_color: utils.get_color_from_hex('#13447d')
<Players>:
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex('#2169af')
Rectangle:
pos: self.pos
size: self.size
Label:
pos: 0, 270
text: 'JOGADORES'
Label:
pos: 0, 150
text: 'Informe o nome do 1° Jogador:'
TextInput:
id: txtt
pos: 270, 400
size: 250, 30
multiline: False
Label:
pos: 0, -20
text: 'Informe o nome do 2° Jogador:'
TextInput:
id: txt
pos: 270, 230
size: 250, 30
multiline: False
Button:
text: 'Iniciar'
pos_hint: {'center_x': .5, 'center_y': .2}
size_hint: 0.2, .1
background_color: utils.get_color_from_hex('#13447d')
on_release: root.start()
<Start_p1>:
Players:
id: players
FloatLayout:
canvas.before:
Color:
rgb: utils.get_color_from_hex('#2169af')
Rectangle:
pos: self.pos
size: self.size
Label:
text:
That is actually a bit tricky. One would expect that you can use:
Label:
text: app.sm.get_screen('players').ids.txt.text
That will technically work, but it won't set up the automatic update if the text of the TextInput changes. A careful reading the documentation explains why, and suggests a work around. Using the suggestion from the documentation, you can do something like this:
Label:
players_screen: app.sm.get_screen('players')
text: self.players_screen.ids.txt.text
This produces the desired result with automatic updates.

Kivy: Starting and Stopping Threads When Button is Clicked

I'm having trouble with the threading in Python and Kivy. I'm trying to implement threading in my kivy app. Basically, when I click a button and the screen switches to the next one, I want to launch a thread, and when I click the 'back' button, the thread should stop. It's a pretty simple task, but my current code doesn't end the thread once I pressed 'back'.
Here is my code. I'm only including the necessary parts:
KV:
<MenuScreen>:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'bgpics/blackboard.png'
FloatLayout:
Button: #THIS IS the button that should start the thread
text: "Learn"
background_normal:'bgpics/chalk1.png'
color: 1, 1, 1, 1
size_hint: .2, .2
font_name: 'fonts/SqueakyChalkSound.ttf'
font_size: '40sp'
pos_hint:{"x":.09,"y":.3}
size_hint: .4, .4
on_press: root.manager.current = 'learncategories'
<LearnScreen>:
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'bgpics/categorybg.jpg'
Button: #THIS IS the button that should stop the thread
text: "BACK"
background_normal:'bgpics/yepaint.png'
color: 0, 0, 0, 1
font_size: '35sp'
font_name: 'fonts/DK Lemon Yellow Sun.otf'
pos: 50, 5
size_hint: .27, .27
on_press: root.manager.current = 'menu'
Python:
class Identifier:
def start_thread(self):
thread1=threading.Thread(target=self.serialtest)
thread1.start()
thread1.join()
def serialtest(self):
lol=1
while (lol>0):
print lol
lol+=1
def serialstop (self):
thread1.kill()
class LearnScreen(Screen):
def on_enter(self):
Identifier().start_thread()
def identify(self):
self.lol=Identifier()
def quitscreen(self):
self.identify.serialstop()

Is there a focus lost event dispatcher for a kivy TextInput?

Problem:
Is there a way to fire an event if a multiline = True TextInput lost its focus?
Background:
I have tried on_touch_up function. But it returns the instances of all my TextInputs, not just the current widget. I tried text_validate_unfocus = False, with the same result.
Code:
import kivy
kivy.require("1.10.1")
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty, NumericProperty
from kivy.uix.textinput import TextInput
from kivy.uix.bubble import Bubble
from kivy.lang import Builder
from kivy.storage.jsonstore import JsonStore
Builder.load_string('''
#: import Window kivy.core.window.Window
<Button>:
background_normal: ''
<Label>:
canvas.before:
Color:
rgba: (0,0.59,0.36,1)
Rectangle:
pos: self.pos
size: self.size
<TextInput>:
hint_text: 'Nuwe nota'
font_size: self.height / 4.5 if self.focus else self.height / 3
background_normal: ''
background_active: ''
foreground_color: (0,0.61,0.36,1) if self.focus else (0.71,0.75,0.71,1)
unfocus_on_touch: False
canvas.after:
Color:
rgb: (0,0,0,1)
Line:
points: self.pos[0] , self.pos[1], self.pos[0] + self.size[0], self.pos[1]
size_hint_y: None
height: Window.height / 6 if self.focus else Window.height / 12
<ChoiceBubble>:
orientation: 'horizontal'
size_hint: (None, None)
size: (160, 120)
pos_hint: {'top': 0.2, 'right': 0.8}
arrow_pos: 'top_left'
BubbleButton:
text: 'Save'
BubbleButton:
text: 'Encrypt..'
BubbleButton:
text: 'Delete'
on_release: root.del_txt_input()
<Notation>:
canvas:
Color:
rgba: (0,0.43,0.37,1)
Rectangle:
pos: self.pos
size: self.size
Label:
pos_hint: {'top': 1, 'right': 0.8}
size_hint: [0.8, None]
height: Window.height / 15
Button:
color: (0,0,0,1)
pos_hint: {'top': 1, 'right': 0.9}
size_hint: [0.1, None]
height: Window.height / 15
Image:
source: 'gear_2.png'
center_y: self.parent.center_y
center_x: self.parent.center_x
size: self.parent.width /1.5, self.parent.height/ 1.5
allow_stretch: True
Button:
color: (0,0,0,1)
pos_hint: {'top': 1, 'right': 1}
size_hint: [0.1, None]
height: Window.height / 15
on_release: root.add_input()
Image:
source: 'plus_text12354.png'
center_y: self.parent.center_y
center_x: self.parent.center_x
size: self.parent.width /1.5, self.parent.height/ 1.5
allow_stretch: True
ScrollView:
size_hint_y: None
size: Window.width, Window.height
pos_hint: {'top': 0.92, 'right': 1}
GridLayout:
id: text_holder
cols: 1
pos_hint: {'top': 0.92, 'right': 1}
padding: 4
size_hint_x: 1
size_hint_y: None
height: self.minimum_height
''')
class ChoiceBubble(Bubble):
pass
class TextInput(TextInput):
got_txt = ObjectProperty(None)
def on_touch_up(self, touch):
if not self.collide_point(*touch.pos):
self.text_validate_unfocus = False
note = Notation()
note.show_bubble
self.got_txt=note.que_txt_input(self)
return super(TextInput, self).on_touch_up(touch)
class Notation(FloatLayout):
which_txt = ObjectProperty(None)
new_txt = ObjectProperty(None)
cnt = NumericProperty(0)
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.the_file=JsonStore('txt_input.json')
self.cnt = self.the_file.count()
lst = self.the_file.keys
def add_input(self):
txt_hld = self.ids.text_holder
self.cnt += 1
self.new_txt = TextInput(id=str(self.cnt))
self.the_file.put(str(self.cnt), the_id=str(self.cnt), the_input='')
txt_hld.add_widget(self.new_txt)
def que_txt_input(self, instance):
self.which_txt = instance
print(instance.text, instance)
return instance
def del_txt_input(self):
print(self.which_txt)
def the_file(self, notestore):
self.notestore = notestore
def show_bubble(self):
self.add_widget(ChoiceBubble())
def get_store(self):
the_keys = list(self.the_file.keys)
print(the_keys)
return the_keys
class theNoteApp(App):
title = 'My Notes'
def build(self):
return Notation()
if __name__ == '__main__':
theNoteApp().run()
Desired Result:
Once the focus is lost I want a bubble widget to be added to the top of my root class. This will give the user the option to save, encrypt or delete the TextInput id and text that just lost its focus, to a JSON file.
Problems
Multiple instances of object, Notation. One from build() method (return Notation()) in App class, and another instance created in on_touch_up() method (note = Notation()) whenever on_touch_up event is fired. Those instances created in on_touch_up() method does not has a visible view i.e. it won't show up in the window.
AttributeError: 'ChoiceBubble' object has no attribute 'del_txt_input'
Text in ChoiceBubble not visible i.e. the default text color is white on white background.
Solutions
Use App.get_running_app().root to get the instantiated root.
Replace root.del_txt_input() with app.root.del_txt_input()
Add color: 0, 0, 0, 1 to class rule, <Label>:
Use on_focus event to display BubbleButton
Snippets - kv
<Label>:
color: 0, 0, 0, 1
...
<ChoiceBubble>:
...
BubbleButton:
text: 'Delete'
on_release: app.root.del_txt_input()
Snippets - py file
class TextInput(TextInput):
got_txt = ObjectProperty(None)
def on_focus(self, instance, value):
if not value: # defocused
note = App.get_running_app().root
note.show_bubble()
self.got_txt = note.que_txt_input(self)
Output
The on_focus event will fire when the focus boolean changes.
I have tried on_touch_up function. But it returns the instances of all my TextInputs, not just the current widget.
This is because you didn't write any code that would limit it to the widget you care about, you can do this if you want to.

Kivy Buttons and Labels size based on display size

I'm trying to figure out how to make my buttons and labels fix perfectly depending on my display size. So if the phone display is different, it will always be in fixed size.
Python Code:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class OpeningScreen(Screen):
pass
class LoginScreen(Screen):
pass
class SignupScreen(Screen):
pass
class ScreenManagement(ScreenManager):
pass
AppKv = Builder.load_file("App.kv")
class MyApp(App):
def build(self):
return AppKv
if __name__ == '__main__':
MyApp().run()
Kv code:
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import hex kivy.utils.get_color_from_hex
#------------------------------------------------------------#
ScreenManagement:
transition: FadeTransition()
OpeningScreen:
LoginScreen:
SignupScreen:
#------------------------------------------------------------#
<OpeningScreen>:
name: "OpeningScreen"
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "Welcome"
color: 1,1,1,1
font_size: 45
size_hint: 0.2,0.1
pos_hint: {"x":0.40, "top":0.995}
Button:
size: 100,75
on_release: app.root.current = "LoginScreen"
text: "Login"
font_size: 50
color: 1,1,1,1
background_color: (0,0,0,1)
background_normal: ""
background_down: ""
size_hint: 0.3,0.2
pos_hint: {"x":0.35, "top":0.7}
Button:
size: 100,75
on_release: app.root.current = "SignupScreen"
text: "Sign up"
font_size: 50
color: 1,1,1,1
background_color: (0,0,0,1)
background_normal: ""
background_down: ""
size_hint: 0.3,0.2
pos_hint: {"x":0.35, "top":0.4}
#------------------------------------------------------------#
<LoginScreen>:
name: "LoginScreen"
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "Login In"
color: 0,0,0,1
font_size: 45
size_hint: 0.2,0.1
pos_hint: {"x":0.40, "top":0.995}
#------------------------------------------------------------#
<SignupScreen>:
name: "SignupScreen"
canvas:
Color:
rgb: 1, 1, 1
Rectangle:
pos: self.pos
size: self.size
Label:
text: "Sign Up"
color: 0,0,0,1
font_size: 45
size_hint: 0.2,0.1
pos_hint: {"x":0.40, "top":0.995}
I would really appreciate if anyone could help me with this. I was trying to find out how to do this but I couldn't
Button and Label sizes can be set using several different approaches:
Use Kivy Metrics. You can set sizes using dp (for example dp(100)), this is a Density-independent Pixel size. There is also a sp (used similarly) that is Scale-independent Pixels (normally used for font sizes)
Use self.texture_size. You can set sizes using this as size: self.texture_size. This will make your Button and Label widgets just large enough to fit the text in it. You can add some padding by using something like:
width: self.texture_size[0] + dp(10)
height: self.texture_size[1] + dp(10)
Use size_hint. This will ensure that the Button and Label widgets take up the same percentage of your display, regardless of the device.
Don't forget to set size_hint to None, None for the first two above to work.

Categories