Unity3D代码中切割图片并且加载帧序列动画

Unity3D代码中切割图片并且加载帧序列动画

在Cocos2dx中,对大图的处理已经封装好了一套自己的API,但是在Unity3D中貌似没有类似的API,或者说我没找到。不过这也在情理之中,毕竟Unity3D是做3D的,要切割图片的地方还是很少的。

因为我用Unity3D主要是用于做2D游戏的(PS:很蛋疼吧?我也觉得),所以就不得不考虑切图和播放序列帧这两个在2D上常见的功能了,下面废话不多说。我的任务是把下面这张图切割成16块,并且按照动画的序列播放出来。

目标图片

查Unity3D的使用手册的过程中,我发现了一个类:Texture2D,他是继承Texture的,主要是用于创建2D纹理的,非常符合切图的需要。

首先,我们需要加载大图,加载大图有一个非常简单的方法,就是创建一个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;
      }
    }
  }

然后没有什么了,代码还是很简单的。下面附上全部的代码,这个我做成了一个小的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://pan.baidu.com/s/1qWpyf5E

原文:http://blog.csdn.net/nxshow/article/details/40554391

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值