貧訓:
【Unity】實作拖拽功能并制作一個拼圖游戲

當我看到這個視頻里的素材, 很饞, 但是原作者也沒有發素材檔案, 只能自己弄素材了, 3D就直接pass了, 不熟和學習成本過高, 那就2D的來, 目的是腳本檔案可以批量把照片分隔成拼圖塊
分解需求
最簡易的矩形ROI分割(剪裁),其本質是多維陣列(矩陣)的切片
1. 分隔成n*m個方塊
2. 拿出一個方塊, 獲取左右方塊 之間的中心圓心坐標, 還有上下方塊 之間的中心圓心坐標, 然后補滿這個圓就可以獲得拼圖的凸出, 消減這個圓可以獲得拼圖的凹入

3. 增加圓心偏移
也就是讓凸出和凹進更加好看點

4. 隨機凹凸
先了解下怎么切圓
python3切割圓形圖片
看完這篇文章可知如何生成圓形圖片
新建一個影像b, 然后把a中符合這個圓的點復制b中, 輸出影像b, 就生成了圓形影像
如何符合圓, 要用到初中的知識點, 點到圓心的距離 <= 半徑
分隔成n*m個方塊
import os
from PIL import Image
# 分割幾行幾列, 二維陣列保存
def SplitImages(img_path, row, col):
path_name = os.path.dirname(img_path)
img = Image.open(img_path).convert("RGBA")
imgSize = img.size
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
pimg = img.load()
imbList = []
for i in range(row):
rowList = []
l = (i + 1) * splitL
for j in range(col):
w = (j + 1) * splitW
imb = Image.new('RGBA', (splitW, splitL),(255,255,255,0))
pimb = imb.load()
for k in range(j * splitW, w):
for z in range(i * splitL, l):
pimb[k - splitW * j, z - i * splitL] = pimg[k,z]
dirPath = path_name + "/" + str(i*10 + j) + ".png"
# imb.save(dirPath)
rowList.append(imb)
imbList.append(rowList)
return imbList
簡單版
不考慮隨機凹凸, 不考慮圓心偏移, 凹凸都是固定的, 從第一個開始向右凸出, 向下凸出
def SplitCircle(imbList, imgPath):
path_name = os.path.dirname(imgPath)
img = Image.open(imgPath).convert("RGBA")
imgSize = img.size
col = len(imbList[0])
row = len(imbList)
if col == 1 and row == 1:
return
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
minV = min(splitW, splitL)
r_d = int(minV / 4) # 要計算 兩個不能比 l 長 并且加上 offset 也不能超過 l
#r_offset = int(minV / 8)
#pSplitW = splitW + (r_d + r_offset) * 2
#pSplitL = splitL + (r_d + r_offset) * 2
pimg = img.load()
pointList = []
for i in range(row):
colPointList = []
for j in range(col):
colPoint = []
rowPoint = []
if j != col - 1:
colPoint = [splitW * (j + 1), int(splitL/2) + i * splitL]
if i != row - 1:
rowPoint = [int(splitW / 2) + j * splitW, splitL * (i + 1)]
colPointList.append({'colPoint': colPoint, 'rowPoint': rowPoint})
pointList.append(colPointList)
for i in range(row):
for j in range(col):
imbImg = imbList[i][j]
new_img = imbImg
if j != col - 1 and i != row - 1:
l = imbImg.size[1]
w = imbImg.size[0]
l = l + r_d
w = w + r_d
new_img = Resize(imbImg, w, l)
elif j == col - 1 and i != row - 1:
new_img = Resize(imbImg, splitW, splitL + r_d)
elif j != col - 1 and i == row - 1:
new_img = Resize(imbImg, splitW + r_d, splitL)
new_img_imb = new_img.load()
if j != col - 1:
new_next_img = imbList[i][j + 1]
new_next_img_imb = new_next_img.load()
# 左右
for k in range((j + 1) * splitW, (j + 1) * splitW + r_d):
for z in range(i * splitL, (i + 1) * splitL):
r_w = pointList[i][j]['colPoint'][0]
r_l = pointList[i][j]['colPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW , z - i * splitL] = pimg[k, z]
new_next_img_imb[k - (j + 1) * splitW, z - i * splitL] = (255,255,255,0)
imbList[i][j + 1] = new_next_img
if i!= row - 1:
new_down_img = imbList[i + 1][j]
new_down_img_imb = new_down_img.load()
# 上下
for k in range(j * splitW, (j + 1) * splitW):
for z in range((i + 1) * splitL, (i + 1) * splitL + r_d):
r_w = pointList[i][j]['rowPoint'][0]
r_l = pointList[i][j]['rowPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW, z - i * splitL] = pimg[k, z]
new_down_img_imb[k - j * splitW, z - (i + 1) * splitL] = (255,255,255,0)
imbList[i + 1][j] = new_down_img
imbList[i][j] = new_img
for i in range(row):
for j in range(col):
dirPath = path_name + "/" + str(i*10 + j) + ".png"
imbList[i][j].save(dirPath)

最終版
隨機凹凸, 考慮圓心偏移
import os
from PIL import Image
import random
# 分割幾行幾列, 二維陣列保存
def SplitImages(img_path, row, col):
path_name = os.path.dirname(img_path)
img = Image.open(img_path).convert("RGBA")
imgSize = img.size
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
pimg = img.load()
imbList = []
for i in range(row):
rowList = []
l = (i + 1) * splitL
for j in range(col):
w = (j + 1) * splitW
imb = Image.new('RGBA', (splitW, splitL),(255,255,255,0))
pimb = imb.load()
for k in range(j * splitW, w):
for z in range(i * splitL, l):
pimb[k - splitW * j, z - i * splitL] = pimg[k,z]
dirPath = path_name + "/" + str(i*10 + j) + ".png"
# imb.save(dirPath)
rowList.append(imb)
imbList.append(rowList)
return imbList
def Resize(img, rizeW, rizel, pastePoint=None):
if pastePoint is None:
pastePoint = [0, 0]
new_im = Image.new('RGBA', [rizeW, rizel],(255,255,255,0))
new_im.paste(img, pastePoint)
return new_im
def SplitCircle(imbList, imgPath):
path_name = os.path.dirname(imgPath)
img = Image.open(imgPath).convert("RGBA")
imgSize = img.size
col = len(imbList[0])
row = len(imbList)
if col == 1 and row == 1:
return
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
minV = min(splitW, splitL)
r_d = int(minV / 4) # 要計算 兩個不能比 l 長 并且加上 offset 也不能超過 l
r_offset = int(minV / 8)
pSplitW = splitW + (r_d + r_offset) * 2
pSplitL = splitL + (r_d + r_offset) * 2
pimg = img.load()
# 存(row - 1) * (col - 1) 個中心點
pointList = []
for i in range(row):
colPointList = []
for j in range(col):
colPoint = []
rowPoint = []
if j != col - 1:
colPoint = [splitW * (j + 1), int(splitL/2) + i * splitL]
if i != row - 1:
rowPoint = [int(splitW / 2) + j * splitW, splitL * (i + 1)]
colPointList.append({'colPoint': colPoint, 'rowPoint': rowPoint})
imbList[i][j] = Resize(imbList[i][j], pSplitW, pSplitL, [r_d + r_offset, r_d + r_offset])
dirPath = path_name + "/" + str(i*10 + j) + ".png"
# imbList[i][j].save(dirPath)
pointList.append(colPointList)
for i in range(row):
for j in range(col):
imbImg = imbList[i][j]
new_img = imbImg
# 圓心靠左 靠右, 默認靠右
lrandNum = random.randint(0, 999999)
drandNum = random.randint(0, 999999)
lrRight = True
drRight = True
if lrandNum < 500000:
lrRight = False
if drandNum < 500000:
drRight = False
new_img_imb = new_img.load()
if j != col - 1:
if lrRight :
new_next_img = imbList[i][j + 1]
new_next_img_imb = new_next_img.load()
# 左右
for k in range((j + 1) * splitW, (j + 1) * splitW + r_d + r_offset):
for z in range(i * splitL, (i + 1) * splitL):
r_w = pointList[i][j]['colPoint'][0] + r_offset
r_l = pointList[i][j]['colPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]
new_next_img_imb[k - (j + 1) * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)
imbList[i][j + 1] = new_next_img
else:
new_next_img = imbList[i][j + 1]
new_next_img_imb = new_next_img.load()
# 左右
for k in range((j + 1) * splitW - r_d - r_offset, (j + 1) * splitW):
for z in range(i * splitL, (i + 1) * splitL):
r_w = pointList[i][j]['colPoint'][0] - r_offset
r_l = pointList[i][j]['colPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_next_img_imb[k - (j + 1) * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]
new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)
imbList[i][j + 1] = new_next_img
if i!= row - 1:
if drRight:
new_down_img = imbList[i + 1][j]
new_down_img_imb = new_down_img.load()
# 上下
for k in range(j * splitW, (j + 1) * splitW):
for z in range((i + 1) * splitL, (i + 1) * splitL + r_d + r_offset):
r_w = pointList[i][j]['rowPoint'][0]
r_l = pointList[i][j]['rowPoint'][1] + r_offset
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]
new_down_img_imb[k - j * splitW + r_d + r_offset, z - (i + 1) * splitL + r_d + r_offset] = (255,255,255,0)
imbList[i + 1][j] = new_down_img
else:
new_down_img = imbList[i + 1][j]
new_down_img_imb = new_down_img.load()
# 上下
for k in range(j * splitW, (j + 1) * splitW):
for z in range((i + 1) * splitL - r_d - r_offset, (i + 1) * splitL):
r_w = pointList[i][j]['rowPoint'][0]
r_l = pointList[i][j]['rowPoint'][1] - r_offset
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_down_img_imb[k - j * splitW + r_d + r_offset, z - (i + 1) * splitL + r_d + r_offset] = pimg[k, z]
new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)
imbList[i + 1][j] = new_down_img
imbList[i][j] = new_img
for i in range(row):
for j in range(col):
dirPath = path_name + "/" + str(i*10 + j) + ".png"
imbList[i][j].save(dirPath)
if __name__ == '__main__':
dirPath = "E:/PythonWorkSpace/slice_pic/"
SplitCircle(SplitImages(dirPath + "a.png", 6, 4) , dirPath + "a.png")

完整專案地址
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/298192.html
標籤:其他
