龙空技术网

Python 玩出花了!一文教你用 Python 制作吃豆人游戏!| 附代码

CSDN 171

前言:

眼前看官们对“基于python的游戏开发”大致比较注重,兄弟们都想要知道一些“基于python的游戏开发”的相关资讯。那么小编也在网络上汇集了一些有关“基于python的游戏开发””的相关内容,希望看官们能喜欢,各位老铁们快快来了解一下吧!

作者 | 李秋键

责编 | Carol

封图 | CSDN 下载自视觉中国

近几年来Python语言得到了快速发展,而Pygame作为Python开发应用和游戏必备的库更是展现了Python的优越性。

而今天我们就将借助Pygame建立吃豆人游戏。

吃豆人是电子游戏历史上的经典街机游戏,由Namco公司的岩谷彻设计并由Midway Games在1980年发行

。Pac-Man被认为是80年代最经典的街机游戏之一,游戏的主角小精灵的形象甚至被作为一种大众文化符号,或是此产业的代表形象。

而Pygame模块是跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。

最终游戏效果如下可见:

实验前的准备

首先我们使用的python版本是3.6.5所用到的模块是pygame模块,用来创建游戏框架。Random模块用来随机生成方向。

素材准备首先我们将图片放到images目录下,背景音乐放到sounds目录下。

如下图可见:

游戏搭建

1、定义一些精灵:整体的类变量定义包括墙类,通过pygame的图片填充作为墙类的加载;同理还包括食物类和角色。而怪物的随机运动使用random产生随机运动方向。

其对应的代码如下:

import random

import pygame

'''墙类'''

class Wall(pygame.sprite.Sprite):

def __init__(self, x, y, width, height, color, **kwargs):

pygame.sprite.Sprite.__init__(self)

self.image = pygame.Surface([width, height])

self.image.fill(color)

self.rect = self.image.get_rect

self.rect.left = x

self.rect.top = y

'''食物类'''

class Food(pygame.sprite.Sprite):

def __init__(self, x, y, width, height, color, bg_color, **kwargs):

pygame.sprite.Sprite.__init__(self)

self.image = pygame.Surface([width, height])

self.image.fill(bg_color)

self.image.set_colorkey(bg_color)

pygame.draw.ellipse(self.image, color, [0, 0, width, height])

self.rect = self.image.get_rect

self.rect.left = x

self.rect.top = y

'''角色类'''

class Player(pygame.sprite.Sprite):

def __init__(self, x, y, role_image_path):

pygame.sprite.Sprite.__init__(self)

self.role_name = role_image_path.split('/')[-1].split('.')[0]

self.base_image = pygame.image.load(role_image_path).convert

self.image = self.base_image.copy

self.rect = self.image.get_rect

self.rect.left = x

self.rect.top = y

self.prev_x = x

self.prev_y = y

self.base_speed = [30, 30]

self.speed = [0, 0]

self.is_move = False

self.tracks =

self.tracks_loc = [0, 0]

'''改变速度方向'''

def changeSpeed(self, direction):

if direction[0] < 0:

self.image = pygame.transform.flip(self.base_image, True, False)

elif direction[0] > 0:

self.image = self.base_image.copy

elif direction[1] < 0:

self.image = pygame.transform.rotate(self.base_image, 90)

elif direction[1] > 0:

self.image = pygame.transform.rotate(self.base_image, -90)

self.speed = [direction[0] * self.base_speed[0], direction[1] * self.base_speed[1]]

return self.speed

'''更新角色位置'''

def update(self, wall_sprites, gate_sprites):

if not self.is_move:

return False

x_prev = self.rect.left

y_prev = self.rect.top

self.rect.left += self.speed[0]

self.rect.top += self.speed[1]

is_collide = pygame.sprite.spritecollide(self, wall_sprites, False)

if gate_sprites is not None:

if not is_collide:

is_collide = pygame.sprite.spritecollide(self, gate_sprites, False)

if is_collide:

self.rect.left = x_prev

self.rect.top = y_prev

return False

return True

'''生成随机的方向'''

def randomDirection(self):

return random.choice([[-0.5, 0], [0.5, 0], [0, 0.5], [0, -0.5]])

2、游戏关卡定义:

在这里设置好了关卡一。关卡的定义必须包括墙的位置,不同关卡墙的位置和怪物的位置不同。更多关卡可以参照设置

