1. 程式人生 > >Unity3D消消樂實現原理

Unity3D消消樂實現原理

基本原理:

    遍歷所有寶石集合,判斷行和列三連的情況,刪除三連,更新上方寶石位置.

1.定義一個寶石指令碼,功能:隨機指定寶石型別,指定寶石位置,iTween動畫,銷燬,顏色

using UnityEngine;
using System.Collections;

public class Gemstone : MonoBehaviour {
	public float xOffset = -4.0f;  //x方向的偏移
	public float yOffset = -1.5f;  //y方向的偏移
	public int rowIndex = 0;       //行號
	public int columnIndex = 0;    //列號

	public GameObject[] gemstoneBgs;  //寶石(gemstone)的陣列
	public int gemstoneType;  //寶石(gemstone)的型別
	public GameController gameController;
	public SpriteRenderer spriteRenderer;
	public bool isSelected{
		set{
			if(value){
				spriteRenderer.color = Color.red;
			}else{
				spriteRenderer.color = Color.white;
			}
		}
	}


	private GameObject gemstoneBg;
	// Use this for initialization
	void Awake(){

	}

	void Start () {
		gameController = GameObject.Find ("GameController").GetComponent<GameController> ();
		spriteRenderer = gemstoneBg.GetComponent<SpriteRenderer> ();
	}
	
	// Update is called once per frame
	void Update () {
	
	}

	public void UpdatePosition(int _rowIndex,int _columnIndex){    //調整gemstone(寶石)的位置
		rowIndex = _rowIndex;
		columnIndex = _columnIndex;
		this.transform.position = new Vector3 (columnIndex*1.2f + xOffset, rowIndex*1.2f + yOffset, 0);
	}

	public void TweenToPostion(int _rowIndex,int _columnIndex){
		rowIndex = _rowIndex;
		columnIndex = _columnIndex;
		iTween.MoveTo (this.gameObject, iTween.Hash ("x",columnIndex * 1.2f + xOffset,"y",rowIndex*1.2f + yOffset,"time",0.3f));
	}

	public void RandomCreateGemstoneBg(){ //生成隨機的寶石型別
		if (gemstoneBg != null)
			return;
		gemstoneType = Random.Range (0, gemstoneBgs.Length);
		gemstoneBg = Instantiate(gemstoneBgs[gemstoneType]) as GameObject;
		gemstoneBg.transform.parent = this.transform;
	}
        //滑鼠點選的回撥方法
	public void OnMouseDown(){
		gameController.Select (this);
	}

	public void Dispose(){
		Destroy (this.gameObject);
		Destroy (gemstoneBg.gameObject);
		gameController = null;
	}
}
指令碼掛在到一個空的預製體上,所有型別的寶石��這個空物體生成,

將所有的寶石預製體拖到集合目錄下

2.定義管理指令碼

宣告一下欄位:

Start裡面初始化;


