Python逃生遊戲,python逃生
從<趣學Python編程>上看到的例子,小人在石頭上跑跳直到達到門
我做了以下改進:
1. 模組化:
- helper.py 含有基類以及碰撞檢測函數
- man.py 小人
- door,py 門
- stone.py 腳踩的石頭
- game.py 主函數,初始化canvas,遊戲主迴圈
2. 修複一個Bug,原先人踩在石頭上會掉下來if btm and falling and self.y == 0 \
and (co.y2 >= self.game.canvas_h \
or collide_bottom(1, co, s_co)): #man stand on the stone
falling = False
素材:
背景bg.gif
門d_1.gif
跑動的小人
man_l_1
man_l_2
man_l_3
man_r_1
man_r_2
man_r_3
模組化代碼:
helper.py
#Objectclass Sprite:def __init__(self, game):self.game = gameself.endGame = Falseself.co = Nonedef move(self):passdef coords(self):return self.coclass Coords:def __init__(self, x1 = 0, y1 = 0, x2 = 0, y2 = 0):self.x1 = x1self.x2 = x2self.y1 = y1self.y2 = y2#intersectiondef inter_x(co1, co2):if (co1.x1 >= co2.x2) or (co1.x2 <= co2.x1):return Falseelse:return Truedef inter_y(co1, co2):if (co1.y1 >= co2.y2) or (co1.y2 <= co2.y1):return Falseelse:return Truedef collide_left(co1, co2):if inter_y(co1,co2) and co1.x1 <= co2.x2 and co1.x1 >= co2.x1:return Truereturn Falsedef collide_right(co1, co2):if inter_y(co1,co2) and co1.x2 <= co2.x2 and co1.x2 >= co2.x1:return Truereturn Falsedef collide_top(co1, co2):if inter_x(co1,co2) and co1.y1 <= co2.y2 and co1.y1 >= co2.y1:return Truereturn Falsedef collide_bottom(y, co1, co2):y = co1.y2 + yif inter_x(co1,co2) and y <= co2.y2 and y >= co2.y1:return Truereturn False
stone.py
from helper import *class Stone(Sprite):def __init__(self, game, x, y, w, h):Sprite.__init__(self, game);#call fatherself.image = game.canvas.create_rectangle(x, y, x + w, y + h, fill='pink')self.co = Coords(x, y, x + w, y + h)
door.py
from helper import *from tkinter import *class Door(Sprite):def __init__(self, game, x, y):Sprite.__init__(self, game);#call fatherself.photo_image = PhotoImage(file = 'd_1.gif');self.image = game.canvas.create_image(x, y, image = self.photo_image, anchor = 'nw')self.co = Coords(x, y, x + 27, y + 30)self.endGame = True
man.py
from helper import *import timefrom tkinter import *class Man(Sprite):def __init__(self, game):Sprite.__init__(self, game);#call fatherself.image_l = [PhotoImage(file="man_l_1.gif"),PhotoImage(file="man_l_2.gif"),PhotoImage(file="man_l_3.gif")]self.image_r = [PhotoImage(file="man_r_1.gif"),PhotoImage(file="man_r_2.gif"),PhotoImage(file="man_r_3.gif")]self.image = game.canvas.create_image(0, 0, image=self.image_l[0], anchor='nw')self.x = -2self.y = 0self.current_img = 0#image indexself.current_img_add = 1self.jump_count = 0#use for jumpself.last_time = time.time()self.co = Coords()game.canvas.bind_all("<Key-Left>", self.turn_left)game.canvas.bind_all("<Key-Right>", self.turn_right)game.canvas.bind_all("<Key-space>", self.jump)def turn_left(self, evt):#if self.y == 0:self.x = -2def turn_right(self, evt):#if self.y == 0:self.x = 2def jump(self, evt):if self.y == 0:self.y = -4self.jump_count = 0#important change img of Mandef animate(self):if self.x != 0 and self.y == 0:if time.time() - self.last_time > 0.1: #change img slowlyself.last_time = time.time()self.current_img += self.current_img_addif self.current_img >= 2:self.current_img_add = -1elif self.current_img <= 0:self.current_img_add = 1if self.x < 0:if self.y != 0:self.game.canvas.itemconfig(self.image, \image = self.image_l[2])else:self.game.canvas.itemconfig(self.image, \image = self.image_l[self.current_img])if self.x > 0:if self.y != 0:self.game.canvas.itemconfig(self.image, \image = self.image_r[2])else:self.game.canvas.itemconfig(self.image, \image = self.image_r[self.current_img])def coords(self):xy = self.game.canvas.coords(self.image)self.co.x1 = xy[0]self.co.y1 = xy[1]self.co.x2 = xy[0] + 27self.co.y2 = xy[1] + 30return self.co#importantdef move(self):self.animate()#for jump case, update yif self.y < 0:self.jump_count = self.jump_count + 1if self.jump_count > 20:self.y = 4elif self.y > 0:self.jump_count = self.jump_count - 1#collision checkco = self.coords()left = Trueright = Truetop = Truebtm = Truefalling = True#1.collide with canvasif self.y > 0 and co.y2 >= self.game.canvas_h:self.y = 0btm = Falseelif self.y < 0 and co.y2 <= 0:self.y = 0top = Falseif self.x > 0 and co.x2 >= self.game.canvas_w:self.x = 0right = Falseelif self.x < 0 and co.x2 <= 0:self.x = 0left = False#2.collide with stonefor s in self.game.sprites:if s == self:continues_co = s.coords()if top and self.y < 0 and collide_top(co, s_co):#collide topself.y = - self.ytop = Falseif btm and self.y > 0 and collide_bottom(self.y, co, s_co):#collide btm#self.y = s_co.y1 - co.y2#if self.y < 0:self.y = 0btm = Falsetop = Falseif btm and falling and self.y == 0 \and (co.y2 >= self.game.canvas_h \or collide_bottom(1, co, s_co)): #man stand on the stonefalling = Falseif left and self.x < 0 and collide_left(co, s_co):#collide leftself.x = 0left = Falseif s.endGame:#if s is doorself.game.running = Falseif right and self.x > 0 and collide_right(co, s_co):#collide rightself.x = 0right = Falseif s.endGame:#if s is doorself.game.running = Falseprint ("btm is %s" % btm);#let the man fallif falling and btm and self.y == 0\and co.y2 < self.game.canvas_h:self.y = 4 self.game.canvas.move(self.image, self.x, self.y)
game.py
from tkinter import *import randomfrom stone import *from man import *from door import *#Game controllerclass Game: def __init__(self): self.tk = Tk() self.tk.title("Run away from gost house") self.tk.resizable(0,0) self.tk.wm_attributes("-topmost", 1) self.canvas = Canvas(self.tk, width = 500, height = 500, highlightthickness=0) self.canvas.pack() self.tk.update() self.canvas_h = 500 self.canvas_w = 500 self.bg = PhotoImage(file="bg.gif") w = self.bg.width() h = self.bg.height() for x in range(0,5): for y in range(0,5): self.canvas.create_image( x * w, y * h, image=self.bg, anchor='nw') self.sprites = [] self.running = True def loop(self): while 1: if self.running: for sprite in self.sprites: sprite.move() self.tk.update_idletasks() self.tk.update() time.sleep(0.01)g = Game()for i in range(60, 500, 30):x = random.randint(0, 450)y = random.randint(-5, 5)width = random.randint(40, 100)g.sprites.append(Stone(g, x, i + y, width, 10))#doordoor = Door(g, 50, 300)g.sprites.append(door)lastStone = Stone(g, 50, 300, 60, 10)g.sprites.append(lastStone)m = Man(g)g.sprites.append(m)g.loop()