大家好,我是Lex 喜欢欺负超人那个Lex
划重点:
1、python开发小游戏,pygame环境搭建;
2、给失眠的小姐姐开发一个迷宫小游戏。
代码干货满满,建议收藏+实操!!!有问题及需要,请留言哦~~
事情是这样的
半夜听到隔壁来来回回 ,忙忙碌碌的声音
我这么心思细腻 体贴入微的python小哥哥
敏锐的感觉到
小姐姐肯定是失眠了
好担心哦,我都睡不着了呢
辗转反侧
最后爬起来撸出了我的python代码
一、环境要求
-
windows系统,python3.6+
-
-
安装游戏依赖模块
-
-
pip install pyqt5
-
-
pip install pygame
二、游戏介绍
1、游戏目标
随机生成一张迷宫地图,将玩家设置在迷宫内部,通过光标 上 下 左 右,来移动玩家,按照迷宫地图的道路来走出迷宫。
2、先上游戏效果图
三、完整开发流程
1、项目主结构
首先,先整理一下项目的主结构,其实看一下主结构,基本就清晰了
-
modules:存放自己写的
python类
-
——
mazes
.py
-
——
misc
.py
-
——
sprites
.py
-
-
resources:存放引用到的图片、音频等等
-
——
audios:音频资源
-
——
images:图片资源
-
-
config
.py:为主配置文件
-
-
maze
.py:主程序文件
-
-
requirements
.txt:需要引入的
python依赖包
2、详细配置
config.py
配置文件中,需要引入os模块,并且配置打开游戏的屏幕大小,并将资源中引用到的图片、音频插入到合适的位置。
因为我们的迷宫游戏,需要划开模块。
-
''
'配置文件'
''
-
import os
-
-
-
''
'屏幕大小'
''
-
SCREENSIZE = (800, 625)
-
''
'游戏素材'
''
-
BGMPATH = os.path.join(os.getcwd(),
'resources/audios/bgm.mp3')
-
HEROPICPATH = os.path.join(os.getcwd(),
'resources/images/hero.png')
-
''
'FPS'
''
-
FPS = 20
-
''
'块大小'
''
-
BLOCKSIZE = 15
-
MAZESIZE = (35, 50)
# num_rows * num_cols
-
BORDERSIZE = (25, 50)
# 25 * 2 + 50 * 15 = 800, 50 * 2 + 35 * 15 = 625
3、随机生成迷宫地图
mazes.py
迷宫虽然是个小游戏,但是我们每次打开,进入 地图需要随机生成一个新地图。
定义randommaze 随机生成地图,并将地图投在主游戏屏幕上
-
'''
-
Function:
-
随机生成迷宫
-
Author:
-
lexsaints
-
'''
-
import pygame
-
import random
-
from .misc
import *
-
-
-
'''一个游戏地图块'''
-
class Block():
-
def __init__(self, coordinate, block_size, border_size, **kwargs):
-
# (col, row)
-
self.coordinate = coordinate
-
self.block_size = block_size
-
self.border_size = border_size
-
self.is_visited =
False
-
# 上下左右有没有墙
-
self.has_walls = [
True,
True,
True,
True]
-
self.color = (
0,
0,
0)
-
'''画到屏幕上'''
-
def draw(self, screen):
-
directions = [
'top',
'bottom',
'left',
'right']
-
for idx, direction
in enumerate(directions):
-
if self.has_walls[idx]:
-
if direction ==
'top':
-
x1 = self.coordinate[
0] * self.block_size + self.border_size[
0]
-
y1 = self.coordinate[
1] * self.block_size + self.border_size[
1]
-
x2 = (self.coordinate[
0] +
1) * self.block_size + self.border_size[
0]
-
y2 = self.coordinate[
1] * self.block_size + self.border_size[
1]
-
pygame.draw.line(screen, self.color, (x1, y1), (x2, y2))
-
elif direction ==
'bottom':
-
x1 = self.coordinate[
0] * self.block_size + self.border_size[
0]
-
y1 = (self.coordinate[
1] +
1) * self.block_size + self.border_size[
1]
-
x2 = (self.coordinate[
0] +
1) * self.block_size + self.border_size[
0]
-
y2 = (self.coordinate[
1] +
1) * self.block_size + self.border_size[
1]
-
pygame.draw.line(screen, self.color, (x1, y1), (x2, y2))
-
elif direction ==
'left':
-
x1 = self.coordinate[
0] * self.block_size + self.border_size[
0]
-
y1 = self.coordinate[
1] * self.block_size + self.border_size[
1]
-
x2 = self.coordinate[
0] * self.block_size + self.border_size[
0]
-
y2 = (self.coordinate[
1] +
1) * self.block_size + self.border_size[
1]
-
pygame.draw.line(screen, self.color, (x1, y1), (x2, y2))
-
elif direction ==
'right':
-
x1 = (self.coordinate[
0] +
1) * self.block_size + self.border_size[
0]
-
y1 = self.coordinate[
1] * self.block_size + self.border_size[
1]
-
x2 = (self.coordinate[
0] +
1) * self.block_size + self.border_size[
0]
-
y2 = (self.coordinate[
1] +
1) * self.block_size + self.border_size[
1]
-
pygame.draw.line(screen, self.color, (x1, y1), (x2, y2))
-
return
True
-
-
-
'''随机生成迷宫类'''
-
class RandomMaze():
-
def __init__(self, maze_size, block_size, border_size, **kwargs):
-
self.block_size = block_size
-
self.border_size = border_size
-
self.maze_size = maze_size
-
self.blocks_list = RandomMaze.createMaze(maze_size, block_size, border_size)
-
self.font = pygame.font.SysFont(
'Consolas',
15)
-
'''画到屏幕上'''
-
def draw(self, screen):
-
for row
in range(self.maze_size[
0]):
-
for col
in range(self.maze_size[
1]):
-
self.blocks_list[row][col].draw(screen)
-
# 起点和终点标志
-
showText(screen, self.font,
'S', (
255,
0,
0), (self.border_size[
0]
-10, self.border_size[
1]))
-
showText(screen, self.font,
'D', (
255,
0,
0), (self.border_size[
0]+(self.maze_size[
1]
-1)*self.block_size, self.border_size[
1]+self.maze_size[
0]*self.block_size+
5))
-
'''创建迷宫'''
-
@staticmethod
-
def createMaze(maze_size, block_size, border_size):
-
def nextBlock(block_now, blocks_list):
-
directions = [
'top',
'bottom',
'left',
'right']
-
blocks_around = dict(zip(directions, [
None]*
4))
-
block_next =
None
-
count =
0
-
# 查看上边block
-
if block_now.coordinate[
1]
-1 >=
0:
-
block_now_top = blocks_list[block_now.coordinate[
1]
-1][block_now.coordinate[
0]]
-
if
not block_now_top.is_visited:
-
blocks_around[
'top'] = block_now_top
-
count +=
1
-
# 查看下边block
-
if block_now.coordinate[
1]+
1 < maze_size[
0]:
-
block_now_bottom = blocks_list[block_now.coordinate[
1]+
1][block_now.coordinate[
0]]
-
if
not block_now_bottom.is_visited:
-
blocks_around[
'bottom'] = block_now_bottom
-
count +=
1
-
# 查看左边block
-
if block_now.coordinate[
0]
-1 >=
0:
-
block_now_left = blocks_list[block_now.coordinate[
1]][block_now.coordinate[
0]
-1]
-
if
not block_now_left.is_visited:
-
blocks_around[
'left'] = block_now_left
-
count +=
1
-
# 查看右边block
-
if block_now.coordinate[
0]+
1 < maze_size[
1]:
-
block_now_right = blocks_list[block_now.coordinate[
1]][block_now.coordinate[
0]+
1]
-
if
not block_now_right.is_visited:
-
blocks_around[
'right'] = block_now_right
-
count +=
1
-
if count >
0:
-
while
True:
-
direction = random.choice(directions)
-
if blocks_around.get(direction):
-
block_next = blocks_around.get(direction)
-
if direction ==
'top':
-
block_next.has_walls[
1] =
False
-
block_now.has_walls[
0] =
False
-
elif direction ==
'bottom':
-
block_next.has_walls[
0] =
False
-
block_now.has_walls[
1] =
False
-
elif direction ==
'left':
-
block_next.has_walls[
3] =
False
-
block_now.has_walls[
2] =
False
-
elif direction ==
'right':
-
block_next.has_walls[
2] =
False
-
block_now.has_walls[
3] =
False
-
break
-
return block_next
-
blocks_list = [[Block([col, row], block_size, border_size)
for col
in range(maze_size[
1])]
for row
in range(maze_size[
0])]
-
block_now = blocks_list[
0][
0]
-
records = []
-
while
True:
-
if block_now:
-
if
not block_now.is_visited:
-
block_now.is_visited =
True
-
records.append(block_now)
-
block_now = nextBlock(block_now, blocks_list)
-
else:
-
block_now = records.pop()
-
if len(records) ==
0:
-
break
-
return blocks_list
4、光标控制玩家
misc.py
通过读取键盘的上下左右光标来移动我们的小可爱
-
'''
-
Function:
-
定义其他必要模块
-
Author:
-
lexsaints
-
'''
-
import sys
-
import pygame
-
-
-
'''在屏幕指定位置显示文字'''
-
def showText(screen, font, text, color, position):
-
text_render = font.render(text,
True, color)
-
rect = text_render.get_rect()
-
rect.left, rect.top = position
-
screen.blit(text_render, rect)
-
return rect.right
-
-
-
'''按钮'''
-
def Button(screen, position, text, font, buttoncolor=(120, 120, 120), linecolor=(20, 20, 20), textcolor=(255, 255, 255), bwidth=200, bheight=50):
-
left, top = position
-
pygame.draw.line(screen, linecolor, (left, top), (left+bwidth, top),
5)
-
pygame.draw.line(screen, linecolor, (left, top
-2), (left, top+bheight),
5)
-
pygame.draw.line(screen, linecolor, (left, top+bheight), (left+bwidth, top+bheight),
5)
-
pygame.draw.line(screen, linecolor, (left+bwidth, top+bheight), (left+bwidth, top),
5)
-
pygame.draw.rect(screen, buttoncolor, (left, top, bwidth, bheight))
-
text_render = font.render(text,
1, textcolor)
-
rect = text_render.get_rect()
-
rect.centerx, rect.centery = left + bwidth /
2, top + bheight /
2
-
return screen.blit(text_render, rect)
-
-
-
'''游戏开始/关卡切换/游戏结束界面'''
-
def Interface(screen, config, mode='game_start'):
-
pygame.display.set_mode(config.SCREENSIZE)
-
font = pygame.font.SysFont(
'Consolas',
30)
-
if mode ==
'game_start':
-
clock = pygame.time.Clock()
-
while
True:
-
screen.fill((
192,
192,
192))
-
button_1 = Button(screen, ((config.SCREENSIZE[
0]
-200)//
2, config.SCREENSIZE[
1]//
3),
'START', font)
-
button_2 = Button(screen, ((config.SCREENSIZE[
0]
-200)//
2, config.SCREENSIZE[
1]//
2),
'QUIT', font)
-
for event
in pygame.event.get():
-
if event.type == pygame.QUIT:
-
pygame.quit()
-
sys.exit(
-1)
-
elif event.type == pygame.MOUSEBUTTONDOWN:
-
if button_1.collidepoint(pygame.mouse.get_pos()):
-
return
True
-
elif button_2.collidepoint(pygame.mouse.get_pos()):
-
pygame.quit()
-
sys.exit(
-1)
-
pygame.display.update()
-
clock.tick(config.FPS)
-
elif mode ==
'game_switch':
-
clock = pygame.time.Clock()
-
while
True:
-
screen.fill((
192,
192,
192))
-
button_1 = Button(screen, ((config.SCREENSIZE[
0]
-200)//
2, config.SCREENSIZE[
1]//
3),
'NEXT', font)
-
button_2 = Button(screen, ((config.SCREENSIZE[
0]
-200)//
2, config.SCREENSIZE[
1]//
2),
'QUIT', font)
-
for event
in pygame.event.get():
-
if event.type == pygame.QUIT:
-
pygame.quit()
-
sys.exit(
-1)
-
elif event.type == pygame.MOUSEBUTTONDOWN:
-
if button_1.collidepoint(pygame.mouse.get_pos()):
-
return
True
-
elif button_2.collidepoint(pygame.mouse.get_pos()):
-
pygame.quit()
-
sys.exit(
-1)
-
pygame.display.update()
-
clock.tick(config.FPS)
-
elif mode ==
'game_end':
-
clock = pygame.time.Clock()
-
while
True:
-
screen.fill((
192,
192,
192))
-
button_1 = Button(screen, ((config.SCREENSIZE[
0]
-200)//
2, config.SCREENSIZE[
1]//
3),
'RESTART', font)
-
button_2 = Button(screen, ((config.SCREENSIZE[
0]
-200)//
2, config.SCREENSIZE[
1]//
2),
'QUIT', font)
-
for event
in pygame.event.get():
-
if event.type == pygame.QUIT:
-
pygame.quit()
-
sys.exit(
-1)
-
elif event.type == pygame.MOUSEBUTTONDOWN:
-
if button_1.collidepoint(pygame.mouse.get_pos()):
-
return
True
-
elif button_2.collidepoint(pygame.mouse.get_pos()):
-
pygame.quit()
-
sys.exit(
-1)
-
pygame.display.update()
-
clock.tick(config.FPS)
-
else:
-
raise ValueError(
'Interface.mode unsupport %s...' % mode)
5、定义主玩家 绘制全图
绘制完整游戏,并定义主角,就叫hero吧
sprites.py
-
'''
-
Function:
-
定义游戏精灵类
-
Author:
-
lexsaints
-
'''
-
import pygame
-
-
-
'''定义hero'''
-
class Hero(pygame.sprite.Sprite):
-
def __init__(self, imagepath, coordinate, block_size, border_size, **kwargs):
-
pygame.sprite.Sprite.__init__(self)
-
self.image = pygame.image.load(imagepath)
-
self.image = pygame.transform.scale(self.image, (block_size, block_size))
-
self.rect = self.image.get_rect()
-
self.rect.left, self.rect.top = coordinate[
0] * block_size + border_size[
0], coordinate[
1] * block_size + border_size[
1]
-
self.coordinate = coordinate
-
self.block_size = block_size
-
self.border_size = border_size
-
'''移动'''
-
def move(self, direction, maze):
-
blocks_list = maze.blocks_list
-
if direction ==
'up':
-
if blocks_list[self.coordinate[
1]][self.coordinate[
0]].has_walls[
0]:
-
return
False
-
else:
-
self.coordinate[
1] = self.coordinate[
1] -
1
-
return
True
-
elif direction ==
'down':
-
if blocks_list[self.coordinate[
1]][self.coordinate[
0]].has_walls[
1]:
-
return
False
-
else:
-
self.coordinate[
1] = self.coordinate[
1] +
1
-
return
True
-
elif direction ==
'left':
-
if blocks_list[self.coordinate[
1]][self.coordinate[
0]].has_walls[
2]:
-
return
False
-
else:
-
self.coordinate[
0] = self.coordinate[
0] -
1
-
return
True
-
elif direction ==
'right':
-
if blocks_list[self.coordinate[
1]][self.coordinate[
0]].has_walls[
3]:
-
return
False
-
else:
-
self.coordinate[
0] = self.coordinate[
0] +
1
-
return
True
-
else:
-
raise ValueError(
'Unsupport direction %s in Hero.move...' % direction)
-
'''绑定到屏幕'''
-
def draw(self, screen):
-
self.rect.left, self.rect.top = self.coordinate[
0] * self.block_size + self.border_size[
0], self.coordinate[
1] * self.block_size + self.border_size[
1]
-
screen.blit(self.image, self.rect)
6、引入音频、图片
启动游戏主程序
maze.py
在主程序中,通过读取配置文件,引入项目资源:包括图片、音频等,并通过定义类,加载游戏地图
-
'''
-
Function:
-
迷宫小游戏
-
Author:
-
lexsaints
-
'''
-
import config
-
import sys
-
import pygame
-
from modules
import *
-
-
-
'''主函数'''
-
def main(config):
-
# 初始化
-
pygame.init()
-
pygame.mixer.init()
-
pygame.font.init()
-
pygame.mixer.music.load(config.BGMPATH)
-
pygame.mixer.music.play(
-1,
0.0)
-
screen = pygame.display.set_mode(config.SCREENSIZE)
-
pygame.display.set_caption(
'一起来学pygame吧——迷宫')
-
font = pygame.font.SysFont(
'Consolas',
15)
-
# 开始界面
-
Interface(screen, config,
'game_start')
-
# 记录关卡数
-
num_levels =
0
-
# 记录最少用了多少步通关
-
best_scores =
'None'
-
# 关卡循环切换
-
while
True:
-
num_levels +=
1
-
clock = pygame.time.Clock()
-
screen = pygame.display.set_mode(config.SCREENSIZE)
-
# --随机生成关卡地图
-
maze_now = RandomMaze(config.MAZESIZE, config.BLOCKSIZE, config.BORDERSIZE)
-
# --生成hero
-
hero_now = Hero(config.HEROPICPATH, [
0,
0], config.BLOCKSIZE, config.BORDERSIZE)
-
# --统计步数
-
num_steps =
0
-
# --关卡内主循环
-
while
True:
-
dt = clock.tick(config.FPS)
-
screen.fill((
255,
255,
255))
-
is_move =
False
-
# ----↑↓←→控制hero
-
for event
in pygame.event.get():
-
if event.type == pygame.QUIT:
-
pygame.quit()
-
sys.exit(
-1)
-
elif event.type == pygame.KEYDOWN:
-
if event.key == pygame.K_UP:
-
is_move = hero_now.move(
'up', maze_now)
-
elif event.key == pygame.K_DOWN:
-
is_move = hero_now.move(
'down', maze_now)
-
elif event.key == pygame.K_LEFT:
-
is_move = hero_now.move(
'left', maze_now)
-
elif event.key == pygame.K_RIGHT:
-
is_move = hero_now.move(
'right', maze_now)
-
num_steps += int(is_move)
-
hero_now.draw(screen)
-
maze_now.draw(screen)
-
# ----显示一些信息
-
showText(screen, font,
'LEVELDONE: %d' % num_levels, (
255,
0,
0), (
10,
10))
-
showText(screen, font,
'BESTSCORE: %s' % best_scores, (
255,
0,
0), (
210,
10))
-
showText(screen, font,
'USEDSTEPS: %s' % num_steps, (
255,
0,
0), (
410,
10))
-
showText(screen, font,
'S: your starting point D: your destination', (
255,
0,
0), (
10,
600))
-
# ----判断游戏是否胜利
-
if (hero_now.coordinate[
0] == config.MAZESIZE[
1] -
1)
and (hero_now.coordinate[
1] == config.MAZESIZE[
0] -
1):
-
break
-
pygame.display.update()
-
# --更新最优成绩
-
if best_scores ==
'None':
-
best_scores = num_steps
-
else:
-
if best_scores > num_steps:
-
best_scores = num_steps
-
# --关卡切换
-
Interface(screen, config, mode=
'game_switch')
-
-
-
'''run'''
-
if __name__ ==
'__main__':
-
main(config)
四、游戏启动方法
1、开发工具启动
如果你配置了开发工具的环境VScode、sublimeText、notepad+、pycharm什么的,可以直接在工具中,运行游戏。
如果没配置,可以使用命令启动。
2、命令行启动 gif
推荐阅读
python实战
【python实战】前女友发来加密的 “520快乐.pdf“,我用python破解开之后,却发现。。。
【python实战】昨晚,我用python帮隔壁小姐姐P证件照 自拍,然后发现...
【python实战】女友半夜加班发自拍 python男友用30行代码发现惊天秘密
【python实战】python你TM太皮了——区区30行代码就能记录键盘的一举一动
【python实战】女神相册密码忘记了,我只用Python写了20行代码~~~
渗透测试
【渗透测试】密码暴力破解工具——九头蛇(hydra)使用详解及实战
【渗透学习】Web安全渗透详细教程+学习线路+详细笔记【全网最全+建议收藏】
【渗透案例】如何用ssh工具连接前台小姐姐的“小米手机”——雷总看了直呼内行!!!
【渗透测试】密码暴力破解工具——九头蛇(hydra)使用详解及实战
pygame系列文章
一起来学pygame吧 游戏开发30例(三)——射击外星人小游戏
一起来学pygame吧 游戏开发30例(四)——俄罗斯方块小游戏
一起来学pygame吧 游戏开发30例(五)——消消乐 小游戏
一起来学pygame吧 游戏开发30例(六)——高山滑雪 小游戏
CSDN官方学习推荐 ↓ ↓ ↓
CSDN出的Python全栈知识图谱,太强了,推荐给大家!
转载:https://blog.csdn.net/weixin_42350212/article/details/117186303