Unity3d笔记:炉石传说中的功能实现解析

播放片头动画:在void OnGUI()中用GUI.DrawTexture()方法显示视频,用GUI.Label()显示提示;Start()中使用MovieTexture().Play()方法播放视频。此界面交互分两种情况:点击一次弹出提示,再点击一次退出视频;动画自动播放完毕退出视频和提示。对于第一种,使用标志位isShowMessage,第一此点击前isShowMessage=false,点击后变成true,第二次点击前isShowMessage=true,通过判断isShowMessage来确定这是第一次点击还是第二次点击。对于第二种,判断如果MovieTexture.isPlaying为false则播放完毕,然后执行StopMov(),注意为了让StopMov()仅执行一次,条件为isDrawMov!=MovieTexture.isPlaying(等同于MovieTexture.isPlaying&&isDrawMov==true)。

英雄选择:只要能判断鼠标点击的图标是哪个英雄人物,并把其spriteName和名字数组的值传递过去即可。找spriteName:让代表英雄的物体名字gameObject.name和图集中代表英雄的spriteName名字一一对应,这样鼠标点击到某英雄图标时就能找到这个英雄的spriteName。找对应存储名字的名字:每个英雄命名最后一位加上数字,通过物体名字即transoform.gameObject.name找到这个字符串,然后用字符数组找出字符串最后一位即:char nameIndex=heroName[heroName.length-1];通过这个nameIndex索引去找名字数组中的名字,当然前提是数组中名字必须和数字号一一对应。

英雄选择面板控制:建一个空物体或者一个UI容器承载选择面板的所有UI元素。在其上挂在脚本控制整个界面的UI交互,比如给元素初始化(一开始隐藏等触发事件后显示),比如TweenScale、TweenPosition等动画播放。

界面的跳转:相关控制都写在相机的脚本StartMenu中。一般界面切换都有动画,所以只要控制动画的播放即可进入其他界面,如:TweenPosition.PlayForward()。注意界面的初始化在Awake()中写上setActive(false)。注意按钮点击事件侦听,用UIButton()中的OnClick()。侦听Tween动画播放完毕,要用到“事件委托”logoTweenScale.AddOnFinished(this.LogoTweenFinished),LogoTweenFinished为方法。

水晶槽设计:UILable显示数量,UISprite显示图案。把功能封装到UpdateShow()方法中,在Update()中调用方法。定义一个UISprite类型数组crystals装水晶和两个变量usableNum,totalNum分别代表可用水晶和总共水晶数,总共水晶控制物体显示,可用水晶控制亮暗不同spriteName。通过遍历数组控制物体显示或者更换spriteName,需要四组遍历:1、控制totalNum后的水晶隐藏(做UI时,sprite摆满槽),即crystals[i].gameObject.SetActive(false);2、控制0到totalNum间的水晶保持显示。3、控制usableNum后面的水晶是暗色,即crystals[i].spriteName = "TextInlineImages_normal";。控制0到usableNum间的水晶是按顺序正常显示,即crystals[i].spriteName = "TextInlineImages_0" + (i + 1);注意i==9时,是"TextInlineImages" + (i + 1)。Lable的显示方法:lable.text = usableNumber + "/" + totalNumber。

历史卡牌槽设计:封装AddCard()方法,在Update()中调用。先进行UI制作,作为新生成历史卡牌的位置信息。在槽内摆满sprite,card1card2…,再摆一个inCard和一个outCard。用instantiate()生成历史卡牌,使用prefab,生成位置为inCard.postion(NGUI在生成后,下一帧会初始化到0位置,所以需要用协程停顿一帧让NGU先I初始化后再运行改变新历史卡牌的位置)StartCoroutine(AddCard()),yield return 0,IEnumerate。下载插件itween(project搜索,选择appstone,然后下载导入),再使用itween.MoveTo()制作位移动画(动画运行的同时代码也能继续执行),移动到card1位置。使用List集合(类似数组)存储新生成的历史卡牌List.Add(GameObject),遍历数组向下移动槽内卡牌即cardList[i].transform.position = cardList[i].transform.position + new Vector3(0, yOffset, 0);同时注意cardList.count>6即满槽时,移出卡牌、删除卡牌、集合中移除即:iTween.MoveTo(cardList[0],outCard.position,1f);  Destroy(cardList[0],2f);cardList.RemoveAt(0)。

