前言
本文将继续上篇完善2048小游戏
- 制作UI,应用于游戏中,完善GameController.cs
- 使用DoTween添加相应的动画插件
- 完善游戏逻辑
- 计分
- 胜利判断
- 失败判断
- 重新开始
- 历史高分
制作UI界面
- 定分辨率 750*1334
选中Game视窗,视窗中添加相应的分辨率 - 在2048MiniGame场景中,删除自带的Direction Light
右键Hierarchy面板,创建UI->Panel
层次结构如下:
3.添加ResManager,用于从Asset的Resources目录中动态加载资源。用于游戏中进行创建。其采用设计模式中的单例模式。
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 用于资源管理,该项目只用于精灵的管理
/// </summary>
public class ResManager
{
private static ResManager instance;
public static ResManager Instance
{
get
{
if (instance == null)
instance = new ResManager();
return instance;
}
}
Dictionary<string, Sprite> spriteMap;
//采用单例设计模式
private ResManager()
{
spriteMap = new Dictionary<string, Sprite>();
Init();
}
//加载并创建字典
private void Init()
{
Sprite[] sprite = Resources.LoadAll<Sprite>("2048Atlas");
for(int i=0;i<sprite.Length;i++)
{
spriteMap.Add(sprite[i].name, sprite[i]);
}
}
//读取项目中的2048Atlas,并且通过图片名称返回相应的Sprite
public Sprite GetSpriteByName(string name)
{
if(spriteMap.ContainsKey(name))
{
return spriteMap[name];
}
return null;
}
}
- 将GameController挂在Panel上,继续为GameController添加功能。
初始化相关引用:游戏Grid、分数Text、历史Text
初始化相应的事件侦听。AddEventListener
创建游戏核心实例core=new GameCore()
core调用StartGame() 开启游戏逻辑
CreateSprite()初始化4x4网格
UpdateMap() 将游戏逻辑中的数字映射到 UI界面上进行显示。
GameCore core;
private Text curScoreText;
private Text hisScoreText;
private Transform gameGrid;
private Image[,] imgArray;
private void Start()
{
curScoreText = transform.Find("CurScore/ScoreText").GetComponent<Text>();
hisScoreText=transform.Find("HisScore/ScoreText").GetComponent<Text>();
gameGrid = transform.Find("GameGrid");
imgArray = new Image[4, 4];
//添加事件侦听
AddEventListener();
//初始化游戏核心
core = new GameCore();
//创建4x4个图片在GameGrid中
CreateSprite();
//游戏开始
core.StartGame();
//更新游戏UI
UpdateMap();
}
private void AddEventListener()
{
EventManager.AddEventListener(Event.UpdateMap, UpdateMap);
}
private void CreateSprite()
{
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
GameObject obj = new GameObject("0");
obj.transform.SetParent(gameGrid);
imgArray[i, j] = obj.AddComponent<Image>();
//还需要对图片Sprite进行设置
imgArray[i, j].sprite = ResManager.Instance.GetSpriteByName("0");
}
}
}
//根据core中的map来映射到imgArray,每个img的名字即是他们的值
private void UpdateMap()
{
int[,] curMap = core.GetMap();
for(int i=0;i<curMap.GetLength(0);i++)
{
for(int j=0;j<curMap.GetLength(1);j++)
{
//比较图片的名字和curMap对应位置的值是否相同,不同则进行修改
string value = imgArray[i, j].name;
if(value!=curMap[i,j].ToString())
{
imgArray[i, j].name = curMap[i, j].ToString();
imgArray[i, j].sprite = ResManager.Instance.GetSpriteByName(curMap[i, j].ToString());
}
}
}
}
扩展:这里添加了一个EventManager,其在软件设计模式常用,称为:订阅者或者观察者模式。可以大大降低程序之间的耦合度。
EventManager.cs
using System;
using System.Collections.Generic;
public enum Event
{
UpdateMap
}
public static class EventManager
{
private static Dictionary<Event, Action> eventList = new Dictionary<Event, Action>();
//添加监听
public static void AddEventListener(Event eve,Action action)
{
if(eventList.ContainsKey(eve))
{
eventList[eve] += action;
}
else
{
eventList.Add(eve, action);
}
}
//移除监听
public static void RemoveEventListener(Event eve,Action action)
{
if(eventList.ContainsKey(eve))
{
eventList[eve] -= action;
if (eventList[eve] == null)
eventList.Remove(eve);
}
}
//触发事件
public static void TriggerEvent(Event e)
{
if(eventList.ContainsKey(e))
{
eventList[e]();
}
}
}
5.最后再GameCore中加上TriggerEvent
完成以上游戏已经初步能够游玩
为游戏添加动画
修改GameController.cs中UpdateMap
引入using DG.Tweening;命名空间
private void UpdateMap()
{
int[,] curMap = core.GetMap();
for(int i=0;i<curMap.GetLength(0);i++)
{
for(int j=0;j<curMap.GetLength(1);j++)
{
//比较图片的名字和curMap对应位置的值是否相同,不同则进行修改
string value = imgArray[i, j].name;
if(value!=curMap[i,j].ToString())
{
imgArray[i, j].name = curMap[i, j].ToString();
imgArray[i, j].sprite = ResManager.Instance.GetSpriteByName(curMap[i, j].ToString());
int x = i; //这里有一次赋值操作,否则后面动画回调会产生越界错误
int y = j;
//只在设置不为空方格的时候添加一个动画
if (curMap[i,j] != 0)
{
imgArray[i, j].transform.localScale = Vector3.one * 0.6f;
Tweener tween=imgArray[i, j].transform.DOScale(1.1f, 0.3f);
tween.onComplete = () =>
{
imgArray[x, y].transform.DOScale(1.0f, 0.1f);
};
}
}
}
}
}
完善游戏
- 添加上计分功能
- 添加上胜利判断
- 添加上失败判断
- 添加上重新开始功能
- 添加上历史最高纪录功能
扩展:历史最高纪录,我们这里采用的Unity的持久化数据层PlayerPrefs。
也可采用Text文本,或者Json等保存(可以尝试做一个存档系统)
关于排行榜功能:也可以尝试去做一做,可以保存到本地排行,也可以试试网络排行
打包发布
总结
- 本章将游戏核心逻辑与UI界面进行关联了起来。
- 对游戏一些常用功能进行了阐述,介绍了两个设计模式。
- 完善了2048小游戏,有兴趣可以对游戏规则进行改造,甚至设置难度分级等玩法
- 发布到手机,能够在手机上进行游玩。
扩展:游戏是怎么进行更新的?