diff options
| author | mo khan <mo@mokhan.ca> | 2025-06-04 17:41:00 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-06-04 17:41:00 -0600 |
| commit | 077744cced7c946e795a713ea2576c42415c79dd (patch) | |
| tree | 1c26fce44ba9679e7974deec1896c330037f16ae | |
| parent | 1d2e2ff117db1170ce7f6f54086e05033bf82f23 (diff) | |
add adventure game
| -rw-r--r-- | adventure/AdventureGame.py | 446 | ||||
| -rw-r--r-- | adventure/GameObject.py | 8 | ||||
| -rw-r--r-- | adventure/mise.toml | 2 | ||||
| -rw-r--r-- | adventure/res/blank-1.jpg | bin | 0 -> 197415 bytes |
4 files changed, 456 insertions, 0 deletions
diff --git a/adventure/AdventureGame.py b/adventure/AdventureGame.py new file mode 100644 index 0000000..62b90ac --- /dev/null +++ b/adventure/AdventureGame.py @@ -0,0 +1,446 @@ +from tkinter import * +from tkinter import ttk +from tkinter import simpledialog +import GameObject +from PIL import Image, ImageTk + +PORTRAIT_LAYOUT = False + +FIRST_LOCATION = 1 +SECOND_LOCATION = 2 +THIRD_LOCATION = 3 +FOURTH_LOCATION = 4 + +command_widget = None +image_label = None +description_widget = None +inventory_widget = None +north_button = None +south_button = None +east_button = None +west_button = None +root = None + +refresh_location = True +refresh_objects_visible = True + +current_location = FIRST_LOCATION +end_of_game = False + +generic_object = GameObject.GameObject("object", FIRST_LOCATION, True, True, False, "description") + +game_objects = [generic_object] + +def perform_command(verb, noun): + + if (verb == "GO"): + perform_go_command(noun) + elif ((verb == "N") or (verb == "S") or (verb == "E") or (verb == "W")): + perform_go_command(verb) + elif ((verb == "NORTH") or (verb == "SOUTH") or (verb == "EAST") or (verb == "WEST")): + perform_go_command(verb) + elif (verb == "GET"): + perform_get_command(noun) + elif (verb == "PUT"): + perform_put_command(noun) + elif (verb == "LOOK"): + perform_look_command(noun) + elif (verb == "X"): + perform_x_command(noun) + else: + print_to_description("huh?") + +def perform_go_command(direction): + + global current_location + global refresh_location + + if (direction == "N" or direction == "NORTH"): + new_location = get_location_to_north() + elif (direction == "S" or direction == "SOUTH"): + new_location = get_location_to_south() + elif (direction == "E" or direction == "EAST"): + new_location = get_location_to_east() + elif (direction == "W" or direction == "WEST"): + new_location = get_location_to_west() + else: + new_location = 0 + + if (new_location == 0): + print_to_description("You can't go that way!") + else: + current_location = new_location + refresh_location = True + +def perform_get_command(object_name): + + global refresh_objects_visible + game_object = get_game_object(object_name) + + if not (game_object is None): + if (game_object.location != current_location or game_object.visible == False): + print_to_description("You don't see one of those here!") + elif (game_object.movable == False): + print_to_description("You can't pick it up!") + elif (game_object.carried == True): + print_to_description("You are already carrying it") + else: + #handle special conditions + if (False): + print_to_description("special condition") + else: + #pick up the object + game_object.carried = True + game_object.visible = False + refresh_objects_visible = True + else: + print_to_description("You don't see one of those here!") + +# +def perform_put_command(object_name): + + global refresh_objects_visible + game_object = get_game_object(object_name) + + if not (game_object is None): + if (game_object.carried == False): + print_to_description("You are not carrying one of those.") + else: + #put down the object + game_object.location = current_location + game_object.carried = False + game_object.visible = True + refresh_objects_visible = True + else: + print_to_description("You are not carrying one of those!") +# +def perform_look_command(object_name): + + global sword_found + global refresh_location + global refresh_objects_visible + + game_object = get_game_object(object_name) + + if not (game_object is None): + + if ((game_object.carried == True) or (game_object.visible and game_object.location == current_location)): + print_to_description(game_object.description) + else: + #recognized but not visible + print_to_description("You can't see one of those!") + + #special cases - when certain objects are looked at, others are revealed! + if (False): + print_to_description("special condition") + global refresh_objects_visible + refresh_objects_visible = True + + else: + if (object_name == ""): + #generic LOOK + refresh_location = True + refresh_objects_visible = True + else: + #not visible recognized + print_to_description("You can't see one of those!") + +def perform_x_command(object_name): + game_object = get_game_object(object_name) + + if not (game_object is None): + if (game_object == generic_object): + #object recognized - implement specific behaviour + print_to_description("You Xd the "+ object_name) + else: + #object recognized - implement generic behaviour + print_to_description("You can't X the " + object_name) + else: + #not recognized + print_to_description("There is no " + object_name) + +def describe_current_location(): + if (current_location == FIRST_LOCATION): + print_to_description("location 1") + elif (current_location == SECOND_LOCATION): + print_to_description("location 2") + elif (current_location == THIRD_LOCATION): + print_to_description("location 3") + elif (current_location == FOURTH_LOCATION): + print_to_description("location 4") + else: + print_to_description("unknown location:" + current_location) + +def set_current_image(): + + if (current_location == FIRST_LOCATION): + #display a jpg using PIL library + image_label.img = ImageTk.PhotoImage( +Image.open +('res/blank-1.jpg')) + elif (current_location == SECOND_LOCATION): + #display image using standard image library (can only be .gif) + image_label.img = PhotoImage(file = 'res/blank-2.gif') + elif (current_location == THIRD_LOCATION): + image_label.img = PhotoImage(file = 'res/blank-3.gif') + elif (current_location == FOURTH_LOCATION): + image_label.img = PhotoImage(file = 'res/blank-4.gif') + else: + #for safety, display an image... code should never reach here + image_label.img = PhotoImage(file = 'res/blank-4.gif') + + image_label.config(image = image_label.img) + + +def get_location_to_north(): + + if (current_location == THIRD_LOCATION): + return FIRST_LOCATION + elif (current_location == FOURTH_LOCATION): + return SECOND_LOCATION + else: + return 0 + +def get_location_to_south(): + + if (current_location == FIRST_LOCATION): + return THIRD_LOCATION + elif (current_location == SECOND_LOCATION): + return FOURTH_LOCATION + else: + return 0 + +def get_location_to_east(): + + if (current_location == FIRST_LOCATION): + return SECOND_LOCATION + elif (current_location == THIRD_LOCATION): + return FOURTH_LOCATION + else: + return 0 + +def get_location_to_west(): + + if (current_location == SECOND_LOCATION): + return FIRST_LOCATION + elif (current_location == FOURTH_LOCATION): + return THIRD_LOCATION + else: + return 0 + +def get_game_object(object_name): + sought_object = None + for current_object in game_objects: + if (current_object.name.upper() == object_name): + sought_object = current_object + break + return sought_object + +def describe_current_visible_objects(): + + object_count = 0 + object_list = "" + + for current_object in game_objects: + if ((current_object.location == current_location) and (current_object.visible == True) and (current_object.carried == False)): + object_list = object_list + ("," if object_count > 0 else "") + current_object.name + object_count = object_count + 1 + + print_to_description("You see: " + (object_list + "." if object_count > 0 else "nothing special.")) + +def describe_current_inventory(): + + object_count = 0 + object_list = "" + + for current_object in game_objects: + if (current_object.carried): + object_list = object_list + ("," if object_count > 0 else "") + current_object.name + object_count = object_count + 1 + + inventory = "You are carrying: " + (object_list if object_count > 0 else "nothing") + + inventory_widget.config(state = "normal") + inventory_widget.delete(1.0, END) + inventory_widget.insert(1.0, inventory) + inventory_widget.config(state = "disabled") + +def handle_special_condition(): + + global end_of_game + + if (False): + print_to_description("GAME OVER") + end_of_game = True + +def print_to_description(output, user_input=False): + description_widget.config(state = 'normal') + description_widget.insert(END, output) + if (user_input): + description_widget.tag_add("blue_text", CURRENT + " linestart", END + "-1c") + description_widget.tag_configure("blue_text", foreground = 'blue') + description_widget.insert(END, '\n') + description_widget.config(state = 'disabled') + description_widget.see(END) + +def build_interface(): + + global command_widget + global image_label + global description_widget + global inventory_widget + global north_button + global south_button + global east_button + global west_button + global root + + root = Tk() + root.resizable(0,0) + + style = ttk.Style() + style.configure("BW.TLabel", foreground="black", background="white") + + image_label = ttk.Label(root) + if (PORTRAIT_LAYOUT): + image_label.grid(row=0, column=0, columnspan =3,padx = 2, pady = 2) + else: + image_label.grid(row=0, column=0, rowspan=3, columnspan=1,padx = 2, pady = 2) + + description_widget = Text(root, width =60, height = 10, relief = GROOVE, wrap = 'word') + description_widget.insert(1.0, "Welcome to my game.\n\nGood Luck!\n\n ") + description_widget.config(state = "disabled") + if (PORTRAIT_LAYOUT): + description_widget.grid(row=1, column=0, columnspan=3, sticky=W, padx=2, pady =2) + else: + description_widget.grid(row=0, column=1, rowspan=1, columnspan=2, padx=2, pady =2) + + command_widget = ttk.Entry(root, width = (25 if PORTRAIT_LAYOUT else 54), style="BW.TLabel") + command_widget.bind('<Return>', return_key_enter) + if (PORTRAIT_LAYOUT): + command_widget.grid(row=2, column=0, padx = 2, pady = 2) + else: + command_widget.grid(row=1, column=1, rowspan=1, columnspan=2) + + button_frame = ttk.Frame(root) + button_frame.config(height = 150, width = 150, relief = GROOVE) + if (PORTRAIT_LAYOUT): + button_frame.grid(row=3, column=0, columnspan =1, padx = 2, pady = 2) + else: + button_frame.grid(row=2, column=1, columnspan =1, padx = 2, pady = 2) + + north_button = ttk.Button(button_frame, text = "N", width = 5) + north_button.grid(row=0, column=1, padx = 2, pady = 2) + north_button.config(command = north_button_click) + + south_button = ttk.Button(button_frame, text = "S", width = 5) + south_button.grid(row=2, column=1, padx = 2, pady = 2) + south_button.config(command = south_button_click) + + east_button = ttk.Button(button_frame, text = "E", width = 5) + east_button.grid(row=1, column=2, padx = 2, pady = 2) + east_button.config(command = east_button_click) + + west_button = ttk.Button(button_frame, text = "W", width = 5) + west_button.grid(row=1, column=0, padx = 2, pady = 2) + west_button.config(command = west_button_click) + + inventory_widget = Text(root, width = (30 if PORTRAIT_LAYOUT else 38), height = (8 if PORTRAIT_LAYOUT else 6), relief = GROOVE , state=DISABLED ) + if (PORTRAIT_LAYOUT): + inventory_widget.grid(row=2, column=2, rowspan = 2, padx = 2, pady = 2,sticky=W) + else: + inventory_widget.grid(row=2, column=2, rowspan = 2, padx = 2, pady = 2,sticky=W) + +def set_current_state(): + + global refresh_location + global refresh_objects_visible + + if (refresh_location): + describe_current_location() + set_current_image() + + if (refresh_location or refresh_objects_visible): + describe_current_visible_objects() + + handle_special_condition() + set_directions_to_move() + + if (end_of_game == False): + describe_current_inventory() + + refresh_location = False + refresh_objects_visible = False + + command_widget.config(state = ("disabled" if end_of_game else "normal")) + +def north_button_click(): + print_to_description("N", True) + perform_command("N", "") + set_current_state() + +def south_button_click(): + print_to_description("S", True) + perform_command("S", "") + set_current_state() + +def east_button_click(): + print_to_description("E", True) + perform_command("E", "") + set_current_state() + +def west_button_click(): + print_to_description("W", True) + perform_command("W", "") + set_current_state() + +def return_key_enter(event): + if( event.widget == command_widget): + command_string = command_widget.get() + print_to_description(command_string, True) + + command_widget.delete(0, END) + words = command_string.split(' ', 1) + verb = words[0] + noun = (words[1] if (len(words) > 1) else "") + perform_command(verb.upper(), noun.upper()) + + set_current_state() + +def set_directions_to_move(): + + move_to_north = (get_location_to_north() > 0) and (end_of_game == False) + move_to_south = (get_location_to_south() > 0) and (end_of_game == False) + move_to_east = (get_location_to_east() > 0) and (end_of_game == False) + move_to_west = (get_location_to_west() > 0) and (end_of_game == False) + + north_button.config(state = ("normal" if move_to_north else "disabled")) + south_button.config(state = ("normal" if move_to_south else "disabled")) + east_button.config(state = ("normal" if move_to_east else "disabled")) + west_button.config(state = ("normal" if move_to_west else "disabled")) + +def play_audio(filename, asynchronous = True, loop = True): + + import platform + operating_system = platform.system() + + if (operating_system == 'Linux'): + from replit import audio + sound = audio.play_file(filename) + sound = audio.play_file('res/cold-moon.wav') + sound.paused = False + #according to documentation, setting .set_loop to -1 should create infinite loop in replit. Can't get it to work + sound.set_loop(-1) + elif (operating_system == 'Windows'): + import winsound + winsound.PlaySound(filename,winsound.SND_FILENAME + \ + (winsound.SND_ASYNC if asynchronous else 0) + \ + (winsound.SND_LOOP if loop else 0) + ) + +def main(): + build_interface() + set_current_state() + root.mainloop() + +main() diff --git a/adventure/GameObject.py b/adventure/GameObject.py new file mode 100644 index 0000000..8fff2a2 --- /dev/null +++ b/adventure/GameObject.py @@ -0,0 +1,8 @@ +class GameObject: + def __init__(self, name, location, movable, visible, carried, description): + self.name = name + self.location = location + self.movable = movable + self.visible = visible + self.carried = carried + self.description = description diff --git a/adventure/mise.toml b/adventure/mise.toml new file mode 100644 index 0000000..eff8f56 --- /dev/null +++ b/adventure/mise.toml @@ -0,0 +1,2 @@ +[tools] +python = "system" diff --git a/adventure/res/blank-1.jpg b/adventure/res/blank-1.jpg Binary files differnew file mode 100644 index 0000000..055102e --- /dev/null +++ b/adventure/res/blank-1.jpg |
