完整项目请参考博客:https://blog.csdn.net/qq_41676090/article/details/96300302

本文为推箱子小游戏C#代码详解第一篇的代码部分,主要讲解

  • System.IO(数据存储)

  • MapGenerator(地图创建)

另外一篇文章将讲解这些代码怎么在Unity中使用

首先,给大家提个问题,什么是IO?

  • IO就是Input/Output,即输入和输出
  • IO的主要用途是读取文件以及写入文件
  • 我们游戏中的地图需要以IO的形式保存及读取

接下来,我们会搞清楚数据存储,同时,我们要开始创建我们的地图!

现在,我们来罗列一下我们需要数据存储功能为我们做些什么:

  • 创建地图(这个是必备的)
  • 读取地图(要是无法读取也就不需要玩这个游戏了【手动滑稽】)
  • 加载本地文件(IO的流程是加载-》处理,也就是说我们要加载好本地文件才能根据情况创建或者读取)
  • 获取全部地图的名字(数组,以方便我们制作关卡选择器来选择关卡)
  • 获取地图数量(这个用来处理全部地图名字的数组,也就是说我们可以从地图数量里限制循环次数)

好,思路分析清楚了,现在我们开始制作我们的地图

1.地图需要什么?

很明显,地图需要不同种类的方块:

  • 地面方块
  • 墙壁方块
  • 箱子存放点方块

其次,地图需要:

  • 箱子
  • 角色

搞明白这些后,我们从最基本的开始,我们只做地图,不管箱子和角色,毕竟有地图了没箱子没角色都无所谓,但是就是有箱子有角色,没地图也玩不了。

我们先做一个箱子类,用枚举(enum)来表明箱子的类型,用这个类来实现一些方法(比如加载图片素材,是否可以穿过以及tag)

写代码的时候,我们首先需要的是引用:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

其次,我们需要声明我们的箱子类型,即我们的枚举:

//方块Type
public enum BlockTypes
{Air=0,Wall=1,Ground=2,Point=3
}

下一步,创建我们的block类

/* * ==============================================================================* 功能描述:方块类 * 创 建 者:JN_X* 创建日期:2019年7月17日* ==============================================================================*/
[RequireComponent(typeof(Image))]
[RequireComponent(typeof(Image),typeof(BoxCollider2D))]
public class Blocks : MonoBehaviour
{void Start(){}void Update(){    }
}

首先,我们需要定义方块的类型,即声明一个BlockTypes,同时,因为我们用的是Unity,为了方便显示图片,我们需要给该脚本绑定一个Image类以及一个碰撞器

然后创建新的Image以及新的BlockTypes

public BlockTypes Type = BlockTypes.Air;public Image Image;

接下来在Start方法里面,把Image变量绑定为该gameObject上面挂载的Image:

Image = this.GetComponent<Image>();

然后,我们写一个SetBlock方法来创建block:

void SetBlock(){switch (Type)//每一帧执行一次检查方块{case BlockTypes.Air:Image.sprite = null;Image.enabled = false;break;case BlockTypes.Wall:Image.sprite = Resources.Load<Sprite>("wall");Image.gameObject.GetComponent<BoxCollider2D>().isTrigger = false;break;case BlockTypes.Ground:Image.sprite = Resources.Load<Sprite>("ground");Image.gameObject.tag = "Ground";break;case BlockTypes.Point:Image.sprite = Resources.Load<Sprite>("point");Image.gameObject.tag = "Point";Image.GetComponent<BoxCollider2D>().size = new Vector2(50, 50);break;default:Image.sprite = null;Image.enabled = false;break;}}

通过Resource.Load方法加载资源文件夹下的文件,通过boxcollider判断block的类检测是否可以碰撞

在Update方法里,我们循环运行这个SetBlock方法以确保方块正确生成

以下是Block类完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//方块Type
public enum BlockTypes
{Air=0,Wall=1,Ground=2,Point=3
}
/* * ==============================================================================* 功能描述:方块类 * 创 建 者:JN_X* 创建日期:2019年7月17日* ==============================================================================*/
[RequireComponent(typeof(Image),typeof(BoxCollider2D))]
public class Blocks : MonoBehaviour
{public BlockTypes Type = BlockTypes.Air;public Image Image;// Start is called before the first frame updatepublic void Start(){Image = this.GetComponent<Image>();}// Update is called once per framevoid Update(){SetBlock();}void SetBlock(){switch (Type)//每一帧执行一次检查方块{case BlockTypes.Air:Image.sprite = null;Image.enabled = false;break;case BlockTypes.Wall:Image.sprite = Resources.Load<Sprite>("wall");Image.gameObject.GetComponent<BoxCollider2D>().isTrigger = false;break;case BlockTypes.Ground:Image.sprite = Resources.Load<Sprite>("ground");Image.gameObject.tag = "Ground";break;case BlockTypes.Point:Image.sprite = Resources.Load<Sprite>("point");Image.gameObject.tag = "Point";Image.GetComponent<BoxCollider2D>().size = new Vector2(50, 50);break;default:Image.sprite = null;Image.enabled = false;break;}}
}

2.IO类

在IO类中,我们要实现以下功能:

  • 文件的操作(创建,更改,读取)
  • 获取地图的数量
  • 获取全部地图名称

在这里,我们以数字0-3来代替方块的类型,

比如说地图有3个方块,是墙壁,地面,箱子摆放点,

数字就会是1 2 3

这里是用类型id+空格+下一个id来存储的,并保存为txt文件

IO类的主要用法就是数据流,重点是创建数据流后用完就关(Close或者Dispose),不然会出现错误

由于时间紧促,这里直接上完整代码,代码中有注释:

using System.IO;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/* * ==============================================================================* 功能描述:数据流的写入与输出 * 创 建 者:JN_X* 创建日期:2019年7月17日* ==============================================================================*/
public class IO : MonoBehaviour
{public string path;//数据路径// Start is called before the first frame updatepublic void Start(){//如果没存档的话创造存档Write("关卡1", "1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 3 1 1 1 2 2 2 2 2 2 1 1 2 1 1 1 2 2 2 1 2 2 1 1 2 1 1 1 2 1 2 1 2 2 1 1 2 1 1 1 3 1 2 1 2 2 1 1 2 1 1 1 1 1 2 2 2 2 2 2 2 2 1 1 1 1 2 2 1 1 1 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 297,341.333 681,212 ");Write("关卡2", "1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 2 2 2 1 1 2 2 2 2 2 2 1 2 2 2 1 1 2 1 2 1 2 2 1 3 2 2 1 1 2 1 2 1 2 2 1 1 2 2 1 1 3 1 2 1 2 2 1 1 2 1 1 1 1 2 2 2 2 2 2 2 2 2 1 1 3 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 811,474 388,211 214,559.33 -214,559.33");Write("0", "");//刷新if (PlayerPrefs.GetInt("New")==0){PlayerPrefs.SetString("ReadMap", "关卡1");PlayerPrefs.SetInt("New", 1);Application.LoadLevel(0);}}// Update is called once per framevoid Update(){
#if UNITY_EDITOR//编辑器下方便调试if (Input.GetKey(KeyCode.X)){PlayerPrefs.DeleteAll();//删除本地数据}
#endif}void FindFile(string MapName)//加载以及创建文件{
#if PLATFORM_STANDALONEpath = Application.dataPath + "/StreamingAssets";
#elif PLATFORM_IOSpath = Application.dataPath + "/Raw";
#elif PLATFORM_ANDROIDpath = "jar:file://" + Application.dataPath + "!/assets/";
#endifif (!Directory.Exists(path + "/Map")){Directory.CreateDirectory(path + "/Map");}if (!File.Exists(path + "/Map/" + MapName + ".txt")){FileStream fs = new FileStream(path + "/Map/" + MapName + ".txt",FileMode.Create);fs.Close();}}public void Write(string MapName,string Text)//写入文件{FindFile(MapName);File.WriteAllText(path + "/Map/" + MapName + ".txt",Text);}public static string ReadText(string MapName)//读取文件{string path;
#if PLATFORM_STANDALONEpath = Application.dataPath + "/StreamingAssets";
#elif PLATFORM_IOSpath = Application.dataPath + "/Raw";
#elif PLATFORM_ANDROIDpath = "jar:file://" + Application.dataPath + "!/assets/";
#endifStreamReader sr = new StreamReader(path + "/Map/" + MapName + ".txt");string value= sr.ReadToEnd();sr.Close();return value;}public static string[] GetMaps()//获取所有地图文件{string path;
#if PLATFORM_STANDALONEpath = Application.dataPath + "/StreamingAssets";
#elif PLATFORM_IOSpath = Application.dataPath + "/Raw";
#elif PLATFORM_ANDROIDpath = "jar:file://" + Application.dataPath + "!/assets/";
#endifDirectoryInfo di = new DirectoryInfo(path + "/Map");string[] ls = new string[di.GetFiles("*.txt").Length];FileInfo[] fs = di.GetFiles("*.txt");for (int i = 0, j = ls.Length; i < j; i++){ls[i] = fs[i].Name.Replace(".txt","");}return ls;}public static int MapCounts()//获取地图总数{string path;
#if PLATFORM_STANDALONEpath = Application.dataPath + "/StreamingAssets";
#elif PLATFORM_IOSpath = Application.dataPath + "/Raw";
#elif PLATFORM_ANDROIDpath = "jar:file://" + Application.dataPath + "!/assets/";
#endifDirectoryInfo di = new DirectoryInfo(path+"/Map");int value= di.GetFiles("*.txt").Length;return (value);}
}

3.MapGenerator生成地图类

由于时间紧促,也直接上代码了,代码里有注释

using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/* * ==============================================================================* 功能描述:地图生成* 创 建 者:JN_X* 创建日期:2019年7月17日* ==============================================================================*/
public class MapGenerator : MonoBehaviour
{public IO IO;//IO类public enum Mode//地图模式{Read = 1,Create = 2,Empty = 3}public Mode MapMode = Mode.Read;//默认读取地图public GameObject[] MapBlocks=new GameObject[108];//分辨率1026*768,一个108个方块public List<string> MapStringList;//全部地图public string ReadMap = "1";//第一关地图为1.txtpublic GameObject EditPre;//用于关卡编辑器的预设体// Start is called before the first frame updatevoid Awake(){IO = FindObjectOfType<IO>();//从游戏内获取IOReadMap = PlayerPrefs.GetString("ReadMap","关卡1");//读取关卡1//根据不同的地图加载,如果是地图0就是编辑器if (ReadMap== "0"){MapMode = Mode.Create;}else{MapMode = Mode.Read;}//切换模式switch (MapMode){//如果是读取地图,就根据里面每一个数字变为数组,并转换为方块case Mode.Read:int l = IO.ReadText(ReadMap).Split(' ').Length;string[] list = IO.ReadText(ReadMap).Split(' ');for (int i = 0; i < l; i++){MapStringList.Add(list[i]);}MapStringList.Remove("");for (int i = 0, j = MapBlocks.Length; i < j; i++){MapBlocks[i].AddComponent<Blocks>();MapBlocks[i].GetComponent<Blocks>().Type = (BlockTypes)int.Parse(MapStringList[i]);MapBlocks[i].GetComponent<Blocks>().Start();}break;//创建地图的时候全部房款变为地面case Mode.Create:for (int i = 0, j = MapBlocks.Length; i < j; i++){GameObject aa = MapBlocks[i];MapBlocks[i].AddComponent<Blocks>();MapBlocks[i].GetComponent<Blocks>().Type = BlockTypes.Ground;MapBlocks[i].GetComponent<Blocks>().Start();//添加Button按钮组件MapBlocks[i].AddComponent<Button>();//用监听器监听点击事件,用()=>{}lambda表达式MapBlocks[i].GetComponent<Button>().onClick.AddListener(() =>Instantiate(EditPre, aa.transform));}break;//空地图case Mode.Empty:for (int i = 0, j = MapBlocks.Length; i < j; i++){MapBlocks[i].AddComponent<Blocks>();MapBlocks[i].GetComponent<Blocks>().Type = BlockTypes.Air;MapBlocks[i].GetComponent<Blocks>().Start();}break;}}// Update is called once per framevoid Update(){}//GUI保存地图按钮,不是很需要//private void OnGUI()//{//    //保存地图代码//    if (GUI.Button(new Rect(0, 0, 100, 100), "save"))//    {//        Save("关卡1");//    }//}//保存地图,将方块转换为id,在保存,将箱子变为坐标在保存public void Save(InputField inputField){string Name = inputField.text;string a = "";for(int i = 0; i < 108; i++){int v = (int)MapBlocks[i].GetComponent<Blocks>().Type;a += v.ToString()+" ";}Chest[] Chests = FindObjectsOfType<Chest>();for(int i = 0, j = Chests.Length; i < j; i++){string x = Chests[i].transform.position.x.ToString();string y = Chests[i].transform.position.y.ToString();a += x+","+y +" ";}IO.Write(Name, a);}
}

4.最后

到这里,我们有3个要创建的代码:

IO,Blocks和MapGenerator

我们将在下一篇文章讲解如何使用,敬请期待!

其他版本

  • Java版本:由莫言情难忘版权归属,点击此处查看详细内容

推箱子小游戏C#代码详解

后续总计会更新3篇文章,为以下内容:

第一篇

  • System.IO(数据存储)

  • MapGenerator(地图创建)

  • Unity中使用 https://blog.csdn.net/qq_41676090/article/details/102067740

第二篇

  • 角色移动

  • 箱子逻辑

  • 关卡自定义编辑

  • Unity中使用

第三篇

  • GameManager(游戏管理)

  • LeverPicker(关卡选择)

  • Unity中使用

本博客版权归属JN_X,今年15,QQ2313551611,欢迎各位小哥哥小姐姐加QQ交流技术,转载请申明出处。

[新手必备]Unity推箱子小游戏C#代码详解(第一篇-代码部分)相关推荐

  1. win32GDI函数编程实现推箱子小游戏

    利用GDI绘图函数实现推箱子小游戏,代码源于上一篇博客 C语言控制台推箱子. 实现方法很简单,把字符用绘图函数绘出的图形替换即可. 从字符控制台到win32界面编程,更加形象化. 代码量大增,主程序就 ...

  2. c 语言推箱子vs,C语言推箱子小游戏教程

    作者GitHub-Pages个人主页 本教程GitHub-Pages链接 本教程百度云下载地址 本教程编写于2016/11/22 Dawson Lee edited this page on Beij ...

  3. c++ 小游戏_C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目

    C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...

  4. 简单的c语言推箱子程序,完整版本的推箱子小游戏,最简单的纯C语言打造

    /*推箱子小游戏 1.定义绘制样式 用二维数组的方式 2.绘制图像 3.找出当前位置 4.逻辑判断,制造动作 根据数学xy轴的规律,这里使用ij 上移,行轴上升,行数减少 下移,行数下降,函数增加 左 ...

  5. c#推箱子小游戏代码_推箱子小游戏V1.0制作

    小游戏实践 推箱子简易版 大家好,我是努力学习争取成为优秀的Game Producer的路人猿,今天来一起做一个推箱子的简易版本V1.0!下面跟我一起做吧~ 我们用到的软件如下: 编辑类 Visual ...

  6. 移动平台开发项目(推箱子小游戏)

    项目目的:实现一个推箱子小游戏 项目架构:使用三个活动类 项目功能: 能在touch中的Action_down动作下,实现小人推着箱子走的效果,全部箱子到达旗帜为过关. 能使用底部Button键来前后 ...

  7. C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流

    C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流 说明:学做了4关推箱子, 仅供初学者参考可用g++ 编译,可以将内容复制到TXT文件,将后缀改为".cp ...

  8. 手把手教你使用Python实现推箱子小游戏(附完整源码)

    文章目录 项目介绍 项目规则 项目接口文档 项目实现过程 前置方法编写 move核心方法编写 项目收尾 项目完善 项目整体源码 项目缺陷分析 项目收获与反思 项目介绍 我们这个项目是一个基于Pytho ...

  9. python推箱子小游戏

    推箱子小游戏 本次小游戏学习视频:https://www.bilibili.com/video/BV1gz411B71H 相关素材:点击这里 import turtle import levelms ...

最新文章

  1. resin启动时报错com.caucho.config.LineConfigException的解决
  2. 学计算机买笔记本是i5 i7,i7不一定比i5好!懂电脑的人选择买i5,而不是i7,究竟怎么回事?...
  3. ios UIScrollView 中控件自动增加间隔
  4. CSDN markdown 如何更改文字字体、样式、颜色、大小?
  5. 一次作死尝试:将自己的linux用rm -rf /会怎样?结果哭了。。
  6. 节省显存新思路,在PyTorch里使用2 bit激活压缩训练神经网络
  7. BASIC-2 01字串
  8. 山东理工大学第十二届ACM程序设计竞赛 - Cut the tree(树上启发式合并+线段树)
  9. android: a system image must be selected to continmue
  10. Openfire服务端安装和配置
  11. DIV下的DIV居中
  12. QCC3040---Local name module
  13. QT的triggered意思
  14. 如何回复审稿人的意见?(总结)
  15. 双月学习OKR(67月)
  16. python应用——分治法实现循环赛
  17. 如何让DIV元素永远居中显示
  18. 20170622《指导生活的算法》
  19. 2021年中国生鲜电商行业发展回顾及未来行业发展策略分析:要增强生鲜农产品的稳定性、降低运营成本[图]
  20. ppt怎么转换成word文档呢?

热门文章

  1. win10 在cmd中将用户切换到管理员权限
  2. Python迁移学习:机器学习算法
  3. 【Redis】Redis各大版本最新版以及系统兼容性测试
  4. linux配置svn开启端口映射,linux 下搭建Subversion (SVN)
  5. Q3净利润“井喷”,亚马逊已握两万亿市值“通关密码”?
  6. 图像压缩小波变换原理
  7. Spring Boot 原理解析—启动类包扫描原理
  8. (邮件/用户)代理协议简介Socket程序发送电子邮件
  9. response.setHeader(Content-Type)与response.setContentType()
  10. el-table滚动条样式修改