对应代码如下:

import pygame

from Sprites import *

NUMLEVELS = 1

'''关卡一'''

class Level1:

def __init__(self):

self.info = 'level1'

'''创建墙'''

def setupWalls(self, wall_color):

self.wall_sprites = pygame.sprite.Group

wall_positions = [[0, 0, 6, 600],

[0, 0, 600, 6],

[0, 600, 606, 6],

[600, 0, 6, 606],

[300, 0, 6, 66],

[60, 60, 186, 6],

[360, 60, 186, 6],

[60, 120, 66, 6],

[60, 120, 6, 126],

[180, 120, 246, 6],

[300, 120, 6, 66],

[480, 120, 66, 6],

[540, 120, 6, 126],

[120, 180, 126, 6],

[120, 180, 6, 126],

[360, 180, 126, 6],

[480, 180, 6, 126],

[180, 240, 6, 126],

[180, 360, 246, 6],

[420, 240, 6, 126],

[240, 240, 42, 6],

[324, 240, 42, 6],

[240, 240, 6, 66],

[240, 300, 126, 6],

[360, 240, 6, 66],

[0, 300, 66, 6],

[540, 300, 66, 6],

[60, 360, 66, 6],

[60, 360, 6, 186],

[480, 360, 66, 6],

[540, 360, 6, 186],

[120, 420, 366, 6],

[120, 420, 6, 66],

[480, 420, 6, 66],

[180, 480, 246, 6],

[300, 480, 6, 66],

[120, 540, 126, 6],

[360, 540, 126, 6]]

for wall_position in wall_positions:

wall = Wall(*wall_position, wall_color)

self.wall_sprites.add(wall)

return self.wall_sprites

'''创建门'''

def setupGate(self, gate_color):

self.gate_sprites = pygame.sprite.Group

self.gate_sprites.add(Wall(282, 242, 42, 2, gate_color))

return self.gate_sprites

'''创建角色'''

def setupPlayers(self, hero_image_path, ghost_images_path):

self.hero_sprites = pygame.sprite.Group

self.ghost_sprites = pygame.sprite.Group

self.hero_sprites.add(Player(287, 439, hero_image_path))

for each in ghost_images_path:

role_name = each.split('/')[-1].split('.')[0]

if role_name == 'Blinky':

player = Player(287, 199, each)

player.is_move = True

player.tracks = [[0, -0.5, 4], [0.5, 0, 9], [0, 0.5, 11], [0.5, 0, 3], [0, 0.5, 7], [-0.5, 0, 11], [0, 0.5, 3],

[0.5, 0, 15], [0, -0.5, 15], [0.5, 0, 3], [0, -0.5, 11], [-0.5, 0, 3], [0, -0.5, 11], [-0.5, 0, 3],

[0, -0.5, 3], [-0.5, 0, 7], [0, -0.5, 3], [0.5, 0, 15], [0, 0.5, 15], [-0.5, 0, 3], [0, 0.5, 3],

[-0.5, 0, 3], [0, -0.5, 7], [-0.5, 0, 3], [0, 0.5, 7], [-0.5, 0, 11], [0, -0.5, 7], [0.5, 0, 5]]

self.ghost_sprites.add(player)

elif role_name == 'Clyde':

player = Player(319, 259, each)

player.is_move = True

player.tracks = [[-1, 0, 2], [0, -0.5, 4], [0.5, 0, 5], [0, 0.5, 7], [-0.5, 0, 11], [0, -0.5, 7],

[-0.5, 0, 3], [0, 0.5, 7], [-0.5, 0, 7], [0, 0.5, 15], [0.5, 0, 15], [0, -0.5, 3],

[-0.5, 0, 11], [0, -0.5, 7], [0.5, 0, 3], [0, -0.5, 11], [0.5, 0, 9]]

self.ghost_sprites.add(player)

elif role_name == 'Inky':

player = Player(255, 259, each)

player.is_move = True

player.tracks = [[1, 0, 2], [0, -0.5, 4], [0.5, 0, 10], [0, 0.5, 7], [0.5, 0, 3], [0, -0.5, 3],

[0.5, 0, 3], [0, -0.5, 15], [-0.5, 0, 15], [0, 0.5, 3], [0.5, 0, 15], [0, 0.5, 11],

[-0.5, 0, 3], [0, -0.5, 7], [-0.5, 0, 11], [0, 0.5, 3], [-0.5, 0, 11], [0, 0.5, 7],

[-0.5, 0, 3], [0, -0.5, 3], [-0.5, 0, 3], [0, -0.5, 15], [0.5, 0, 15], [0, 0.5, 3],

[-0.5, 0, 15], [0, 0.5, 11], [0.5, 0, 3], [0, -0.5, 11], [0.5, 0, 11], [0, 0.5, 3], [0.5, 0, 1]]

