超级扫雷二代:任务模式

更新日期:2025-03-10

阅读次数:74

背景介绍

超级扫雷是一款类似扫雷的游戏。

经典扫雷有两个痛点:

  • 高级大概无解。高级经常遇到二选一,无法推理解决。
  • 简单。高级扫雷中数字3就是极限,4非常少,5678几局都遇不到一次。经常玩扫雷的人都能把所有形状背下来,太简单了。

对此我们添加了视距与石头,在保证扫雷有解的同时,使得扫雷更加具有挑战性。

  • 视距:扫雷默认显示3×3的雷数。我们的玩家可以选择5×5或者7×7。
  • 石头:石头是一种特殊的格子,开局即可见,不可点击。所有石头按照【中央密集,四周疏松】的方式分布。

我们的游戏中有大量的4 5 6的格子,甚至7 8都是几乎必出的。但是必然有解。

参考图: 叹息之墙

之前我们开发了一代游戏,并发布到了Steam。目前一代游戏可运行(如上图)。我们现在要开发的是二代。 一代新手引导做的不好,二代主要是优化新手引导。 一代的代码结构不差(但也说不上完美)。至少做到了:每个UI界面一个文件,UI与数据分离,本地化与存档都是单独的文件,复用的代码放到库文件夹中,库与项目用命名空间区分。

1.1:修改一代(已完成)

  • 抽离出一个Steam开关(一个静态函数,带bool参数),使得代码中可以一行代码来切换【是否启用Steam检查】。然后你将开关设置为【不启用Steam检查】。
  • 砍掉50关设计,只保留一关,其内容为原本的第50关。砍掉选关面板。【开始游戏】按钮改为【标准模式】按钮,点击后直接进入第50关。
  • 砍掉解锁设计,默认所有功能全部解锁。砍掉【全功能解锁】【全关卡解锁】按钮。
  • 砍掉服务器与通讯相关代码。排行榜只保留本地排行。

任务时间:两天。 本次任务主要是熟悉一下本项目。

1.2:关卡编辑器

  • 主菜单添加关卡编辑器按钮,点击进入关卡编辑器
  • 关卡编辑器中,玩家可以新建关卡、查看并编辑前台与后台状态、保存。也可以根据零数与石峰来随机化生成(50关就是如此随机生成的)。布局方面,左侧是自定义关卡列表,中央是关卡网格,右侧是功能按钮,暂时简单设置就行、后续任务等美术组做完后会让你调整美术。功能包括:
    public interface I指令 { bool Invoke(); }
    public interface I编辑器设置关卡名称指令 : I指令 { [排序(1)] string 名称 { get; } };
    public interface I编辑器设置关卡简介指令 : I指令 { [排序(1)] string 简介 { get; } };
    public interface I编辑器设置关卡宽度指令 : I指令 { [排序(1)] int 宽度 { get; } }; (已屏蔽)
    public interface I编辑器设置关卡高度指令 : I指令 { [排序(1)] int 高度 { get; } };
    public interface I编辑器设置关卡左扩指令 : I指令 { }; (已屏蔽)
    public interface I编辑器设置关卡右扩指令 : I指令 { };
    public interface I编辑器设置关卡上扩指令 : I指令 { };
    public interface I编辑器设置关卡下扩指令 : I指令 { };
    public interface I编辑器设置关卡左缩指令 : I指令 { };
    public interface I编辑器设置关卡右缩指令 : I指令 { };
    public interface I编辑器设置关卡上缩指令 : I指令 { };
    public interface I编辑器设置关卡下缩指令 : I指令 { };
    public interface I编辑器随机生成关卡指令 : I指令 { [排序(1)] double 零数 { get; } [排序(2)] double 石峰 { get; } };
    public interface I编辑器总览新建关卡指令 : I指令 { };
    public interface I编辑器总览编辑关卡指令 : I指令 { [排序(1)] string 名称 { get; } };(已屏蔽)
    public interface I编辑器总览删除关卡指令 : I指令 { [排序(1)] string 名称 { get; } };(已屏蔽)
    public interface I编辑器总览游玩关卡指令 : I指令 { [排序(1)] string 名称 { get; } };(已屏蔽)
    public interface I编辑器当前保存关卡指令 : I指令 { };(已屏蔽)
    public interface I编辑器当前另存关卡指令 : I指令 { [排序(1)] string 名称 { get; } };
    public interface I编辑器坐标轮换后台指令 : I指令 { [排序(1)] int 横轴 { get; } [排序(2)] int 纵轴 { get; } };(已屏蔽)
    public interface I编辑器坐标轮换前台指令 : I指令 { [排序(1)] int 横轴 { get; } [排序(2)] int 纵轴 { get; } };
    public interface I打开编辑器指令 : I指令 { };(已屏蔽)
    public interface I关闭编辑器指令 : I指令 { };

数据参考如下结构:

    public interface IModel { };
    public interface I编辑器数据 : IModel {
        public string 当前关卡名 { get; }(已屏蔽)
        public bool 已保存 { get; }
        public I关卡数据 当前关卡 { get; }
        public List<I关卡数据> 所有关卡 { get; }
    }
    public interface I关卡数据 : IModel {
        public Grid<I地块> 网格 { get; set; } (已屏蔽)
        public 视距类型 视距 { get; set; }
        public bool 视野 { get; set; }
        public string 名称 { get; set; }
        public string 介绍 { get; set; }
        public int 宽度 { get; }
        public int 高度 { get; }
        public int 总雷 { get; }
        public int 总旗 { get; }
        public int 生命 { get; set; }
        public DateTime 开始时间 { get; set; }
        public DateTime 结束时间 { get; set; }
        public TimeSpan 用时 { get; }
    }
    public interface I地块 : IModel {
        public 后台类型 后台 { get; set; }
        public 前台类型 前台 { get; set; }
        public int 视距1雷数 { get; set; }
        public int 视距2雷数 { get; set; }
        public int 视距3雷数 { get; set; }
    }
    public enum 后台类型 {
        空地,
        地雷,
        石头,
    }
    public enum 前台类型 {
        开启,
        关闭,
        旗子,
    }
    public enum 视距类型 {
        一,
        二,
        三,
    }

