本科课程【虚拟现实引擎Unity3D】实验4 - 卡牌游戏完善

x33g5p2x  于2022-05-16 转载在 其他  
字(8.1k)|赞(0)|评价(0)|浏览(569)

大家好,我是【1+1=王】, 热爱java的计算机(人工智能)渣硕研究生在读。
如果你也对java、人工智能等技术感兴趣,欢迎关注,抱团交流进大厂!!!
Good better best, never let it rest, until good is better, and better best.

近期会把自己本科阶段的一些课程设计、实验报告等分享出来,供大家参考,希望对大家有帮助。

博客更新至专栏【课程设计实验报告】:https://blog.csdn.net/weixin_43598687/category_11640051.html

一、 实验目的

  1. 掌握虚拟现实游戏开发的基本流程

二、 实验内容

1. 实验任务

修改第10章卡牌游戏,将牌面改成9行8列,每种花色的牌面编号为1-9,同一花色同一排面编号的牌出现两次。加入计时、计分、及时间限制功能,牌面配对成功、失败时的音效提示,在限制时间内完成全部配对或未完成全部配对的音效提示,能确定结束游戏或重玩游戏。

2. 程序设计

1) 数据输入(输入哪些数据、个数、类型、来源、输入方式)
初始化输入以及Unity界面参数设置

2) 数据存储(输入数据在内存中的存储)
(1)卡牌控制的数据存储:int _id存储卡牌的编号数据,游戏对象cardBack存储游戏对象,场景控制器对象controller存储控制器对象;
(2)游戏控制的数据存储:int gridRows和int gridCols分别存储网格中的行和列,offsetX和offsetY分别存储卡牌的x,y坐标,originateCard存储原始卡牌,images[]数组存储卡牌图片数据,scoreLabel存储TextMesh中的文本信息,_firstRevealed和_secondRevealed分别存储第一张和第二张翻转的卡牌信息,_score存储分数,number[]数组存储洗牌清单,card存储网格中的卡牌信息,index存储网格的位置;
(3)游戏界面控制的数据存储:targetObject存储目标对象信息,targetMessage存储发送的消息,highlightColor存储颜色信息;
(4)摄像机移动的数据存储:没有数据存储

3) 数据处理
(1)卡牌控制的数据处理:
id()方法用于获取卡牌的编号

  1. public int id {
  2. get {return _id;}
  3. }

显示不同的卡牌图像时,Unity 3D通过程序加载图像,更换Sprite Renderer中的精灵图片,采用GetComponent().sprite = image;语句实现;
通过不可见的SceneController来设置图像MemoryCard.cs中的新公有方法

  1. [SerializeField] private SceneController controller;
  2. private int _id;
  3. public int id {
  4. get {return _id;}
  5. }
  6. public void SetCard(int id, Sprite image) {
  7. _id = id;
  8. GetComponent<SpriteRenderer>().sprite = image;
  9. }
  10. OnMouseDown()方法实现匹配得分和显示卡牌
  11. public void OnMouseDown() {
  12. if (cardBack.activeSelf && controller.canReveal) {
  13. cardBack.SetActive(false);
  14. controller.CardRevealed(this);
  15. }
  16. }
  17. Unreveal()方法实现卡牌的翻转
  18. public void Unreveal() {
  19. cardBack.SetActive(true);
  20. }