self.ghost_sprites.add(player)

elif role_name == 'Pinky':

player = Player(287, 259, each)

player.is_move = True

player.tracks = [[0, -1, 4], [0.5, 0, 9], [0, 0.5, 11], [-0.5, 0, 23], [0, 0.5, 7], [0.5, 0, 3],

[0, -0.5, 3], [0.5, 0, 19], [0, 0.5, 3], [0.5, 0, 3], [0, 0.5, 3], [0.5, 0, 3],

[0, -0.5, 15], [-0.5, 0, 7], [0, 0.5, 3], [-0.5, 0, 19], [0, -0.5, 11], [0.5, 0, 9]]

self.ghost_sprites.add(player)

return self.hero_sprites, self.ghost_sprites

'''创建食物'''

def setupFood(self, food_color, bg_color):

self.food_sprites = pygame.sprite.Group

for row in range(19):

for col in range(19):

if (row == 7 or row == 8) and (col == 8 or col == 9 or col == 10):

continue

else:

food = Food(30*col+32, 30*row+32, 4, 4, food_color, bg_color)

is_collide = pygame.sprite.spritecollide(food, self.wall_sprites, False)

if is_collide:

continue

is_collide = pygame.sprite.spritecollide(food, self.hero_sprites, False)

if is_collide:

continue

self.food_sprites.add(food)

return self.food_sprites

3、游戏创建:在通过关卡定义墙等位置后以及精灵自身属性怪物运动、食物定义等后,通过调用已经创建好的类达到搭建游戏的目的。

具体如下可见:

import os

import sys

import pygame

import Levels

'''定义一些必要的参数'''

BLACK = (0, 0, 0)

WHITE = (255, 255, 255)

BLUE = (0, 0, 255)

GREEN = (0, 255, 0)

RED = (255, 0, 0)

YELLOW = (255, 255, 0)

PURPLE = (255, 0, 255)

SKYBLUE = (0, 191, 255)

BGMPATH = os.path.join(os.getcwd, 'resources/sounds/bg.mp3')

ICONPATH = os.path.join(os.getcwd, 'resources/images/icon.png')

FONTPATH = os.path.join(os.getcwd, 'resources/font/ALGER.TTF')

HEROPATH = os.path.join(os.getcwd, 'resources/images/pacman.png')

BlinkyPATH = os.path.join(os.getcwd, 'resources/images/Blinky.png')

ClydePATH = os.path.join(os.getcwd, 'resources/images/Clyde.png')

InkyPATH = os.path.join(os.getcwd, 'resources/images/Inky.png')

PinkyPATH = os.path.join(os.getcwd, 'resources/images/Pinky.png')

'''开始某一关游戏'''

def startLevelGame(level, screen, font):

clock = pygame.time.Clock

SCORE = 0

wall_sprites = level.setupWalls(SKYBLUE)

gate_sprites = level.setupGate(WHITE)

hero_sprites, ghost_sprites = level.setupPlayers(HEROPATH, [BlinkyPATH, ClydePATH, InkyPATH, PinkyPATH])

food_sprites = level.setupFood(YELLOW, WHITE)

is_clearance = False

while True:

for event in pygame.event.get:

if event.type == pygame.QUIT:

sys.exit(-1)

pygame.quit

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_LEFT:

for hero in hero_sprites:

hero.changeSpeed([-1, 0])

hero.is_move = True

elif event.key == pygame.K_RIGHT:

for hero in hero_sprites:

hero.changeSpeed([1, 0])

hero.is_move = True

elif event.key == pygame.K_UP:

for hero in hero_sprites:

hero.changeSpeed([0, -1])

hero.is_move = True

elif event.key == pygame.K_DOWN:

for hero in hero_sprites:

hero.changeSpeed([0, 1])

hero.is_move = True

if event.type == pygame.KEYUP:

if (event.key == pygame.K_LEFT) or (event.key == pygame.K_RIGHT) or (event.key == pygame.K_UP) or (event.key == pygame.K_DOWN):