你不必定义接口,直接定义数据。(因为Grid用接口的话会出现协变逆变问题) 指令也可以不定义,直接定义为函数。 在保存数据时使用FileWrite函数,参考一代中的本地存档代码。一个关卡一个文件,所有自定义关卡保存在默认存档路径下【自定义关卡】文件夹中。 注意:我们使用PanelConfig来生成UI控件,比如:

                头像 = 上区.创建矩形(new PanelConfig() {
                    矩形模式 = 矩形模式.固定无文本,
                    Position = $"0 0 80 80",
                    ImageColor = new(255, 255, 255, 1)
                });
                昵称 = 上区.创建矩形(new PanelConfig() {
                    矩形模式 = 矩形模式.固定文本框,
                    Position = $"{文字位置} 0 100% 30",
                    TextColor = 白色V4,
                    TextSize = 30,
                    Font = 游戏字体,
                });

其中,Position的格式是【左 上 宽 高】,每一项的格式可以是【5+20%】这样的两项算式,两项位置可以颠倒,百分比表示相对于父物体的宽/高。 你可以查看【矩形模式】来了解所有支持的模式。有任何疑问可以随时提问。 任务时间:五天。

1.3:挑战模式

修复bug:

  • (未定,等你做完1.2之后我检查后描述)

新增:

  • 主菜单添加【挑战模式】按钮,点击后打开一个关卡网格(参考之前被删除的选关界面。删除每一项的排行榜与进入按钮,点击项直接进入),其中是【StreamingAssets】路径下【挑战关卡】文件夹中的内容。挑战关卡需依次解锁。(挑战关卡文件命名为【1-1 单切.json】格式,按文件名开头的序号排序。你先用编辑器+随机化来生成几个挑战关卡,后续我会使用关卡编辑器创建挑战关卡。)
  • 主菜单添加【自定义模式】按钮,同上,其中内容为默认存档下【自定义关卡】的内容。
  • 在挑战模式的游戏内界面中,右上角增加一个按钮【下一关】。如果已经是最后一关,那么点击时弹窗提示是最后一关。

任务时间:四天。

1.4:教程模式

  • 新增主菜单按钮:教程模式。如果已完成教程,那么末尾加一个对号。
  • 当未完成教程就开始游戏时,弹窗警告:还未进行教程,确定直接开始游戏吗?确定,我是扫雷老玩家/不确定,我先看看教程。
  • 在正式游戏界面中,旁白加入基本规则介绍
    • 地块分为打开与关闭两个状态。打开所有非雷地块则胜利。
    • 左键可以打开地块,右键可以给地块插旗。
    • 旗子:不可点击
    • 石头:不可点击。不是雷。
    • 视距1时:数字表示3×3范围的雷数。
    • 视距2时:数字表示5×5范围的雷数。
    • 视距3时:数字表示7×7范围的雷数。
    • 视野:激活时自动统计地块范畴内的旗子数量。
  • 教程设定是一个列表,每一项是I关卡数据。并且,给I关卡数据加一个字段【高亮坐标】,给关卡编辑器中添加这个设置。在前台UI中,那个坐标高亮,并且显示一个旁白文本(关卡数据的简介字段)。玩家点击那个坐标后,进入列表的下一项;列表全部完成后,教程结束。旁白下方有【5/9】这样的文本,表示教程进度。
  • 教程我会使用关卡编辑器制作,文件名陈格式为【1-认识布局.json】这样的格式,位于【StreamingAssets】路径下【教程关卡】文件夹。(每个关卡我会保证一键通关。)你先随便做几个教程,然后我会使用关卡编辑器加入教程。

任务时间:五天。

2.1:本地化重构、弹窗重构

  • 用户在设置修改语言时,所有文本自动变化,而不需要重启。(目前的本地化代码有两部分,混乱。其中一部分可以自动变化,另一部分(古老的)需要重启生效。你需要把古老的全部改为现代的。)
  • 弹窗重构(不使用预制体。并且,弹窗也要让本地化生效)
  • 设置的性能分析。目前设置按钮第一次点开很卡,你来检查原因并修改。

任务时间:五天

2.2:本地多账号与排行榜

  • 主菜单增加一个账号选择区域(类似植物大战僵尸)。不同账号不共享教程进度、挑战进度、标准战绩、自定义关卡。
  • 移出所有联网功能以及相关代码。排行榜全本地,可以切换多账号或单账号两个模式。单账号就是每次通关时的数据(使用SQLite,保存关卡局面),多账号就是:过关次数、总过关率、七关过关率、最高七关过关率、最快时间。
  • 每次胜利时,将I关卡数据保存。在单账号排行榜中点击一个条目右侧的查看局面按钮时,会进入关卡编辑器、显示那一关的终局局面。

任务时间:五天

2.3:美术升级

  • 主菜单、编辑器、战斗界面。我发美术效果图与素材图给你,你实装。

任务时间:三天