回合制.docx
- 文档编号:4291584
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:13
- 大小:366.99KB
回合制.docx
《回合制.docx》由会员分享,可在线阅读,更多相关《回合制.docx(13页珍藏版)》请在冰豆网上搜索。
回合制
今天呢,我们来说说回合制。
博主曾经坦言自己是一个喜欢国产RPG游戏的人,《仙剑奇侠传》、《轩辕剑》、《古剑奇谭》等游戏都为博主带来了许多温暖的回忆。
那么什么是回合制呢?
让我们将视线转移到三足鼎立的三国时代,只见张飞挺着丈八蛇矛,大喝一声:
三姓家奴休走,与我大战三百回合。
布大怒,举起画戟,便要刺来。
这是我们记忆中最原始的关于回合印象,可见这里的回合是指对战双方武将骑着马对冲,人随着马的惯性对打,如果双方都没有死,就调转马头,再来一次。
这便是最初的回合的概念。
而追朔到欧洲的燧石枪时代,对战双方则是按照各自阵营站成整齐的一排,听口令按次序互相击毙。
当你打完后,就必须等待我开枪,这才是回合制的精髓,在《刺客信条》等游戏中我们可以一窥当年欧洲战场之宏伟壮观。
同样地,当两个人要决斗时,就是拿着手枪挨个打,直到有人倒下为止,这就是回合制,伟大的诗人普希金就是这样死的。
可见回合制是体现人文精神的、尊重规则、尊重原则的一种历史产物。
而在我们的生活中,篮球、扑克、象棋、麻将都是回合制的,如果没有回合制,就将没有规则和秩序。
真正的侠客不在于武,而在于适可而止,我们不是在战场上胡乱厮杀,而是而是冷静地停下来,安静地思考策略,谋划下一回合的进攻和防守。
而这就是回合制,如果说回合制代表了人类最原始的一种文化形态,那么这种形态可能是一种落后的形态,因为最初的游戏受到硬件水平的影响,回合制是一种最为折中的办法。
从这个角度上来看,回合制非但不落后,而且有点高贵、古典的气息流淌在里面,这就是为什么国产单机游戏都喜欢使用回合制这一战斗模式的原因所在,我们不羡慕国外游戏大作的酣畅淋漓、我们不羡慕国外游戏大作的奢华精致,我们只想找回属于我们的最初的归属。
那是一种流淌了五千年的血液,那是一段述说了五千年的故事,那是一个执着了五千年的梦想,因为如此,所以我们懂得了什么叫做热爱,什么叫做温暖,什么叫做责任,什么叫做感动。
好了,今天的游戏我们就先聊到这里啦,下面我们开始今天的内容。
在文章开始,我们已将回合制的战斗模式讲解得很清楚了。
那么,如果在Unity3D游戏中实现一个回合制游戏呢?
我们从最简单的一对一模式来设计回合制游戏的原型。
我们可以游戏的状态划分为下面三种状态:
1、我方角色生命值为0,则游戏结束,角色输。
2、敌方角色生命值为0,则游戏结束,角色赢。
3、如果双方角色生命值均不为0,则反复执行下面的过程:
当当前操作状态为AI时,敌人根据AI算法逻辑行动
当当前操作状态为玩家时,根据玩家操作执行行动
这就是我们今天实现回合制游戏的算法原型。
我们下面将根据这一原型来实现一个回合制游戏的示例。
首先我们创建一个简单的游戏场景,如图所示:
在这个游戏场景中,我们的Samuzai将作为我们的游戏主角,而Gorilla将作为我们的敌人。
我们分别为它们创建对应的脚本文件Player.cs、EnemyAI.cs以及用于全局控制的TurnGame.cs。
Player.cs脚本负责玩家相关逻辑的实现,EnemyAI脚本负责敌人AI的相关逻辑,TurnGame脚本负责回合制游戏的核心部分。
好了。
我们下面来一起来看这三部分的脚本代码:
首先在Player脚本中,我们需要做三件事情:
(1)显示和隐藏玩家的操作界面、
(2)玩家攻击招式的设定、(3)玩家生命值的设计。
我们来一起看代码:
[csharp] viewplaincopy
1.using UnityEngine;
2.using System.Collections;
3.
4.public class Player :
MonoBehaviour {
5.
6. //定义玩家最大生命值为100
7. public int HP=100;
8. //是否等待玩家输入
9. public bool isWaitPlayer=true;
10.
11. //当前回合数
12. private int index=1;
13. //动画组件
14. private Animation mAnimation;
15.
16. void Start ()
17. {
18. mAnimation=GetComponent
19. }
20.
21. //受到伤害
22. void OnDamage(int mValue)
23. {
24. HP-=mValue;
25. }
26.
27. void OnGUI()
28. {
29. //如果处于等待玩家输入状态,则显示操作窗口
30. if(isWaitPlayer)
31. {
32. GUI.Window(0,new Rect(Screen.width/2+150,Screen.height/2-150,200,200),InitWindow,"请选择技能或仙术");
33. }
34. }
35.
36. void InitWindow(int ID)
37. {
38.
39. if(GUI.Button(new Rect(0,20,200,30),"御剑术"))
40. {
41. mAnimation.Play("Attack");
42. //将操作权交给敌人
43. isWaitPlayer=false;
44. Debug.Log("在第"+index+"回合:
主角使用了御剑术");
45. index+=1;
46.
47. }
48. if(GUI.Button(new Rect(0,50,200,30),"万剑诀"))
49. {
50. mAnimation.Play("Attack");
51. //将操作权交给敌人
52. isWaitPlayer=false;
53. Debug.Log("在第"+index+"回合:
主角使用了万剑诀");
54. index+=1;
55. }
56. if(GUI.Button(new Rect(0,80,200,30),"仙风云体"))
57. {
58. mAnimation.Play("Attack");
59. //将操作权交给敌人
60. isWaitPlayer=false;
61. Debug.Log("在第"+index+"回合:
主角使用了仙风云体");
62. index+=1;
63. }
64. if(GUI.Button(new Rect(0,110,200,30),"化相真如"))
65. {
66. mAnimation.Play("Attack");
67. //将操作权交给敌人
68. isWaitPlayer=false;
69. Debug.Log("在第"+index+"回合:
主角使用了化相真如");
70. index+=1;
71. }
72. if(GUI.Button(new Rect(0,140,200,30),"酒神"))
73. {
74. mAnimation.Play("Attack");
75. //将操作权交给敌人
76. isWaitPlayer=false;
77. Debug.Log("在第"+index+"回合:
主角使用了酒神");
78. index+=1;
79. }
80. }
81.}
在该脚本中,我们设定角色的最大生命值为100,然后通过一个bool类型的isWaitPlayer来判断是否处于等待玩家执行下一步行动的状态,如果处于改状态则显示操作界面,这样玩家就可以施展不同的技能,这里我们使用了系统的GUI系统。
最终实现的效果是类似于仙剑奇侠传游戏的效果,如图:
接下里我们来讲解敌人AI的脚本,敌人需要在玩家执行结束后随机进行一个操作,所以这里需要用到概率,我们一起来看脚本:
[csharp] viewplaincopy
1.using UnityEngine;
2.using System.Collections;
3.
4.public class EnemyAI :
MonoBehaviour {
5.
6. //定义敌人最大生命值为100
7. public int HP=100;
8. public bool isWaitPlayer=true;
9. //当前回合数
10. private int index=1;
11. //动画组件
12. private Animation mAnimation;
13.
14.
15. void Start()
16. {
17. mAnimation=GetComponentInChildren
18. }
19.
20. void OnDamage(int mValue)
21. {
22. HP-=mValue;
23. }
24.
25.
26. ///
27. /// 执行敌人的AI算法
28. ///
29. public void StartAI()
30. {
31. if(!
isWaitPlayer)
32. {
33. if(HP>20)
34. {
35. //80%的攻击招式一
36. if(Random.Range(1,5)%5!
=1)
37. {
38. Debug.Log("在第"+index+"回合:
敌人使用了攻击招式一");
39. mAnimation.Play("Howl");
40. //在这里加上特效和伤害
41. index+=1;
42. isWaitPlayer=true;
43. }
44. //20%的攻击招式二
45. else
46. {
47. Debug.Log("在第"+index+"回合:
敌人使用了攻击招式二");
48. mAnimation.Play("Howl");
49. index+=1;
50. isWaitPlayer=true;
51. }
52. }else
53. {
54. switch(Random.Range(1,5)%5)
55. {
56. case 0:
57. Debug.Log("在第"+index+"回合:
敌人使用了攻击招式三");
58. mAnimation.Play("Howl");
59. index+=1;
60. isWaitPlayer=true;
61. break;
62. case 1:
63. Debug.Log("在第"+index+"回合:
敌人使用了攻击招式四");
64. mAnimation.Play("Howl");
65. index+=1;
66. isWaitPlayer=true;
67. break;
68. case 2:
69. Debug.Log("在第"+index+"回合:
敌人使用了攻击招式五");
70. mAnimation.Play("Howl");
71. index+=1;
72. isWaitPlayer=true;
73. break;
74. }
75. }
76. }
77. }
78.}
类似地,我们在这里使用一个bool类型的变量isWaitPlayer来表示敌人是否处于等待玩家执行操作的状态,如果该值为false,则表明玩家已经执行完操作,此时敌人应该按照AI算法来实现随机的攻击,其中概率部分的代码如下:
[csharp] viewplaincopy
1.Random.Range(1,5)%5!
=1
这一句代码表示80%的概率,因为只有Random.Range(1,5)返回值为5时结果才会为1。
如果我们以后希望在游戏中为敌人增加概率,我们都可以使用这种方法。
游戏中使用概率的地方还是比较多的,比如在仙剑奇侠传游戏中的逃跑率、暴击率、避让率都是通过这种方式来实现的。
大家可能注意到了我在这两个脚本中所有技能或者招式都是使用了一个动画,这当然是为了简化程序,让我们专注于游戏的核心实现,这一点希望大家谅解啊,而在两个脚本中的回合数index主要是为了调试程序的方便,具体应用中可以不用这个变量。
好了,在介绍完玩家和敌人的脚本后,我们一起来看今天的核心脚本——TurnGame脚本:
[csharp] viewplaincopy
1.using UnityEngine;
2.using System.Collections;
3.
4.public class TurnGame :
MonoBehaviour {
5.
6. ///
7. /// 回合制游戏战斗模式原型
8. /// 说明:
本程序以最简单一对一回合制游戏为例,基于Unity3D游戏实现回合制游戏算法
9. /// 如果需要实现多人对多人的回合制游戏算法,需要设计行动条算法
10. /// 基本的思路是将游戏状态划分为三种状态:
11. /// 1、我方角色生命值为0,游戏结束,玩家输
12. /// 2、敌方角色生命值为0,游戏结束,玩家赢
13. /// 3、双方生命值均不为0,则循环执行下列过程:
14. /// 当当前操作状态为AI时,敌人根据AI算法逻辑行动
15. /// 当当前操作状态为玩家时,根据玩家操作执行行动
16. ///
17.
18.
19. //定义玩家及敌人
20. public Transform mPlayer;
21. public Transform mEnemy;
22.
23. //定义玩家及敌人脚本类
24. private Player playerScript;
25. private EnemyAI enemyScript;
26.
27. //默认操作状态为玩家操作
28. private OperatorState mState=OperatorState.Player;
29.
30. //定义操作状态枚举
31. public enum OperatorState
32. {
33. Quit,//游戏结束
34. EnemyAI,//AI逻辑
35. Player//玩家逻辑
36. }
37.
38. void Start ()
39. {
40. //获取玩家及敌人脚本类
41. playerScript=mPlayer.GetComponent
42. enemyScript=mEnemy.GetComponent
43. }
44.
45. //延迟等待显示操作界面
46. IEnumerator WaitUI()
47. {
48. yield return new WaitForSeconds
(1);
49. enemyScript.isWaitPlayer=true;
50. }
51.
52. //延迟等待
53. IEnumerator WaitAI()
54. {
55. yield return new WaitForSeconds(2.5F);
56. enemyScript.isWaitPlayer=false;
57. }
58.
59. //为AI设计延迟时间,使其在我方行动结束后2.5F秒的时间内发起攻击
60. IEnumerator UpdateLater()
61. {
62. yield return new WaitForSeconds(2.5F);
63. //敌人停止等待
64. enemyScript.isWaitPlayer=false;
65. //敌人执行AI
66. enemyScript.StartAI();
67. }
68.
69. void Update ()
70. {
71. //如果敌我双方有一方生命值为0,则游戏结束
72. if(playerScript.HP==0)
73. {
74. mState=OperatorState.Quit;
75. Debug.Log("玩家输");
76. }else if(enemyScript.HP==0)
77. {
78. mState=OperatorState.Quit;
79. Debug.Log("玩家赢");
80. }else
81. {
82. switch(mState)
83. {
84. case OperatorState.Player:
85. //如果玩家操作结束,则立即隐藏操作界面,等待2秒钟后敌人AI操作开始
86. if(!
playerScript.isWaitPlayer)
87. {
88. //让敌人等待2秒钟再发起攻击
89. StartCoroutine("UpdateLater");
90. //执行完后等待玩家,5秒钟后显示操作界面,玩家可以继续操作
91. StartCoroutine("WaitUI");
92. mState=OperatorState.EnemyAI;
93. }
94. break;
95. case OperatorState.EnemyAI:
96. //如果敌人AI操作结束,则玩家开始操作
97. if(enemyScript.isWaitPlayer)
98. {
99. //玩家操作
100. playerScript.isWaitPlayer=true;
101. StartCoroutine("WaitUI");
102. //操作完后执行AI
103. Start
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 回合