定義如下方法:

		/// <summary>
		/// 生成寶石的方法
		/// </summary>
		/// <returns>返回一個定義好的寶石.</returns>
		/// <param name="rowIndex">Row 行座標.</param>
		/// <param name="columnIndex">Column 列座標.</param>
	public Gemstone AddGemstone(int rowIndex,int columnIndex){  //生成寶石
				//克隆一個寶石
		Gemstone c = Instantiate (gemstone) as Gemstone;
		c.transform.parent = this.transform;//指定父物體
		c.GetComponent<Gemstone>().RandomCreateGemstoneBg();//呼叫寶石本身上寶石指令碼的隨機指定寶石型別的方法
		c.GetComponent<Gemstone>().UpdatePosition (rowIndex,columnIndex);//呼叫借用行號和列號自動排列(指定位置)的方法
		return c;
	}

		/// <summary>
		/// 查詢行號和列好對應寶石的方法
		/// </summary>
		/// <returns>The gemstone.</returns>
		/// <param name="rowIndex">Row index.</param>
		/// <param name="columnIndex">Column index.</param>
	public Gemstone GetGemstone(int rowIndex,int columnIndex){    //通過行號和列號,取得所對應位置的寶石
		ArrayList temp = gemstoneList [rowIndex] as ArrayList;
		Gemstone c = temp [columnIndex] as Gemstone;
		return c;
	}
	
	public void SetGemstone(int rowIndex,int columnIndex, Gemstone c){  //設定所對應列號和列號位置的寶石
		ArrayList temp = gemstoneList [rowIndex] as ArrayList;
		temp [columnIndex] = c;
	}

		//點選當前寶石的時候,指定當前寶石的color,如果當前寶石為空時,表示是第一次點選,那麼顏色指定為紅色,如果不為空的話,表示是第二點選(即交換的物件)
	public void Select(Gemstone c){
		//Destroy (c.gameObject);   //測試,讓所點選的物體消失

		if (currentGemstone == null) {
			currentGemstone = c;
			currentGemstone.isSelected = true;
			return;
		}else{
			if( Mathf.Abs(currentGemstone.rowIndex - c.rowIndex) + Mathf.Abs(currentGemstone.columnIndex - c.columnIndex) == 1 ){//判斷是否挨著的

								StartCoroutine (ExangeAndMatches(currentGemstone,c));//開啟協程,實現寶石交換並且檢測是否匹配
			}else{
				GetComponent<AudioSource>().PlayOneShot(errorClip);
			}


			currentGemstone.isSelected = false;
			currentGemstone = null;
		}
	}

	IEnumerator ExangeAndMatches(Gemstone c1,Gemstone c2){  //實現寶石交換並且檢測是否匹配
		Exchange(c1,c2);//呼叫交換寶石的方法
		yield return new WaitForSeconds (0.5f);//等待0.5s

		if(CheckHorizontalMatches() || CheckVerticalMatches() ){//經過水平檢測和垂直檢測後,如若有成功匹配的
			RemoveMatches();//執行刪除寶石的方法
		}
		else{//如果沒有匹配的寶石,直接在交換回來
//			Debug.Log ("沒有檢測到相同的寶石,交換回來!!");
			Exchange(c1,c2);
		}
	}
	 /// <summary>
	 /// 水平檢測的方法,返回一個布林值
	 /// </summary>
	 /// <returns><c>true</c>, if horizontal matches was checked, <c>false</c> otherwise.</returns>
	bool CheckHorizontalMatches(){   //實現檢測水平方向的匹配
		bool isMatches = false;
				//遍歷列表中的所有寶石
		for (int rowIndex = 0; rowIndex < rowNum; rowIndex++) {
			for(int columnIndex =0; columnIndex < columnNum - 2; columnIndex++){
								//判斷相同行挨著的寶石的型別
				if((GetGemstone (rowIndex,columnIndex).gemstoneType == GetGemstone (rowIndex,columnIndex + 1).gemstoneType ) && (GetGemstone (rowIndex,columnIndex).gemstoneType == GetGemstone (rowIndex,columnIndex + 2).gemstoneType )){
//					Debug.Log ("發現行相同的寶石");
										//將三聯的寶石放到三聯數組裡面
					AddMatches (GetGemstone (rowIndex,columnIndex));
					AddMatches (GetGemstone (rowIndex,columnIndex + 1));
					AddMatches (GetGemstone (rowIndex,columnIndex + 2));
					isMatches = true;
				}
			}	
		}
		return isMatches;
	
	}
		/// <summary>
		/// 垂直檢測的方法,同事也會返回一個布林值
		/// </summary>
		/// <returns><c>true</c>, if vertical matches was checked, <c>false</c> otherwise.</returns>
	bool CheckVerticalMatches(){   //實現檢測垂直方向的匹配
		bool isMatches = false;
				//遍歷所有寶石
		for(int columnIndex = 0; columnIndex < columnNum; columnIndex++){
			for(int rowIndex = 0; rowIndex < rowNum -2 ;rowIndex++){
								//判斷相同列挨著的寶石的型別
				if((GetGemstone(rowIndex,columnIndex).gemstoneType == GetGemstone (rowIndex + 1,columnIndex).gemstoneType ) & (GetGemstone(rowIndex,columnIndex).gemstoneType == GetGemstone (rowIndex + 2,columnIndex).gemstoneType )  ){
//					Debug.Log ("發現列相同的寶石");
										//將三聯的寶石放到三聯列表裡
					AddMatches (GetGemstone (rowIndex,columnIndex));
					AddMatches (GetGemstone (rowIndex +1,columnIndex));
					AddMatches (GetGemstone (rowIndex +2,columnIndex));
					isMatches = true;
				}
			}

		}

		return isMatches;
	}

	void AddMatches(Gemstone c){
		if(matchesGemstone == null)
			matchesGemstone = new ArrayList();
		int index = matchesGemstone.IndexOf (c);  //檢測該寶石是否已在陣列當中
		if(index == -1){//如果沒有在三聯列表裡,新增進去
			matchesGemstone.Add (c);
		}
	}

		/// <summary>
		/// 刪除三聯的寶石
		/// </summary>
	void RemoveMatches(){    //刪除匹配的寶石
		for(int i=0; i< matchesGemstone.Count; i++){//遍歷三聯的列表
			Gemstone c = matchesGemstone[i] as Gemstone;
			RemoveGemstone(c);//呼叫刪除寶石的方法
		}
		matchesGemstone = new ArrayList ();//重新更新三聯列表
		StartCoroutine (WaitForCheckMatchesAgain ());//開啟攜程,檢測是否還有因為銷燬三聯寶石以後還有自動匹配的三聯寶石,如果有直接銷燬
	}

	IEnumerator WaitForCheckMatchesAgain(){
		yield return new WaitForSeconds (0.5f);
		if (CheckHorizontalMatches () || CheckVerticalMatches ()) {
			RemoveMatches ();	
		}
	}


	void RemoveGemstone(Gemstone c){  //刪除寶石
		//Debug.Log ("刪除寶石!");
		c.Dispose ();
		GetComponent<AudioSource>().PlayOneShot (match3Clip);
		for (int i=c.rowIndex +1; i<rowNum; i++) {//更新銷燬寶石對應列上方寶石的位置,下滑的動畫
			Gemstone temGemstone = GetGemstone (i,c.columnIndex);
			temGemstone.rowIndex --;
			SetGemstone(temGemstone.rowIndex,temGemstone.columnIndex,temGemstone);
			//temGemstone.UpdatePosition (temGemstone.rowIndex,temGemstone.columnIndex);
			temGemstone.TweenToPostion (temGemstone.rowIndex,temGemstone.columnIndex);
		}

		Gemstone newGemstone = AddGemstone (rowNum, c.columnIndex);//在空缺的位置新增寶石
		newGemstone.rowIndex--;
		SetGemstone (newGemstone.rowIndex, newGemstone.columnIndex, newGemstone);
		//newGemstone.UpdatePosition (newGemstone.rowIndex, newGemstone.columnIndex);
		newGemstone.TweenToPostion (newGemstone.rowIndex, newGemstone.columnIndex);
	}

		/// <summary>
		/// 交換寶石的方法
		/// </summary>
		/// <param name="c1">C1.</param>
		/// <param name="c2">C2.</param>
	public void Exchange(Gemstone c1,Gemstone c2){  //實現寶石之間交換位置
		GetComponent<AudioSource>().PlayOneShot (swapClip);  //播放交換的聲音
		SetGemstone (c1.rowIndex, c1.columnIndex, c2);
		SetGemstone (c2.rowIndex, c2.columnIndex, c1);

		//交換c1,c2的行號
		int tempRowIndex;
		tempRowIndex = c1.rowIndex;
		c1.rowIndex = c2.rowIndex;
		c2.rowIndex = tempRowIndex;

		//交換c1,c2的列號
		int tempColumnIndex;
		tempColumnIndex = c1.columnIndex;
		c1.columnIndex = c2.columnIndex;
		c2.columnIndex = tempColumnIndex;

		//c1.UpdatePosition (c1.rowIndex, c1.columnIndex);
		//c2.UpdatePosition (c2.rowIndex, c2.columnIndex);
				//ITween動畫將兩個寶石移動到指定的行號和列號的位置上
		c1.TweenToPostion (c1.rowIndex, c1.columnIndex);
		c2.TweenToPostion (c2.rowIndex, c2.columnIndex);

	}


}
將Controller指令碼掛在到一個空物體上,新增Audio Source元件

