当前位置 博文首页 > python 实现简单的吃豆人游戏

    python 实现简单的吃豆人游戏

    作者:tinytsunami 时间:2021-04-30 17:53

    效果展示:

    程序简介

    1.使用pygame模组
    2.在material目录下有一些素材
    3.吃豆人的游戏主体
    4.吃豆人怪物的AI(未使用深度学习)

    主要代码

    main.py

    import pygame, sys
    from pygame.locals import *
    from unit import user, enemy
    import random
    
    #constant initialize
    FPS = 60
    BLOCK_SIZE = 24
    WIDTH = 29
    HEIGHT = 15
    WINDOW_WIDTH = WIDTH * BLOCK_SIZE
    WINDOW_HEIGHT = HEIGHT * BLOCK_SIZE
    MAP_NAME = "./material/map.maze"
    BGM_NAME = "./material/bgm.ogg"
    BLOCK_IMAGE = "./material/block.png"
    FOOD_IMAGE = "./material/food.png"
    GAMEOVER_IMAGE = "./material/gameover.png"
    SERVER_PORT = 30000
    ENEMY_COUNT = 4
    OX = 1
    OY = 1
    DELAY = 8
    
    #pygame initialize
    pygame.init()
    display = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    clock = pygame.time.Clock()
    block_image = pygame.image.load(BLOCK_IMAGE)
    food_image = pygame.image.load(FOOD_IMAGE)
    gameover_image = pygame.image.load(GAMEOVER_IMAGE)
    bgm = pygame.mixer.music.load(BGM_NAME)
    scene = "game"
    unit_list = []
    game_map = []
    
    #map initialize
    def load_map(filename):
    	global game_map
    	game_map.clear()
    	file = open(filename, 'r')
    	for line in file.readlines():
    		game_map.append(list(line.strip()))
    		pass
    	pass
    
    #set passport
    def through(position):
    	x = position[0]
    	y = position[1]
    	in_range = (x >= 0 and x < WIDTH) and (y >= 0 and y < HEIGHT)
    	in_space = (not game_map[y][x] == '1')
    	return (in_range and in_space)
    	pass
    
    #gameover?
    def check_gameover(user_pos, enemy_pos):
    	global scene
    	gameover = (enemy_pos[0] == user_pos[0] and enemy_pos[1] == user_pos[1])
    	if gameover:
    		scene = "gameover"
    		pass
    	return gameover
    	pass
    
    #gameover
    def gameover():
    	pygame.mixer.music.stop()
    	keys = pygame.key.get_pressed()
    	if keys[K_RETURN]:
    		initialize()
    		pass
    	display.fill((0, 0, 0))
    	x = (WINDOW_WIDTH-gameover_image.get_width())/2
    	y = (WINDOW_HEIGHT-gameover_image.get_height())/2
    	display.blit(gameover_image, (x, y))
    	pygame.display.update()
    	pass
    
    #unit initialize
    def initialize_unit():
    	unit_list.clear()
    	ox = random.randint(1, WIDTH - 2)
    	oy = random.randint(1, HEIGHT - 2)
    	while not through((ox, oy)):
    		ox = random.randint(1, WIDTH - 2)
    		oy = random.randint(1, HEIGHT - 2)
    	unit_list.append(user(OX, OY))
    	for i in range(0, ENEMY_COUNT):
    		enemy_color = i % 4
    		ox = random.randint(1, WIDTH - 2)
    		oy = random.randint(1, HEIGHT - 2)
    		while not through((ox, oy)):
    			ox = random.randint(1, WIDTH - 2)
    			oy = random.randint(1, HEIGHT - 2)
    		unit_list.append(enemy(enemy_color, ox, oy))
    		pass
    	pass
    
    #initialize
    def initialize():
    	global scene
    	load_map(MAP_NAME)
    	initialize_unit()
    	scene = "game"
    	pygame.mixer.music.play(-1)
    
    #system update
    def system_update():
    	clock.tick(FPS)
    	for event in pygame.event.get():
    		if event.type == pygame.QUIT:
    			sys.exit()
    	pass
    
    #update control
    control_clock = [0, DELAY]
    def control_update():
    	#user control
    	if control_clock[0] > control_clock[1]:
    		user = unit_list[0]
    		keys = pygame.key.get_pressed()
    		passport = False
    		pos = user.position
    		if keys[K_UP]: 
    			pos = user.move(through(user.next(0)))
    		elif keys[K_RIGHT]: 
    			pos = user.move(through(user.next(1)))
    		elif keys[K_DOWN]:
    			pos = user.move(through(user.next(2)))
    		elif keys[K_LEFT]:
    			pos = user.move(through(user.next(3)))
    			pass
    		game_map[pos[1]][pos[0]] = '0'
    		#enemy control
    		u_pos = unit_list[0].position
    		for index in range(1, len(unit_list)):
    			enemy = unit_list[index]
    			if check_gameover(u_pos, enemy.position): break
    			enemy.track(u_pos)
    			passport = through(enemy.next())
    			enemy.move(passport)
    			while not passport:
    				enemy.clockwise()
    				passport = through(enemy.next())
    				enemy.move(passport)
    			pass
    		control_clock[0] = 0
    		pass
    	else:
    		control_clock[0] += 1
    		pass
    	pass
    
    #update screen
    def screen_update():
    	display.fill((0, 0, 0))
    	for i in range(0, HEIGHT):
    		for j in range(0, WIDTH):
    			x = j * BLOCK_SIZE
    			y = i * BLOCK_SIZE
    			if game_map[i][j] == '1':
    				display.blit(block_image, (x, y))
    			elif game_map[i][j] == '4':
    				display.blit(food_image, (x, y))
    				pass
    			pass
    		pass
    	for unit in unit_list:
    		unit.update()
    		x = unit.position[0] * BLOCK_SIZE
    		y = unit.position[1] * BLOCK_SIZE
    		display.blit(unit.image, (x, y), unit.image_rect())
    	pygame.display.update()
    	pass
    
    #first
    initialize()
    
    #main loop
    while True:
    	system_update()
    	if scene == "game":
    		control_update()
    		screen_update()
    	else:
    		gameover()
    		pass
    	pass

    unit.py

    import pygame
    import math
    import random
    
    USER_IMAGE = "./material/user.png"
    ENEMY_IMAGE = [("./material/enemy%d.png" % i) for i in range(1, 5)]
    
    class unit():
    	def __init__(self, filename):
    		super(unit, self).__init__()
    		self.image = pygame.image.load(filename)
    		self.clock = [0, 5]
    		self.direction = 0
    		self.position = [1, 1, 1, 1]
    		self.index = 0
    		self.source_rect = 0
    		pass
    
    	def update(self):
    		self.animation_update()
    		pass
    
    	def animation_update(self):
    		self.clock[0] += 1
    		if self.clock[0] > self.clock[1]:
    			if self.index < 4:
    				self.index += 4
    			else:
    				self.index -= 4
    			self.source_rect = self.image_rect()
    			self.clock[0] = 0
    			pass
    		pass
    
    	def move(self, passport):
    		if passport:
    			pos = self.position[:]
    			self.position[0] = self.position[2]
    			self.position[1] = self.position[3]
    		else:
    			self.position[2] = self.position[0]
    			self.position[3] = self.position[1]
    			pos = self.position
    			pass
    		return pos
    		pass
    
    	def next(self):
    		self.ahead()
    		return (self.position[2], self.position[3])
    		pass
    
    	def turn(self, direction):
    		self.direction = direction % 4
    		self.index = self.direction
    		pass
    
    	def ahead(self):
    		if self.direction == 0:
    			self.position[3] -= 1
    		elif self.direction == 1:
    			self.position[2] += 1
    		elif self.direction == 2:
    			self.position[3] += 1
    		elif self.direction  == 3:
    			self.position[2] -= 1
    		pass
    
    	def image_rect(self):
    		w = self.image.get_width()
    		h = self.image.get_height()
    		ox = math.floor(w / 4 * (self.index % 4)) 
    		oy = math.floor(h / 2 * math.floor(self.index / 4))
    		return pygame.Rect((ox, oy), (24, 24))
    
    class user(unit):
    	def __init__(self, x, y):
    		super(user, self).__init__(USER_IMAGE)
    		self.position = [x, y, x, y]
    		pass
    
    	def next(self, direction):
    		self.turn(direction)
    		self.ahead()
    		return (self.position[2], self.position[3])
    		pass
    
    class enemy(unit):
    	def __init__(self, id, x, y):
    		filename = ENEMY_IMAGE[id]
    		super(enemy, self).__init__(filename)
    		self.position = [x, y, x, y]
    		pass
    
    	def track(self, user_pos):
    		rand_dir = [1,2,3,4]
    		self.turn(random.choice(rand_dir))
    		pass
    
    	def clockwise(self):
    		self.turn(self.direction + 1)
    		pass
    
    class enemy_user(unit):
    	def __init__(self, x, y):
    		filename = ENEMY_IMAGE[0]
    		super(enemy_user, self).__init__(filename)
    		self.position = [x, y, x, y]
    		pass
    
    	def move(self, x, y):
    		self.position[0] = x
    		self.position[1] = y
    		pass

    总结:

    程序还有许多地方可以完善,如怪物的AI,时间的判定等等,有兴趣的大佬可以加以修改完善。

    完整项目下载:https://github.com/tinytsunami/Python-Game

    js
    下一篇:没有了