Stage.1——井字棋

k :这学期选了3d游戏编程呢
13:是啊
k :这周也终于来了,期待已久的第一个游戏编程作业
13:没错呢
k :那么,我们就来做个井字棋吧
13:哦,这个还挺好做的,我记得之前看过,就是直接用GUI来做吧,简单的九个Button就可以实现了,然后用一个一维或者是二维的数组来记录状态就好了吧

//在OnGUI函数中,OnGUI()跟Update()函数一样,一般每一帧都会调用
void OnGUI(){
    //int judge()判断游戏是否结束,很简单,只要最后判断一下counter == 9就好
    int result = judge();
    if(result == 0)
        //平局
        return;
    if(result == 1)
        //先手胜。。。
    if(result == 2)
        //后手胜。。。
    //int turn 用来标识本次落子的玩家
    //int[,] state = new int[3,3] 记录棋盘状态的二维数组
    for(int i = 0;i < 3;i++){
        for(int j = 0;j < 3;j++){
            if(state[i,j] == 0 && GUI.Button(new Rect(), "")){
                state[i,j] = turn;
                //change turn ...
            }
            if(state[i,j] == turn1){
                GUI.Button(new Rect(), string_or_texture);
            }
            if(state[i,j] == turn2){
                GUI.Button(new Rect(), string_or_texture);
            }
        }
    }
}

k :不过,既然都叫3d游戏编程了,果然还是得做3d游戏才比较对吧?
13:哈?这个作业不是本来就是让我们学习一下GUI才是目的的嘛(疑惑)
k :我们的目的,不是做一个井字棋吗?学习什么的就不要管那么多了,愉快的把游戏做出来才对啊,你是为什么选这门课的?(一脸无奈)
13:。。。(哇,超想暴打一顿的)
k :好,现在开始了!天下第一3d井字棋大会!
13:。。。。呃,嗯,其实也一样吧,首先是棋盘吧。既然要做棋盘的话,首先会想到的就是。。。
k :方块(Cube)吧
13:方块。。。好吧没错
k :好,那么就这样。。。
13:喂
k :嗯?
13:你。。。想这样弄9个立方体吗?(操作:GameObject -> 3D Object -> Cube * 9)
k :不行吗
13:白痴
k :你说什么?
13:没有,你听错了。话说,不说Duplicate,你应该知道预设(Prefab)吧
k :预设?什么gu。。。啊,哦,预设啊,预设嘛,这种程度的东西我还是懂的,不就是什么,预先。。额。。弄好的咩物件嘛
13:(明显就不知道,但是似乎也没有说错。。。)你至少给我去看一下官方资料也行啊,你什么都不知道就想要做?
k :哼,这你就i不懂了,世界都是从无到有的知道吗,关键要有气势,探索未知的热情!唉,现在的大学生就知道循规蹈矩,不懂得独立探索
13:探索未知 = 井字棋???还有你不也是大学生吗?
k :别在意太多细节嘛,不管怎么说,如果靠自己做出来的话,还是挺有成就感的对吧
13:为什么一副经历了许多的样子?我们现在还什么都没做出来呢。。。既然这样,那你倒是说一下棋子怎么办?
k :哈?那不也一样吗?(GameObject -> 3d Object ->Sphere * 9)
13:放九个棋子在场景中。。。这画面。。。
k :很棒吧?然后玩家落子的时候就点击一颗丢过去就行了
13 :打冰壶吗。。。(不怀好意)那我们下次做个围棋怎样?
k :行啊
13:你来负责场景,我来写脚本
k :好啊。。。咦?额。。那个,围棋要多少个子来着?
13:唔嗯,不太清楚,不过也按点数来算的话,19 * 19,361个吧。嘛,反正你的话肯定没问题的对吧
k :额。。哈哈哈哈。。。
13:哈哈哈哈
k :。。。
13:。。。
k :那个
13:什么
k :预设是什么
13:哈(叹气),你看这样,Assets -> Create -> Prefab,看到没,在project标签页中的Assets文件夹中就出现了一个。。。
k :啊,白色的块
13:。。。好吧,对,点击它,看,在Inspector里我们便可以看到里面什么都没有,相比较当我们点击,比如说,这个ku。。立方体
k :喔~有Transform还有Mesh Renderer什么的
13:没错,这时的预设还没有任何组件,是空的,当我们把一个ku。。。立方体!托放到预设上时。。。
k :出现了!野生的块!
13:野生的。。。感觉上似乎没错。。。总之,这样我们就得到了一个组成棋盘方格的预设了,我们给他一个名字吧。。
k :格列兹曼
13:确实是格子没错但是太现实了,就叫grid就行,那接下来才是重点。。。
k :所以到底有什么用啊,你讲了半天跟没讲一样,我快无聊死了
13:你这家伙,什么都不会还真敢说啊。你等着看(打打打打打。。。),好,click,运行。喂
k :嗯?什么。。。咦?怎么,好多方块啊!哇,还在增加,5000,不对,6000,10000.。。。可恶,无法计算(摘下眼镜捏在了手中)
13:就是简单的脚本而已啊,你发什么神经?
k :脚本?
13:对,C#写的脚本,通过这个脚本利用我们生成好的预设克隆出来的

GameObject cube = Instantiate(Resources.load("grid"), new Vector3(), Quaternion.identity) as GameObject;

//要在Assets里面新建一个Resources文件夹,把预设放在里面就可以用Resources.load(string name)来获得预设了

