python游戏开发-SproutLand
开发环境配置
安装好python环境后,下载pygame模块,使用如下命令下载
pip install pygame
注:python版本选择不要过高,选择3.6到3.8版本范围即可
pygame项目快速搭建
以飞机大战游戏为例,快速上手pygame,首先创建游戏窗口
import sys``import pygame`` ``# 初始化pygame引擎``pygame.init()``# 设置窗口大小``SCREEN_WIDTH = 640` `SCREEN_HEIGHT = 820` `screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))``# 设置窗口游戏名``pygame.display.set_caption('Sprout land')``# 设置游戏窗口颜色``screen.fill('white')``# 刷新游戏窗口``pygame.display.update()`` ``while True:` `"""` `用于获取当前事件队列中的所有事件` `事件可以是用户输入(例如按键、鼠标点击)或系统生成的事件(例如窗口关闭事件)` `调用 pygame.event.get() 函数将返回一个包含当前事件队列中所有事件的列表` `"""` `for event in pygame.event.get():` `# event.type 来判断不同类型的事件` `if event.type == pygame.QUIT:` `pygame.quit()` `sys.exit()` `# 游戏功能` `pygame.display.update()
执行代码如图所示
在游戏窗口内贴图
# 获取图像的形状参数和位置参数``screen_rect = screen.get_rect()``plane_image = pygame.image.load('plane.gif')``plane_rect = plane_image.get_rect() # 获取飞机的形状和位置参数``plane_rect.center = screen_rect.center # 将飞机位置中心放置在窗口中央``screen.blit(plane_image, plane_rect)
用户输入控制贴图移动
while True:` `for event in pygame.event.get():` `# event.type 来判断不同类型的事件` `if event.type == pygame.QUIT:` `pygame.quit()` `sys.exit()` `elif event.type == pygame.KEYDOWN: # 用户按下键盘` `if event.key == pygame.K_LEFT:` `plane_rect.x -= 10` `if event.key == pygame.K_RIGHT:` `plane_rect.x += 10` `if event.key == pygame.K_UP:` `plane_rect.y -= 10` `if event.key == pygame.K_DOWN:` `plane_rect.y += 10`` ` `# 绘制图像` `screen.fill('white') # 将游戏窗口填满白色,可遮盖飞机之前在窗口内的显示` `screen.blit(plane_image, plane_rect) # 绘制飞机` `pygame.display.update() # 刷新窗口
SproutLand游戏简要介绍
这是一款休闲小游戏,玩家可控制游戏角色进行移动,并使用不同的工具在地图中实现砍树、耕种等,另外可与商人进行商品交易,此外游戏天气会随机变化,以及新的一天(当玩家回家休息时)的游戏重置,游戏演示视频如下
创建项目及文件目录
项目目录如图所示,其中code文件夹存放代码文件,其余的文件夹则是游戏资源文件夹
在main.py中定义启动类game,将游戏内容的处理部分封装在Level类中,同时定义一个计时器类Timer
项目类的声明
这里只简要介绍main.py、level.py以及player.py文件内的内容,详细的功能实现可在具体项目内阅读源码以及查看详细的注解,项目资源获取方式在本文章末尾
main.py
class Game:` `def __init__(self):` `# 初始化pygame引擎` `pygame.init()` `# 设置窗口大小` `self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))` `# 设置窗口游戏名` `pygame.display.set_caption('Sprout land')` `# 创建时钟对象:控制游戏的帧率并确保游戏在不同的设备上运行时具有一致的速度,.tick() 方法来限制游戏循环的速度` `self.clock = pygame.time.Clock()` `self.level = Level()`` ` `def run(self):` `while True:` `for event in pygame.event.get():` `# event.type 来判断不同类型的事件` `if event.type == pygame.QUIT:` `pygame.quit()` `sys.exit()` `# dt游戏帧率` `dt = self.clock.tick() / 1000` `self.level.run(dt)` `pygame.display.update()`` ``if __name__ == '__main__':` `game = Game()` `game.run()
player.py
该文件中定义了游戏角色类Player,继承了pygame库中的Sprite类,Sprite类可用于创建游戏精灵(Sprite),可理解为游戏对象,精灵是游戏中可移动的图像或者角色,拥有自己的属性、图像、位置并具有与其他精灵互动的能力,例如创建MySprite精灵类
class MySprite(pygame.sprite.Sprite):` `def __init__(self):` `super().__init__() # 调用父类的初始化方法` `self.image = pygame.Surface((50, 50)) # 创建图像` `self.image.fill((255, 0, 0)) # 填充红色` `self.rect = self.image.get_rect() # 获取图像的矩形区域` `self.rect.center = (200, 200) # 设置图像的初始位置`` ` `def update(self):` `self.rect.x += 1 # 每次更新使精灵向右移动一个单位
Player类
class Player(pygame.sprite.Sprite):` `# pos:位置,group:组群` `def __init__(self, pos, group, collision_sprites, tree_sprites, interaction, soil_layer, toggle_shop):` `super().__init__(group)`` ` `self.import_assets() # 自定义方法,导入人物的各种运动动作素材` `self.status = 'down_idle'` `self.frame_index = 0`` ` `# 角色创建` `self.image = self.animations[self.status][self.frame_index]` `self.rect = self.image.get_rect(center=pos)` `# 角色所处层级` `self.z = LAYERS['main']`` ` `# 移动参数` `self.direction = pygame.math.Vector2() # 角色二维数组的位置参数` `self.pos = pygame.math.Vector2(self.rect.center)` `self.speed = 200`` ` `# 碰撞` `self.hitbox = self.rect.copy().inflate((-126, -70))` `self.collision_sprites = collision_sprites`` ` `# 调用计时器` `self.timers = {` `'tool use': Timer(350, self.use_tool),` `'tool switch': Timer(200),` `'seed use': Timer(350, self.use_seed),` `'seed switch': Timer(200)` `}`` ` `# 工具` `self.tools = ['hoe', 'axe', 'water']` `self.tool_index = 0` `self.selected_tool = self.tools[self.tool_index]`` ` `# 种子` `self.seeds = ['corn', 'tomato']` `self.seed_index = 0` `self.selected_seed = self.seeds[self.seed_index]`` ` `# 库存` `self.item_inventory = {` `'wood': 20,` `'apple': 20,` `'corn': 20,` `'tomato': 20` `}` `self.seed_inventory = {` `'corn': 5,` `'tomato': 5,` `}` `self.money = 200`` ` `# 角色的各种交互` `self.tree_sprites = tree_sprites` `self.interaction = interaction` `self.sleep = False` `self.soil_layer = soil_layer` `self.toggle_shop = toggle_shop`` ` `# 音效` `self.watering = pygame.mixer.Sound('../audio/water.mp3')` `self.watering.set_volume(0.2)
level.py
项目的核心代码,level类实现了游戏各种对象的实现即在游戏窗口中绘制图像以及游戏逻辑的编写,例如游戏角色的各种交互(碰撞、与商人对话)、以及控制天气的变化等
Level类
class Level:` `# 初始化信息` `def __init__(self):` `# 获取当前显示窗口的 Surface 对象(即游戏屏幕),获取到对象后可在屏幕上绘图` `self.display_surface = pygame.display.get_surface()` `# sprite groups(游戏对象组)` `self.all_sprites = CameraGroup()` `"""` `pygame.sprite.Group():用于管理和操作精灵(Sprite)对象的集合` `下面是一些常用的 Group 类方法:` `add(sprite):将一个精灵对象添加到组中。` `remove(sprite):从组中移除指定的精灵对象。` `sprites():返回组中所有的精灵对象。` `update(*args):调用组中每个精灵对象的 update() 方法,用于更新精灵的状态。` `draw(surface):将组中的每个精灵对象绘制到指定的显示窗口表面(surface)上。` `"""` `self.collision_sprites = pygame.sprite.Group() # 碰撞` `self.tree_sprites = pygame.sprite.Group() # 树` `self.interaction_sprites = pygame.sprite.Group() # 交互` `# 创立游戏对象` `self.soil_layer = SoilLayer(self.all_sprites, self.collision_sprites)` `self.setup()` `self.overlay = Overlay(self.player)` `self.transition = Transition(self.reset, self.player)` `# sky(天气:控制下雨天,以及下雨天影响耕种土地)` `self.rain = Rain(self.all_sprites)` `self.raining = randint(0, 10) > 7 # 是否下雨:True下雨,False晴天` `self.soil_layer.raining = self.raining` `self.sky = Sky()` `# shop(主菜单,购买种子和出售物品)` `self.menu = Menu(self.player, self.toggle_shop)` `self.shop_active = False # 是否处于商店状态`` ` `# music(设置游戏背景音乐)` `self.success = pygame.mixer.Sound('../audio/success.wav')` `self.success.set_volume(0.1) # 设置音量大小` `self.music = pygame.mixer.Sound('../audio/music.mp3')` `self.music.set_volume(0.4)` `self.music.play(loops=-1)
在使用精灵时,通常会创建一个精灵组(Sprite Group),并将精灵对象添加到该组中来方便管理。可以使用 pygame.sprite.Group 类来创建精灵组,并使用 add 方法来添加精灵对象,例如
# 创建精灵对象``sprite = MySprite()`` ``# 创建精灵组并添加精灵对象``sprite_group = pygame.sprite.Group()``sprite_group.add(sprite)
setup()函数,在Level类中用于创建游戏中的对象(精灵)
`def setup(self):` `# 获取游戏相关数据(地图上的障碍物)[tmx_data 是一个 TMX 格式的地图数据对象]` `tmx_data = load_pygame('../data/map.tmx')`` ` `# 绘制房子` `for layer in ['HouseFloor', 'HouseFurnitureBottom']: # 地板和地毯` `"""` `get_layer_by_name(layer) 是用于根据图层名获取对应图层的方法` `tiles() 是用于获取指定图层上的所有瓦片(Tile)的方法` `"""` `for x, y, surf in tmx_data.get_layer_by_name(layer).tiles():` `Generic((x * TILE_SIZE, y * TILE_SIZE), surf, self.all_sprites, LAYERS['house bottom'])` `for layer in ['HouseWalls', 'HouseFurnitureTop']: # 墙和家具` `for x,y,surf in tmx_data.get_layer_by_name(layer).tiles():` `Generic((x * TILE_SIZE, y * TILE_SIZE), surf, self.all_sprites)`` ` `# 绘制栅栏` `for x, y, surf in tmx_data.get_layer_by_name('Fence').tiles():` `Generic((x * TILE_SIZE, y * TILE_SIZE), surf, [self.all_sprites, self.collision_sprites])`` ` `# 绘制水` `water_frames = import_folder('../graphics/water')` `for x, y, surf in tmx_data.get_layer_by_name('Water').tiles():` `Water((x * TILE_SIZE, y * TILE_SIZE), water_frames, self.all_sprites)` `# 绘制树` `for obj in tmx_data.get_layer_by_name('Trees'):` `Tree(pos=(obj.x, obj.y),` `surf=obj.image,` `groups=[self.all_sprites, self.collision_sprites, self.tree_sprites],` `name=obj.name,` `player_add=self.player_add)`` ` `# 绘制野花` `for obj in tmx_data.get_layer_by_name('Decoration'):` `WildFlower((obj.x, obj.y), obj.image, [self.all_sprites, self.collision_sprites])`` ` `# 碰撞边界` `for x, y, surf in tmx_data.get_layer_by_name('Collision').tiles():` `Generic((x * TILE_SIZE,y * TILE_SIZE), pygame.Surface((TILE_SIZE, TILE_SIZE)), self.collision_sprites)` `# 玩家` `for obj in tmx_data.get_layer_by_name('Player'):` `if obj.name == 'Start':` `self.player = Player(pos=(obj.x, obj.y),` `group=self.all_sprites,` `collision_sprites=self.collision_sprites,` `tree_sprites=self.tree_sprites,` `interaction = self.interaction_sprites,` `soil_layer= self.soil_layer,` `toggle_shop=self.toggle_shop)` `if obj.name == 'Bed':` `Interaction((obj.x, obj.y), (obj.width, obj.height), self.interaction_sprites, obj.name)`` ` `if obj.name == 'Trader':` `Interaction((obj.x, obj.y), (obj.width, obj.height), self.interaction_sprites, obj.name)`` ` `Generic(pos=(0, 0),` `surf=pygame.image.load('../graphics/world/ground.png').convert_alpha(),` `groups=self.all_sprites,` `z=LAYERS['ground'])`
游戏打包成可执行文件
1.下载pyinstaller模块
pip installer pyinstaller
2.准备好一个游戏可执行封面.ico图标,可随意找一张图片,之后选择在线图片转.ico网站实现转换即可
游戏开发完成后,打包成可执行的exe文件,进入项目代码文件夹,打开cmd
执行命令
pyinstaller -i 图标.ico -n 游戏名 -F 主入口文件.py
注:若使用的是conda环境,则需先启动conda环境,再执行命令,不是使用conda环境可直接执行命令
只打包项目的代码,不会打包资源文件,生成的文件如下
创建一个游戏文件夹,将打包的文件,以及资源文件放在该游戏文件夹下,即可执行游戏
注:可执行文件.exe存放在dist打包文件夹下,如图
点击下方安全链接前往获取
CSDN大礼包:《Python入门&进阶学习资源包》免费分享
👉Python实战案例👈
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
👉Python书籍和视频合集👈
观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。
👉Python副业创收路线👈
这些资料都是非常不错的,朋友们如果有需要《Python学习路线&学习资料》,点击下方安全链接前往获取
CSDN大礼包:《Python入门&进阶学习资源包》免费分享
本文转自网络,如有侵权,请联系删除。