经典小游戏开发思路和算法之推箱子(2) 桃扇骨 2022-03-29 04:10 328阅读 0赞 **游戏简介**:推箱子是一个超经典的游戏,目的是锻炼玩家的逻辑思考能力。 **游戏规则**:这个游戏是在一个正方形的棋盘上进行的,每一个方块表示一个地板或一面墙。地板可以通过,墙面不可以通过。地板上放置了箱子,一些地板被标记为储存位置。玩家被限定在棋盘上,可以水平或垂直移动到空的方块上(不会穿过墙或箱子)。箱子不得被推入其他箱子或墙壁,也不能被拉出。箱子的数量等于储存位置的数量。当所有箱子都被安放到储存地点时,游戏胜利。 **开发思路**:首先是生成地图,用二维数组来储存地图信息,每个元素用不同的数字来标记不同的对象。(例如:0表示空白,1表示墙,2表示角色,3表示箱子,9表示终点(中间空余的值是为了方便添加其他颜色的箱子等))。 地图的生成:通过遍历地图二维数组,读取每个元素的数值,根据数值标记生成不同的地图对象。也可用一维数组表示,其二维数组映射到一维数组的公式为: b\[i*n+j\]==a\[i\]\[j\].其中,设数组有m行n列,i,j分别表示数组内的行数和列数(0<i<m,o<j<n). 角色移动:使角色在9*9的一位数组中移动,其中左上角为原点。 箱子移动:与角色移动相同。 **游戏实现**: 代码如下: using System.Collections; using System.Collections.Generic; using UnityEngine; public class Done_Build : MonoBehaviour { public static int[] temp_map; public int[] final_map; public GameObject[] destoryObj; public Sprite[] mapSprites; public bool playerDestory = false; public bool boxDestory = false; GameObject g; public GameObject mapPrefab;//地图的墙壁 public GameObject playerPrefab;//角色 public GameObject boxPrefab;//箱子 public GameObject finalBoxPrefab;//到终点后的箱子 public GameObject finalPrefab;//游戏获胜后刷新一张图片,用于提示游戏获胜。 /// <summary> /// 数组初始化 /// </summary> private void Awake() { final_map = new int[9 * 9];//传值数组 temp_map = new int[] { 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 0, 1, 0, 3, 0, 1, 0, 1, 1, 1, 1, 0, 3, 0, 1, 0, 1, 9, 1, 1, 1, 1, 3, 1, 1, 1, 9, 1, 0, 1, 1, 0, 0, 0, 0, 9, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0 }; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { final_map[j * 9 + i] = temp_map[j * 9 + i]; } } } // Use this for initialization void Start() { BuildMap(); } /// <summary> /// 地图初始化 /// </summary> void BuildMap() { destoryObj = new GameObject[9 * 9];//用于销毁GameObject int i = 0; for (int y = 0; y < 9; y++) { for (int x = 0; x < 9; x++) { switch (temp_map[i]) { case 1: //生成墙壁 case 0://无图 g = Instantiate(mapPrefab) as GameObject; g.transform.position = new Vector3(x, -y, 0); g.name = x.ToString() + y; destoryObj[y * 9 + x] = g; Sprite icon = mapSprites[temp_map[i]];//使贴图与地图数组吻合 g.GetComponent<SpriteRenderer>().sprite = icon; break; case 2://生成人物 g = Instantiate(playerPrefab) as GameObject; g.transform.position = new Vector3(x, -y, 0); g.name = "Player"; destoryObj[y * 9 + x] = g; break; case 3://生成箱子 g = Instantiate(boxPrefab) as GameObject; g.transform.position = new Vector3(x, -y, 0); g.name = "Box"; destoryObj[y * 9 + x] = g; break; } if (i < 80) { i++; } } } } /// <summary> /// 角色移动 /// </summary> void PlayerMove() {//获取各项数值 int x, y; int x_num = 0; int y_num = 0; //获取Player坐标 Transform playerPos = GameObject.Find("Player").GetComponent<Transform>(); x = (int)playerPos.position.x; y = (int)playerPos.position.y; //获取界面移动坐标数值 x_num = FindObjectOfType<Done_GameController>().x_num; y_num = FindObjectOfType<Done_GameController>().y_num; //获取动画 一定要放在销毁Player前 string animator_name = FindObjectOfType<Done_GameController>().animator_name; //销毁原有Player Destroy(destoryObj[-y*9+x]); g = Instantiate(playerPrefab) as GameObject; g.GetComponent<Animator>().Play(animator_name); g.transform.position = new Vector3(x + x_num, y + y_num, 0); g.name = "Player"; //将新的Player存入销毁数组 destoryObj[-((y + y_num) * 9) + x + x_num] = g; playerDestory = false; } /// <summary> /// 箱子移动 /// </summary> void BoxMove() {//获取各项数值 int x, y; int x_num = 0; int y_num = 0; //获取界面移动坐标数值及Box界面编号 x_num = FindObjectOfType<Done_GameController>().x_num; y_num = FindObjectOfType<Done_GameController>().y_num; //获取相应Box坐标 Transform playerPos = GameObject.Find("Player").GetComponent<Transform>(); x = (int)playerPos.position.x + x_num;//Player的X坐标+x_num为下一个目标点的X坐标,即为相应Box的X坐标,Y同理 y = (int)playerPos.position.y + y_num; //销毁原有Box Destroy(destoryObj[-y * 9 + x]); if (final_map[-((y + y_num) * 9) + x + x_num]== 0 || final_map[-((y + y_num) * 9) + x + x_num] == 3) { g = Instantiate(boxPrefab) as GameObject; g.transform.position = new Vector3(x + x_num, y + y_num, 0); g.name = "Box"; } else if (final_map[-((y + y_num) * 9) + x + x_num] == 9) { g = Instantiate(finalBoxPrefab) as GameObject; g.transform.position = new Vector3(x + x_num, y + y_num, 0); g.name = "FinalBox"; } //将新的Box存入销毁数组 destoryObj[-((y + y_num) * 9) + x + x_num] = g; playerDestory = false; boxDestory = false; } private void Update() { if (playerDestory)//如果Player移动并且原有Player需要销毁 { if (boxDestory)//如果Box移动并且原有Box需要销毁 { BoxMove(); } PlayerMove(); } //游戏结束判定 if (GameObject.Find("Box") == null&&GameObject.Find("Final")==null) { g = Instantiate(finalPrefab) as GameObject; g.transform.position = new Vector3(4, -4, 0); g.name = "Final"; } } } using System.Collections; using System.Collections.Generic; using UnityEngine; public class Done_GameController : MonoBehaviour { public int x_num = 0; public int y_num = 0; public bool IsChange = false; public int box_num; public string animator_name; // Use this for initialization void Start() { } public bool IsMove() { int x, y; //获取Player坐标 Transform playerPos = GameObject.Find("Player").GetComponent<Transform>(); x = (int)playerPos.position.x; y = (int)playerPos.position.y; GameObject g; // 如果人物下一个运动目标点为空 if ((Done_Build.temp_map[-y * 9 + x + (int)dir] == 0 || Done_Build.temp_map[-y * 9 + x + (int)dir] == 9) && IsChange == true) { //改变数组内人物位置 Done_Build.temp_map[-y * 9 + x] = 0; Done_Build.temp_map[-y * 9 + x + (int)dir] = 2; // 回传数据 //FindObjectOfType<Done_Build>().temp_map = temp_map; IsChange = false; FindObjectOfType<Done_Build>().playerDestory = true; return true; } //如果人物下一个运动目标点为墙壁 else if (Done_Build.temp_map[-y * 9 + x + (int)dir] == 1 && IsChange == true) { IsChange = false; return false; } // 如果人物下一个运动目标点为箱子 else if (Done_Build.temp_map[-y * 9 + x + (int)dir] == 3 && (Done_Build.temp_map[-y * 9 + x + (int)dir*2] == 0 || Done_Build.temp_map[-y * 9 + x + (int)dir*2] == 9) && IsChange == true) //temp_map[-y * 9 + x + array_num]:下一个运动目标点的数组位置 { //改变数组内人物及箱子位置 Done_Build.temp_map[-y * 9 + x] = 0; Done_Build.temp_map[-y * 9 + x + (int)dir] = 2; Done_Build.temp_map[-y * 9 + x + (int)dir*2] = 3; //回传数据 //FindObjectOfType<Done_Build>().temp_map = temp_map; IsChange = false; FindObjectOfType<Done_Build>().playerDestory = true; FindObjectOfType<Done_Build>().boxDestory = true; return true; } return false; } public enum Direction { Up = -9,Down = 9,Left = -1,Right = 1} public Direction dir; // Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.UpArrow)) { dir = Direction.Up; } if (Input.GetKeyDown(KeyCode.DownArrow)) { dir = Direction.Down; } if (Input.GetKeyDown(KeyCode.LeftArrow)) { dir = Direction.Left; } if (Input.GetKeyDown(KeyCode.RightArrow)) { dir = Direction.Right; } switch (dir) { case Direction.Up: IsChange = true; x_num = 0; //生成新Gameboject时的实际位置坐标 y_num = 1; animator_name = "Up"; //动画控制 break; case Direction.Down: IsChange = true; x_num = 0; y_num = -1; animator_name = "Down"; break; case Direction.Left: IsChange = true; x_num = -1; y_num = 0; animator_name = "Left"; break; case Direction.Right: IsChange = true; x_num = 1; y_num = 0; animator_name = "Right"; break; } IsMove(); } }
还没有评论,来说两句吧...