• 【跟我一起学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


  • 相关阅读:
    python 抓取网页
    Vim XDebug调试PHP php远程调试
    10 条 nmap 技巧
    Linux修改文件及文件夹权限
    mysql 常用命令 汇总
    VS2010打开过多的IntelliTrace.exe进程导致虚拟内存不足的解决办法
    黄聪:MYSQL远程连接失败:ERROR 1130: mysql 1130连接错误的有效解決方法
    黄聪:WordPress搬家更换域名教程
    黄聪:使用 ALinq 实现 Linq to MySQL【转】
    黄聪:Filezilla 二进制上传设定
  • 原文地址:https://www.cnblogs.com/llguanli/p/7201933.html
Copyright © 2020-2023  润新知