炉石传说 C# 开发笔记
最近在大连的同事强力推荐我玩 炉石传说,一个卡牌游戏。加上五一放一个很长很长的假期,为了磨练自己,决定尝试开发一个C#的炉石传说。
这件事情有人已经干过了,开发了一个网页版的炉石,但是貌似不能玩。。。。
http://cnodejs.org/topic/529c1366a6957a0809485f3d
如果这位同志看到这篇文章,请一定和我联系!!
rudermail@qq.com或Q我377372779
第一天
开始学习炉石传说的玩法,最好的方法是不停的玩游戏。
一个应用是否逻辑清晰,取决于你对于业务的了解程度,一般到开发后期发现有些逻辑内聚和耦合发生问题,往往都是前期对于业务的理解不够透彻。
很多开发都往往是随着业务逻辑的了解,进行不停的重构,当然,这个也是一个必然的过程,但是如果能够在前期就了解业务的话,则可以节约后期大量的时间。
由于长期做对日软件的缘故,式样书,设计书先行是根深蒂固的思想。所有设想都先以文字或者伪代码的形式写下来,进行一些假想的验证。
整个项目的平衡感,脉络,各个模块,层次结构都在这个时候定下来。这个时候是修改成本最低的阶段,等到后期这些模块再重新划分,风险就高了。
通过第一天的学(you)习(xi),大概整理除了一个脉络:
(文字版本的不是很好看,下面的Excel版本,浏览器也看不到。。)
卡牌基础
法术卡牌
熟读各种法术牌,讲法术牌分类
随从卡牌
各种特性的整理,可以参考各种网络上的资料
武器卡牌
比较简单的类型
游戏环境
英雄
生命值
基本技能
武器
牌堆
套牌
手牌
手里的牌
战场
7个位置的随从
法力水晶
由于某些卡牌会改变水晶,也为了细化系统,法力水晶升级为一个独立的类
第二天
开始进行Coding。由于英语不是很好,有一些单词不知道,然后开始中英文夹杂编码。
很久前,也讨论过中文编程的问题,其实很多变量,用中文还是英语完全没有限制。
写代码只要能让自己和维护的人读得懂就可以了。毕竟即使你用英语变量,你的注释还是中文的。。。
当然,如果你想让代码能够国际化,特别是开源项目,能用标准的英语来写代码是极好的。
NUnit用的不是很好,所以,自己写了一些GUI的界面来做一些简单的UT测试。
第三天
代码的重构,设计书和代码的同步。
很多项目,在一开始的时候还有设计书,然后在开发的时候,往往重构好代码后,设计书还是重构之前的样子。
IDE可以自动重构代码,但是不能自动重构设计书。。。。
国内项目不注重文档,所以这种情况很常见。日系的开发,设计书则相当重要,一个是为了日后维护能有个依据,二是为了能够明确责任。
这个地方为什么要修改,对于整体项目有什么影响,都能从设计书的修改履历中看出端倪。
代码和设计书同步的时候,也是一个反思的机会,看看现阶段写的代码,是不是很干净优雅,
往往将代码转换为设计书的时候,可以看到代码的问题。特别是代码的一致性上,散落在不同地方的代码,经过整理,用#region归纳后,可以看到很多问题。
第四天
炉石C#版本不是短时间内可以完成的,在完成整个炉石之前,可以考虑用当前的代码,先制作一些小的工具。
一来可以拉拢人气,隔一段时间有个小的可以检证的成果物,不至于半途而废;
二来,小工具的制作也是为了炉石服务的,有些小工具的代码也可以反馈到炉石主体代码。
我向来反对一开始就要做个了不起的东西,或者只开发了不起的东西,忘记了留下二次开发的接口或者周边产品的接口。
魔法的定义
魔法类型
攻击
回复
召唤
卡牌 奥术智慧
变形 变羊术
水晶 幸运币
奥秘
魔法关系
或者 抉择系:例如:抉择: 对一个随从造成3点伤害;或者造成1点伤害并抽一张牌。
并且 有副作用的魔法,例如:造成4点伤害,随机弃一张牌。
目标选择模式
随机
全体
指定
目标选择方向
本方
对方
无限制
目标选择角色
随从
英雄
全体
标准效果点数
伤害效果点数、治疗效果点数、抽牌数
实际效果点数
由于某些卡牌效果会影响效果点数
效果回数
例如:奥术飞弹是3次1点伤害
附加信息
难以用上面的规则的卡牌,特殊的附加信息
奥术智慧的定义:
1.有一个效果:抽两张牌
2.成本是1点
3.对象时本方
/// <summary>
/// 初始化奥术智慧
/// </summary>
/// <returns></returns>
public static Card.MagicCard Get奥术智慧()
{
Card.MagicCard 奥术智慧 = new Card.MagicCard();
奥术智慧.SN = "M000002";
奥术智慧.Name = "奥术智慧";
奥术智慧.Description = "随机抽两张牌。";
奥术智慧.Rare = Card.CardBasicInfo.稀有程度.绿色;
//使用成本
奥术智慧.ActualCostPoint = ;
奥术智慧.StandardCostPoint = ;
奥术智慧.JoinType = Card.MagicCard.EffectJoinType.None; //随机抽两张牌
Card.MagicCardStockEffect cardStockEffect = new Card.MagicCardStockEffect();
cardStockEffect.StandardEffectPoint = ;
cardStockEffect.EffectCount = ;
cardStockEffect.EffectTargetSelectDirect = Card.CardUtility.TargetSelectDirectEnum.本方;
奥术智慧.FirstMagicDefine = cardStockEffect;
return 奥术智慧;
}
第五天
我一直在考虑,AI是不是能代替人。
炉石这样的游戏,有许多常用的套路,只要组好了套牌,然后能够将很多常用的卡牌组合,优先策略教授给AI,应该可以做到和人对战。
和国际象棋,围棋比起来,炉石这样的游戏,胜利无非是:运气好,套牌组的合理,正确衡量场面上各种对方卡牌的威胁程度,熟练使用各种套路,有耐心,不犯低级错误。
运气好,套牌组的合理,这个事情,前者人和AI都一样,套牌可以人组好后直接给AI使用。
正确衡量场面上各种对方卡牌的威胁程度:这个也不难,其实卡牌的使用成本已经是一个可以量化的威胁度指标了。
熟练使用各种套路:对方出了一个 10/10 (合理的阀值)的家伙,如果有变羊术,就变掉;对手一大堆血量3,4的随从,就用清场的牌,这些套路也很直观
有耐心,不犯低级错误:这个是AI的长处,AI绝对不会忘记还有魔法可以直接 打脸,还有可以使用的随从去 打脸
当然,对于顶级高手AI还不是可以简单的取胜,审时度势,及时调整战略的能力,人还是有着无可比拟的优势。
第六天
看看客户端和服务器端分工如何:
顺便提一句,日常文档的编写,WPS不比Office差,支持国货
核心库 Card.DLL 还有客户端,服务器,之间要连接起来
客户端-服务器-核心库 核心库:委托形式 /// <summary>
/// 抽牌委托
/// </summary>
/// <param name="IsFirst">先后手区分</param>
/// <param name="magic">法术定义</param>
public delegate List<CardBasicInfo> delegateDrawCard(Boolean IsFirst, int DrawCount);
/// <summary>
/// 抽牌魔法(服务器方法)
/// </summary>
public static delegateDrawCard DrawCard; 客户端:实现委托 /// <summary>
/// 初始化
/// </summary>
public static void Init() {
//抽牌的具体方法
CardUtility.DrawCard += DrawCardAtServer;
} /// <summary>
/// 抽牌(服务器方法)
/// </summary>
/// <returns></returns>
public static List<String> DrawCardAtServer(Boolean IsFirst, int Count)
{
//向服务器提出请求,获得牌
return GameStatus.DrawCard(IsFirst,Count);
} 服务器端:实际操作牌堆 /// <summary>
/// 抽牌
/// </summary>
/// <param name="IsFirst"></param>
/// <param name="Count"></param>
/// <returns></returns>
public static List<String> DrawCard(Boolean IsFirst, int Count)
{
var targetStock = IsFirst ? FirstCardStock : SecondCardStock;
return targetStock.DrawCard(Count);
} (调用Card核心库方法) /// <summary>
/// 抽卡
/// </summary>
/// <param name="CardCount"></param>
/// <returns></returns>
public List<String> DrawCard(int CardCount)
{
List<String> newList = new List<String>();
for (int i = ; i < CardCount; i++)
{
if (CardList.Count == ) break;
newList.Add(CardList.Pop());
}
return newList;
}
第七天
考虑服务器和客户端的开发。
客户端-服务器通信
TCP协议,类似于网站那样的短连接。
玩家A 服务器消息区 玩家B
回合开始 STARTTURN
使用卡牌A,造成结果B USE:A|EFFECT:B 每隔5秒从服务器端读一次A的行为,改变当前战场状态,知道读取到ENDTRUN消息
使用卡牌C,造成结果D USE:C|EFFECT:D
回合结束 ENDTURN
STARTTURN 回合开始
每隔5秒从服务器端读一次B的行为,改变当前战场状态,知道读取到ENDTRUN消息 USE:A|EFFECT:B 使用卡牌A,造成结果B
USE:C|EFFECT:D 使用卡牌C,造成结果D
ENDTURN 回合结束
请求分类 (3位)
游戏
新建一个游戏 新建一个游戏
加入一个游戏 加入一个游戏
认输 认输,退出一个游戏
等待游戏列表 获取等待加入者游戏的列表
确认游戏启动状态 确认游戏是否处于启动状态
是否为先手 是否为先手
动作
抽牌 抽牌
回合结束 回合结束
行动 改变战场的动作
下面这个链接是OneDriver上共享的设计书,有些图形对象无法在浏览器中显示,不知道能不能通过下载的方式保存到本地,然后打开。
代码在GitHub上面,不过为了帮MongoDB的项目拉人气,所以,将代码放到了MongoDB的解决方案里面了。
大家下载代码的时候,顺手点个赞吧 Star 一下
https://github.com/magicdict/MagicMongoDBTool
炉石传说 C# 开发笔记的更多相关文章
- 炉石传说 C# 开发笔记(6月底小结)
炉石传说的开发,已经有30个工作日了. 关于法术的定义方法,有过一次重大的变更:法术效果是整个炉石的核心,正是因为丰富的法术效果,才造就了炉石的可玩性. 原来构思的时候,对于法术效果没有充分的理解,所 ...
- 炉石传说 C# 开发笔记 (续)
炉石传说山寨的工作一直在进行着,在开发过程中深深体会到,对于业务的理解和整个程序的架构的整理远比开发难得多. 在开发过程中,如果你的模型不合理,不准确,很有可能造成代码的混乱,冗余,难以维护和扩展性比 ...
- 炉石传说 C# 开发笔记 (源代码整理公开)
源代码已经整理过了,去除了不需要的项目. 注意:以前文章中出现过的Git已经变更过了,请以前关注过,Fork过的朋友,重新Fork一下. GitHub地址 卡牌XML文件的做成:(Git上面是没有XM ...
- 炉石传说 C# 开发笔记(BS模式Demo)
原来这个项目,一直想做成CS模式的,BS模式对于炉石这样的游戏来说比较困难. 暴雪到现在也只出了 Windows 和 iPad版本的炉石,最大的问题还是在于如何在小屏幕下,实现最佳的客户体验. Win ...
- 炉石传说 C# 开发笔记 (法术篇)
炉石的设计,最核心的内容是法术效果. 法术卡牌,无疑是法术的集中体现,但是,法术效果除了在法术卡牌之外,也不除不在. 随从的战吼,亡语,奥秘的揭示等等都是法术效果的体现. 法术卡牌在炉石里面有很多种( ...
- 炉石传说 C# 开发笔记(BS上线尝试)
昨天买了一个月的1G 1核的服务器,由于不是新用户,所以没有享受到阿里的6个月免费的优惠. (阿里脑残,为什么不对于续费或者升级免费呢?) 在服务器的通讯上面已经OK了,完全绕过了ASP.NET,就是 ...
- 炉石传说 C# 开发笔记 (初版)
法术资料说明 1.资料的准备 从GitHub上面获得的工程里面,是没有XML卡牌资料配置的,这个是需要你自己生成的. 打开炉边处说的客户端 然后按下 卡牌资料生成 将炉石资料文件设定为 Github ...
- 炉石传说__multiset
炉石传说 Problem Description GG学长虽然并不打炉石传说,但是由于题面需要他便学会了打炉石传说.但是传统的炉石传说对于刚入门的GG学长来说有点复杂,所以他决定自己开发一个简化版 ...
- fzu Problem - 2232 炉石传说(二分匹配)
题目链接:http://acm.fzu.edu.cn/problem.php?pid=2232 Description GG学长虽然并不打炉石传说,但是由于题面需要他便学会了打炉石传说.但是传统的炉石 ...
随机推荐
- 翻译-使用Spring WebService生成SOAP Web Service
原文链接:http://spring.io/guides/gs/producing-web-service/ 生成SOAP web service 该指南将带领你使用Spring创建一个基于SOAP的 ...
- table下属标签与标签中间不能加其他任何标签
今天设计网页,很想在table下面的caption下面加hr标签,不能正常解析,后来发现hr标签可以显示,但是用浏览器查看解析,发现hr在table上面进行了解析,不会再caption下面显示, 又连 ...
- 每天一个linux命令(58):telnet命令
telnet命令通常用来远程登录.telnet程序是基于TELNET协议的远程登录客户端程序.Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式.它为用户 ...
- Bootstrap~大叔封装的弹层
回到目录 对于Bootstrap的弹层,插件有很多,今天主要用的是它自带的功能,通过bootstrap提供的模式窗口来实现的,而大叔主要对使用方法进行了封装,开发人员可以自己动态传入弹层的HTML内容 ...
- H5常用代码:适配方案2
前面的通过视口做适配的方案由于安卓低版本原生浏览器的存在,在许多场合不尽如人意,会在低版本安卓上出现,不缩放,手动缩放未禁止的问题. 于是出现了第二种适配方案,既然通过视口缩放可以兼容,那为什么不直接 ...
- fir.im Weekly - 揭秘直播移动 APP 技术实现
2016年直播似乎无处不在,作为一个开发者也许需要补充下关于直播技术点.本期 fir.im Weekly 整理了一些开发者对于直播实践项目中的技术经验与直播技术架构分析等内容,还有一些关于 iOS . ...
- salesforce 零基础开发入门学习(一)Salesforce功能介绍,IDE配置以及资源下载
目前国内已经有很多公司做salesforce,但是国内相关的资料确是少之又少.上个月末跳槽去了新公司,主要做的就是salesforce,不过当时想要看一些相关资料确实比较难.为了避免想要零基础学习的人 ...
- IOS开发之控件篇UINavigationController第一章 - 介绍
UINavigationController是一个比较常见的控件,它连接个视图,例如一个视图走到另外一个视图,之间的联系都可以用这个NavigationController的方法 一般都会由两个部分组 ...
- Zend Studio导入ThinkPHP工程
1.一般来说,thinkPHP文件工程(简称php工程)要部署到www下面,那么可以先复制一份php工程到非www文件夹的地方(如桌面): 2.打开zend studio右键,File-New-Loc ...
- Android应用中使用AsyncHttpClient来异步网络数据(转载)
摘要: 首先下载AsyncHttpClient的库文件,可以自行搜索,可以到下面地址下载 http://download.csdn.net/detail/xujinyang1234/5767419 测 ...