(2)游戏控制的数据处理:
通过不可见的SceneController来设置图像创建空对象绑定SceneController.cs

  1. [SerializeField] private MemoryCard originalCard;
  2. [SerializeField] private Sprite[] images;
  3. void Start() {
  4. int index = j * gridCols + i;
  5. int id = numbers[index];
  6. card.SetCard(id, images[id]);
  7. }
  8. 实例化一个网格的卡牌,8次复制一个卡牌并定位到一个网格中
  9. for (int i = 0; i < gridCols; i++) {
  10. for (int j = 0; j < gridRows; j++) {
  11. MemoryCard card;
  12. // use the original for the first grid space
  13. if (i == 0 && j == 0) {
  14. card = originalCard;
  15. } else {
  16. card = Instantiate(originalCard) as MemoryCard;
  17. }
  18. // next card in the list for each grid space
  19. int index = j * gridCols + i;
  20. int id = numbers[index];
  21. card.SetCard(id, images[id]);
  22. float posX = (offsetX * i) + startPos.x;
  23. float posY = -(offsetY * j) + startPos.y;
  24. card.transform.position = new Vector3(posX, posY, startPos.z);
  25. }
  26. 打乱卡牌并且使每种卡牌都有两张
  27. int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
  28. numbers = ShuffleArray(numbers);
  29. 实现匹配、得分、和翻开一对卡牌
  30. private MemoryCard _firstRevealed;
  31. private MemoryCard _secondRevealed;
  32. private int _score = 0;
  33. public bool canReveal {
  34. get {return _secondRevealed == null;}
  35. }
  36. 保存并比较翻开的卡牌
  37. public void CardRevealed(MemoryCard card) {
  38. if (_firstRevealed == null) {
  39. _firstRevealed = card;
  40. } else {
  41. _secondRevealed = card;
  42. StartCoroutine(CheckMatch());
  43. }
  44. Knuth洗牌算法
  45. private int[] ShuffleArray(int[] numbers) {
  46. int[] newArray = numbers.Clone() as int[];
  47. for (int i = 0; i < newArray.Length; i++ ) {
  48. int tmp = newArray[i];
  49. int r = Random.Range(i, newArray.Length);
  50. newArray[i] = newArray[r];
  51. newArray[r] = tmp;
  52. }
  53. return newArray;
  54. }

(3)游戏界面控制的数据处理:
从SceneController中调用LoadLevel按钮的SendMessage尝试调用SceneController中的Restart方法

  1. public void Restart() {
  2. Application.LoadLevel("Scene");
  3. }
  4. OnMouseEnter()方法实现对游戏界面中的按钮控制,当鼠标滑到按钮上执行的操作
  5. public void OnMouseEnter() {
  6. SpriteRenderer sprite = GetComponent<SpriteRenderer>();
  7. if (sprite != null) {
  8. sprite.color = highlightColor;
  9. }
  10. OnMouseExit()方法实现对游戏界面中的按钮控制,当鼠标离开按钮执行的操作
  11. public void OnMouseExit() {
  12. SpriteRenderer sprite = GetComponent<SpriteRenderer>();
  13. if (sprite != null) {
  14. sprite.color = Color.white;
  15. }
  16. }
  17. OnMouseDown()方法实现对游戏界面中的按钮控制,当鼠标按下按钮执行的操作
  18. public void OnMouseDown() {
  19. transform.localScale = new Vector3(1.1f, 1.1f, 1.1f);
  20. }
  21. OnMouseUp()方法实现对游戏界面中的按钮控制,当鼠标松开按钮执行的操作
  22. public void OnMouseUp() {
  23. transform.localScale = Vector3.one;
  24. if (targetObject != null) {
  25. targetObject.SendMessage(targetMessage);
  26. }
  27. }

(4)摄像机移动的数据处理:
控制摄像机的上下移动,使其可以点击超出运行界面的卡牌

  1. void Update()
  2. {
  3. if( Input.GetAxis("Mouse ScrollWheel") > 0 )
  4. {
  5. transform.Translate(Vector3.up * Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 500f);
  6. }
  7. if (Input.GetAxis("Mouse ScrollWheel") < 0)
  8. {
  9. transform.Translate(-Vector3.down * Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 500f);
  10. }
  11. }

4) 数据输出
初始界面:可以通过鼠标滚动显示下面几行的牌


当鼠标放在按钮之上的界面:按钮颜色发生变化

按下按钮之后的界面:按钮大小发生变化

翻牌之后的界面:;两张扑克牌花色不同时不能得分

两张扑克牌的花色相同数字不同时同样不能得分

两张牌的花色和数字都匹配时即可得分,并且牌不会翻回去


得分之后牌面不会翻转,可以继续翻其他的牌

三、 实验环境

  1. 操作系统:WINDOWS 10
  2. 开发工具:Unity3D
  3. 实验设备:PC

源代码

  1. MemoryCard
  2. using UnityEngine;
  3. using System.Collections;
  4. public class MemoryCard : MonoBehaviour {
  5. [SerializeField] private GameObject cardBack;
  6. [SerializeField] private SceneController controller;
  7. private int _id;
  8. public int id {
  9. get {return _id;}
  10. }
  11. public void SetCard(int id, Sprite image) {
  12. _id = id;
  13. GetComponent<SpriteRenderer>().sprite = image;
  14. }
  15. public void OnMouseDown() {
  16. if (cardBack.activeSelf && controller.canReveal) {
  17. cardBack.SetActive(false);
  18. controller.CardRevealed(this);
  19. }
  20. }
  21. public void Unreveal() {
  22. cardBack.SetActive(true);
  23. }
  24. }
  25. SceneController
  26. using UnityEngine;
  27. using System.Collections;
  28. using UnityEngine.UI;
  29. public class SceneController : MonoBehaviour {
  30. public const int gridRows = 9;
  31. public const int gridCols = 8;
  32. public const float offsetX = 2f;
  33. public const float offsetY = 2.5f;
  34. [SerializeField] private MemoryCard originalCard;
  35. [SerializeField] private Sprite[] images;
  36. [SerializeField] private TextMesh scoreLabel;
  37. private MemoryCard _firstRevealed;
  38. private MemoryCard _secondRevealed;
  39. private int _score = 0;
  40. public bool canReveal {
  41. get {return _secondRevealed == null;}
  42. }
  43. // Use this for initialization
  44. void Start() {
  45. Vector3 startPos = originalCard.transform.position;
  46. // create shuffled list of cards
  47. int[] numbers = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 };
  48. numbers = ShuffleArray(numbers);
  49. // place cards in a grid
  50. for (int i = 0; i < gridCols; i++) {
  51. for (int j = 0; j < gridRows; j++) {
  52. MemoryCard card;
  53. // use the original for the first grid space
  54. if (i == 0 && j == 0) {
  55. card = originalCard;
  56. } else {
  57. card = Instantiate(originalCard) as MemoryCard;
  58. }
  59. // next card in the list for each grid space
  60. int index = j * gridCols + i;
  61. int id = numbers[index];
  62. card.SetCard(id, images[id]);
  63. float posX = (offsetX * i) + startPos.x;
  64. float posY = -(offsetY * j) + startPos.y;
  65. card.transform.position = new Vector3(posX, posY, startPos.z);
  66. }
  67. }
  68. }
  69. // Knuth shuffle algorithm
  70. private int[] ShuffleArray(int[] numbers) {
  71. int[] newArray = numbers.Clone() as int[];
  72. for (int i = 0; i < newArray.Length; i++ ) {
  73. int tmp = newArray[i];
  74. int r = Random.Range(i, newArray.Length);
  75. newArray[i] = newArray[r];
  76. newArray[r] = tmp;
  77. }
  78. return newArray;
  79. }
  80. public void CardRevealed(MemoryCard card) {
  81. if (_firstRevealed == null) {
  82. _firstRevealed = card;
  83. } else {
  84. _secondRevealed = card;
  85. StartCoroutine(CheckMatch());
  86. }
  87. }
  88. private IEnumerator CheckMatch() {
  89. // increment score if the cards match
  90. if (_firstRevealed.id == _secondRevealed.id) {
  91. _score++;
  92. scoreLabel.text = "Score: " + _score;
  93. }
  94. // otherwise turn them back over after .5s pause
  95. else {
  96. yield return new WaitForSeconds(.5f);
  97. _firstRevealed.Unreveal();
  98. _secondRevealed.Unreveal();
  99. }
  100. _firstRevealed = null;
  101. _secondRevealed = null;
  102. }
  103. public void Restart() {
  104. Application.LoadLevel("Scene");
  105. }
  106. }
  107. UIButton
  108. using UnityEngine;
  109. using System.Collections;
  110. public class UIButton : MonoBehaviour {
  111. [SerializeField] private GameObject targetObject;
  112. [SerializeField] private string targetMessage;
  113. public Color highlightColor = Color.cyan;
  114. public void OnMouseEnter() {
  115. SpriteRenderer sprite = GetComponent<SpriteRenderer>();
  116. if (sprite != null) {
  117. sprite.color = highlightColor;
  118. }
  119. }
  120. public void OnMouseExit() {
  121. SpriteRenderer sprite = GetComponent<SpriteRenderer>();
  122. if (sprite != null) {
  123. sprite.color = Color.white;
  124. }
  125. }
  126. public void OnMouseDown() {
  127. transform.localScale = new Vector3(1.1f, 1.1f, 1.1f);
  128. }
  129. public void OnMouseUp() {
  130. transform.localScale = Vector3.one;
  131. if (targetObject != null) {
  132. targetObject.SendMessage(targetMessage);
  133. }
  134. }
  135. }
  136. CameraMove
  137. using System.Collections;
  138. using System.Collections.Generic;
  139. using UnityEngine;
  140. public class CameraMove : MonoBehaviour
  141. {
  142. void Update()
  143. {
  144. if( Input.GetAxis("Mouse ScrollWheel") > 0 )
  145. {
  146. transform.Translate(Vector3.up * Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 500f);
  147. }
  148. if (Input.GetAxis("Mouse ScrollWheel") < 0)
  149. {
  150. transform.Translate(-Vector3.down * Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime * 500f);
  151. }
  152. }
  153. }

博客更新至专栏【课程设计实验报告】:https://blog.csdn.net/weixin_43598687/category_11640051.html

相关文章