Python基于tkinterGUI的冒险交互小游戏项目总结

前言

Python课程的作业,最初的版本是玩家使用文字进行游戏,但实际体验感相当差,现在利用GUI进行可视化交互,方便玩家进行游戏。

不过许多功能是为了踩点拿分做,代码结构现在回过来看看emmm。但总之对能跑起来,各个功能都可以正常运行,没啥大bug。

游戏说明

这是一款冒险游戏。玩家在一个破败的基地中醒来。玩家需要通过探索基地来寻找帮助其回家的物品,但也会有许多陷阱和宝藏。玩家需要在基地收集足够的钥匙,击败怪物方可逃离。

1.游戏地图

游戏地图为两张,分为一层和二层,只有收集所需武器以及钥匙才可以击杀最终boss

一层地图:

二层地图:

2.类图

3.代码

代码主要分为四个部分:GUI(负责界面交互)、Game(游戏主要逻辑)、Room(游戏房间设置)、Player(玩家HP、武器、钥匙等物品)

顺便设置了自动化测试(确保功能可以正常运行)以及log记录(方便玩家查看自己的行动历史)

GUI代码如下:

import tkinter as tk
from tkinter import messagebox, RIGHT, LEFT, TOP, NW, DISABLED, NORMAL, BOTTOM

import tkinter
from PIL import ImageTk, Image
from Game import Game

import datetime


class MyGame_FIRSTUI:
    def __init__(self, root,PLAYER_IMAGE):
        '''
        User initial interface
        Enter user nickname
        :param root:
        '''
        # Create the model instance ...
        self.PLAYER_IMAGE=PLAYER_IMAGE
        #PLAYER_IMAGE=0

        self.root = root
        self.root.config()
        self.userframe = tk.Frame(self.root, width=1100, height=700)
        self.userframe.pack_propagate(0)  # Prevents resizing
        self.userframe.pack()
        self.userframe.columnconfigure(0, pad=5)
        for i in range(7):
            self.userframe.rowconfigure(i, pad=5)

        self.start_image = ImageTk.PhotoImage(Image.open('images/welcome.png'))
        self.image1 = ImageTk.PhotoImage(Image.open("images/player.png"))
        self.image2 = ImageTk.PhotoImage(Image.open("images/player2.gif"))
        self.start = tk.Label(self.userframe, image=self.start_image, width=1100, height=300)
        self.start.grid(row=0,column=0)
        self. label = tk.Label(self.userframe, text='Please enter user name', font=('Sans', '15', 'bold'))
        self.label.grid(row=1, column=0)
        self.button = tk.Button(self.userframe, text='start', command=self.change,font=('Sans', '15', 'bold'))
        self.button.grid(row=3,column=0, ipady=10, pady=10)
        self.player_name = tk.Entry(self.userframe, text='player_name')
        self.player_name.grid(row=2,column=0, ipady=10, pady=10)
        self.label_w = tk.Label(self.userframe, text='Please choose your Avatar', font=('Sans', '15', 'bold'))
        self.label_w.grid(row=4,column=0)
        self.button_image1=tk.Button(self.userframe,image=self.image1,compound=tkinter.BOTTOM,text='Avatar 1', command=self.Avatar1)
        self.button_image1.grid(row=5, column=0)
        self.button_image2 = tk.Button(self.userframe, image=self.image2,compound=tkinter.BOTTOM,text='Avatar 2', command=self.Avatar2)
        self.button_image2.grid(row=6, column=0)

    def change(self):
        """
            close the firstUI and start the secondUI
            Global variable: PLAYER_NAME
            Error prevention and recovery
        """
        global PLAYER_NAME
        try:
            PLAYER_NAME = self.player_name.get()
            if PLAYER_NAME.isalpha() == False:
                raise (ValueError())
        except ValueError:
            messagebox.showinfo("NOTE",message="Please use String type!")
        else:
            self.userframe.destroy()
            myApp = MyGame_secondUI(self.root,self.PLAYER_IMAGE)

    def Avatar1(self):
        #global PLAYER_IMAGE
        self.PLAYER_IMAGE=1
    def Avatar2(self):
        #global PLAYER_IMAGE
        self.PLAYER_IMAGE=2