然后我们只需要这样,用两个for循环就可以得到棋盘并绑定到一个二维数组上了

//private GameObject[,] ChessTable = new GameObject[3,3]
//初始化在Start()里面进行,不过放在Restart()里方便我们重启游戏
void Start(){
    Restart();
}
//
void Restart(){
    for(int i = 0;i < 3;i++){
        for(int j = 0;j <3;j++){
            ChessTable[i,j] = Instantiate(Resources.Load("grid"), new Vector3(i, 0, j), Quaternion.identity) as GameObject;
            ChessTable[i,j].transform.parent = this.transform;
            //顺便初始化一下状态
            state[i,j] = 0;
        }
    }
}

看吧,这样我们就得到了一个棋盘了~
k :。。。
13:怎么,惊讶得说不出来?还是突然意识到自己的一无所有和知识浅薄之后开始认真思考起了自己的存在意义了?
k :欸?你说什么?
13:没有是你听错了
k :我说
13:(充满期待)嗯
k :这个棋盘看起来像一坨哦(如图所示,一坨)
这里写图片描述
13:。。。一。。坨?
k :是啊,你看因为颜色都一样所以看起来都连成一块了
13:额。。。确实是
k :应该那样比较好吧,比如说像国际象棋那样的
13:唔。。。
k :所以说要这样啦

//每次循环改变一下贴图,每条对角线的下标的和相同,相邻对角线下标和奇偶性不同,所以
ChessTable[i,j].GetComponent<Renderer>().material = new Material(Shader.Load((i + j)%2?material1:material2));

这样颜色就不一样了吧
ChessTable
13:哇。。。没想到这个没脑子的笨蛋白痴居然。。。似乎有种莫名的欣慰感是怎么回事?
k :你在一本正经的说什么,我在这旁边哦
13:没有我什么都没说。嗯,这个不错啊,等下棋子似乎也可以用这个方式来呢
k :没错吧,我很厉害吧?
13:(无视)那接下来就是棋子了,同样是要创建一个棋子的预设呢,就是要用这个了
k :丸子
13:恩恩恩,没错没错,然后,就是要来处理一下点击事件了,因为不是用按钮呢,所以我们要自己来写一个点击事件的句柄呢。你刚刚说什么了?
k :就是那个Sphere嘛
13:啊,嗯对(似乎刚刚又听到什么更加过分的东西了)。这个句柄就很简单了,我们只需要在OnMouseUp()中进行射线碰撞检测就行了

void OnMouseUp(){
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RayCastHit hit;
    //判断是否检测到了
    if(Physics.RayCast(ray, out hit)){
        //画条线看的更清楚
        Debug.DrawLine(ray.origin, hit.point);
        //既然是射线,那我们获得的肯定是碰撞体了,所以没有碰撞体这个组件的是检测不到的!
        GameObject grid = hit.collider.gameObject;
        //用一个一维数组保存即可,因为我们不需要知道位置在哪,只需要方便我们销毁就行,用一个counter来记录数量
        chess[counter] = Instantiate(Resources.Load("Chess"), grid.transform.position, Quaternion.identity) as GameObject;
        //同时我们还可以利用counter来判断回合
        chess[counter].GetComponent<Renderer>().material = new Material(Shader.Find(counter%2?material1:material2));
    }
}

摧毁还有判断的很简单呢
k :是啊
13:。。。你说的话很微妙啊
k :什么啊,你刚刚写了什么忘了吗?棋子的材质的那个哦,我想出来的哦?
13:今天运势不太好呢,要去买本黄历了,感觉虽然是现代社会,但是一些古代的东西还是挺重要的呢
k :嗯?啊,对呢
13:(无语)好吧,那最后剩下的就是显示结果呢
k :OnGUI()
13:Σ(っ °Д °;)っ
k :喂,你刚刚一开始不就讲过了吗?讲过的就算是我也知道的哦
13:哇,厉害呢。好那最后就是3d的OnGUI了,嘛其实还是一摸一样的没什么区别

void OnGUI(){
    //生成一个菜单栏
    GUI.Box (new Rect (10, 10, 100, 90), "Menu");
    if (GUI.Button (new Rect (20, 40, 80, 20), "NewGame")) {
        NewGame ();
    }
    //判断是否有胜利者
    bool result = Judge ();
    if (result) {
        //根据当前回合判断胜负
        GUI.Box (new Rect (Screen.width / 2 - 100, Screen.height / 2 + 50, 200, 100), turn == 1 ? "红先负" : "红先胜");
        //可以用Screen把结果显示在中间
        if (GUI.Button (new Rect (Screen.width / 2 - 80, Screen.height / 2, 160, 20), "新游戏"))
            this.Restart ();
    }
    else{
        //没有胜负,棋子数量为9,那肯定就是和咯
        if (counter == 9) {
            GUI.Box (new Rect (Screen.width / 2 - 100, Screen.height / 2 + 50, 200, 100), "红先和");
            if (GUI.Button (new Rect (Screen.width / 2 - 80, Screen.height / 2, 160, 20), "新游戏"))
                this.Restart ();
        }
    }
}

运行游戏就可以玩了!
这里写图片描述
13:那这样子就结束了呢
k :是啊,终于完了啊~
13:是我的错觉吗?为什么你刚刚露出了好像刚刚工作下班回家的疲劳感?明明基本上什么都没做吧
k :那么到此结束了,大家一起去收服神奇宝贝吧!
13:大木讲座??

-完

猜你喜欢

转载自blog.csdn.net/Lyn_B/article/details/79706644