工程下載連結:

http://download.csdn.net/detail/gaoheshun/9900322

完整Unity3D工程消消樂升級版:

http://download.csdn.net/detail/gaoheshun/9900326

相關推薦

Unity3D實現原理

基本原理:     遍歷所有寶石集合,判斷行和列三連的情況,刪除三連,更新上方寶石位置. 1.定義一個寶石指令碼,功能:隨機指定寶石型別,指定寶石位置,iTween動畫,銷燬,顏色 using UnityEngine; using System.Collections;

RocketMQ源碼分析之RocketMQ事務實現原理中篇----事務息狀態回查

下一個 核心 with chcon detail 偏移 ffffff begin n) 上節已經梳理了RocketMQ發送事務消息的流程(基於二階段提交),本節將繼續深入學習事務狀態消息回查,我們知道,第一次提交到消息服務器時消息的主題被替換為RMQ_SYS_TRANS_H

基於Unity3D引擎的簡易版開心

閒來無事,寫點東西。想到之前有用過u3d,也是怕自己以後忘了,放csdn上留存一下。 先上程式碼。 思路是通過給一個圖形新增指令碼Grid.cs ,再通過總控的指令碼使用兩個for迴圈批量生成圖形方塊。 using UnityEngine; using System.Col

【轉】息隊列原理