class MyGame_secondUI:
    def __init__(self, root,PLAYER_IMAGE):
        '''
        The main interface of the game
        :param root:
        '''
        # Create the model instance ...
        self.PLAYER_IMAGE=PLAYER_IMAGE
        self.game = Game()
        self.res = False
        self.root = root
        self.people_x=225
        self.people_y=125
        self.nowroom='outside'

        # Create the GUI
        #add menubar
        menubar=tk.Menu()
        menubar.add_command(label="Quit",command=root.destroy)
        root.config(menu=menubar)
        menubar.add_command(label="About",command=self.about)
        root.config(menu=menubar)

        # add frame
        self.frame1 = tk.Frame(root, width=850,height=640, bg='GREY', borderwidth=2)
        self.frame1.pack_propagate(0)   # Prevents resizing
        self.frame1.pack(side = LEFT)
        self.frame2 = tk.Frame(root, width=250, height=650, borderwidth=2)
        self.frame2.pack_propagate(0)  # Prevents resizing
        self.frame2.pack(side = RIGHT)
        self.frame3 = tk.Frame(self.frame2, width=250, height=350, borderwidth=2)
        self.frame3.pack_propagate(0)  # Prevents resizing
        self.frame3.pack(side = TOP)
        self.frame4 = tk.Frame(self.frame2, width=250, height=350, borderwidth=2)
        self.frame4.pack_propagate(0)  # Prevents resizing
        self.frame4.pack(side = TOP)
        self.frame5 = tk.Frame(self.frame2, width=250, height=350, borderwidth=2)
        self.frame5.pack_propagate(0)  # Prevents resizing
        self.frame5.pack(side=TOP)

        self.frame3.columnconfigure(0, pad=10)
        for i in range(6):
            self.frame3.rowconfigure(i,pad=10)
        for i in range(2):
            self.frame4.columnconfigure(i, pad=10)
        for i in range(4):
            self.frame4.rowconfigure(i,pad=10)

        #get images
        #global PLAYER_IMAGE
        if self.PLAYER_IMAGE==2:
            self.character = ImageTk.PhotoImage(Image.open("images/player2.gif"))
        else:
            self.character = ImageTk.PhotoImage(Image.open("images/player.png"))
        self.east = ImageTk.PhotoImage(Image.open("images/east.png"))
        self.west=ImageTk.PhotoImage(Image.open("images/west.png"))
        self.south=ImageTk.PhotoImage(Image.open("images/south.png"))
        self.north=ImageTk.PhotoImage(Image.open("images/north.png"))
        self.weapon = ImageTk.PhotoImage(Image.open("images/axe.png"))
        self.coin = ImageTk.PhotoImage(Image.open("images/coin.png"))
        self.heart=ImageTk.PhotoImage(Image.open("images/heart.png"))
        self.wolf= ImageTk.PhotoImage(Image.open("images/wolf.png"))
        self.bear= ImageTk.PhotoImage(Image.open("images/Bear_Run.png"))

        self.garden_bg= ImageTk.PhotoImage(Image.open("images/Garden.png"))
        self.oustide_bg= ImageTk.PhotoImage(Image.open("images/outside.jpg"))
        self.lab_bg=ImageTk.PhotoImage(Image.open("images/lab.png"))
        self.diningroom_bg=ImageTk.PhotoImage(Image.open("images/diningroom.png"))
        self.beasment_bg=ImageTk.PhotoImage(Image.open("images/basement.png"))
        self.shop_bg=ImageTk.PhotoImage(Image.open("images/shop.png"))
        self.lobby_bg=ImageTk.PhotoImage(Image.open("images/lobby.png"))
        self.gym_bg=ImageTk.PhotoImage(Image.open("images/gym.png"))
        self.loung_bg=ImageTk.PhotoImage(Image.open("images/loung.png"))
        self.portal_bg=ImageTk.PhotoImage(Image.open("images/portal.png"))
        self.office_bg=ImageTk.PhotoImage(Image.open("images/office.png"))
        self.storehouse_bg=ImageTk.PhotoImage(Image.open("images/storehouse.png"))
        self.destination_bg=ImageTk.PhotoImage(Image.open("images/destination.png"))
        self.corridor_bg = ImageTk.PhotoImage(Image.open("images/corridor.png"))
        self.logo=ImageTk.PhotoImage(Image.open("images/destination-logo.png"))
        self.key=ImageTk.PhotoImage(Image.open("images/Key.png"))

        #add button
        options = ['background introduction', 'button introduction']    # List with all options
        self.v = tk.StringVar(self.frame3)
        self.v.set("help")  # default value
        self.v.trace("w", self.help)
        self.w = tk.OptionMenu(self.frame3, self.v, *options)
        self.w.grid(row=0, column=0)
        self.button_bag=tk.Button(self.frame3,text="use bag",command=lambda :self.usebag())
        self.button_bag.grid(row=1, column=0)
        self.button_weapon=tk.Button(self.frame3,text="weapon",image=self.weapon,compound=tkinter.BOTTOM,command=lambda :self.checkweapon())
        self.button_weapon.grid(row=4, column=0)

        #direction
        self.button_north=tk.Button(self.frame4,text="north",image=self.north,compound=tkinter.BOTTOM,
                                    command=lambda :self.North())
        self.button_north.grid(row=0, column=0)
        self.button_south = tk.Button(self.frame4, text="soth", image=self.south,compound=tkinter.BOTTOM,
                                      command=lambda: self.South())
        self.button_south.grid(row=0, column=1)
        self.button_west=tk.Button(self.frame4,text="west",image=self.west,compound=tkinter.BOTTOM,
                                   command=lambda :self.West())
        self.button_west.grid(row=1, column=0)
        self.button_east=tk.Button(self.frame4,text="east",image=self.east,compound=tkinter.BOTTOM,
                                   command=lambda :self.East())
        self.button_east.grid(row=1, column=1)
        self.stair=ImageTk.PhotoImage(Image.open("images/wooden_stairs-ns.png"))
        self.button_up=tk.Button(self.frame4,text="upstairs",image=self.stair,compound=tkinter.BOTTOM,command=lambda :self.Up())
        self.button_up.grid(row=2,column=0)
        self.button_down = tk.Button(self.frame4, text="downstairs",image=self.stair,compound=tkinter.BOTTOM,command=lambda :self.Down())
        self.button_down.grid(row=2,column=1)
        self.button_down.configure(state=DISABLED)


        #LABEL
        self.label_HP=tk.Label(self.frame5,text="Your life:"+str(self.game.player.life)+"HP",image=self.heart,compound=tkinter.LEFT)
        self.label_HP.pack(side=TOP)
        self.label_COIN=tk.Label(self.frame5,text="Your coin:"+str(self.game.player.coins),image=self.coin,compound=tkinter.LEFT)
        self.label_COIN.pack(side=TOP)
        self.label_KEY=tk.Label(self.frame5,text="Your key:"+str(self.game.player.total_keys),image=self.key,compound=tkinter.LEFT)
        self.label_KEY.pack(side=TOP)

        #picture_room
        self.cv=tk.Canvas(self.frame1,bg ='white',width=850,height=650)
        # Create rectangle with coordinates
        #garden=self.cv.create_rectangle(25, 25, 175, 100)
        self.garden=self.cv.create_image(25, 25, anchor=NW,image=self.garden_bg)
        self.cv.create_text(70, 35, text="GARDEN",fill="white")
        door1=self.cv.create_rectangle(75, 100, 125, 125,outline="",fill="grey")
        #corridor=self.cv.create_rectangle(25, 125, 175, 200)
        self.corridor=self.cv.create_image(25, 125,anchor=NW,image=self.corridor_bg)
        self.cv.create_text(70, 135, text="CORRIDOR",fill="white")
        door2 = self.cv.create_rectangle(75, 200, 125, 225,outline="",fill="grey")
        #lounge=self.cv.create_rectangle(25, 225, 175, 300)
        self.loung = self.cv.create_image(25, 225, anchor=NW, image=self.loung_bg)
        self.cv.create_text(70, 235, text="LOUNGE",fill="white")
        door3 = self.cv.create_rectangle(75, 300, 125, 325,outline="",fill="grey")
        #gym=self.cv.create_rectangle(25, 325, 175, 400)
        self.gym=self.cv.create_image(25, 325, anchor=NW, image=self.gym_bg)
        self.cv.create_text(70, 335, text="GYM",fill="white")
        door4 = self.cv.create_rectangle(75, 400, 125, 425,outline="",fill="grey")
        #destination=self.cv.create_rectangle(25, 425, 175, 500)
        self.destination = self.cv.create_image(25, 425, anchor=NW, image=self.destination_bg)
        self.cv.create_text(70,435, text="DISTINATION",fill="white")
        door5=self.cv.create_rectangle(175, 150, 225, 175,outline="",fill="grey")
        #outside=self.cv.create_rectangle(225, 125, 375, 200)
        self.outside = self.cv.create_image(225, 125, anchor=NW, image=self.oustide_bg)
        self.cv.create_text(270,135, text="OUTSIDE",fill="white")
        door6 = self.cv.create_rectangle(275,200,325,225,outline="",fill="grey")
        #lab=self.cv.create_rectangle(225,225,375,300)
        self.lab = self.cv.create_image(225,225, anchor=NW, image=self.lab_bg)
        self.cv.create_text(270,235, text="LAB",fill="white")
        door7 = self.cv.create_rectangle(275,300,325,325,outline="",fill="grey")
        #storehouse=self.cv.create_rectangle(225,325,375,400)
        self.storehouse = self.cv.create_image(225,325, anchor=NW, image=self.storehouse_bg)
        self.cv.create_text(270,335, text="STOREHOUSE",fill="white")
        door8 = self.cv.create_rectangle(275,400,325,425,outline="",fill="grey")
        #basement=self.cv.create_rectangle(225,425,375,500)
        self.basement=self.cv.create_image(225,425,anchor=NW,image=self.beasment_bg)
        self.cv.create_text(270,435, text="BASEMENT",fill="white")
        door9 = self.cv.create_rectangle(375,150,425,175,outline="",fill="grey")
        #lobby=self.cv.create_rectangle(425,125,575,200)
        self.lobby = self.cv.create_image(425,125, anchor=NW, image=self.lobby_bg)
        self.cv.create_text(450,135, text="LOBBY",fi
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值