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

#Object
class Sprite:
	def __init__(self, game):
		self.game = game
		self.endGame = False
		self.co = None
		
	def move(self):
		pass
		
	def coords(self):
		return self.co


class Coords:
	def __init__(self, x1 = 0, y1 = 0, x2 = 0, y2 = 0):
			self.x1 = x1
			self.x2 = x2
			self.y1 = y1
			self.y2 = y2

#intersection
def inter_x(co1, co2):
	if (co1.x1 >= co2.x2) or (co1.x2 <= co2.x1):
		return False
	else:
		return True
		
def inter_y(co1, co2):
	if (co1.y1 >= co2.y2) or (co1.y2 <= co2.y1):
		return False
	else:
		return True
		
def collide_left(co1, co2):
	if inter_y(co1,co2) and co1.x1 <= co2.x2 and co1.x1 >= co2.x1:
		return True
	return False

def collide_right(co1, co2):
	if inter_y(co1,co2) and co1.x2 <= co2.x2 and co1.x2 >= co2.x1:
		return True
	return False
	
def collide_top(co1, co2):
	if inter_x(co1,co2) and co1.y1 <= co2.y2 and co1.y1 >= co2.y1:
		return True
	return False

def collide_bottom(y, co1, co2):
	y = co1.y2 + y
	if inter_x(co1,co2) and y <= co2.y2 and y >= co2.y1:
		return True
	return False
	

stone.py

from helper import *

class Stone(Sprite):
	def __init__(self, game, x, y, w, h):
		Sprite.__init__(self, game);#call father
		self.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 father
		self.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 time
from tkinter import *

class Man(Sprite):
	def __init__(self, game):
		Sprite.__init__(self, game);#call father
		self.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 = -2
		self.y = 0
		self.current_img = 0#image index
		self.current_img_add = 1
		self.jump_count = 0#use for jump
		self.last_time = time.time()
		self.co = Coords()
		game.canvas.bind_all("", self.turn_left)
		game.canvas.bind_all("", self.turn_right)
		game.canvas.bind_all("", self.jump)
		
	def turn_left(self, evt):
		#if self.y == 0:
			self.x = -2
			
	def turn_right(self, evt):
		#if self.y == 0:
			self.x = 2
			
	def jump(self, evt):
		if self.y == 0:
			self.y = -4
			self.jump_count = 0
	
	#important change img of Man
	def animate(self):
		if self.x != 0 and self.y == 0:
			if time.time() - self.last_time > 0.1:  #change img slowly
				self.last_time = time.time()
				self.current_img += self.current_img_add
				if self.current_img >= 2:
					self.current_img_add = -1
				elif self.current_img <= 0:
					self.current_img_add = 1
		if 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] + 27
		self.co.y2 = xy[1] + 30
		return self.co
	
	#important
	def move(self):
		self.animate()
		#for jump case, update y
		if self.y < 0:
			self.jump_count = self.jump_count + 1
			if self.jump_count > 20:
				self.y = 4
		elif self.y > 0:
			self.jump_count = self.jump_count - 1
		
		#collision check
		co = self.coords()
		left = True
		right = True
		top = True
		btm = True
		falling = True
		
		#1.collide with canvas
		if self.y > 0 and co.y2 >= self.game.canvas_h:
			self.y = 0
			btm = False
		elif self.y < 0 and co.y2 <= 0:
			self.y = 0
			top = False
		if self.x > 0 and co.x2 >= self.game.canvas_w:
			self.x = 0
			right = False
		elif self.x < 0 and co.x2 <= 0:
			self.x = 0
			left = False
			
		#2.collide with stone
		for s in self.game.sprites:
			if s == self:
				continue
			s_co = s.coords()
			if top and self.y < 0 and collide_top(co, s_co):#collide top
				self.y = - self.y
				top = False
			if 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 = 0
				btm = False
				top = False
			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
			if left and self.x < 0 and collide_left(co, s_co):#collide left
				self.x = 0
				left = False
				if s.endGame:#if s is door
					self.game.running = False
			if right and self.x > 0 and collide_right(co, s_co):#collide right
				self.x = 0
				right = False
				if s.endGame:#if s is door
					self.game.running = False
		
		print ("btm is %s" % btm);
		#let the man fall
		if 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 random
from stone import *
from man import *
from door import *

#Game controller
class 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))
#door
door = 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()


你可能感兴趣的:(Python)