鱼C论坛

 找回密码
 立即注册
查看: 2010|回复: 0

[作品展示] 非常无聊的作品:怎么把pygame的过程录制到mp4

[复制链接]
发表于 2020-6-23 12:03:51 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
首先,用的是cv2模块,也就是没有音频,只是动画,不过mp4压缩比大,体积小,windows支持自动播放(比如flash格式flv是不支持的)。
所谓录制,就是一帧一帧图像写入video,想想很简单,不过有个数据接口问题,代码如下(插入到pygame的刷新一帧函数的结束部分即可):

  1.     def printAll(self):
  2.         #。。。。。。。pygame表示各种物体代码块
  3.         if CMG.step == 1:
  4.             fps = 12
  5.             size = (800,570)
  6.             file_path = r"C:\Users\Administrator\Desktop\aa1" + str(int(time.time())) + ".mp4v"#导出路径
  7.             fourcc = cv2.VideoWriter_fourcc('I','4','2','0')#不同视频编码对应不同视频格式(例:'I','4','2','0' 对应avi格式)
  8.             CMG.video = cv2.VideoWriter( file_path, fourcc, fps, size )
  9.         else:
  10.             imagestring = pygame.image.tostring(CMG.screen.subsurface(0,0,800,570),"RGB")
  11.             pilImage = Image.frombytes("RGB", (800,570), imagestring)
  12.             img = cv2.cvtColor(numpy.asarray(pilImage),cv2.COLOR_RGB2BGR)
  13.             
  14.             CMG.video.write(img)        #把图片写进视频
  15.             if CMG.step == len(CMG.gameAnswer)+1:
  16.                 CMG.video.release() #释放
复制代码


