Hello!I'm making a game in kivy. Up until now I've been working with only one screen - the game. Today I've been trying to implement the ScreenManager. The main game class on which everything is drawn was previously a widget. I now changed it into a Screen.All the methods of the 'Board' class are working, but it only draws for a moment, after which the screen goes black, throwing out: "Exception IndexError: 'list index out of range' in 'kivy.graphics.instructions.RenderContext.apply'" each frame.Here are my files reduced to only what is necessary for demonstrating the error, so that it's easier to navigate
# main.py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.graphics import Rectangle
from kivy.graphics import Rectangle
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.clock import Clock
TILE_PIXEL_SIZE = 51
class GameScreenManager(ScreenManager):
pass
class Player(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.coords = (500 // 2, 500 // 2)
# calculate pos for bliting
self.pos = (self.coords[0] * TILE_PIXEL_SIZE, self.coords[1] * TILE_PIXEL_SIZE)
class Board(Screen):
thing = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
def on_touch_down(self, touch):
print(touch.pos)
def update(self, dt): #! you are calling this *very* often
print('board.canvas.before *before* add rectangle', len(self.canvas.before.children))
# self.canvas.before.clear() #! I commented that line and it "works"
self.canvas.before.add(
Rectangle(
size=(51, 51),
pos=(5 * TILE_PIXEL_SIZE, 5 * TILE_PIXEL_SIZE)
)
)
print('board.canvas.before *after* add rectangle', len(self.canvas.before.children))
class Game(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
sm = ScreenManager()
board = Board(name='game')
#sm.add_widget(board)
Clock.schedule_interval(board.update, 1.0 / 60.0)
return board
Game().run()
# This file use tabs :/
#
# if the the Kivy app class is named Game, Kivy will try load game.kv (default behavior)
# So you don't need to load it manually, at least if: main.py where Game class is defined
# and Game().run() is called is in the same directory as ``game.kv``
#
# ./main.py
# ./game.kv
#
<Player>:
size: 51, 51
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.graphics import Rectangle
from kivy.uix.screenmanager import Screen,ScreenManager
from kivy.clock import Clock
TILE_PIXEL_SIZE = 51
Builder.load_file('C:\\Users\\user\\PycharmProjects\\untitled2\\mainKv')
class GameScreenManager(ScreenManager):
pass
class Player(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.coords = (500 // 2, 500 // 2)
# calculate pos for bliting
self.pos = (self.coords[0] * TILE_PIXEL_SIZE, self.coords[1] * TILE_PIXEL_SIZE)
class Board(Widget):
thing = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
def on_touch_down(self, touch):
print(touch.pos)
def update(self, dt):
self.canvas.before.clear()
self.canvas.before.add(Rectangle(size=(51, 51),
pos=(5 * TILE_PIXEL_SIZE, 5 * TILE_PIXEL_SIZE)))
class Game(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def build(self):
board = Board()
Clock.schedule_interval(board.update, 1.0 / 60.0)
return board
Game().run()
<Player>:
size:51,51
canvas.after:
Color:
rgba: 0,0,0,1
Rectangle:
pos:self.pos
size:self.size
<Board>:
thing:player
Player:
id:player