使用Python生成MAME边框布局

我花了几个小时来调整一个不错的小脚本,以帮助我使用Python更快地为现有艺术品生成MAME边框布局。

如果您不知道MAME挡板的用途,请看一下。 这是我们的老朋友加拉加(Galaga),没有任何奇特的效果或艺术品:

是的,“这是Galaga”,但看起来并不像街机游戏中的那样。 它是无菌的和无聊的。 这是相同的游戏,但带有边框图稿和一些HLSL效果:

现在看起来就像我记得的加拉加!

在其中获得HLSL效果是一个完全不同的话题。 但是我发现这些“边框”周围的艺术品有数百个,甚至数千个。 问题在于它们大多数没有MAME布局文件,或者它们不正确。

布局文件只是一个XML文件,它将仿真屏幕放置在图稿中的正确位置。 看起来像这样:

   












您会看到,如果您有数百种游戏,那么弄清楚这些坐标将变得很有趣或很快。

您将编辑脚本以将其指向包含多个Bezel图像文件的目录。 脚本运行时,它将依次弹出每个图像,并让您在屏幕位于图像内的位置绘制一个矩形。 然后按空格键或任何其他键。 它将生成Layout XML,并将其与边框图一起移动到为游戏命名的文件夹中。 然后,您要做的就是将其放入MAME / artwork文件夹,然后保存Bezel 。 我听了一些颤抖的环境音乐时经历了400个表圈,这非常放松。

您可以在我的Git存储库中找到它,以及自述文件。 如果您改善此脚本,请考虑向我发送请求请求。

这是一个足够小的脚本,因此我将在此处向您展示。 它需要具有Numpy 1.13.1和OpenCV 3.3.1 + contrib作为依赖项的Python 3.6.1+。

  #导入必要的软件包 
导入操作系统
将numpy导入为np
导入cv2
导入csv
进口壁垒
dirName =“ ./arcade-bezel-overlays/”
MAX_DISPLAY_H = 1920
MAX_DISPLAY_V = 1080
xy1 =()
xy2 =()
bezelImage = np.array([])
gameName =“”
方面= 1.0
mouseIsDown = False
def drawRect(img,xy_1,xy_2):
如果xy_1!=()和xy_2!=():
cv2.rectangle(img,xy_1,xy_2,(0,255,0),2)
def makeTemplate(名称,img,xy_1,xy_2):
宽度= img.shape [1]
高度= img.shape [0]
模板= f'''












'''
返回模板
def parseAllGames():
游戏= {}
用open('resolutions.csv')作为csvfile:
reader = csv.DictReader(csvfile,delimiter =“;”)
对于阅读器中的行:
games [str(row [“ game_name”])] =行
回归游戏
def click_and_move(事件,x,y,标志,参数):
全局xy1,xy2,mouseIsDown,gameName,bezelImage,aspect
如果事件== cv2.EVENT_LBUTTONDOWN:
xy1 =(x,y)
xy2 =()
mouseIsDown = True
elif事件== cv2.EVENT_LBUTTONUP:
xy2 =(x,y)
mouseIsDown = False
elif mouseIsDown和event == cv2.EVENT_MOUSEMOVE:
xa = int(xy1 [0] +长宽比*(y-xy1 [1]))
#按住SHIFT键以限制游戏方面
xy2 =(xa,y)如果标志&cv2.EVENT_FLAG_SHIFTKEY else(x,y)
#在感兴趣的区域周围绘制一个矩形
imgCopy = bezelImage.copy()
drawRect(imgCopy,xy1,xy2)
cv2.imshow(gameName,imgCopy)
def EstimateRect(game,img):
全球方面
gw = float(game [“ video_x”])
gh = float(game [“ video_y”])
纵横比= gw / gh
宽度= img.shape [1]
高度= img.shape [0]
顶部= 0.025 *高度
底部= 0.975 *高度
vspan =底部-顶部
hspan =宽高比* vspan
左= 0.5 *(宽度-hspan)
右=宽度-0.5 *(宽度-hspan)
return(int(left),int(top)),(int(right),int(bottom))
def mainLoop():
全局xy1,xy2,bezelImage,gameName
all_games = parseAllGames()
ld = os.listdir(dirName)
对于ld中的文件名:
#print(“ opening” + dirName + filename)
gameName = str(os.path.splitext(文件名)[0])
如果all_games中的gameName:
游戏= all_games [gameName]
bezelImage = cv2.imread(dirName +文件名)
cv2.namedWindow(gameName,cv2.WINDOW_NORMAL)
宽度=最小值(MAX_DISPLAY_H,bezelImage.shape [1])
高度=最小值(MAX_DISPLAY_V,bezelImage.shape [0])
cv2.resizeWindow(gameName,width,height)
xy1,xy2 = estimateRect(游戏,bezelImage)
imgCopy = bezelImage.copy()
drawRect(imgCopy,xy1,xy2)
cv2.imshow(gameName,imgCopy)
cv2.setMouseCallback(gameName,click_and_move)
cv2.waitKey(0)
模板= makeTemplate(gameName,bezelImage,xy1,xy2)
os.makedirs(f'out / {gameName}',0o777,True)
f =打开(f'out / {gameName} /default.lay','w')
f.write(模板)
f.close()
#shutil.copyfile(dirName + filename,f'out / {gameName} / {filename}')
shutil.move(dirName + filename,f'out / {gameName} / {filename}')
cv2.destroyAllWindows()
其他:
打印(f“警告:无法在所有已知的MAME条目列表中找到{gameName}。”)
mainLoop()

希望对您有用,请告诉我您的想法!