I'm trying to make a text adventure with tkinter and I'm slowly getting something together. I'm trying to display commands as they come from room to room but even though the buttons appear, nothing happens when I press them.
game.py
#!/usr/bin/python # -*- coding: utf-8 -*- import world from player import Player from ui import * def main(): gui = Window(root()) while True: gui.mainloop() else: pass if __name__ == '__main__': main()
ui.py
#!/usr/bin/python # -*- coding: utf-8 -*- import tkinter as tk from tkinter import ttk import world, tiles, action from player import Player class Window(tk.Frame): def __init__(self, master): tk.Frame.__init__(self, master=master) self.master = master self.player = Player() self.init_ui() def init_ui(self): self.master.title("****") self.tabs = Tabs(self.master) world.load_tiles() self.world = world.tile_exists(self.player.location_x, self.player.location_y) self.update_main() def update_main(self): self.world.scene_init() self.world.modify_player(self.player) self.tabs.update_tab(self.world, self.player) def _label(self, master, text, side=None, anchor=None): new_label = tk.Label(master, text=text) new_label.pack(side=side, anchor=anchor) def _button(self, master, text, command, side=None, anchor=None): new_button = tk.Button(master, text=text, command=command) new_button.pack(side=side, anchor=anchor) class Tabs(Window): def __init__(self, master): self.master = master self.nb = ttk.Notebook(self.master) nb_1 = ttk.Frame(self.nb) self.frame_1 = tk.Frame(nb_1, bg='red', bd=2, relief=tk.SUNKEN, padx=5, pady=5) self.frame_1.pack(expand=1, fill='both', side=tk.LEFT) self.nb.add(nb_1, text='Game') self.nb.pack(expand=1, fill='both', side=tk.LEFT) def update_tab(self, world, player): avaliable_actions = world.avaliable_actions() self._label(self.frame_1, world.display_text(), side=tk.LEFT, anchor=tk.N) for action in avaliable_actions: self._button(self.frame_1, text=action, command=player.do_action(action, **action.kwargs), side=tk.BOTTOM, anchor=tk.E) def root(): root = tk.Tk() root.geometry("600x350+200+200") return root
world.py
#!/usr/bin/python # -*- coding: utf-8 -*- _world = {} def tile_exists(x, y): """Returns the tile at the given coordinates or None if there is no tile. :param x: the x-coordinate in the worldspace :param y: the y-coordinate in the worldspace :return: the tile at the given coordinates or None if there is no tile """ return _world.get((x, y)) def load_tiles(): with open('scenes.txt', 'r') as f: rows = f.readlines() x_max = len(rows[0].split('\t')) for y in range(len(rows)): cols = rows[y].split('\t') for x in range(x_max): tile_name = cols[x].replace('\n', '') _world[(x, y)] = None if tile_name == '' else getattr(__import__('tiles'), tile_name)(x, y) return _world
tiles.py
#!/usr/bin/python # -*- coding: utf-8 -*- import world, action from player import Player class MapTile(): def __init__(self, x, y): self.x = x self.y = y def display_text(self): pass # raise NotImplementedError() def modify_player(self, the_player): raise NotImplementedError() def adjacent_moves(self): moves = [] if world.tile_exists(self.x + 1, self.y): moves.append(action.MoveEast()) if world.tile_exists(self.x - 1, self.y): moves.append(action.MoveWest()) if world.tile_exists(self.x, self.y - 1): moves.append(action.MoveNorth()) if world.tile_exists(self.x, self.y + 1): moves.append(action.MoveSouth()) return moves def avaliable_actions(self): '''Returns all of the default avaliable_actions in a room''' moves = self.adjacent_moves() # moves.append(action.ViewInventory()) return moves class Scene_1(MapTile): def scene_init(self): self.location = 'Scene_1' self.long_desc = 'Welcome to {}, the shittiest place on earth.'.format(self.location) self.short_desc = 'Eh, I don\'t care.' def display_text(self): return self.long_desc def modify_player(self, the_player): self.first = True return self.display_text() class Scene_2(MapTile): def scene_init(self): self.location = 'Scene_2' self.long_desc = 'This is {}, but noone gives a damn.'.format(self.location) self.short_desc = 'Eh, I don\'t care, really.' def display_text(self): return self.long_desc def modify_player(self, the_player): self.first = True return self.display_text()
player.py
#!/usr/bin/python # -*- coding: utf-8 -*- class Player(): '''Base for player''' def __init__(self): self.inventory = [] self.hp = 100 self.location_x, self.location_y = 1, 1 self.victory = False def is_alive(self): return self.hp >= 0 def do_action(self, action, **kwargs): action_method = getattr(self, action.method.__name__) if action_method: action_method(**kwargs) def print_inventory(self): for item in self.inventory: print(item, 'n') def move(self, dx, dy): self.location_x += dx self.location_y += dy def move_north(self): self.move(dx=0, dy=-1) def move_south(self): self.move(dx=0, dy=1) def move_east(self): self.move(dx=1, dy=0) def move_west(self): self.move(dx=-1, dy=0)
action.py
#!/usr/bin/python # -*- coding: utf-8 -*- from player import Player class Action(): def __init__(self, method, name, **kwargs): """Creates a new action :param method: the function object to execute :param name: the name of the action :param ends_turn: True if the player is expected to move after this action else False :param hotkey: The keyboard key the player should use to initiate this action """ self.method = method self.name = name self.kwargs = kwargs def __str__(self): return "{}".format(self.name) class MoveNorth(Action): def __init__(self): super().__init__(method=Player.move_north, name='north') class MoveSouth(Action): def __init__(self): super().__init__(method=Player.move_south, name='south') class MoveEast(Action): def __init__(self): super().__init__(method=Player.move_east, name='east') class MoveWest(Action): def __init__(self): super().__init__(method=Player.move_west, name='west') class ViewInventory(Action): """Prints the player's inventory""" def __init__(self): super().__init__(method=Player.print_inventory, name='View inventory', hotkey='i') class Attack(Action): def __init__(self, enemy): super().__init__(method=Player.attack, name="Attack", hotkey='a', enemy=enemy) class Flee(Action): def __init__(self, tile): super().__init__(method=Player.flee, name="Flee", hotkey='f', tile=tile)