init.py
import tkinter
from BoxGame.Move import Move
from BoxGame.Map import Map
from BoxGame.init_paint import init_paint
def main():
# 新建一个窗口windows
windows = tkinter.Tk()
# 框架长宽设置为500x500,表头设置为‘推箱子小游戏’
# 箱子尺寸为64x64
s = 64
pa = init_paint(windows,"640x640","推箱子小游戏",s)
# 画出游戏开始界面
pa.paint_windows()
# 进入消息循环
windows.mainloop()
if __name__ == '__main__':
main()
init_paint.py
import tkinter
from BoxGame.Move import Move
from BoxGame.Map import Map
from BoxGame.Role import Role
# 引入字体模块
import tkinter.font as tkFont
class init_paint:
"""
窗口绘制
1.窗口的绘制-paint_windows
i,选择关卡-nextPass
2.地图的绘制-paint_canvas
3.人物的绘制
4.人物的移动-init_move
"""
cvs,image_role,image_role_file,image_file1,lb,bt,s = None,None,None,None,None,None,0
image_bg,image_bt = None,None
def __init__(self,windows,size,title,s):
self.windows = windows
self.size = size
self.title = title
self.map = Map.map1[0]
self.s = s
def paint_windows(self):
global lb,bt,image_bg,image_bt
self.windows.geometry(self.size)
self.windows.title(string=self.title)
# 菜单制作
menubase = tkinter.Menu(self.windows)
menubar = tkinter.Menu(menubase)
menulist_cs = ["游戏开始", "第一关", "第二关","退出游戏"]
for x in menulist_cs:
menubar.add_separator()
if x == "第二关":
menubar.add_command(label=x,command=self.nextPass)
else:
menubar.add_command(label=x)
menubase.add_cascade(label="游戏", menu=menubar)
menubase.add_cascade(label="帮助")
self.windows["menu"] = menubase
image_bg = tkinter.PhotoImage(file='image/bg1.png')
image_bt = tkinter.PhotoImage(file='image/begin.png')
cvs_bg = tkinter.Canvas(self.windows, width=640, heigh=640)
cvs_bg.create_image(0, 0, anchor='nw', image=image_bg)
ft = tkFont.Font(family='宋体', size=40, weight=tkFont.BOLD)
cvs_bg.create_text(320,200,anchor='center',text="推箱子小游戏",font=ft,fill="orangered")
bt = tkinter.Button(self.windows,image=image_bt,text="游戏开始",cursor="hand2",command=self.paint_canvas)
cvs_bg.pack()
bt.place(relx=0.5, rely=0.5, anchor="center")
self.cvs_bg = cvs_bg
self.bt = bt
def paint_canvas(self):
"""
初始化地图信息:
1、清空游戏开始界面
2、画墙、箱子
:return: None
"""
if self.cvs_bg != None:
self.cvs_bg.pack_forget()
if self.bt != None:
self.bt.place_forget()
global cvs,image_role_file,image_role,image_file1
# 新建一个画布
cvs = tkinter.Canvas(self.windows, width=640, heigh=640, bg="gray")
# 画出地图的围墙和箱子
gamemap = Map(cvs, self.map)
gamemap.setBoxGrade()
gamemap.draw()
# 设置游戏角色初始位置、图片,画出游戏角色
place_x = self.s+(self.s-37)/2
place_y = self.s*9
role = Role(place_x,place_y,"image/role.png")
role.setImage(cvs)
image_role = role.getImage()
cvs.pack()
Move(self.s, self.s*9, self.map, cvs,self.windows,image_role)
def nextPass(self):
self.map = Map.map1[1]
Role.py
import tkinter
class Role:
"""
类属性:
image_role_file:tkinter.PhotoImage对象
image_role:canvas.create_image对象,用于角色的移动move
"""
image_role_file,image_role = None,None
def __init__(self,place_x,place_y,image_file):
"""
构造函数:实例初始化
:param place_x:初始化位置-横坐标
:param place_y:初始化位置-纵坐标
:param image_file:游戏角色的图片路径
"""
self.place_x = place_x
self.place_y = place_y
self.image_file = image_file
def setImage(self,cvs):
"""
设置create_image游戏角色实例对象
:param cvs:canvas画布
:return:
"""
global image_role_file,image_role
image_role_file = tkinter.PhotoImage(file=self.image_file)
image_role = cvs.create_image(self.place_x, self.place_y, anchor='nw', image=image_role_file, tag="role")
def getImage(self):
return image_role
Map.py
import tkinter
class Map:
"""
类属性:
wall_file:tkinter.PhotoImage对象-墙
box_file:tkinter.PhotoImage对象-箱子
blue_file:tkinter.PhotoImage对象-目标点
img_x:绘图时的x轴坐标
img_y:绘图时的y轴坐标
all_grade:对应目标点数量
map地图:暂时先在Map中设置,新版本放到json中
"""
wall_file,box_file,blue_file,img_x,img_y = None,None,None,0,0
all_grade = 0
map1 = [[[1, 1, 1, 1, 1, 1, 3, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 2, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 3, 1, 1, 1]],#1_end
[[1, 1, 1, 1, 1, 1, 3, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
[1, 0, 0, 2, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 3, 1, 1, 1]]]
"""
map中:0为空地,1为围墙,2为箱子,3是目标地
"""
def __init__(self,cvs,map):
"""
:param cvs:canvas画布对象
:param map:地图二维数组
"""
self.cvs = cvs
self.map = map
def setBoxGrade(self):
"""
获取所有目标点的位置,赋值给类属性
:return:
"""
for x in self.map:
for y in x:
if y == 3:
Map.all_grade += 1
def draw(self):
"""
第一次绘制地图:
i、根据地图的二维数组来绘制,1为墙,2为箱子,3为目标点
:return:
"""
global img_x,img_y,wall_file,box_file,blue_file
img_x = 0
img_y = 0
wall_file = tkinter.PhotoImage(file='image/wall.png')
box_file = tkinter.PhotoImage(file='image/box.png')
blue_file = tkinter.PhotoImage(file="image/point.png")
for x in self.map:
for y in x:
if y == 1:
self.cvs.create_image(img_x, img_y, anchor='nw', image=wall_file,tag="wall")
elif y ==2:
self.cvs.create_image(img_x, img_y, anchor='nw', image=box_file,tag="box")
elif y ==3:
self.cvs.create_image(img_x+(64-32)/2, img_y+(64-32)/2, anchor='nw', image=blue_file,tag="blue")
img_x += 64
img_x = 0
img_y += 64
def againDrawBox(self):
"""
目的:重绘箱子的位置
要点:需要把PhotoImage设置为全局变量,create_image()才能在画布上显示
:return: None
"""
global img_x,img_y,box_file
img_x = 0
img_y = 0
self.cvs.delete("box")
box_file = tkinter.PhotoImage(file='image/box.png')
for x in self.map:
for y in x:
if y ==2:
self.cvs.create_image(img_x, img_y, anchor='nw', image=box_file,tag="box")
img_x += 64
img_x = 0
img_y += 64
Move.py
import tkinter
from BoxGame.Map import Map
# 引入字体模块
import tkinter.font as tkFont
class Move:
level = 1
grade = 0
image_bg = None
def __init__(self,place_x,place_y,map,cvs,windows,image_role):
self.pl_x = place_x
self.pl_y = place_y
self.map = map
self.cvs = cvs
# 移动
"""
在移动时:
若移动方向为空地,则是对+1或者-1部分地图进行探查是否可移动
若移动方向为箱子,则是对+2或者-2部分地图进行探查是否可移动
"""
windows.bind_all("<KeyPress-Up>", lambda event: self.upClick(event, image_role, cvs))
windows.bind_all("<KeyPress-Left>", lambda event: self.leftClick(event, image_role, cvs))
windows.bind_all("<KeyPress-Right>", lambda event: self.rightClick(event, image_role, cvs))
windows.bind_all("<KeyPress-Down>", lambda event: self.downClick(event, image_role, cvs))
def add_x(self):
# 靠墙角时的情况,不然会超出索引
if int(self.pl_x/64)+1 > 9:
return False
wall = self.map[int(self.pl_y/64)][int(self.pl_x/64)+1]
if self.pl_x <= 64*9:
if wall == 0:
self.pl_x += 64
return True
elif wall == 2 or wall == 3:
if int(self.pl_x/64)+2 > 9:
return False
box = self.map[int(self.pl_y/64)][int(self.pl_x/64)+2]
if box == 0:
self.pl_x += 64
return "boxmove"
if box == 3:
self.pl_x += 64
self.grade += 1
return "bluemove"
return False
def cut_x(self):
if int(self.pl_x/64)-1 < 0:
return False
wall = self.map[int(self.pl_y/64)][int(self.pl_x/64)-1]
if self.pl_x >=64:
if wall == 0 or wall == 3:
self.pl_x -= 64
return True
elif wall == 2:
if int(self.pl_x/64)-2 < 0:
return False
box = self.map[int(self.pl_y/64)][int(self.pl_x/64)-2]
if box == 0:
self.pl_x -= 64
return "boxmove"
if box == 3:
self.pl_x -= 64
self.grade += 1
return "bluemove"
return False
def add_y(self):
if int(self.pl_y/64)+1 >9:
return False
wall = self.map[int(self.pl_y/64)+1][int(self.pl_x/64)]
if self.pl_y <= 64*9:
if wall == 0 or wall == 3:
self.pl_y += 64
return True
elif wall == 2:
if int(self.pl_y/64)+2 > 9:
return False
box = self.map[int(self.pl_y/64)+2][int(self.pl_x/64)]
if box == 0:
self.pl_y += 64
return "boxmove"
if box == 3:
self.pl_y += 64
self.grade += 1
return "bluemove"
return False
def cut_y(self):
if int(self.pl_y/64)-1 < 0:
return False
wall = self.map[int(self.pl_y/64)-1][int(self.pl_x/64)]
if self.pl_y >=64:
if wall == 0 or wall == 3:
self.pl_y -= 64
return True
elif wall == 2:
if int(self.pl_y/64)-2 < 0:
return False
box = self.map[int(self.pl_y/64)-2][int(self.pl_x/64)]
if box == 0:
self.pl_y -= 64
return "boxmove"
if box == 3:
self.pl_y -= 64
self.grade += 1
return "bluemove"
return False
def upClick(self,event,img,cvs):
move_id = self.cut_y()
if move_id == True:
cvs.move(img,0,-64)
elif move_id == "boxmove":
self.map[int(self.pl_y / 64)+ 0][int(self.pl_x / 64) ] = 0
self.map[int(self.pl_y / 64)- 1][int(self.pl_x / 64) ] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img,0,-64)
elif move_id == "bluemove":
self.map[int(self.pl_y / 64)+ 0][int(self.pl_x / 64) ] = 0
self.map[int(self.pl_y / 64)- 1][int(self.pl_x / 64) ] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img,0,-64)
print("%d个箱子进洞啦"%(self.grade))
self.gameover()
def leftClick(self,event,img,cvs):
move_id = self.cut_x()
if move_id == True:
cvs.move(img,-64,0)
elif move_id == "boxmove":
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) + 0] = 0
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) - 1] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img, -64, 0)
elif move_id == "bluemove":
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) + 0] = 0
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) - 1] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img, -64, 0)
print("%d个箱子进洞啦"%(self.grade))
self.gameover()
def rightClick(self,event,img,cvs):
move_id = self.add_x()
if move_id == True:
cvs.move(img,64,0)
elif move_id == "boxmove":
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) + 0] = 0
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) + 1] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img, 64, 0)
elif move_id == "bluemove":
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) + 0] = 0
self.map[int(self.pl_y / 64)][int(self.pl_x / 64) + 1] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img, 64, 0)
print("%d个箱子进洞啦" % (self.grade))
self.gameover()
def downClick(self,event,img,cvs):
move_id = self.add_y()
if move_id == True:
cvs.move(img,0,64)
elif move_id == "boxmove":
self.map[int(self.pl_y / 64)+ 0][int(self.pl_x / 64) ] = 0
self.map[int(self.pl_y / 64)+ 1][int(self.pl_x / 64) ] = 2
Map(self.cvs, self.map).againDrawBox()
cvs.move(img,0,64)
elif move_id == "bluemove":
# 改变地图数组的值,0为空地,2为箱子
self.map[int(self.pl_y / 64)+ 0][int(self.pl_x / 64) ] = 0
self.map[int(self.pl_y / 64)+ 1][int(self.pl_x / 64) ] = 2
# 重绘盒子位置
Map(self.cvs, self.map).againDrawBox()
# 角色移动
cvs.move(img,0,64)
print("%d个箱子进洞啦" % (self.grade))
self.gameover()
def gameover(self):
global image_bg
print(self.grade,Map.all_grade)
print(len(Map.map1))
# 当箱子到位数等于本地图箱子总数时,进入下一个地图
if self.grade == Map.all_grade:
# 当游戏等级等于地图列表长度
if Move.level == len(Map.map1):
self.cvs.pack_forget()
image_bg = tkinter.PhotoImage(file='image/bg1.png')
self.cvs.create_image(0, 0, anchor='nw', image=image_bg)
ft = tkFont.Font(family='宋体', size=40, weight=tkFont.BOLD)
self.cvs.create_text(320, 320, anchor='center', text="通关啦!", font=ft, fill="orangered")
self.cvs.pack()
return False
self.cvs.pack_forget()
Map.all_grade = 0
self.grade = 0
Move.level += 1
map = Map(self.cvs,Map.map1[1])
map.setBoxGrade()
map.draw()
# 把Move实例里的地图数组改变为第二张地图,不然的话只会重新绘图,但是实例里的地图数组还是前一张地图里的
self.map = Map.map1[1]
self.cvs.pack()