【跟我一起學Unity3D】代碼中分割圖片而且載入幀序列動畫
在Cocos2dx中。對大圖的處理已經封裝好了一套自己的API,可是在Unity3D中貌似沒有類似的API(好吧,實際上是有的,並且功能更強大),或者說我沒找到。
只是這也在情理之中,畢竟Unity3D是做3D的。要分割圖片的地方還是非常少的。
由於我用Unity3D主要是用於做2D遊戲的(PS:非常蛋疼吧?我也認為),所以就不得不考慮切圖和播放序列幀這兩個在2D上常見的功能了,以下廢話不多說。
我的任務是把以下這張圖分割成16塊。而且依照動畫的序列播放出來。
查Unity3D的使用手冊的過程中,我發現了一個類:Texture2D,他是繼承Texture的,主要是用於創建2D紋理的,很符合切圖的須要。
首先,我們須要載入大圖。載入大圖有一個很easy的方法。就是創建一個public的Texture2D類成員變量,然後在編輯器中直接拖動到上去給他賦值就能夠了。
當然也能夠採用動態載入圖片資源的方法,這樣的方法比較麻煩。須要把圖片先轉換成二進制流,然後賦值給Texture2D
//載入圖片資源 void LoadTexture() { using (FileStream file = File.Open (Application.dataPath + "/Textures/Player.png", FileMode.Open)) { using (BinaryReader reader = new BinaryReader(file)) { m_texPlayer = new Texture2D (192, 256, TextureFormat.ARGB4444, false); texture.LoadImage (reader.ReadBytes((int)file.Length)); } } }
載入完之後就要分割了。主要思路就是,兩個for循環,一個表示行,一個表示列,然後再循環每一個像素點。把每一個像素點裏面的顏色復制出來給分割的Texture2D,最後把Texture2D組合成一個4x4的矩陣數組。
以下是第一步:
for (int i = 0; i < m_iMinPicColumnCount; ++i) { for (int j = 0; j < m_iMinPicRowCount; ++j) DePackTexture(i, j); }
上面的終於處理調用了一個DePackTexture,這個函數是用於實際上的分割的。
//切圖 void DePackTexture(int i, int j) { int cur_x = i * m_iMinPicWidth; int cur_y = j * m_iMinPicHeight; Texture2D newTexture = new Texture2D(m_iMinPicWidth, m_iMinPicHeight); for (int m = cur_y; m < cur_y + m_iMinPicHeight; ++m) { for (int n = cur_x; n < cur_x + m_iMinPicWidth; ++n) { newTexture.SetPixel(n - cur_x, m - cur_y, m_texPlayer.GetPixel(n, m)); } } newTexture.Apply(); m_texPlayers[i, j] = newTexture; }切圖值得註意的就是兩點,一點就是找好位置,還有一點就是運行完SetPixel操作後一定要運行Apply,不然是沒有效果的。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
以下是幀序列動畫,幀序列動畫實際上就是將圖片依照一定的順序載入上去,值得註意的是全部的GUI操作一定要放到OnGUI裏面。
void DrawAnimation(Texture[,] tex, Rect rect) { //繪制當前幀 GUI.DrawTexture(rect, tex[m_iCurFram, m_iCurAnimation], ScaleMode.StretchToFill, true, 0.0f); //計算限制幀的時間 m_fTime += Time.deltaTime; //超過限制幀切換貼圖 if (m_fTime >= 1.0 / m_fFps && m_bStop == false) { //幀序列切換 m_iCurFram = ++m_iCurFram % m_iMinPicRowCount; //限制幀清空 m_fTime = 0; //超過幀動畫總數從第0幀開始 if (m_iCurFram >= tex.Length) { m_iCurFram = 0; } } }
然後沒有什麽了,代碼還是非常easy的。以下附上所有的代碼。這個我做成了一個小的demo,含有動畫的開始和暫停功能。並且還有動畫的幀速調整的功能。
(最後會附上demo的地址)
using UnityEngine; using System.Collections; using System; public class CTexture : MonoBehaviour { //大圖的人 public Texture2D m_texPlayer; //小圖的人 private Texture2D[,] m_texPlayers; //當前幀 private int m_iCurFram; //當前動畫 private int m_iCurAnimation; //限制幀的時間 private float m_fTime = 0; //小圖的寬和高 public int m_iMinPicWidth = 48; public int m_iMinPicHeight = 64; //一行有多少個小圖 public int m_iMinPicRowCount = 4; //一列有多少個小圖 public int m_iMinPicColumnCount = 4; //動畫控制 //暫停 private bool m_bStop = false; //一秒多少幀 private float m_fFps = 4; private string m_sFps = ""; void Start() { m_texPlayers = new Texture2D[4, 4]; m_iCurAnimation = 0; m_sFps = m_fFps.ToString(); //載入圖片資源 LoadTexture(); for (int i = 0; i < m_iMinPicColumnCount; ++i) { for (int j = 0; j < m_iMinPicRowCount; ++j) DePackTexture(i, j); } } void Update() { if(Input.GetKeyDown(KeyCode.A)) { m_iCurAnimation = 2; } if (Input.GetKeyDown(KeyCode.S)) { m_iCurAnimation = 3; } if (Input.GetKeyDown(KeyCode.W)) { m_iCurAnimation = 0; } if (Input.GetKeyDown(KeyCode.D)) { m_iCurAnimation = 1; } } void OnGUI() { DrawAnimation(m_texPlayers, new Rect(100, 100, m_iMinPicWidth, m_iMinPicHeight)); if(GUI.Button(new Rect(200,20,80,50),"開始/暫停")) { m_bStop = m_bStop == false ?true : false ; } m_sFps = GUI.TextField(new Rect(200, 80, 80, 40), m_sFps); if (GUI.Button(new Rect(200, 150, 50, 40), "應用")) { m_fFps = float.Parse(m_sFps); } } //載入圖片資源 void LoadTexture() { using (FileStream file = File.Open (Application.dataPath + "/Textures/Player.png", FileMode.Open)) { using (BinaryReader reader = new BinaryReader(file)) { m_texPlayer = new Texture2D (192, 256, TextureFormat.ARGB4444, false); texture.LoadImage (reader.ReadBytes((int)file.Length)); } } } //切圖 void DePackTexture(int i, int j) { int cur_x = i * m_iMinPicWidth; int cur_y = j * m_iMinPicHeight; Texture2D newTexture = new Texture2D(m_iMinPicWidth, m_iMinPicHeight); for (int m = cur_y; m < cur_y + m_iMinPicHeight; ++m) { for (int n = cur_x; n < cur_x + m_iMinPicWidth; ++n) { newTexture.SetPixel(n - cur_x, m - cur_y, m_texPlayer.GetPixel(n, m)); } } newTexture.Apply(); m_texPlayers[i, j] = newTexture; } void DrawAnimation(Texture[,] tex, Rect rect) { //繪制當前幀 GUI.DrawTexture(rect, tex[m_iCurFram, m_iCurAnimation], ScaleMode.StretchToFill, true, 0.0f); //計算限制幀的時間 m_fTime += Time.deltaTime; //超過限制幀切換貼圖 if (m_fTime >= 1.0 / m_fFps && m_bStop == false) { //幀序列切換 m_iCurFram = ++m_iCurFram % 4; //限制幀清空 m_fTime = 0; //超過幀動畫總數從第0幀開始 if (m_iCurFram >= tex.Length) { m_iCurFram = 0; } } } }
demo地址:http://download.csdn.net/detail/baijiajie2012/8092625
【跟我一起學Unity3D】代碼中分割圖片而且載入幀序列動畫