完整例子代码(解迷宫过程录制成mp4)
  1. import pygame
  2. import sys
  3. import os
  4. import random
  5. import time
  6. from pygame.locals import *
  7. import tkinter as tk
  8. from tkinter import *
  9. import tkinter.messagebox  # 要使用messagebox先要导入模块
  10. import cv2
  11. import numpy
  12. from PIL import Image, ImageDraw
  13. from PIL import ImageFont


  14. class Maze:
  15.     size = None
  16.     print_str=(('##','  '),('#',' '))
  17.     map = None
  18.     direct = ((-2,0),(2,0),(0,2),(0,-2),(-2,0),(2,0),(0,2))

  19.     @staticmethod
  20.     def check_move(map,yx):
  21.         for d in range(0,4):
  22.             if(map[yx[0]+Maze.direct[d][0]][yx[1]+Maze.direct[d][1]] == 0):
  23.                 return True
  24.         return False
  25.     @staticmethod
  26.     def create_maze(size_para):
  27.         WAY = 1
  28.         size=[size_para[0]*2+3,size_para[1]*2+3]
  29.         Maze.size = size
  30.         direct = Maze.direct
  31.         center=[random.randint(1,size[0]-1)//2*2,random.randint(1,size[1]-1)//2*2]
  32.         map= [[100]*size[1] for i in range(size[0])]
  33.         for y in range(size_para[0]):
  34.             for x in range(size_para[1]):
  35.                 map[2*y+2][2*x+2] = 0
  36.         step0_nodes = [center]
  37.         map[center[0]][center[1]] = WAY
  38.         step1_nodes = []

  39.         while len(step0_nodes) > 0:
  40.             node_no = random.randint(0,len(step0_nodes)-1)
  41.             yx= step0_nodes[node_no]
  42.             if not Maze.check_move(map,yx):
  43.                 step0_nodes.pop(node_no)
  44.                 continue
  45.             direct_start = random.randint(0,3)
  46.             for d in range(direct_start,direct_start+4):
  47.                 y=yx[0]+direct[d][0]
  48.                 x=yx[1]+direct[d][1]
  49.                 if(map[y][x] == 0):
  50.                     step1_nodes.append((y,x))
  51.                     map[yx[0]+direct[d][0]//2][yx[1]+direct[d][1]//2] = WAY
  52.                     map[y][x] = WAY
  53.                     break
  54.             step0_nodes.extend(step1_nodes)
  55.             step1_nodes.clear()
  56.         Maze.map = map

  57.     @staticmethod
  58.     def solve_maze(startY,endYX):
  59.         WAY = 1
  60.         direct = Maze.direct
  61.         center=(startY*2+2,2,-1)
  62.         map = Maze.map
  63.         steps_nodes = []
  64.         step0_nodes = [center]
  65.         map[center[0]][center[1]] = 0
  66.         step1_nodes = []

  67.         while len(step0_nodes) > 0:
  68.             steps_nodes.append(step0_nodes)
  69.             for n in range(0,len(step0_nodes)):
  70.                 yx= step0_nodes[n]
  71.                 for d in range(0,4):
  72.                     y=yx[0]+direct[d][0]
  73.                     x=yx[1]+direct[d][1]
  74.                     y3=yx[0]+direct[d][0]//2
  75.                     x3=yx[1]+direct[d][1]//2
  76.                     if(map[y3][x3] != 100 and map[y][x] == WAY ):
  77.                         step1_nodes.append((y,x,n))
  78.                         map[yx[0]+direct[d][0]][yx[1]+direct[d][1]] = 0
  79.                         if y == endYX[0]*2 and x== endYX[1]*2:
  80.                             steps_nodes.append(step1_nodes)
  81.                             return steps_nodes
  82.             step0_nodes = step1_nodes[:]
  83.             step1_nodes.clear()
  84.         return None

  85. class CMG: #画面显示管理
  86.     screen = None
  87.     map = None
  88.     gameAnswer = None
  89.     WHITE = (255, 255, 255)
  90.     GREEN = (0, 255, 0)
  91.     RED = (255, 0, 0)
  92.     BLUE = (0, 0, 255)
  93.     blocksize = 0
  94.     step = 0
  95.     back_ground = None

  96.     def __init__(self,screen,map,gameAnswer):
  97.         if CMG.screen == None:
  98.             #print("#############OS.PATH=%s"% os.path.dirname(os.path.abspath(__file__)))
  99.             CMG.screen = screen
  100.             CMG.map = map
  101.             CMG.gameAnswer = gameAnswer
  102.             if 800//len(map[0]) > 570//len(map):
  103.                 CMG.blocksize = 570//len(map)
  104.             else:
  105.                 CMG.blocksize = 800//len(map[0])
  106.         #如果存在对象成员
  107.         self.init_game_info()

  108.     def init_game_info(self):
  109.         pass

  110.     def printAll(self):
  111.         if CMG.step > len(CMG.gameAnswer):
  112.             return
  113.         CMG.screen.fill((0, 0, 0))
  114.         size = Maze.size
  115.         if CMG.back_ground == None:
  116.             for y in range(1,size[0]-1):
  117.                 for x in range(1,size[1]-1):
  118.                     val = CMG.map[y][x]
  119.                     if y%2==1 and x%2==0 and val == 100:
  120.                         #start_pos = [(y*CMG.blocksize,x*CMG.blocksize)]
  121.                         end_pos = [((x-1)*CMG.blocksize,y*CMG.blocksize),((x+1)*CMG.blocksize,y*CMG.blocksize)]
  122.                         pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
  123.                     elif y%2==0 and x%2==1 and val == 100:
  124.                         end_pos = [(x*CMG.blocksize,(y-1)*CMG.blocksize),(x*CMG.blocksize,(y+1)*CMG.blocksize)]
  125.                         pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
  126.             select_rect = CMG.screen.subsurface(0,0,800,570)
  127.             CMG.back_ground = select_rect.copy()
  128.         else:
  129.             self.screen.blit(CMG.back_ground,(0,0))
  130.         if CMG.step == len(CMG.gameAnswer):
  131.             step = CMG.step - 1
  132.             step_node = CMG.gameAnswer[step]
  133.             yx = step_node[len(step_node)-1]
  134.             while(yx[2]!=-1):
  135.                 y = yx[0]
  136.                 x = yx[1]
  137.                 step -= 1
  138.                 step_node = CMG.gameAnswer[step]
  139.                 yx = step_node[yx[2]]
  140.                 pygame.draw.rect(CMG.screen, CMG.WHITE, (((x-1)*CMG.blocksize+2,(y-1)*CMG.blocksize+2), (CMG.blocksize*2-4, CMG.blocksize*2-4)), 0)
  141.         else:
  142.             step_node = CMG.gameAnswer[CMG.step]
  143.             for s in range(0,len(step_node)):
  144.                 yx = step_node[s]
  145.                 y = yx[0]
  146.                 x = yx[1]
  147.                 #pygame.draw.rect(background, (0, 255, 0), ((200, 5), (100, 100)), 3)
  148.                 pygame.draw.rect(CMG.screen, CMG.WHITE, (((x-1)*CMG.blocksize+2,(y-1)*CMG.blocksize+2), (CMG.blocksize*2-4, CMG.blocksize*2-4)), 0)

  149.         CMG.step += 1
  150.         
  151.         if CMG.step == 1:
  152.             fps = 12
  153.             size = (800,570)
  154.             file_path = r"C:\Users\Administrator\Desktop\aa1" + str(int(time.time())) + ".mp4v"#导出路径
  155.             fourcc = cv2.VideoWriter_fourcc('I','4','2','0')#不同视频编码对应不同视频格式(例:'I','4','2','0' 对应avi格式)
  156.             CMG.video = cv2.VideoWriter( file_path, fourcc, fps, size )
  157.         else:
  158.             imagestring = pygame.image.tostring(CMG.screen.subsurface(0,0,800,570),"RGB")
  159.             pilImage = Image.frombytes("RGB", (800,570), imagestring)
  160.             img = cv2.cvtColor(numpy.asarray(pilImage),cv2.COLOR_RGB2BGR)
  161.             
  162.             CMG.video.write(img)        #把图片写进视频
  163.             if CMG.step == len(CMG.gameAnswer)+1:
  164.                 CMG.video.release() #释放
  165.         

  166.     def moveAll(self):
  167.         pass

  168. #------------------------------------------------
  169. #tkinter,pygame混合区 START
  170. #------------------------------------------------
  171. root = tk.Tk()
  172. root.resizable(0,0)

  173. embed = tk.Frame(root, width = 800, height = 570) #creates embed frame for pygame window
  174. embed.grid(columnspan = (800), rowspan = 730) # Adds grid
  175. embed.pack(side = TOP) #packs window to the left

  176. buttonwin = tk.Frame(root, width = 800, height = 150)
  177. buttonwin.pack(side = BOTTOM)

  178. os.environ['SDL_WINDOWID'] = str(embed.winfo_id())
  179. os.environ['SDL_VIDEODRIVER'] = 'windib'

  180. screen = pygame.display.set_mode((800,570))

  181. #pygame.init()
  182. pygame.display.init()
  183. pygame.mixer.init()
  184. #------------------------------------------------
  185. #tkinter,pygame混合区 END
  186. #------------------------------------------------

  187. #参数,因为函数内要使用之外的变量,需要globe,因此全部打包
  188. class PARAM:
  189.     STATUS = 0
  190.     TICK_NORMAL = 5

  191. #按钮动作区 =====================================
  192. def exit_game():
  193.     global param
  194.     param.STATUS = 100
  195. #控件定义区 =====================================
  196. button_exit_b = Button(buttonwin,text = '退出画面', width=7, command=exit_game)
  197. button_exit_b.place(x=740,y=100)


  198. #状态,参数,循环中使用,比如STATUS=0:初次进入,1:...100:退出
  199. param = PARAM()
  200. Maze.create_maze([50,70])
  201. steps_nodes = Maze.solve_maze(0,(49,69))
  202. param.cmg = CMG(screen,Maze.map,steps_nodes)
  203. #------------------------------------------------
  204. #主函数,使用pygame框架,无限LOOP对各种事件然后相应处理
  205. #------------------------------------------------
  206. def main():
  207.     global param
  208.     #pygame.mixer.music.play(-1)
  209.     clock = pygame.time.Clock()

  210.     while True:
  211.         #这段event代码是必须的,哪怕在这个程序中不需要,不执行的话整个框架转不动
  212.         for event in pygame.event.get():
  213.             if event.type == QUIT:
  214.                 sys.exit()

  215.         #画面按钮按下后,修改param.STATUS,实际动作这里实现
  216.         if  param.STATUS == 100:
  217.             #退出按钮
  218.             if tk.messagebox.askokcancel('提示', '要退出画面吗'):
  219.                 break
  220.             param.STATUS = 0
  221.         elif param.STATUS == 10:
  222.             pass
  223.             
  224.         param.cmg.printAll()

  225.         #显示游戏画面
  226.         pygame.display.flip()
  227.         #设置帧率:长期画面不操作,设置成最闲
  228.         clock.tick(param.TICK_NORMAL)
  229.             
  230.         root.update()

  231. main()
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-22 18:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表