手持卡牌设计:封装两个方法:GetCard()获取卡牌和LoseCard()失去卡牌。GetCard():用NGUITools.AddChild()添加卡牌,iTween.MoveTo(go,toPosition,1f)移动卡牌到手持牌位置(制作UI,定好两个标记位card1card2),其中toPosition = card1.position + new Vector3(yOffset, 0, 0)*myCard.Count,这里myCard是集合用于接收新生成的卡牌(myCard.Add(go))。LoseCard():用Destroy()和RemoveAt()分别把该物体删除和从集合中移除。然后移动该卡牌后卡牌的位置, for (int i = index; i < myCard.Count; i++){Vector3 toPosition = card1.position + new Vector3(yOffset, 0, 0)*i;iTween.MoveTo(myCard[i], toPosition, 0.5f);}这里index表示第几张卡牌。

随机生成卡牌:封装一个RandomGenerateCard()方法,使用NGUITools.AddChild()生成卡牌,添加两个卡牌fromCard和toCard用来设定新卡牌位置。在Update()中变换卡片,首先定义计时器timer、变换持续时间transformTime和装卡牌sprite名字的数组cardName,通过变换数组的Index来变换卡牌内容即:index %= cardName.Length;nowGenerateCard.spriteName = cardName[index];这里的Index是当前播放到了第几帧(当前时间除以播放一帧需要的时间)即:int index = (int)(timer / (1 / transformCard))。在RandomGenerateCard()中移动动画播放那一刻开始设置标志位isTransforming=true,这样在Update()中就开始变换卡片了。

计时绳:定义一个周期时间cycleTime,一个计时器timer。当一周期内时间只剩下15秒时计时绳开始显示并播放动画计时即:if(clycleTime-timer<15){wickPopeSprite.width = (int)(((cycleTime - timer) / 15f) * width);}(把绳子分成15份,随着时间流逝,长度越来越小;width为初始绳长)当计时绳计时完毕即if(timer>cycleTime){强制切换回合}。

血量显示:在hero1中创建其子物体Lable显示血量,封装TakeDamage(int damage)和Treat(int treat)方法,利用形参传递伤害和治疗值。定义最大最小血量hpMax和hpMin,调用Treat()方法时如果hp>hpMax则hp=hpMax。这里注意hero1和hero2代码几乎类似,所有定义一个Hero类,让原先的hero1和hero2类继承Hero可使代码更简洁,需要注意的是原先private访问修饰符有些需要改成protected让子类也能访问父类中变量。

完成发牌:在游戏控制里面添加给hero1发牌方法GenerateCardForHero1(),在此方法中分别调用预制体card中脚本CardGenerate中RandomGenerateCard()和MyCard中的AddCard()方法一次,表示发一张牌。为了让卡牌变换播放完成,需要留足两秒再发下一张,因此要做成协程模式。即方法前加IEnumerator,Update()中用StartCoroutine()调用它。注意生成卡牌方法需要有返回值,类型为GameObject,这样在发牌的脚本中能取到该卡牌,而AddCard()方法也要做成形参,这样能把卡牌传递到AddCard()中(手持卡牌)进行卡牌排序操作。

血量攻击卡牌三者depth设置:在原始卡牌Card中定义SetDepth(int depth)方法计算三者depth,即:sprite.depth = depth;hpLable.depth = depth + 1;attackLable.depth = depth + 1。在手持卡牌MyCard中,等生成卡牌变成手持卡牌后(卡牌被添加到集合中后)把参数传递过来,这个参数在每张卡间相差2即:go.GetComponent().SetDepth(startDepth + myCard.Count*2)。