精彩 調用 管理 應用程序 利用 耦合 不能 開發者 一段 發布-訂閱消息模式 一、訂閱雜誌 我們很多人都訂過雜誌,其過程很簡單。只要告訴郵局我們所要訂的雜誌名、投遞的地址,付了錢就OK。出版社定期會將出版的雜誌交給郵局,郵局會根據訂閱的列表,將雜誌送達消費者手中。這樣我

Unity開發了一款開心

遊戲開發 Unity3D 開心消消樂 三消 介紹2016年公司投資了一款三消項目,一共花費了300萬,後來項目死了。我對項目做了簡單的整理,自己做了一個相對比較完整的三消遊戲。原項目過於復雜,我做了很多簡化,不過也含有最初項目60%的核心技術,近期準備分享給大家。 菜單界面 地圖場景

Java常用息隊列原理介紹及性能對比

創新 序列化 knowledge rom sage 特定 了解 代碼 lang 消息隊列使用場景為什麽會需要消息隊列(MQ)?解耦 在項目啟動之初來預測將來項目會碰到什麽需求,是極其困難的。消息系統在處理過程中間插入了一個隱含的、基於數據的接口層,兩邊的處理過程都要實現

牛客練習賽30 D 二分圖 最小覆蓋

ace main char left algorithm fde endif tor shu POJ 2226 比這題難一點在於它要求覆蓋的行或者列只能覆蓋*不能覆蓋到.我們同樣可以構造二分圖,對於原圖中的每一個‘*‘都可以把它當做一條邊,連接的是它所在*聯通列的最上一點

牛客練習賽30

r神在和小b比賽玩一個名為“消消樂”的遊戲,在一個n*m的棋盤上,一些棋子分佈在格點上,遊戲玩家有一個名為超藍光波的武器,可以消除一行或者一列的所有棋子,使用超藍光波需要耗費一點能量,消除完所有的棋子之後,花費能量越少得分越高。 r神為了超過排名第一的小b,奪得榮譽稱號“天下第一”,他需要尋求你的幫助,他希望

