在好例子网,分享、交流、成长!
您当前所在位置:首页C# 开发实例C#游戏开发 → C# 消消乐游戏源码(Unity3d)

C# 消消乐游戏源码(Unity3d)

C#游戏开发

下载此实例
  • 开发语言:C#
  • 实例大小:197.94M
  • 下载次数:85
  • 浏览次数:1030
  • 发布时间:2019-07-19
  • 实例类别:C#游戏开发
  • 发 布 人:fingers
  • 文件格式:.zip
  • 所需积分:2
 相关标签: unity3D unity 消消乐 游戏

实例介绍

【实例简介】

基于unity3d引擎的消消乐游戏

【实例截图】

from clipboard

from clipboard

from clipboard

【核心代码】

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
/// <summary>
/// 糖果容器管理,交换,删除,添加,动画,特效
/// </summary>
public class GameController : MonoBehaviour 
{
public enum Condition 
{
NORMAL,
CRUSH,
EXCHANGE
}
public Condition state = Condition.EXCHANGE;
//糖果容器对象
public CandyBox candyBox;
//第一次点击选择的CandyBox
private CandyBox whichTimeClickBox;
//行列总数
public int rowNum = 8, columnNum = 8;
//保存糖果容器矩阵的二维数组
private ArrayList candyArr;
//保存消除糖果容器的数组
private ArrayList matches;
//爆炸特效
public ParticleSystem fx; 
//相机震动用transform
public Transform c_transform;
//时间进度条
public Slider slider;
public AudioSource au;
public AudioClip crushSound, wrongSound, comboSound4, comboSound5;
//震动总时间
public float shakeTime = 0.2f;
//振幅
public float shakeLevel = 1f;
//震动速率
public float shakeSpeed = 5f;
//背景切换的时间
private float playTime = 6;
//背景索引
private int bgIndex = 0;
public SpriteRenderer bgRenderer;
//背景图
public Sprite[] bg;
//重随提示信息
public Text message;
//分数组件
public Text showScore;
private int presentScore = 0;
//每个Candy的分数
public int eachGrade = 50;
//单例
private GameController instance;
public GameController Instance()
{
if(instance == null)
instance = this;
return instance;
}
void Start () 
{
state = Condition.EXCHANGE;
presentScore = 0;
bgIndex = 0;
//保存了每一行的ArrayList
candyArr = new ArrayList();
for (int rowIndex = 0; rowIndex < rowNum; rowIndex ) 
{
//保存了一行中每个Candybox
ArrayList temp = new ArrayList();
for (int columnIndex = 0; columnIndex < columnNum; columnIndex ) 
{
temp.Add(AddCandyBox(rowIndex, columnIndex, false));
}
candyArr.Add(temp);
}
StartCoroutine(WaitForCheck(0.8f));
}
/// <summary>
/// 向界面上特定位置添加新的CandyBox
/// </summary>
/// <param name="rowIndex">行索引</param>
/// <param name="columnIndex">列索引</param>
/// <param name="ifTop">是否是顶部添加元素</param>
/// <returns>返回添加的新元素对象CandyBox</returns>
private CandyBox AddCandyBox(int rowIndex, int columnIndex, bool ifTop)
{
CandyBox c;
//初始生成位置
if(!ifTop)
{
c = Instantiate (candyBox,this.transform.position,this.transform.rotation) as CandyBox;
}
else
{
Vector3 insTopPos = new Vector3(columnIndex, rowNum);
c = Instantiate (candyBox,insTopPos,this.transform.rotation) as CandyBox;
}
//将CandyBox设为GameController子物体
c.transform.parent = this.transform; 
//将本脚本引用传给CandyBox脚本
c.gameController = this; 
c.columnIndex = columnIndex;
c.rowIndex = rowIndex;
//设置CandyBox位置
// if(!ifTop)
// {
// c.UpdatePosition(); 
// }
// else
// {
c.TweenToPosition();
// }

return c;
}
void Update () 
{
//随时间切换背景
playTime -= Time.deltaTime;
if(playTime <= 0)
{
playTime = 6;
SwitchBG();
}
//随时间流逝进度条减少,归零则游戏结束
slider.value = Mathf.Clamp(slider.value -= Time.deltaTime * 0.1f, 0, 1);
if(slider.value == 0)
{
SceneManager.LoadScene("OverScene");
}

if(Input.touchCount == 1)
{
if(Input.GetTouch(0).phase == TouchPhase.Began)
{
if(state == GameController.Condition.NORMAL)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
RaycastHit hit;
if(Physics.Raycast(ray , out hit))
{
Select(hit.transform.GetComponent<CandyBox>());
}

}
}
if(Input.GetTouch(0).phase == TouchPhase.Ended)
{
if(state == GameController.Condition.NORMAL)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
RaycastHit hit;
if(Physics.Raycast(ray , out hit))
{
Select(hit.transform.GetComponent<CandyBox>());
}
}
}
}
}
/// <summary>
/// 切换背景
/// </summary>
void SwitchBG()
{
bgRenderer.sprite = bg[bgIndex];
bgIndex ;
if(bgIndex >= 3)
{
bgIndex = 0;
}
}
/// <summary>
/// 点选CandyBox,先后判断,交换逻辑控制
/// </summary>
/// <param name="cb">第一次点选的元素</param>
public void Select(CandyBox cb)
{
if(whichTimeClickBox == null)
{
whichTimeClickBox = cb;
return ;

else if(whichTimeClickBox != cb)
{
//邻接元素才可交换
if(Mathf.Abs(whichTimeClickBox.rowIndex - cb.rowIndex) Mathf.Abs(whichTimeClickBox.columnIndex - cb.columnIndex) == 1)
{
state = Condition.EXCHANGE;
Exchange(whichTimeClickBox,cb);
StartCoroutine(WaitForCheck(0.8f));
}
//重置首次点选元素
whichTimeClickBox = null;
}
}
/// <summary>
/// 交换两元素(数组,界面都换)(一层封装)
/// </summary>
/// <param name="cb1">选择的元素1</param>
/// <param name="cb2">选择的元素2</param>
private void Exchange(CandyBox cb1, CandyBox cb2)
{
DoExchange(cb1, cb2);
StartCoroutine(Wait(0.4f, cb1, cb2));

}
IEnumerator Wait(float t, CandyBox cb1, CandyBox cb2)
{
yield return new WaitForSeconds(t);
//如果交换后不能实现消除,则换回两元素(只是换回,不再循环检测消除了,否则会无限交换)
if(CheckMatches(false))
{
au.PlayOneShot(crushSound);
RemoveMatches();
}
else
{
au.PlayOneShot(wrongSound);
DoExchange(cb1, cb2);
}
}
/// <summary>
/// 交换两元素(数组,界面都换)(实现层)
/// </summary>
/// <param name="cb1">选择的元素1</param>
/// <param name="cb2">选择的元素2</param>
void DoExchange(CandyBox cb1, CandyBox cb2)
{
state = Condition.EXCHANGE;
//数组矩阵中也交换元素
SetCandyBox(cb1.rowIndex, cb1.columnIndex, cb2);
SetCandyBox(cb2.rowIndex, cb2.columnIndex, cb1);
//交换行列索引
cb1.rowIndex = cb1.rowIndex cb2.rowIndex;
cb2.rowIndex = cb1.rowIndex - cb2.rowIndex;
cb1.rowIndex = cb1.rowIndex - cb2.rowIndex;
cb1.columnIndex = cb1.columnIndex cb2.columnIndex;
cb2.columnIndex = cb1.columnIndex - cb2.columnIndex;
cb1.columnIndex = cb1.columnIndex - cb2.columnIndex;
//更新位置
cb1.TweenToPosition();
cb2.TweenToPosition();
}
/// <summary>
/// 获取数组矩阵特定元素
/// </summary>
/// <param name="rowIndex">行索引</param>
/// <param name="columnIndex">列索引</param>
/// <returns>返回获取的元素对象CandyBox</returns>
private CandyBox GetCandyBox(int rowIndex, int columnIndex)
{

ArrayList tmp = candyArr[rowIndex] as ArrayList;
CandyBox cb = tmp[columnIndex] as CandyBox;
return cb; 
}
/// <summary>
/// 向数组矩阵中添加元素
/// </summary>
/// <param name="rowIndex">行索引</param>
/// <param name="columnIndex">列索引</param>
/// <param name="cb">要添加的元素对象</param>
private void SetCandyBox(int rowIndex, int columnIndex, CandyBox cb)
{
ArrayList tmp  = candyArr[rowIndex] as ArrayList;
tmp[columnIndex] = cb;
}
/// <summary>
/// 删除元素,下移元素,添加新元素
/// </summary>
/// <param name="willRemoveCandyBox">将要删除的元素</param>
private void Remove(CandyBox willRemoveCandyBox)
{
//删除传入元素
willRemoveCandyBox.Dispose();
int col = willRemoveCandyBox.columnIndex;
//使其上元素都下降一格
for(int row = willRemoveCandyBox.rowIndex 1; row < rowNum; row )
{
CandyBox upCandyBox = GetCandyBox(row, col);
upCandyBox.rowIndex--;
upCandyBox.TweenToPosition();
//在数组中也改动
SetCandyBox(row - 1, col, upCandyBox);
}
//顶部添加新元素
CandyBox newCandyBox = AddCandyBox(rowNum - 1, col, true);
//在数组中也改动
SetCandyBox(rowNum - 1, col, newCandyBox);
}
/// <summary>
/// 检测有无可消除行列
/// </summary>
/// <param name="isTry">标识是否用于检测死图</param>
/// <returns></returns>
private bool CheckMatches(bool isTry)
{
return CheckHorizontalMatches(isTry) || CheckVerticalMatches(isTry);
}
/// <summary>
/// 检测行有无可消除
/// </summary>
    /// <param name="isTry">标识是否用于检测死图</param>
/// <returns></returns>
private bool CheckHorizontalMatches(bool isTry)
{
bool result = false;
for(int row = 0; row < rowNum; row )
{
for(int col = 0; col < columnNum - 2; col )
{
if((GetCandyBox(row,col).type == GetCandyBox(row,col 1).type) &&
       (GetCandyBox(row, col 1).type == GetCandyBox(row, col 2).type))
{
result = true;
if(!isTry)
{
AddMatch(GetCandyBox(row,col));
AddMatch(GetCandyBox(row,col 1));
AddMatch(GetCandyBox(row, col 2));
}
}
}
}
return result;
}
/// <summary>
/// 检测列有无消除
/// </summary>
/// <param name="isTry">标识是否用于检测死图</param>
/// <returns></returns>
private bool CheckVerticalMatches(bool isTry)
{
bool result = false;
for(int col = 0; col < columnNum; col )
{
for(int row = 0; row < rowNum - 2; row )
{
if((GetCandyBox(row,col).type == GetCandyBox(row 1,col).type) &&
       (GetCandyBox(row 1, col).type == GetCandyBox(row 2, col).type))
{
result = true;
if(!isTry)
{
AddMatch(GetCandyBox(row,col));
AddMatch(GetCandyBox(row 1,col));
AddMatch(GetCandyBox(row 2, col));
}
}
}
}
return result;
}
/// <summary>
/// 将可消除的元素加入待消除数组
/// </summary>
/// <param name="cb">可消除元素</param>
private void AddMatch(CandyBox cb)
{
if(matches == null)
{
matches = new ArrayList();
}
//如果此元素不存在于数组,就添加,防止重复添加
int index = matches.IndexOf(cb);
if(index == -1)
{
matches.Add(cb);
}
}
/// <summary>
/// 遍历删除待消除数组中的元素
/// </summary>
private void RemoveMatches()
{
state = Condition.CRUSH;
//相机震动
StartCoroutine(Shake());
CandyBox temp;

if(matches.Count == 4 || matches.Count > 5)
{
au.PlayOneShot(comboSound4);
}
else if(matches.Count == 5)
{
au.PlayOneShot(comboSound5);
}

for(int i = 0; i < matches.Count; i )
{
temp = matches[i] as CandyBox;
//播放爆炸特效
ParticleSystem ps = Instantiate(fx,temp.transform.position,temp.transform.rotation);
Destroy(ps.gameObject, 1);
Remove(temp);
//加分
AddScore(eachGrade);
//重置进度条
ResetSlider();
}
//重置数组
matches = new ArrayList();
StartCoroutine(WaitForCheck(0.8f));
}
/// <summary>
/// 重置进度条
/// </summary>
private void ResetSlider()
{
slider.value = 1;
}
/// <summary>
/// 加分
/// </summary>
/// <param name="eachNum">每个Candy的分数</param>
private void AddScore(int eachNum)
{
presentScore = eachNum;
Global.score = presentScore;
showScore.text = presentScore.ToString();
}
/// <summary>
/// 延迟检测消除协程
/// </summary>
/// <param name="t">延迟时间</param>
IEnumerator WaitForCheck(float t)
{
yield return new WaitForSeconds(t);
//再次检测消除
if(CheckMatches(false))
{
au.PlayOneShot(crushSound);
RemoveMatches();
}
else
{
state = Condition.NORMAL;
//检测死图
if(CheckDeadMap())
{
StartCoroutine(Message(3));
//重随
Refresh();
}
}
}
IEnumerator Message(float t)
{
message.enabled = true;
iTween.ShakeScale(message.gameObject,new Vector3(1,1,1),0.5f);
yield return new WaitForSeconds(t);
message.enabled = false;
}
/// <summary>
/// 检测是否死图
/// 思想是,在数组里模拟交换所有纵横相邻的元素,然后检测是否可消
/// 注意点是,模拟交换后要记得还原回去
/// </summary>
/// <returns>是死图就返回true</returns>
private bool CheckDeadMap()
{
bool isdeadmap = true;
//横向交换检测
for(int row = 0; row < rowNum; row )
{
for(int col = 0; col < columnNum - 1; col )
{
CandyBox cb1 = GetCandyBox(row, col);
CandyBox cb2 = GetCandyBox(row, col 1);
SetCandyBox(cb1.rowIndex, cb1.columnIndex, cb2);
SetCandyBox(cb2.rowIndex, cb2.columnIndex, cb1);
if(CheckMatches(true))
{
isdeadmap = false;
}
SetCandyBox(cb1.rowIndex, cb1.columnIndex, cb1);
SetCandyBox(cb2.rowIndex, cb2.columnIndex, cb2);
if(!isdeadmap)
{
return isdeadmap;
}
}
}
//纵向交换检测
for(int col = 0; col < columnNum; col )
{
for(int row = 0; row < rowNum - 1; row )
{
CandyBox cb1 = GetCandyBox(row, col);
CandyBox cb2 = GetCandyBox(row 1, col);
SetCandyBox(cb1.rowIndex, cb1.columnIndex, cb2);
SetCandyBox(cb2.rowIndex, cb2.columnIndex, cb1);
if(CheckMatches(true))
{
isdeadmap = false;
}
SetCandyBox(cb1.rowIndex, cb1.columnIndex, cb1);
SetCandyBox(cb2.rowIndex, cb2.columnIndex, cb2);
if(!isdeadmap)
{
return isdeadmap;
}
}
}
return isdeadmap;
}
/// <summary>
/// 重新随机全部元素(清除数组,重新添加元素(界面,数组))
/// </summary>
public void Refresh()
{
state = Condition.EXCHANGE;
for (int row = 0; row < rowNum; row ) 
{
for (int col = 0; col < columnNum; col ) 
{
GetCandyBox(row,col).Dispose();
}
}
candyArr.Clear();
candyArr = new ArrayList();
for (int row = 0; row < rowNum; row ) 
{
ArrayList temp = new ArrayList();
for (int col = 0; col < columnNum; col ) 
{
temp.Add(AddCandyBox(row, col, false));
}
candyArr.Add(temp);
}
StartCoroutine(WaitForCheck(0.8f));
}
/// <summary>
/// 相机震动协程
/// </summary>
IEnumerator Shake()
{
Vector3 oriPos = c_transform.localPosition;
float spendTime = 0;
while(spendTime < shakeTime)
{
Vector3 randomPoint = oriPos Random.insideUnitSphere * shakeLevel;
c_transform.localPosition = Vector3.Lerp(c_transform.localPosition, randomPoint, Time.deltaTime * shakeSpeed);
yield return null;
spendTime = Time.deltaTime;
}
c_transform.localPosition = oriPos;
}
}



实例下载地址

C# 消消乐游戏源码(Unity3d)

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

第 1 楼 云朵边上 发表于: 2019-12-10 12:40 22
不能运行

支持(0) 盖楼(回复)

第 2 楼 Gentleman` 发表于: 2019-12-10 21:24 41
为什么点击没反应?

支持(0) 盖楼(回复)

发表评论

(您的评论需要经过审核才能显示)

查看所有2条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警