[RTS] 远古帝国

游戏链接https://pan.baidu.com/s/1eSd4ZHg
这是我开发的一款策略战棋游戏[远古帝国]
他是我以前上学时经常玩的一款游戏 虽然现在市面上有很多重置版但是我还是喜欢玩原版 因为里面的战斗数据非常平衡 你能从中获得更多的乐趣
所以我尽量还原经典 仔细分析数据 力求完美(上下左右是wsad或方向键控制 确认键是空格或回车)


首先是移动范围的渲染

 
这里的人物移动范围可以在ACGame.Sprite中的MoveRange里配置

 
然后是地图 这张大地图都是由15*15的小地图拼接起来的

 
每张小地图上都挂了ACGame.Terrain脚本
CustomDepth设置的是移动到该地形需消耗的移动点
Def则是角色在该地形上的防御加成

 
当玩家点击了目的地 角色便会沿着路线移动过去

 

 
当角色移动完毕会跳出一个提示框显示是否结束当前移动
如果角色移动的目的地中有敌人则会出现攻击选项

 
每个角色的攻击范围不同 可以在脚本中配置

 
如果角色附近有多个敌人 玩家可以按上下左右键选择要攻击的敌人

 
然后就可以开始攻击

 
玩家攻击完成后敌人也会反击

 
角色的攻击力是一个范围 在脚本中可以配置 每次会从中随机取一个值

 
攻击的计算公式是(攻击方的攻击力-敌人防御-地形防御加成)*攻击方的血量百分比
这样可以保证攻击时血量较多的一方比较有利
玩家也可以利用山地 房屋等有防御加成的地形攻击敌人
也可以先使用满血的单位攻击 然后再使用残血单位补刀如果玩家或者敌人血量为0 则会爆出一块墓碑

 
接下来是购买界面

 
点击下方左右箭头可以在各个兵种之间切换 这里实现了无缝滚动
然后是我的代码
代码一共分为两大类 分别叫abstract和business
abstract中存放的都是接口 抽象类 和工具类 它们不依赖于business 所以不仅可以运用于当前项目 也可以在其他项目中使用
business存放具体的业务逻辑 这里的代码依赖关系比较复杂
这样的分类也是我研究了好久 我曾经试过将所有的类都面向接口 耦合也降到最低 但是这样做没有意义
因为就算面向了接口 但最终还是要把各处代码组合在一起 耦合还是存在 并且修改的话还是有可能修改好几处地方
后来我取消了接口 又发现代码变得更加难以维护
最后我做了分类 因为既然我没办法把所有的类全部独立 也不能把所有的类依赖在一起 那我就索性把独立性较强的类和处理业务逻辑的类分开
这样就诞生了abstract和business而在实际编程中经常会出现business的代码写到一半发现之前写过 然后把重复的逻辑整理好放到abstract中
而放入abstract中的代码基本不会再去放回business

 
在abstarct中有一个分类是专门存放设计模式的
虽然里面就两个类 但代码中远不止这两种设计模式
放在这里仅仅是因为它们整个类里都在做设计模式做的事
而且其他模式则和其他逻辑耦合在一起

 
首先是DynamicFactroy
他本质是一个工厂模式 但是没有一本书上会有这种工厂模式 这是我自创的
这里就做两件事 先找字典中有没有你要的对象 没有就用反射创建一个

 
第二个是单例模式
我知道学过c++的人都会七八种单例模式的写法
但是这里我就按照unity的思路写一个就行了

 
还有一个非常棘手的问题就是对象的初始化参数
按照我们以前的思路 要么把类中需要初始化的数据在声明时就赋值
要么写一个构造器 但是在unity中 如果你的类继承了MonoBehaviour你就没办法使用有参构造器了
因为unity要序列化你的脚本显示在inspector上 它走的是无参构造器 就算你写了有参构造器他也不会走 而且会报警
我看到很多老外的代码里直接写了个setter 我觉得这样做违背了初始化这个词的两个初衷
首先破坏了封装 你的内部变量可以在对象创建后随意修改
其次有空数据的风险 如果你的代码没有调用相关setter 编译不会察觉 那你的变量就为null了
这里我的解决方法是写一个ResourceManager 你可以看到它使用了我的单例模式

 
然后在脚本执行顺序中把他放到第一个

 
这样我就可以在代码中的任何地方随意调用初始化好的参数

 
但是你可以看到ResourceManager中有各种各样的控件 光标 相机等
我的项目有这些控件 而你的项目不大可能也有这些
所以ResourceManager应该归到business中
那如果ResourceManager是business了 那么abstract中继承了MonoBehaviour的类也想要初始化参数怎么办
这里还有一个办法
就是在这些类中写一个抽象函数作为构造函数这里拿一个放大特效脚本做例子它的效果是激活后 物体会从一个点慢慢的放大成原来的样子
接下来说说状态模式 里面存放的全是游戏业务逻辑
如果你按下一个键后需要一大堆if else 那么你就需要状态模式
我发现HeadFirstParttern一书中的状态模式有些不足
第一 他的状态会频繁的创建
第二 他的状态切换必须经过Update
而我的状态对象的获取是通过我的动态工厂获得的 同一个状态只有一个对象
然后我的状态切换并不是通过update切换的 而是通过GoNextState<T>()
这样我可以在任何事件中切换状态
我的状态模式基类

 
状态子类 可以看到当子类中触发了点击事件后会进入MoveState

 
进入MoveState后角色移动完毕又进入BehaviourState

 
在BehaviourState中玩家如果选择移动结束则回到InitialState 如果选择攻击 则进入SelectEmyState

 
在这个项目里一共有八个状态

 
他们之间的切换过程可以在inspector中可以看到

 
这里出现了一个GameManager 起始它的作用就是刷新游戏状态
这样我的游戏中只有一个update在运行

 
接下来是最困难的地方 就是地形的遍历
作为一个策略战棋游戏 最必不可少的就是地图遍历
这里我使用了四叉树
而这里的四叉树和一些算法书上不一样 一般数据结构的节点都会先建立一个四叉树节点类
然后在类中存一个泛型数据 但我觉得这样用的时候不方便
所以我的写法是每一个节点都包含了它上下左右四个同类型的节点

 
设计好了四叉树 那么在遍历前先要把他们连接起来
这里我写个接口IQuadNodeSetter用于设置四叉树的四个节点

 
然后是定义位置接口IPositional 因为我想通过物体的位置关系来连接

 
连接之前我会对所有的地形根据位置进行排序 所以还要用到IComparable<IPositional>
所以一个节点连接的所有接口准备齐了 把它们合在一起就是ILinkable接口

 
任何类只要实现了ILinkable接口就可以在PLinkQuadNode中被连接成四叉树

 
在unity的界面中是这样的

 
点击连接按钮它就会连接子节点中所有实现ILinkable的节点

 
你可以看到我并没有开始运行游戏 而Terrain中已经有了值
这样我就可以在游戏运行之前就连接好四叉树 不会在游戏中消耗性能
所以PLinkQuadNode中的P表示的是Preprocess
凡是这种脚本都放在Preprocess文件分类中有了连接好的四叉树 那么就可以遍历了
这里我写了三种遍历器 而且每种遍历器都使用了策略模式和享元模式

 
第一个构造器中使用的IIterateBehaviour接口用来定义遍历时的行为

 
先实现接口

 
再把他们组合起来

 
最后呈现出来的效果

 

如果改变遍历时的行为

 
就会这样渲染

 
这里我还可以使用相同的遍历行为 但使用不同的遍历方法 这样就从策略模式变成桥接模式了

 

 

 

 
这里我测试了遍历的逻辑

 

 
我建立了一个测试文件夹 里面存放test代码

 
每次遍历到一个节点 就把它z轴提高 这样我可以清除的看到是否有重复遍历

 
最后是享元模式 每个遍历器都可以选择创建新的变量 也可以公用其他遍历器实例的变量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容