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

时间: 2024-10-18 15:00:20

【跟我一起学Unity3D】代码中分割图片而且载入帧序列动画的相关文章

【跟我一起学Unity3D】代码中切割图片并且加载帧序列动画

在Cocos2dx中,对大图的处理已经封装好了一套自己的API,但是在Unity3D中貌似没有类似的API,或者说我没找到.不过这也在情理之中,毕竟Unity3D是做3D的,要切割图片的地方还是很少的. 因为我用Unity3D主要是用于做2D游戏的(PS:很蛋疼吧?我也觉得),所以就不得不考虑切图和播放序列帧这两个在2D上常见的功能了,下面废话不多说.我的任务是把下面这张图切割成16块,并且按照动画的序列播放出来. 查Unity3D的使用手册的过程中,我发现了一个类:Texture2D,他是继承

Android程序如何在代码中改变图片原有的颜色

最近一边找工作一边完善之前的项目.之前安卓初中级的项目是模仿酷狗音乐播放器的.下载一个apk文件,改后缀,解压,然后根据官方应用的布局,用得到的图片照着做出来.记得酷狗首页有好几种主要图标,解压后得到的白色加透明组合成的,但官方应用是换主题颜色会跟着改变,这回正好有空就网上找来方法跟着改. 因为只是把白色改成别的颜色,所以不难. package com.example.ex_tupian; import android.app.Activity; import android.graphics.

用正则从html代码中提取图片路径

$str = '<div align="center"> <img src="http://www.99tyg.com/public/images/e8/67/26/fc699f23244f7ca7cd360092f6ba5d641d61fe88.jpg?1476757957#h"></div>'; preg_match_all('/<img.*?src="(.*?)".*?>/is',$str,$

TextView之代码中设置图片的操作

/** * 实例化首页订单通知条 */ private TextView getTextView() { // 实例化一个线性布局的参数 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); lp.setMargins(0, 12, 0, 0); textView = new TextView(HomeActivity.

代码: 两列图片瀑布流(一次后台取数据,图片懒加载。下拉后分批显示图片。图片高度未知,当图片onload后才显示容器)

代码: 两列图片瀑布流(一次后台取数据,无ajax,图片懒加载.下拉后分批显示图片.图片高度未知,当图片onload后才显示容器) [思路]: 图片瀑布流,网上代码有多种实现方式,也有各类插件.没找到合意的,所以根据网上找的一段代码,进行了较大改动. 需引用 zepto 或 jquery. 我这个是应用于手机上的,两列瀑布流,图片高度未知——等图片的onloaded事件触发后,才对容器进行计算和定位. 大容器是 $("#imgList"),容器格子是$(".pin"

imagesLoaded – 检测网页中的图片是否加载

imagesLoaded 是一个用于来检测网页中的图片是否载入完成的 JavaScript 工具库.支持回调的获取图片加载的进度,还可以绑定自定义事件.可以结合 jQuery.RequireJS 使用. 插件下载     效果演示 使用示例: // element imagesLoaded( document.querySelector('#container'), function( instance ) { console.log('all images are loaded'); });

unity3D项目中如何避免硬代码(C#)

平时做项目,代码中是不允许出现硬代码的,一般我们是怎么处理的呢? 那么硬代码又是什么呢? 我们俗称的硬代码:eg:  1 public UIlabel label; 2 label.text = "欢迎来到梦幻岛";  这样我们俗称为硬代码. 好了,那么该如何避免,话不多说,直接上图: 这是一种处理方式,TXT 格式的文档,前面是ID,后面是描述性文字. 可是我们该如何在项目中访问这个txt文件里面的数据呢? 话不多说,直接上代码: 1 using UnityEngine; 2 usi

Unity3d 在代码中修改PlayerSetting的Scripting Backend选择IL2CPP/Mono

在Unity3d 自动打包过程中,如果是要提交到AppStore审核的,需要支持64位,就需要在PlayerSetting中选择 Scripting Backend 为IL2CPP. Unity并没有提供一个明确的接口来设置ScriptingBackend,但是通过查询 PlayerSettings 的所有函数发现有一个属性设置公用接口可以使用. 在代码中可以通过设置属性来选择IL2CPP. 文章转自http://blog.csdn.net/huutu/ http://www.thisisgam

09应用输入管理器转动场景--《程序员学Unity3d》

为什么极品飞车等等游戏,都可以通过系统设置很方面地根据自己喜欢设置操作方式,有人喜欢用箭头来控制没有喜欢用用"W,S,A,D"来控制,这就说明了程序员不会把控制方式写死在程序里面,来看看Unity3d如何让用户可以随时修改"快捷键". 优点:不仅方便后期维护,也可以减少很多代码. Edit --Project Settings -- Input 打开输入管理器 前面17组是系统配置的,可以修改或删除. 将Size改为18,新增一组.(名称为Test,对应按键为 a)