创建卡牌游戏原型
Last Update:
创建卡牌游戏原型
开发日志
日志4.14
没想到一个卡牌游戏项目的复杂程度能这么大,我感觉无从下手。
日志4.15
制作了简陋的UI界面,甚至几乎没有任何可以装载的图片。
跑去制作了一个Python程序,用来批量处理md文件。
日志4.16
开始参考NueDeck代码模板进行开发。
日志4.17
创建卡牌行为枚举,创建了能够打出去并造成影响的卡牌。
实现了卡牌行为中间间,并在GameApp中进行初始化。
战斗的基本框架搭建完成。
接下来的任务:
1、制作抽牌、打牌动画,为卡牌添加特效、mana消耗
2、制作玩家和关卡敌人的数据注入。
日志4.18
制作了卡牌、玩家、敌人的数据注入。
并且对卡牌造成的影响能够正确做到。
编写UI更新的逻辑。
维护玩家卡组、抽牌堆、弃牌堆。
4.19
制作了敌人血条UI、敌人AI(固定行为模式和随机行为模式)
尝试维护玩家抽牌堆、弃牌堆。


4.20
教训:如果你在尝试运行时修改ScriptableObject数据,将会引起一场灾难。
最好只用来做数据的初始化。
问题来源ScriptableObject:在运行时修改meta文件并保存上一次Play的运行结果,当你退出编辑器后(大退),修改会重置;如果SetDirty的话,会将数据保存。
开发过程中遇到的困难
1、种子seed是怎么做的?这使得我难以复现同一局游戏。
肉鸽的随机:拿一个初始随机数种子,只要遇到需要用到随机数的地方,就使用这个种子通过某种去生成一个新的种子,然后再将这个新种子保存起来,然后后面再用到的时候就用这个生成的新种子去生成,重复上面的。
2、怎么提供保存机制?使得我能够从上次的进度中加载并继续。
3、没有开发资源(图片、icon、音效等
4、反射相关的内容。
5、如何搭建策划也能使用的框架?
->CardData为CardBase注入数据,让自定义卡牌不再充满苦难(悲
6、程序执行顺序总是有问题,报空指针是最难受的(悲
7、UI的更新逻辑使我头疼。
8、Debug
highlight the text
开发使用的版本/包/资源
Universal RenderPine
TextMeshPro
Cinemachine
DOTween
TrueShadow
Spine-Unity=>创建小人动画
参考项目:
NueDeck(一个代码模板,提供了Roguelike卡牌类游戏的基础功能)
Arefnue/NueDeck: Open source, roguelike deck-building card game template (github.com)
导入开发使用的资源
Spine骨骼动画(构成了角色的所有动画)
一些卡牌图片、UI、GUI
特效、粒子效果等
icon来自Orders | Fanatical的RPG Game Builder Assets Kit($15)
创建并搭建场景
1、主菜单场景
2、GamePlay场景
3、地图线路选择场景(Map)
可以通过SceneLoader在场景中进行切换。
创建Menu场景
放置开始和退出按钮
创建GamePlay场景
搭建游玩时的UI界面
包括顶部的通用设置界面
血量
主动道具
coins,用于购买的硬币
settings,设置按钮
collections,收藏品背包
和底部的战斗界面
mana,打出卡牌需要消耗能量
end turn按钮,进入下一回合的按钮
cardsCanvas,用于存放卡牌的位置
抽牌堆
弃牌堆
创建地图线路选择场景
提供一个能够选择随机行进路线的地图。
研究NueDeck框架内容
1、大量使用ScriptableObject作为数据文件存储,用以快捷地配置数据。
2、可以了解,卡牌类的游戏UI交互是不可或缺的一部分,甚至说比重相当大。
3、回合制战斗:
枚举实现
1 | |
1 | |
1 | |
绘制框架图
完成回合制卡牌GameLoop
制作可以打出的卡牌UI
控制卡牌能够选中、缩放、拖拽
发牌动画以及打出卡牌后的动画
卡牌管理
管理玩家的牌组(想必是一个 List
结构来存储相应的数据)。 管理玩家的抽牌堆、弃牌堆,提供抽牌、弃牌等方法。
调用UIManager来实现上述方法。
提供使用UseCard方法,调用DoAction来使用卡牌。
查看抽牌堆,查看弃牌堆
制作UI管理器UIManager
- 控制玩家UI的显示=>获取UI的画布组件,通过enable/disable,显示/隐藏UI
- 绘制卡牌,提供动画。
- 编写UI更新逻辑。
制作回合制卡牌战斗系统CombatMananger
依据CombatType控制进入不同的回合。
做战斗的初始化工作:
生成敌人(√)
生成玩家(√)
显示战斗UI(√)
(待定)使用收藏品被动()
初始化CombatType为玩家回合。(√)
有一个机制:存储和加载
某个类创建的ScriptableObject存放了玩家的所有信息。
在每次战斗的时候重新从那里加载信息。包括剩余血量、存放的内容等。
创建一张能够打出去并造成影响的牌!
定义卡牌的行为抽象类,包含parameters和可能用到的组件
一个行为枚举,代表不同的行为
定义基础的几个卡牌行为
Attack
Defend
DrawCard
RestoreHealth
Strength
…other
定义使用卡牌方法,依据行为枚举来指定打出的牌
1、指定目标(包括self和target)
2、需要一个中间件来打出卡牌
定义这个中间件:
开始时自动初始化它。
设置一个字典来存储所有的行为枚举-行为类实例。
当打出卡牌时,给出字典[行为类型]即可获取行为类实例,执行DoAction来实现影响。
实现这个中间件
为这个中间件Debug
当什么时候使用卡牌方法?鼠标OnDrag的时候选择目标!!!
动态地构建Params?
使用输入检测检测在onDrag的时候开启检测协程。
检测协程在射线检测到hit2D的目标时,为param设置卡牌作用目标target
否则只设置其他的参数:
CardBase(当前打出的卡),
BaseCharacter Self(指玩家);
在endDrag的时候关闭该协程。并将params置为null
创建角色BaseCharacter
创建玩家Player
- 数据注入
创建敌人Enemy
- 同上
完善卡牌Action(数据交互方面的内容)
1、消耗mana
2、使用AudioManager播放音效,指定卡牌Params为其提供audio
3、使用EffectManager播放特效,并在打出卡牌时播放动画。
4、为卡片添加描述等参数内容。
5、实现抽牌效果。
6、抽牌堆、弃牌堆等内容
创建敌人AI
- 类似于创建卡牌的行为,创建敌人行为。
1 | |