實驗總結與反思

問題重述 背景介紹: 《開心消消樂》是一款樂元素研發的三消類休閒遊戲。遊戲中消除的物件為小動物的頭像,包括小浣熊、小狐狸、小青蛙和小雞等動物頭像。玩家通過移動動物頭像位置湊夠同行/同列3個或3個以上即可消除。 現在定義消消樂規則如下: 1.遊戲中共允許K種物件,分佈在大小為M×N的格

JavaScript實戰操作—成語

一 預覽 二 開發步驟 基本面向過程的思想。沒有面向物件的部分。 準備好成語庫。db.js 選出每一關的成語。 對成語進行亂序。 初始化表格的同時,將單個字放到每個單元格的按鈕上展示。 對tbody進行點選事件的監聽。事件函式中獲取btn。用變數記錄選中的文字

Gaussian-Jordan列主元元 matlab實現

可能的問題:無唯一解;輸入極小近似0;列主元太小; function x = my_solve(A,b) matrix = [A,b]; R = my_rref(matrix); x = R(:,end); function x = my_rref(matrix) n

CCF201512-2 消除類遊戲(

問題描述         消除類遊戲是深受大眾歡迎的一種遊戲,遊戲在一個包含有n行m列的遊戲棋盤上進行,棋盤的每一行每一列的方格上放著一個有顏色的棋子,當一行或一列上有連續三個或更多的相同顏色的棋子時,這些棋子都被消除。當有多處可以被消除時,這些地方的棋子將同時被消除。

從零開始製作基於Unity引擎的寶石——開篇設計(一)

市場上有些消消樂真好玩,比如hxxxxxpop,pxxxxsaga這類,所以這下想自己從零開始先做一個消消樂,然後再一點點新增遊戲內容進去,順便問下有沒有遊戲公司要找程式撈一下我。 前言 市場上已經有很多消消樂的遊戲了,前段時間剛想做一個簡單的消消樂,在網上翻了

牛客練習賽30D——

比賽的時候不會做… 然後今天才得知是一道原題,一道二分圖最小覆蓋點的模板題… 為什麼大佬什麼演算法都會,什麼題都做過… 程式碼: #include <bits/stdc++.h> using

kafka息通信原理學習(1)

coord 例子 eba alt sub 序列化 strac system str 關於 Topic 和 Partition:   Topic: 在 kafka 中,topic 是一個存儲消息的邏輯概念,可以認為是一個消息集合。每條消息發送到 kafka 集群的消息都有一個

碎片化 《

MainActivity   public class MainActivity extends AppCompatActivity { private Toolbar toolbar; @Override protected void onCreate

Python PIL自動定位

先看定位好的效果圖:自動定位黃色的星星。 from PIL import Image, ImageDraw import math import operator from functools import reduce src_img = Image.open("xxl.png

net.sz.framework 框架 ORM 超過億條資料排行榜分析 天王蓋地虎

序言 天王蓋地虎, 老婆馬上生孩子了,在家待產,老婆喜歡玩消消樂類似的休閒遊戲,閒置狀態,無聊的分析一下消消樂遊戲的一些技術問題; 由於我主要是伺服器研發,客戶端屬於半吊子,所以就分析一下消消樂排行榜問題; 第一章 消消樂排行榜大致分為好友排行榜和全國排行榜; 好友排行榜和全國排行榜的其實是重合的只是需要

計蒜之道複賽 騰訊

騰訊消消樂 狀壓dp 題目連結 題意是就點進去題目鏈說的那樣. 看一下資料由於n<18 然後考慮用狀壓dp dp[i][s] 表示消去i次得到的狀態為s的方案數,1代表刪了0代表還沒刪,當我們列舉到一個狀態s時,取出所有0位,然後列舉其中的一

自制遊戲 程式碼 my.js

/** * Created by wxraopf on 2017-11-17. */ var lastCell = {}; var _lastCell = {}; var isMove = false; Vue.component('obj-list', { p