hero.is_move = False

screen.fill(BLACK)

for hero in hero_sprites:

hero.update(wall_sprites, gate_sprites)

hero_sprites.draw(screen)

for hero in hero_sprites:

food_eaten = pygame.sprite.spritecollide(hero, food_sprites, True)

SCORE += len(food_eaten)

wall_sprites.draw(screen)

gate_sprites.draw(screen)

food_sprites.draw(screen)

for ghost in ghost_sprites:

# 幽灵随机运动(效果不好且有BUG)

'''

res = ghost.update(wall_sprites, None)

while not res:

ghost.changeSpeed(ghost.randomDirection)

res = ghost.update(wall_sprites, None)

'''

# 指定幽灵运动路径

if ghost.tracks_loc[1] < ghost.tracks[ghost.tracks_loc[0]][2]:

ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])

ghost.tracks_loc[1] += 1

else:

if ghost.tracks_loc[0] < len(ghost.tracks) - 1:

ghost.tracks_loc[0] += 1

elif ghost.role_name == 'Clyde':

ghost.tracks_loc[0] = 2

else:

ghost.tracks_loc[0] = 0

ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])

ghost.tracks_loc[1] = 0

if ghost.tracks_loc[1] < ghost.tracks[ghost.tracks_loc[0]][2]:

ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])

else:

if ghost.tracks_loc[0] < len(ghost.tracks) - 1:

loc0 = ghost.tracks_loc[0] + 1

elif ghost.role_name == 'Clyde':

loc0 = 2

else:

loc0 = 0

ghost.changeSpeed(ghost.tracks[loc0][0: 2])

ghost.update(wall_sprites, None)

ghost_sprites.draw(screen)

score_text = font.render("Score: %s" % SCORE, True, RED)

screen.blit(score_text, [10, 10])

if len(food_sprites) == 0:

is_clearance = True

break

if pygame.sprite.groupcollide(hero_sprites, ghost_sprites, False, False):

is_clearance = False

break

pygame.display.flip

clock.tick(10)

return is_clearance

'''显示文字'''

def showText(screen, font, is_clearance, flag=False):

clock = pygame.time.Clock

msg = 'Game Over!' if not is_clearance else 'Congratulations, you won!'

positions = [[235, 233], [65, 303], [170, 333]] if not is_clearance else [[145, 233], [65, 303], [170, 333]]

surface = pygame.Surface((400, 200))

surface.set_alpha(10)

surface.fill((128, 128, 128))

screen.blit(surface, (100, 200))

texts = [font.render(msg, True, WHITE),

font.render('Press ENTER to continue or play again.', True, WHITE),

font.render('Press ESCAPE to quit.', True, WHITE)]

while True:

for event in pygame.event.get:

if event.type == pygame.QUIT:

sys.exit

pygame.quit

if event.type == pygame.KEYDOWN:

if event.key == pygame.K_RETURN:

if is_clearance:

if not flag:

return

else:

main(initialize)

else:

main(initialize)

elif event.key == pygame.K_ESCAPE:

sys.exit

pygame.quit

for idx, (text, position) in enumerate(zip(texts, positions)):

screen.blit(text, position)

pygame.display.flip

clock.tick(10)

'''初始化'''

def initialize:

pygame.init

icon_image = pygame.image.load(ICONPATH)

pygame.display.set_icon(icon_image)

screen = pygame.display.set_mode([606, 606])

pygame.display.set_caption('吃豆人')

return screen

'''主函数'''

def main(screen):

pygame.mixer.init

pygame.mixer.music.load(BGMPATH)

pygame.mixer.music.play(-1, 0.0)

pygame.font.init

font_small = pygame.font.Font(FONTPATH, 18)

font_big = pygame.font.Font(FONTPATH, 24)

for num_level in range(1, Levels.NUMLEVELS+1):

if num_level == 1:

level = Levels.Level1

is_clearance = startLevelGame(level, screen, font_small)

if num_level == Levels.NUMLEVELS:

showText(screen, font_big, is_clearance, True)

else:

showText(screen, font_big, is_clearance)

最终运行程序结果如下:

源码地址:

提取码:rj9f

作者简介:

李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等等。

标签: #基于python的游戏开发 #python编程小游戏 #python怎么玩 #怎样用python做游戏 #用python做一个游戏