前言
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