卡牌可拖拽:给卡牌挂一个脚本DragableCard,让其继承UIDragDrogItem,并重写OnDragDrogRelease()方法。即protected override void OnDragDropRelease(GameObject surface){base.OnDragDropRelease(surface);}推拽区域设定:用widget画一个区域,通过判断surface.tag是否为该widget否则调用卡牌顺序更新方法即MyCard中的UpdateShow()。即:if(surface.tag!=null&&surface.tag=="widget"){调用卡牌排序方法}

解决Lable只能自适应一次:血量和攻击的Lable只能自适应一次,我们只需要重新运行下UIAnchor脚本即可,所以我们在卡牌缩小的时候(即MyCard脚本)加上运行UIAnchor的脚本即可。在MyCard脚本中调Card脚本中的ResetShow()方法,在ResetShow()中写显示UIAnchor的代码即:hpLable.GetComponent().enabled = true;

卡牌属性初始化:在Card脚本中完成卡牌消耗水晶needCraystal、攻击力harm、血量hp的初始化。因卡牌的sprite名字上面带有了这三者信息所以只要从sprite.spriteName提取相关信息即可。needCraystal=spriteName[5]-'0';harm=spriteName[7]-'0';hp=spriteName[9]-'0'。

如何出牌:要做两个事情,一是卡牌从手持挪到桌面,二是桌面卡牌排序摆放。在桌面卡牌摆放区容器上挂上脚本FightCard,里面分别添加AddCard()和CalsPosition()方法分别处理以上两件事。AddCard()中把当前拖拽卡牌父类挂到容器上然后在集合中添加此卡牌即go.transform.parent = this.transform;cardList.Add(go);并且确定卡牌摆放位置用itween播放位置移动动画即iTween.MoveTo(go,targetPos,0.5f)。在CalsPosition()中计算卡牌摆放的位置信息得到targetPos的值,如果是偶数摆放在左边并返回一个位置即if (Index%2==0){Vector3 pos = new Vector3(card1.position.x-(Index/2*xOffset),card1.position.y,card1.position.z);return pos。最后在拖拽脚本中调用AddCard()方法和MyCard脚本中Remove()方法(只一条代码:myCard.Remove(go)),这里注意拖拽脚本的参数surface即代表当前容器。

水晶的消耗和回合刷新:在水晶槽管理脚本Hero1Crystal中分别封装消耗水晶方法GetCrystal()和回合重置水晶方法ResetCrystalNumber()。一个回合后水晶总数totalCrystal会加1且可用水晶usableCrystal注满即usableNumber = totalNumber,然后再调用水晶显示方法UpdateShow()更新显示。消耗水晶需要有返回值且要带形参,形参是把卡牌消耗值传递过来,这时如果可用水晶usableCrystal>卡牌消耗水晶number,则usableCrystal-=number;UpdateShow();return true。返回值是判断是否成功取得水晶值,没有说明水晶不够用返回flase即return false。最后在推拽脚本中把卡牌水晶消耗值传递给水晶消耗处理函数即bool isSuccess = hero1Crystal.GetCrystal(needCrystal);然后通过判断isSuccess判断是否能进行出牌操作。

敌人卡牌管理和战斗区:分为获取卡牌和卡牌移除。AddCard()添加卡牌分为制定卡牌父类、加入到集合中、移动到手中动画,Remove()移除卡牌只要直接删除即可cardList.Remove(go)。同英雄一样添加一个容器然后挂上FightCard脚本。

初始化卡牌数值和显示:在卡牌创建的时候初始化卡牌,即Card中初始化函数InitProperty()在CardGenerate脚本等sprite显示后调用此方法。


转自http://blog.sina.com.cn/s/blog_48e72b7c0102wm1z.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值