class InfoWindow: def __init__(self, model: World): self.model = model self.window = Toplevel() self.window.title('Информация об объектах и мире') self.window.geometry("640x600+250+200") self._inner_init() self.frame.pack() self.window.mainloop() def _inner_init(self): self.frame = Frame(self.window, width=640, height=600, bd=2) self.frame.grid_bbox(2, 2) self._about_world() self._about_creatures() def _about_world(self): self.world_indo = self.model.info() TEXT = "Кол-во объектов: {cr_count}\n" \ "Из них живые: {cr_alive}".format(**self.world_indo) Label(self.frame, text=TEXT).grid(row=1, column=1) def _about_creatures(self): lb = Listbox(self.frame, height=15, width=50, selectmode=SINGLE) lb.bind('<<ListboxSelect>>', self._onselect) lb.grid(row=1, column=2) items = self.model.creatures.items() items = sorted(items, key=lambda k: k[0][0] * self.model.width + k[0][1]) for (x, y), creature in items: lb.insert(END, [x, y, creature.life]) self.canvas = NeuroCanvas(self.frame, (2, 2), 400, 300) def _onselect(self, evt): w = evt.widget index = int(w.curselection()[0]) value = w.get(index) x, y, *_ = value[1:].split(",") x = int(x) y = int(y) cr = self.model.creatures[(x, y)] neuro = cr.genome self.canvas.draw(neuro)
class InitScreen: def __init__(self, master): self.funcs = {} self.master = master self.controller = InitScreenController(master) self.master.title('parent') self.master.geometry('640x480+200+150') self.set_param_init() self.frame.pack() self.master.mainloop() def set_param_init(self): self.frame = Frame(width=400, height=300, bd=2) self.frame.grid_bbox(2, 4 + default_fields_count) self._buttons_init() self.entrys = {} _vcmd = self.frame.register(self._validate) count = 0 for block_name, block in default_params.items(): Label(self.frame, text=_convert(block_name), background="#999", justify=LEFT).grid( row=count, column=1 ) count += 1 for name, _default in block.items(): default, func = _default Label(self.frame, text=_convert(name), justify=LEFT).grid( row=count, column=1 ) # self.entrys[_convert(name)] = "" sv = StringVar( value=default_params[block_name][name][0]) e = Entry(self.frame) self.entrys[name] = sv self.funcs[e] = func e.config(validate='key', vcmd=(_vcmd, "%P", "%W"), textvariable=sv) e.grid(row=count, column=2) count += 1 Label(self.frame, text="Количество существ:", justify=LEFT).grid( row=count, column=1 ) self.creature_count = \ Label(self.frame, text='0', justify=LEFT) self.creature_count.grid( row=count, column=2 ) def _buttons_init(self): self.load_button = Button(self.frame, text='Загрузить', command=self.load_button_press) self.load_button.grid(row=4 + default_fields_count, column=1) self.start_button = Button(self.frame, text='Старт', command=self.start_button_press) self.start_button.grid(row=4 + default_fields_count, column=2) self.master.protocol('WM_DELETE_WINDOW', self.exit) def _validate(self, P, W): e = self.frame.nametowidget(W) func = self.funcs[e] try: func(P) except ValueError: return False else: return True def _collect_params(self): params = deepcopy(default_params) for block in params.values(): for key in block: func = block[key][1] block[key] = func(self.entrys[key].get()) return params def start_button_press(self): params = self._collect_params() if self.controller.model: self.game_screen = GameScreen(self.master, params, model=self.controller.model) else: self.game_screen = GameScreen(self.master, params) self.frame.forget() def load_button_press(self): self.controller.load_button_press() model = self.controller.model self.creature_count.config(text=str(len(model.creatures))) for block in model.params.values(): for k, v in block.items(): if k == "in_layers": v = ", ".join([str(x) for x in v]) self.entrys[k].set(v) def exit(self): exit()
class GameScreen: def __init__(self, master, params, model=None): self.master = master self.controller = GameScreenController(params, model=model) self.width = self.controller.model.width self.height = self.controller.model.height self.graphic_init() self.is_run = True self.run() def draw(self): # Сделать 4 солнца model = self.controller.model x, y = model.sun_x, model.sun_y suns = [(x, y), (x - self.width, y), (x, y - self.height), (x - self.width, y - self.height)] for x, y in suns: self.canvas.create_rectangle( max(0, x), max(0, y), min(x + model.sun_size, self.width + 1), min(y + model.sun_size, self.height + 1), fill="yellow", ) for coord, creature in model.creatures.items(): color = "#00{:0>2}00".format(hex(int(creature.life * 255))[2:]) if not creature.alive: color = "red" func = self.canvas.create_oval func(coord[0], coord[1], coord[0] + 6, coord[1] + 6, fill=color) def graphic_init(self): self.frame = Frame(self.master, bd=2) self.button_frame = Frame(self.frame, bd=2) self.button_frame.grid_bbox(row=1, column=4) self.start_stop_button = Button(self.button_frame, text="Пауза", command=self.start_stop_pressed) self.start_stop_button.grid(row=1, column=2) self.save_button = Button(self.button_frame, text="Сохранить", command=self.save_pressed) self.save_button.grid(row=1, column=1) self.info_button = Button(self.button_frame, text="Инфо", command=self.info_pressed, state=DISABLED) self.info_button.grid(row=1, column=4) self.add_button = Button(self.button_frame, text="Добавить существо", command=self.add_pressed) self.add_button.grid(row=1, column=3) self.canvas = Canvas(self.frame, width=self.width, height=self.height) self.canvas.pack(side=TOP) self.button_frame.pack() self.frame.pack() def start_stop_pressed(self): self.is_run = not self.is_run self.start_stop_button.config(text="Пауза" if self.is_run else "Старт") self.info_button.config(state=DISABLED if self.is_run else ACTIVE) self.run() def save_pressed(self): filename = asksaveasfilename(title="Сохранить мир") if filename: try: self.controller.save_pressed(filename) except Exception as e: messagebox.showerror("Не удалось сохранить файл", str(e)) def info_pressed(self): InfoWindow(self.controller.model) def add_pressed(self): self.controller.add_pressed() def run(self): if self.is_run: self.canvas.delete("all") self.controller.run() self.draw() self.master.after(1, self.run)