Unity3d制作简单拼图游戏
本文为原创,如需转载请注明原址:http://blog.csdn.net/cube454517408/article/details/7907247
最近一直在使用Unity,对它有了一些小的使用心得
今天写一个简单的拼图游戏实例来和大家分享一下Unity中material.mainTextureOffset和material.mainTextureScale的作用和用法
mainTextureOffset和mainTextureScale是Material类中的两个方法
mainTextureOffset指的是主纹理偏移
mainTextureScale指的是主纹理缩放
默认一个material的mainTextureOffset是0,0,mainTextureScale是1,1
表示原图正常显示,没有缩放,如下图
当我们改变mainTextureScale的值时纹理只会显示一部分,其范围是[0,1];
如我们将mainTextureScale.x设置为0.5时,可以看到纹理只显示u方向的50%
同理,我们将mainTextureScale.y设置为0.5时,可以看到纹理只显示v方向的50%
mainTextureOffset属性表示纹理的起始偏移,为0时没有偏移,mainTextureOffset.x指u方向的偏移量,mainTextureOffset.y指v方向的偏移量。其范围也是[0,1]。这里要注意:偏移的起点在图像的左下角
我们设置mainTextureOffset.x为0.2,如下图:
可以看到纹理向左偏移了20%
我们设置mainTextureOffset.y为0.2,如下图:
可以看到纹理向下偏移了20%
应用这两个属性,我们可以只截取图片的一部分来显示,如:
mainTextureOffset = new Vector2(0.5, 0.5);
mainTextureScale= new Vector2(0.5, 0.5);
将只显示原图的右上角1/4区域,如下图:
有了对以上两个属性的了解,我们可以来制作一个简单的拼图游戏
思路:
1.将一张图片切分为raw*volumn的raw*volumn张碎片
2.每一张碎片只显示图片的一部分
3.将它们按一个顺序和位置排列,使其看起来像一张完整的图片
玩法:
点击Start按钮后,开始游戏。选中碎片并将其拖放在正确的位置上,如放置正确则不可再被拖动。直到所有碎片放置正确。
点击Next Texture按钮可切换背景和碎片显示的图片
制作流程:
新建一个游戏场景Test,设置摄像机属性如下(采用正交摄像机(2D)将其标签设置MainCamera):
创建两个plane,其中一个改名为Background并为其选择一个材质;另一个plane也选择一个材质要和前一个不同,选择shader为Unlit/Transparent (自发光),将其设为不可见。创建一个空对象,起名为Body,如下图:
创建一个c#脚本main.cs,绑定在Body对象下。Inspector设置如下:
main.cs脚本如下:
using UnityEngine;
using System.Collections;
public class main : MonoBehaviour {
public GameObject _plane; //用来实例碎片的对象
public GameObject _planeParent; //碎片对象所要绑定的父节点
public GameObject _background; //显示暗色的背景图
public Texture2D[] _texAll; //用来更换的纹理
public Vector3[] _RandomPos; //开始时, 碎片随机分布的位置
public int raw = 3; //图形切分的行数
public int volumn = 3; //图形切分的列数
public float factor = 0.25f; //一个范围比例因子, 用来判断碎片是否在正确位置范围内
GameObject[] _tempPlaneAll;
float sideLength = 0; //背景图的边长(正方形)
int finishCount = 0; //完成的碎片数量
int _index = 0;
Vector2 originPoint; //第一个碎片的位置
Vector2 space; //碎片与碎片之间的间隔(中心距x,y)
void Start()
{
sideLength = _background.transform.localScale.x;
space.x = sideLength / volumn;
space.y = sideLength / raw;
originPoint.x = -((volumn - 1) * space.x) / 2;
originPoint.y = ((raw - 1) * space.y) / 2;
Vector2 range;
range.x = space.x * factor * 10f;
range.y = space.y * factor * 10f;
_tempPlaneAll = new GameObject[raw * volumn];
int k = 0;
//完成所有碎片的有序排列位置和uv纹理的截取
for(int i = 0 ; i != raw ; ++i)
{
for(int j = 0 ; j != volumn ; ++j)
{
GameObject tempObj = (GameObject)Instantiate(_plane);
tempObj.name = "Item" + k;
tempObj.transform.parent = _planeParent.transform;
tempObj.transform.localPosition = new Vector3((originPoint.x + space.x * j) * 10f, (originPoint.y - space.y * i) * 10f, 0);
tempObj.transform.localScale = new Vector3(space.x, 1f, space.y);
Vector2 tempPos = new Vector2(originPoint.x + space.x * j, originPoint.y - space.y * i);
float offset_x = (tempPos.x <= 0 + Mathf.Epsilon) ? (0.5f - Mathf.Abs((tempPos.x - space.x / 2) / sideLength)) : (0.5f + (tempPos.x - space.x / 2) / sideLength);
float offset_y = (tempPos.y <= 0 + Mathf.Epsilon) ? (0.5f - Mathf.Abs((tempPos.y - space.y / 2) / sideLength)) : (0.5f + (tempPos.y - space.y / 2) / sideLength);
float scale_x = Mathf.Abs(space.x / sideLength);
float scale_y = Mathf.Abs(space.y / sideLength);
tempObj.renderer.material.mainTextureOffset = new Vector2(offset_x, offset_y);
tempObj.renderer.material.mainTextureScale = new Vector2(scale_x, scale_y);
tempObj.SendMessage("SetRange", range);
_tempPlaneAll[k] = tempObj;
++k;
}
}
}
void OnGUI()
{
//开始游戏
if(GUI.Button(new Rect(10, 10, 100, 30), "Play"))
StartGame();
//更换纹理
if(GUI.Button(new Rect(10, 80, 100, 30), "Next Textrue"))
ChangeTex();
}
void StartGame()
{
//将所有碎片随机分布在左右两边
for(int i = 0 ; i != _tempPlaneAll.Length ; ++i)
{
int tempRank = Random.Range(0, _RandomPos.Length);
_tempPlaneAll[i].transform.localPosition = new Vector3(_RandomPos[tempRank].x, _RandomPos[tempRank].y, 0f);
}
//通知所有子对象, 开始游戏
gameObject.BroadcastMessage("Play");
}
void SetIsMoveFale()
{
gameObject.BroadcastMessage("IsMoveFalse");
}
void IsFinish()
{
//计算放置正确的碎片数量
++finishCount;
if(finishCount == raw * volumn)
Debug.Log("Finish!");
}
void ChangeTex()
{
_background.renderer.material.mainTexture = _texAll[_index];
gameObject.BroadcastMessage("SetTexture", _texAll[_index++]);
if(_index > _texAll.Length - 1)
_index = 0;
}
}
再创建一个c#脚本为plane.cs,绑定在Plane对象下。Inspector设置如下:
注意:要为Plane对象添加一个Collider组件,因为Plane对象的scale与Unity的基本单位(米)的比例为10:1,因此这里Collider的Size要设置为10
plane.cs脚本如下:
using UnityEngine;
using System.Collections;
public class plane : MonoBehaviour {
Transform mTransform;
Vector3 offsetPos; //鼠标点与所选位置的偏移
Vector3 finishPos = Vector3.zero; //当前碎片的正确位置
Vector2 range; //碎片正确位置的范围, 由SetRange函数设置
float z = 0;
bool isPlay = false; //是否进行游戏?
bool isMove = false; //当前碎片是否跟随鼠标移动
void Start()
{
mTransform = transform;
finishPos = mTransform.localPosition;
}
void Update()
{
if(!isPlay)
return ;
//当鼠标进入碎片中按下时, 记录与碎片中心位置的偏差; 并使碎片跟随鼠标移动(多张碎片叠在一起时,只选其中一张跟随)
Vector3 tempMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
if(Input.GetMouseButtonDown(0) && tempMousePos.x > collider.bounds.min.x && tempMousePos.x < collider.bounds.max.x
&& tempMousePos.y > collider.bounds.min.y && tempMousePos.y < collider.bounds.max.y)
{
mTransform.parent.SendMessage("SetIsMoveFale");
offsetPos = mTransform.position - tempMousePos;
z = mTransform.position.z;
isMove = true;
}
//跟随鼠标移动
if(isMove && Input.GetMouseButton(0))
{
tempMousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mTransform.position = new Vector3(tempMousePos.x + offsetPos.x, tempMousePos.y + offsetPos.y, z - 0.1f);
}
//鼠标放开后停止跟随
if(Input.GetMouseButtonUp(0))
{
mTransform.position = new Vector3(mTransform.position.x, mTransform.position.y, z);
isMove = false;
}
//判断是否到达正确位置(如进入正确位置范围, 碎片自动设置在正确位置, 并不可被再移动)
IsFinish();
}
void IsFinish()
{
if(mTransform.localPosition.x > finishPos.x - range.x && mTransform.localPosition.x < finishPos.x + range.x
&& mTransform.localPosition.y > finishPos.y - range.y && mTransform.localPosition.y < finishPos.y + range.y)
{
isPlay = false;
mTransform.localPosition = finishPos;
mTransform.parent.SendMessage("IsFinish");
}
}
//开始游戏
void Play()
{
isPlay = true;
}
void IsMoveFalse()
{
isMove = false;
}
void SetRange(Vector2 _range)
{
range = _range;
}
//更换纹理
void SetTexture(Texture2D _tex)
{
mTransform.renderer.material.mainTexture = _tex;
}
}
现在可以开始游戏了,如下图:
程序源码及打包文件在此下载:http://download.csdn.net/detail/cube454517408/4525682
使用方法:打开一个空Unity场景,点击Assets->Import Package->Custom Package导入即可。注意:不要有中文路径
Unity3d制作简单拼图游戏相关推荐
- 用flash制作简单拼图游戏
简介: 可能有很多玩Flash的朋友都曾和我一样想自己动手制作一个拼图游戏,但是苦于不知道实现的方法或不了解ActionScript(以下简称AS)而心存遗憾.别急,今天盗匪就告诉你如何利用Flash ...
- H5原生js简单拼图游戏
H5原生js简单拼图游戏 演示地址 效果展示 源码 index.html puzzle.css puzzle.js 源码下载 演示地址 链接: 演示地址 效果展示 源码 index.html < ...
- 用c语言做一个五子棋程序,C语言制作简单五子棋游戏
原标题:C语言制作简单五子棋游戏 C语言制作简单的五子棋游戏 学习C语言的人很多,但是用C语言很少,而用来为自己所用,来做游戏的人就更少了,很多人都是跟着学校学习,学校讲到哪就坐到哪,但是以后却还是不 ...
- python制作五子棋_python制作简单五子棋游戏
python制作简单五子棋游戏 来源:中文源码网 浏览: 次 日期:2019年11月5日 [下载文档: python制作简单五子棋游戏.txt ] (友情提示:右键点上行txt文档名->目标另存 ...
- php拼图游戏开发,原生javascript制作的拼图游戏实现方法详解
本文实例讲述了原生javascript制作的拼图游戏实现方法.分享给大家供大家参考,具体如下: 实现方法 //1.让所有的li(在ul里)可以拖拽 //2.交换li的位置 计算背景图位置 //1.让 ...
- 用 JavaScript 实现简单拼图游戏
本篇主要讲解,如何利用原生的 JavaScript 来实现一个简单的拼图小游戏. 线上体验地址:拼图 一.游戏的基础逻辑 想用一门语言来开发游戏,必须先了解如何使用这门语言来实现一些基础逻辑,比如图像 ...
- python制作简单拼图小游戏
开发工具 **Python版本:**3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 关注公众号:Python学习指南,回复"拼图"即可获取源码 环境搭建 ...
- 使用unity3d制作像素鸟游戏
个人博客文章链接:http://www.huqj.top/article?id=140 unity3d虽然是被设计用来制作3D游戏的,但是它提供了很多2D组件,所以也可以轻松的设计制作2D游戏,下面记 ...
- Qt实现简单拼图游戏
文章目录 前言 演示图 1.ShowWidget.h 2.ShowWidget.cpp 3.MainWindow.h 4.MainWindow.cpp 前言 自己简单实现了下拼图功能.本来开始只是想显 ...
最新文章
- 【转】U3D手游《苍穹变》性能优化经验谈
- numpy基础(part6)--协方差与相关系数
- 程序员修仙之路-数据结构之 CXO让我做一个计算器
- kali wifi密码 破解
- android 个人标准身高计算器,Android开发:标准身高计算器应用的…
- Win7/8/10系统下Protel 99 SE不能添加元件库 File is not recognized
- 802.1x协议身份认证
- Java web 集成使用QQ互联
- 谷歌SEO专业术语指南
- 计算机相关专业学历重要么?
- 奥维 最新 图源2023
- web前端开发主要培训哪些内容
- python3凸优化
- 3d效果图制作傻瓜软件_不会3D软件,也能轻松制作三维效果图!
- 深度挖掘:FIashGet下载隐藏链接[转]
- 驾照科目一知识点——1、准驾车型
- Linux指南| 第2部分
- Cocos Creator 2.3.3 更新说明,效率即是一切!
- Android: JellyBean 彩蛋
- 《中国移动大数据数据治理体系.pdf》限时开放下载!