unity3d游戏开发(一)——圈圈叉叉
参考:http://game.ceeger.com/forum/read.php?tid=1719
———————————————————开始—————————————
好吧,吹了那么多我们开始吧,先发个最终截图
当然,你觉得3个格子太少,你还可以扩展成任意格子的,只要你有足够的创意....
游戏是自娱自乐的 圈圈先下一步,然后叉叉下一步,圈圈再下一步.....
———————————先来制作UI部分—————————————————
我的游戏基本上用ngui作为ui层,我会在第一节课详细的讲一下ngui的操作,灰常详细的...
以后我的教程都会忽略这部分的详细过程...
我的教程中绝对不会出现一句系统自带的GUI东西,我都会用NGUI来代替它
让我们打开一个全新的unity项目,然后删除掉主相机,导入ngui...
接着NGUi菜单- > Create a New UI ->然后会出现一个这样的面板,点Create your UI
—————————————————新手可跳过这部分——————————
我建议你们新建一个命名为2dLayer的层,然后设置成它,至于为什么这样做,是为了养成一个良好的习惯,为了以后3d和2d的东西混杂一起时,物理碰撞光线渲染什么的都可以简单的通过这个层,Default这个层在我看来是很危险的 因为你不知何时何地某个东西和它发生了关系....
顺便日西下我其他项目的层...
——————————————————请继续——————————
这时候场景还是空空如也 不过我们的看到场景中多了一个由UI Root (2D)构成的树结构的东西
然后我们最好先确定我们最终要导出的程序屏幕大小是多少,比如我的屏幕设置成了800*600
那么我们先选择UI Root (2D)->然后在右边的属性面板中这样
UIRoot这个脚本的Auto删掉勾,然后Manual Height设置成600...
(注意Transform的Scale是自动设置的 你不用动它)
然后选择Panel,然后Ngui菜单->Create a widget -> 出现了一个新面板
这时候先不要着急, 先放到一边,点回资源文件夹中NGUI Examples自带的SciFi 的 资源 SciFi Atlas
像这样 直接拖动SciFi Atlas 到新面板的Atlas中, Font 也是如此,将SciFi Font - Header 拖到新面板的Font中
这样子,Template选择Label
成功出现一个New Label的字样在屏幕上....
=,=这个Label用来给我们的游戏提示输赢信息.....
——————
然后我们再一次这样子创建一个button....方法和上面几乎一样,这时Altas和Font应该不用再拖动了
Template选择button,
background选择Dark,
在屏幕上出现了一个button了,然后选择button,删除掉UIButton offset 这个脚本(我可不想选什么的时候都乱动一下)
菜单-> component -> NGUI -> interaction -> button message 的脚本
请将button message 脚本的target设置为 UI Root(2d)
然后 Function Name 设置为 ButtonPress
这里这样设置是为了下面我们的程序来调用的....
将boxCollider 的 x 和 y 分别设置成40,这个东西很重要 因为我们鼠标点击的时候就靠这个...
好了 到此我希望你还能跟得上我的节奏....
选择button,然后将它下面的子物体Label删去... 添加两个新的Sprite...
添加方法和上面的一样:菜单 -> NGUI - > create a widget ...
Template 选择 sprite 然后
其中一个sprite选择 X , 然后将名字改成Chacha
另一个sprite选择 Button , 然后将名字改成Quan
Chacha的Depth改成1,Scale 改成(25,25,1)
Quan的Depth改成2,Scale 改成(40,40,1)
SlicedSprite (Dark)的Depth改成0,Scale 改成(50,50,1)
其中一个Chacha的截图
大功告成
到此为止,我们的UI/交互层 算是全部做好了....
—————————————————新手可跳过这部分——————————
我们在游戏制做过程中一定要规划好游戏的逻辑层次关系,比如我推崇最起码的三层游戏结构
UI/交互层 <--> 逻辑层 <--> 数据层 这样的关系 各层之间留有一定的接口可以相互访问,绝对不要将所有的东西放在一起,这样会混乱得难以管理的
游戏越大型 这样的层次就越重要....
不过这个圈圈叉叉游戏还是用不到数据层了...
—————————————————下面我们开始逻辑层的接口部分——————————
终于要开始写代码了 基动啊.....
创建一个名为QuanQuan的c#脚本,然后付在UI Root (2D)上,我们目前整个游戏都靠这个脚本来管理
首先我们想到的肯定是把这个Label和Button 作为2d的接入口传到脚本中
public GameObject gamePanel; //将Panel这个物体拖到这里
public GameObject ShowLable; //将Label这个物体拖到这里
public GameObject _Qizi; //将Button这个物体拖到这里
简单吧...然后我们定义棋盘的大小,我们先规定这个棋盘必须是n*n的-,-就是长和宽一样啦
public int number_N = 3; //棋盘大小
public int TwohengWidth = 50; //两个棋子的距离
最后如图:public的接口算是写好了....
(注 那个HengWidth属性在这个游戏中大家可无视....,还有number_N 请设置成3)
———————————然后我们讨论下核心的判断部分————————————————
这种明显的方块格子的游戏,很多时候我们一眼就应该想到用 int[][] 这样的2维数组来存储和判断信息....
我们这里设置空的方块为0 叉叉的用-1表示 圈圈用1表示
每下一步的时候,判断横边,竖边,斜边 每一边相加的结果是不是3或者是-3 这样子就可以判断输赢了
比如一开始的状态
{
0 , 0 , 0
0 , 0 , 0
0 , 0 , 0
}
某种赢了的状态
{
0 , 0 , 0
1, 1 , 1
-1 , -1 , 0
}
————————————游戏的状态机制————————————————
我们下棋的时候总是这样:我下完一步,然后到你下一步,一直到最终结束
enum GameState
{
MyAction,
AiAction,
GameOver,
}
GameState gameState = GameState.MyAction;
—————————————start()应该放什么—————————————
首先算出一个左下角的原点OriginPoint,以方便我们排列整个棋盘
然后根据棋盘的大小创建3*3个棋子(复制于_Qizi)
mQizi[i, j] = Instantiate(_Qizi) as GameObject;
mQizi[i, j].name = "qizi_"+i+"_"+j; //命名很重要 因为我们在button获取信息时就是通过name的不同来区分不同物体的
mQizi[i, j].transform.parent = _Qizi.transform.parent; //设置相同的父物体方便我们管理
mQizi[i, j].transform.localPosition = new Vector3(OriginPoint.x + (j) * TwohengWidth, OriginPoint.y + (i) * TwohengWidth, 0);
mQizi[i, j].transform.localScale = new Vector3(1, 1, 1); //父物体改变后我们应该重新设置scale
mQizi[i,j].transform.FindChild("Quan").GetComponent().enabled = false;
mQizi[i,j].transform.FindChild("Chacha").GetComponent().enabled = false;
—————————————updata应该放什么———————————————
nothing , 这个简单的游戏机制导致我们不用设置“等待”和 “过渡” 这样的东西....
—————————————扩展学习部分———————
通常我们见到的简单的状态机都是类似这样的设置..
void updata()
{
if (gameState == MyAction){}
else if(gameState == AiAction){}
else if(gameState==GameOver){}
}
———————————button怎么交互———————————————
还记得池塘边的夏荷么 还记得上面的Button message 发送给ui root的fun 函数么
我们对物体进行 y_x 这样的命名就是方便干这个的...
void ButtonPress(GameObject o) 这个函数要通过GameObject o这样的参数得到它自身
简单来说,我们点了button之后就sendmessage给这个函数了
通过对button的名字的操作 可以得到物体所处的横竖坐标
string[] _strArr = (o.name).Split(new char[]{'_'});
int _row = Convert.ToInt32(_strArr[1]);
int _column = Convert.ToInt32(_strArr[2]);
比如这个qizi_0_0就是表示左下角数起的0,0 这个棋子
int数组中坐标排列方式
{
(2,0),(2,1),(2,2)
(1,0),(1,1),(1,2)
(0,0),(0,1),(0,2)
}
然后我们判断现在的游戏状态(也就是是谁在下)
if (gameState == GameState.MyAction) 这样
然后判断下的棋子是不是空格(只有空格子能下)
if (isNullStep(BoxMatrix , _row, _column))
能下的空格子的话就改变BoxMatrix【】【】的值,改成1或者-1
———————重要的逻辑判断———————
分为4大步骤:
1先判断横列
2判断数列
3如果是斜边的话,判断斜边的列
4如果TotleStep ==棋盘大小,则和局 游戏结束
这里说得好简单 其实真正写起来这个好复杂....
——————————
完整代码:
using UnityEngine;
using System.Collections;
using System; /**
* by:KuKu小夭
* email:djy2130@qq.com
*/ public class QuanQuan : MonoBehaviour {
public GameObject gamePanel;
public GameObject ShowLable;
public GameObject _Qizi;
public int number_N = ;//行列数
public int TwohengWidth = ;//两个横边之间的间隔 private int BoxHeight;
private int BoxWidth;
private int[,] BoxMatrix;
private Vector3 OriginPoint;//左下角原点的位置
private int TotleStep = ;//总共下的次数,如果次数等于棋盘的大小则和局
private int _winTotle = ; //几个子连一起为赢。 enum GameState
{
MyAction,
AiAction,
GameOver,
}
GameState gameState = GameState.MyAction; void Start()
{ BoxHeight = number_N;
BoxWidth = number_N; BoxMatrix = new int[BoxHeight, BoxWidth];
//0 表示空,1表示圈,-1表示叉
//创建一个和棋盘等数量的int数组
OriginPoint = new Vector3(-(BoxWidth - ) * 0.5f * TwohengWidth, -(BoxHeight - ) * 0.5f * TwohengWidth, );
/*
if (number_N%2==0)
{
OriginPoint = new Vector3(-(BoxWidth-1) * 0.5f * TwohengWidth, -(BoxHeight-1) * 0.5f * TwohengWidth, 0);
}else{
OriginPoint = new Vector3(-(BoxWidth-1) * 0.5f * TwohengWidth, -(BoxHeight-1) * 0.5f * TwohengWidth, 0);
}
*/ //最重要的部分
GameObject[,] mQizi = new GameObject[BoxWidth,BoxHeight];
for (int i = ; i < BoxWidth; i++)
{
for (int j = ; j < BoxHeight; j++)
{
BoxMatrix[i, j] = ;
mQizi[i, j] = Instantiate(_Qizi) as GameObject;
mQizi[i, j].name = "qizi_"+i+"_"+j; //命名很重要 因为我们在button获取信息时就是通过name的不同来区分不同物体的
mQizi[i, j].transform.parent = _Qizi.transform.parent;
mQizi[i, j].transform.localPosition = new Vector3(OriginPoint.x + (j) * TwohengWidth, OriginPoint.y + (i) * TwohengWidth, );
mQizi[i, j].transform.localScale = new Vector3(, , );
}
}
_Qizi.transform.localPosition = new Vector3(-, , );//这个东西移到屏幕外
//Destroy(_Qizi);
} //动作
void ButtonPress(GameObject o)
{
if (gameState == GameState.MyAction)
{
string[] _strArr = (o.name).Split(new char[]{'_'});
int _row = Convert.ToInt32(_strArr[]);
int _column = Convert.ToInt32(_strArr[]);
//Debug.Log(_row + "," + _column);
if (isNullStep(BoxMatrix , _row, _column))
{
BoxMatrix[_row, _column] = ;
o.transform.FindChild("Quan").GetComponent<UISprite>().enabled = true;
bool isGameover = Logic(BoxMatrix, _row, _column);
if (isGameover) { gameState = GameState.GameOver; }
else{ gameState = GameState.AiAction;}
}
}
else if (gameState == GameState.AiAction)
{
string[] _strArr = (o.name).Split(new char[] { '_' });
int _row = Convert.ToInt32(_strArr[]);
int _column = Convert.ToInt32(_strArr[]);
//Debug.Log(_row + "," + _column);
if (isNullStep(BoxMatrix , _row, _column))
{
BoxMatrix[_row, _column] = -;
o.transform.FindChild("Chacha").GetComponent<UISprite>().enabled = true;
bool isGameover = Logic(BoxMatrix, _row, _column);
if (isGameover) { gameState = GameState.GameOver; }
else { gameState = GameState.MyAction; }
}
}
} bool isNullStep(int[,] _Matrix, int row, int column)
{
if (_Matrix[row, column] == )
{
return true;
}
return false;
} bool Logic(int[,] _Matrix,int row, int column)
{
//check row
int _totle = ;
for(int i=; i < number_N;i++)
{
_totle += _Matrix[i,column];
}
if (_totle == _winTotle)
{
Winner(); return true;
}
else if (_totle == - * _winTotle)
{
Winner(); return true;
} //check column
_totle = ;
for(int i=; i < number_N;i++)
{
_totle += _Matrix[row,i];
}
if (_totle == _winTotle)
{
Winner(); return true;
}
else if (_totle == - * _winTotle)
{
Winner(); return true;
} ////check left xie 这里只判断最长的斜对角线
//if(row ==column){
// _totle = 0;
// for (int i = 0; i < number_N; i++)
// {
// _totle += _Matrix[i, i];
// }
// if (_totle == number_N)
// {
// Winner(1); return true;
// }
// else if (_totle == -1 * number_N)
// {
// Winner(2); return true;
// }
//} ////check right xie 这里只判断对角线
//if(row == number_N - 1 - column)
//{
// _totle = 0;
// for (int i = 0; i < number_N; i++)
// {
// _totle += _Matrix[i, number_N - i-1];
// }
// if (_totle == number_N)
// {
// Winner(1); return true;
// }
// else if (_totle == -1 * number_N)
// {
// Winner(2); return true;
// }
//} int iCount = row + column;
//check left xie
_totle = ;
//把棋盘分成两部分,沿对角线分
if (iCount < number_N) //在对角线下部分,必定有[x,0]
{
for (int j = ; j < iCount + ; j++)
{
_totle += _Matrix[iCount - j, j];
}
if (_totle == _winTotle)
{
Winner(); return true;
}
else if (_totle == - * _winTotle)
{
Winner(); return true;
}
}
else //在对角线上,必定有[8,x]
{
int i = * (number_N - ) - iCount;
for (int j = number_N - , k = number_N - - i; j >= number_N - - i; j--, k++)
{
_totle += _Matrix[j, k];
}
if (_totle == _winTotle)
{
Winner(); return true;
}
else if (_totle == - * _winTotle)
{
Winner(); return true;
}
} //check right xie
_totle = ;
if (column >= row) //对角线下方
{
int i = number_N - (column - row);
for (int j = ; j < i; j++)
{
_totle += _Matrix[j, j + column - row];
}
if (_totle == _winTotle)
{
Winner(); return true;
}
else if (_totle == - * _winTotle)
{
Winner(); return true;
}
}
else //对角线上方
{
int i = number_N + (column - row);
for (int j = ; j < i; j++)
{
_totle += _Matrix[j - column + row, j];
} if (_totle == _winTotle)
{
Winner(); return true;
}
else if (_totle == - * _winTotle)
{
Winner(); return true;
}
}
//检查是不是和局
TotleStep++;
if (TotleStep == BoxHeight * BoxWidth)
{
Winner();return true;
} return false;
} void Winner(int player)
{
if (player==)
{
ShowLable.GetComponent<UILabel>().enabled = true;
ShowLable.GetComponent<UILabel>().text = "winner 1";
}
else if (player == )
{
ShowLable.GetComponent<UILabel>().enabled = true;
ShowLable.GetComponent<UILabel>().text = "winner 2";
}
else
{
ShowLable.GetComponent<UILabel>().enabled = true;
ShowLable.GetComponent<UILabel>().text = "no winner";
}
}
}
项目下载地址:http://pan.ceeger.com/viewfile.php?file_id=1823&file_key=0KzsoygG
unity3d游戏开发(一)——圈圈叉叉的更多相关文章
- Unity3D游戏开发初探—2.初步了解3D模型基础
一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...
- 从一点儿不会开始——Unity3D游戏开发学习(一)
一些废话 我是一个windows phone.windows 8的忠实粉丝,也是一个开发者,开发数个windows phone应用和两个windows 8应用.对开发游戏一直抱有强烈兴趣和愿望,但奈何 ...
- Unity3D游戏开发之连续滚动背景
Unity3D游戏开发之连续滚动背景 原文 http://blog.csdn.net/qinyuanpei/article/details/22983421 在诸如天天跑酷等2D游戏中,因为游戏须要 ...
- Unity3D游戏开发从零单排(四) - 制作一个iOS游戏
提要 此篇是一个国外教程的翻译,尽管有点老,可是适合新手入门. 自己去写代码.debug,布置场景,能够收获到非常多.游戏邦上已经有前面两部分的译文,这里翻译的是游戏的最后一个部分. 欢迎回来 在第一 ...
- [Unity3D]Unity3D游戏开发之飞机大战项目解说
大家好,我是秦元培,欢迎大家继续关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei. 首先感谢大家对我博客的关注,今天我想和大家分享的是一个飞机大战的项目.这是一个比較综合的 ...
- [Unity3D]Unity3D游戏开发《反对》说到游戏(上)——目标跟踪
朋友,大家好.我是秦培,欢迎关注我的博客.我的博客地址blog.csdn.net/qinyuanpei. 首先博主要自我反省,过了这么久才来更新博客,这段时间主要是在忙着写期末的作业,所以博主基本上没 ...
- [Unity3D]Unity3D游戏开发3D选择场景中的对象,并显示轮廓效果强化版
大家好,我是秦培,欢迎关注我的博客,我的博客地址blog.csdn.net/qinyuanpei. 在上一篇文章中,我们通过自己定义着色器实现了一个简单的在3D游戏中选取.显示物体轮廓的实例. 在文章 ...
- [Unity3D]Unity3D游戏开发之跑酷游戏项目解说
大家好,我是秦元培.我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客. 大家晚上好.我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.c ...
- [Unity3D]Unity3D游戏开发之异步记载场景并实现进度条读取效果
大家好,我是秦元培.欢迎大家关注我的博客,我的博客地址是:blog.csdn.net/qinyuanpei.终于在各种无语的论文作业中解脱了,所以立即抓紧时间来这里更新博客.博主本来计划在Unity3 ...
- [Unity3D]Unity3D游戏开发之伤害数值显示
大家好,我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei.众所周知,在RPG游戏策划中最为重要的一个环节是数值策划.数值策划是一个关于游戏平衡方面的概念 ...
随机推荐
- redis的hash操作在集中式session中的应用
在集群部署时,为了高可用性的目的,往往把session进行共享,共享分为两种:session复制和集中式管理. redis在session集中式管理中可以起到比较大的作用. 制约session集中式共 ...
- [COCOS2DX]官网helloworld在VS2012中的部署
VS2012.JDK.Eclipse(和adt插件)之类的基本安装这里直接略过. 以下为对cocos2dx 3.5版本在VS2012中部署的摸索: 开源项目“愤怒的小鸟”原来设置: .;..\Clas ...
- Linux学习之路:shell变量(一)
一.变量的显示与设置 1.变量的显示运用echo命令 +$符号: 上图例子显示的是系统变量,咱们可以自己设置变量 2.设置变量运用“=”符号 设置了变量NIU 值为“niunai” 变量设置规则: ( ...
- posix thread互斥量
互斥量 互斥量(Mutex)是“mutual exclusion”的缩写.互斥量是实现线程同步,和保护同时写共享数据的主要方法.使用互斥量的典型顺序如下:1. 创建和初始一个互斥量 2. 多个线程尝试 ...
- 【转】MyBatis学习总结(七)——Mybatis缓存
[转]MyBatis学习总结(七)——Mybatis缓存 一.MyBatis缓存介绍 正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持 一级缓存: 基于PerpetualC ...
- akka构建简单分布式应用
http://www.cnblogs.com/hequn/articles/3764630.html 当程序的要求达到一台计算机的极限时,我们便需要将程序分布式化,让程序运行在多台计算机上.akka提 ...
- C++多态性与C#的比较
多态性:统一操作作用于不同的对象可以有不同的解释,产生不同的执行结果.多态性可以分为两种:一是编译时的多态性,一是运行时的多态性. 编译时的多态性包括重载.覆盖.运算符重载.对于非虚的 ...
- Android通过tcpdump抓包(wifi, 2g, 3g都可以)
http://blog.csdn.net/deng529828/article/details/20646197 1. 手机要有root权限 2. 下载tcpdump http://www.str ...
- JQuery弹出层,实现弹层切换,可显示可隐藏。
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <t ...
- asp:第三平台登陆
第三平台登陆接口申请网址: http://open.51094.com/ 文档: 第三方合作登录平台使用说明 为方便更多的开发朋友,本人特将当前市面上所有支持第三方联合登录的接口集为一体,以前需要多次 ...