Наследование от главного класса и работа в одном окне
Разбираюсь с ООП. Создал меню игры "Battle City".
При нажатии на кнопку в окне - создаётся новое окно, мне необходимо оставаться только в одном объекте (окне), в классе MainMenu, заменяя лишь контент внутри него (главное меню -> 1 лвл -> 2 лвл...).
Файл main.py:
import arcade
import level_one
from constans import SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, AMOUNT_PLAYERS
class MainMenu(arcade.Window):
def __init__(self, width, height, title):
super().__init__(width, height, title)
self.yellow_tank = Tank()
self.main_menu = arcade.load_texture('images/main_menu2.png')
...
...
...
def on_key_press(self, key, modifiers):
global AMOUNT_PLAYERS
...
if key == arcade.key.ENTER and self.yellow_tank.center_y == 410:
# print('Один игрок')
AMOUNT_PLAYERS = 1
elif key == arcade.key.ENTER and self.yellow_tank.center_y == 363:
# print('Два игрока')
AMOUNT_PLAYERS = 2
level_one.LevelOne(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE) # ПРОБЛЕМА
if __name__ == '__main__':
window = MainMenu(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
window.setup()
arcade.run()
А также level_one.py:
import arcade
import main
from main import MainMenu
from constans import SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE
class LevelOne(main.MainMenu):
def __init__(self, width, height, title):
super().__init__(width, height, title)
print('hello')
self.main_menu = arcade.load_texture('images/main_menu.jpg')
def on_draw(self):
arcade.draw_texture_rectangle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT, self.main_menu)
Пожалуйста, подскажите, как работать исключительно в одном окне между разными модулями?
Ответы (1 шт):
Проблема в том, что вы создаете два окна. У вас LevelOne и MainMenu наследуются от Window и вы создаете по экземпляру каждого класса. Потому и показывается два окна. Сейчас структура классов такая:
Она неправильная, так как LevelOne и MainMenu не должны быть окнами.
Нужно это изменить и сделать, чтоб был только один экземпляр окна. Имеет смысл создать его один раз и чтоб он вызывал обработчики (делегировал обработку) текущему "екрану" (это я так назвал, но вы можете назвать, как вам кажется более подходящим). Тут (как и во всем ООП) важно:
- разделить обязанности между классами.
- один класс должен отвечать за одну вещь
Например, окно программы (см. класс MainWindow), по моему, не должно знать о деталях игры, т.е. например, что существуют какие-то танки. Я бы сделал его ответственным только за делегирование сообщений текущему екрану. Структура может быть такая:
В коде это будет выглядеть как-то так:
# main_window.py
class MainWindow(arcade.Window):
def __init__(self, width, height, title, screens, current_screen):
self.screens = {screen.__class__:screen for screens in screens}
self.current_screen = current_screen
def on_key_press(self, key, modifiers):
return self.current_screen.on_key_press(key, modifires)
def on_draw(self):
return self.current_screen.on_draw()
def switch_to_screen(self, screen_id):
self.current_screen = screens[screen_id]
class ScreenBase:
def __init__(self, main_window):
self.main_window = main_window
def switch_to_screen(self, screen_id):
self.main_window.switch_to_screen(screen_id)
# level_one.py
class LevelOneScreen(main_window.ScreenBase):
def __init__(self, main_menu_screen_id):
self.main_menu_screen_id = main_menu_screen_id
...
def on_draw(self):
arcade.draw_texture_rectangle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, SCREEN_WIDTH, SCREEN_HEIGHT, self.main_menu)
# main_menu.py
class MainMenuScreen(main_window.ScreenBase):
def __init__(self, level_one_screen_id):
self.level_one_screen_id = level_one_screen_id
...
def on_key_press(self, key, modifiers):
global AMOUNT_PLAYERS
...
if key == arcade.key.ENTER and self.yellow_tank.center_y == 410:
# print('Один игрок')
AMOUNT_PLAYERS = 1
elif key == arcade.key.ENTER and self.yellow_tank.center_y == 363:
# print('Два игрока')
AMOUNT_PLAYERS = 2
self.switch_to_screen(level_one_screen_id)
# main.py
SCREENS = [MainMenuScreen(LevelOneScreen), LevelOneScreen(MainMenuScreen)]
if __name__ == '__main__':
window = MainWindow(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE,
SCREENS, MainMenuScreen)
window.setup()
arcade.run()

