Zephus 发表于 2022-1-3 13:53

Python游戏开发,Pygame模块,Python从零开始带大家 ...

开发工具
Python版本: 3.7.4
相关模块:
pygame模块;
以及一些python自带的模块。
环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。
原理简介

首先,我们打开原版游戏的开始界面,发现是这样的:



具体而言,我们的思路是先定义一个按钮类,来模拟原始游戏中的“开始游戏”,“游戏说明”和“离开游戏”这三个按键的功能:


'''按钮类'''
class Button(pygame.sprite.Sprite):
    def __init__(self, text, fontpath, fontsize, position, color_selected=(255, 0, 0), color_default=(255, 255, 255)):
      pygame.sprite.Sprite.__init__(self)
      self.text = text
      self.color_selected = color_selected
      self.color_default = color_default
      self.font = pygame.font.Font(fontpath, fontsize)
      self.font_render = self.font.render(text, True, color_default)
      self.rect = self.font_render.get_rect()
      self.rect.center = position
    '''更新函数: 不断地更新检测鼠标是否在按钮上'''
    def update(self):
      mouse_pos = pygame.mouse.get_pos()
      if self.rect.collidepoint(mouse_pos):
            self.font_render = self.font.render(self.text, True, self.color_selected)
      else:
            self.font_render = self.font.render(self.text, True, self.color_default)
    '''绑定到屏幕上'''
    def draw(self, screen):
      screen.blit(self.font_render, self.rect)
复制代码

主要的原理就是不断检测鼠标是否在对应的按钮区域,如果在,则对按钮的颜色做出改变(这里是变成红色),否则按钮使用默认的颜色(这里是白色),以此来向玩家表明这是可点击的按钮。
然后,我们来实例化它三次来添加这三个按钮到游戏的开始界面中:


'''游戏开始界面'''
class StartGameInterface():
    def __init__(self, cfg):
      self.cfg = cfg
      self.play_btn = Button('开始游戏', cfg.FONTPATH_CN, 50, (cfg.SCREENSIZE//2, cfg.SCREENSIZE - 400))
      self.intro_btn = Button('游戏说明', cfg.FONTPATH_CN, 50, (cfg.SCREENSIZE//2, cfg.SCREENSIZE - 300))
      self.quit_btn = Button('离开游戏', cfg.FONTPATH_CN, 50, (cfg.SCREENSIZE//2, cfg.SCREENSIZE - 200))
    '''外部调用'''
    def run(self, screen):
      # 魔塔
      font = pygame.font.Font(self.cfg.FONTPATH_CN, 80)
      font_render_cn = font.render('魔塔', True, (255, 255, 255))
      rect_cn = font_render_cn.get_rect()
      rect_cn.center = self.cfg.SCREENSIZE // 2, 200
      # Magic Tower
      font = pygame.font.Font(self.cfg.FONTPATH_EN, 80)
      font_render_en = font.render('Magic Tower', True, (255, 255, 255))
      rect_en = font_render_en.get_rect()
      rect_en.center = self.cfg.SCREENSIZE // 2, 350
      # (Ver 1.12)
      font = pygame.font.Font(self.cfg.FONTPATH_CN, 40)
      font_render_version = font.render('(Ver 1.12)', True, (255, 255, 255))
      rect_ver = font_render_version.get_rect()
      rect_ver.center = self.cfg.SCREENSIZE // 2, 400
      clock = pygame.time.Clock()
      while True:
            screen.fill((0, 0, 0))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                  pygame.quit()
                  sys.exit(0)
                elif event.type == pygame.MOUSEBUTTONDOWN:
                  if event.button == 1:
                        mouse_pos = pygame.mouse.get_pos()
                        if self.play_btn.rect.collidepoint(mouse_pos):
                            return True
                        elif self.quit_btn.rect.collidepoint(mouse_pos):
                            pygame.quit()
                            sys.exit(0)
                        elif self.intro_btn.rect.collidepoint(mouse_pos):
                            self.showgameintro(screen)
            for btn in :
                btn.update()
                btn.draw(screen)
            for fr, rect in zip(, ):
                screen.blit(fr, rect)
            pygame.display.flip()
            clock.tick(self.cfg.FPS)
    '''显示游戏简介'''
    def showgameintro(self, screen):
      font = pygame.font.Font(self.cfg.FONTPATH_CN, 20)
      font_renders = [
            font.render('魔塔小游戏.', True, (255, 255, 255)),
            font.render('游戏素材来自: http://www.4399.com/flash/1749_1.htm.', True, (255, 255, 255)),
            font.render('游戏背景故事为公主被大魔王抓走, 需要勇士前往魔塔将其救出.', True, (255, 255, 255)),
            font.render('python工程狮.', True, (255, 255, 255)),
            font.render('微信公众号: python工程狮.', True, (255, 255, 255)),
            font.render('版权所有.', True, (255, 255, 255)),
      ]
      rects =
      for idx, rect in enumerate(rects):
            rect.center = self.cfg.SCREENSIZE // 2, 50 * idx + 100
      clock = pygame.time.Clock()
      while True:
            screen.fill((0, 0, 0))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                  pygame.quit()
                  sys.exit(0)
                elif event.type == pygame.MOUSEBUTTONDOWN:
                  if event.button == 1:
                        mouse_pos = pygame.mouse.get_pos()
                        if self.play_btn.rect.collidepoint(mouse_pos):
                            return True
                        elif self.quit_btn.rect.collidepoint(mouse_pos):
                            pygame.quit()
                            sys.exit(0)
                        elif self.intro_btn.rect.collidepoint(mouse_pos):
                            return
            for btn in :
                btn.update()
                btn.draw(screen)
            for fr, rect in zip(font_renders, rects):
                screen.blit(fr, rect)
            pygame.display.flip()
            clock.tick(self.cfg.FPS)
复制代码

其他额外的代码主要是显示游戏的标题等信息,都很简单,就不详细讨论了,会pygame的小伙伴肯定都能写出来
接下来,我们来看下游戏开始之后的界面是长什么样子的




具体而言,我们可以先在文本文件里定义游戏地图的样子,类似下图所示这样子,其中每个数字代表一种游戏元素:



游戏中的图片素材我也已经收集到了网上找到的别人整理好的游戏素材:


于是,我们可以写一个游戏地图文件的解析类,就像这样:


'''游戏地图解析类'''
class MapParser():
    def __init__(self, blocksize, filepath, element_images, offset=(0, 0), **kwargs):
      self.count = 0
      self.switch_times = 15
      self.image_pointer = 0
      self.offset = offset
      self.blocksize = blocksize
      self.element_images = element_images
      self.map_matrix = self.parse(filepath)
    '''解析'''
    def parse(self, filepath):
      map_matrix = []
      with open(filepath, 'r') as fp:
            for line in fp.readlines():
                line = line.strip()
                if not line: continue
                map_matrix.append()
      return map_matrix
    '''将游戏地图画到屏幕上'''
    def draw(self, screen):
      self.count += 1
      if self.count == self.switch_times:
            self.count = 0
            self.image_pointer = int(not self.image_pointer)
      for row_idx, row in enumerate(self.map_matrix):
            for col_idx, elem in enumerate(row):
                position = col_idx * self.blocksize + self.offset, row_idx * self.blocksize + self.offset
                if elem+'.png' in self.element_images:
                  image = self.element_images
                  image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
                  screen.blit(image, position)
复制代码

[点击并拖拽以移动]
其中parse函数其实就是读取存放游戏地图信息的文本文件,然后draw函数其实就是根据读取的地图信息,将对应的游戏元素图片绑定到地图上进行显示。另外,image_pointer,switch_times,count这三个变量是为了实现原版地图中场景元素闪烁的效果,就像这样:



根据这个原理,我们可以轻松地画出魔塔所有层中的原始地图,定义的游戏地图文件如下图所示:


效果如下图所示:




ok,总结一下,就是这期主要实现了魔塔游戏中每一层的初始画面,python超全资料库安装包学习路线项目源码免费分享
页: [1]
查看完整版本: Python游戏开发,Pygame模块,Python从零开始带大家 ...