太阳神三国杀 Mac 版构建指南

构建指南

写在前面

如果您使用的是一台苹果机,那么您可以忽视这一段文字。
如果您希望使用一台 Windows 系统的设备编译 OS X 或 iOS 平台下的太阳神三国杀,你可以使用 VMWare 为您的电脑添加一台虚拟机。相关介绍请参考超详细 VMware Workstation 10 安装 Mac OS X Mavericks

Mac os X 平台

开始构建前,请尽量保证您的系统不低于 OS X 10.8 Mountain Lion. 您可以在 App Store 中免费升级您的系统。

安装 XCode

首先您需要在您的 OS X 系统上安装 XCode。XCode 是苹果公司向开发人员提供的集成开发环境,用于开发 Mac OS X 和 iOS 的应用程序。凭借您的苹果账号,您可以在您系统自带的 App Store 中免费下载。

您未曾安装过的话,这里的 open 应该为 get。下载后 XCode 就会出现在您的 LaunchPad 中。

安装Qt

请您到Qt project 的官方网站下载页面下载最新版本的 Qt。这里您可以选择完全免费的 Community 版本。下载后,整个安装过程十分简单。

获取源代码

请您从源码地址获得最新版本的源代码。您可以使用 git 工具(推荐完全免费的SourceTree)。如果您不懂得如何使用 git,您可以直接点击源代码页面右侧的Clone in DesktopDownload ZIP以获得源代码。当您下载完毕后,请您将其解压到您喜欢的目录。

安装swig

您需要下载和安装swig
点击一个新版本的文件夹进入后,请确保您下载的版本不低于 3.0.2.您只需下载后缀为 .tar.gz 的文件。

下载完成后,解压缩这个压缩包。打开您的terminal,依次输入
./configure –without-pcre
make
sudo make install

如果您看到一大长串,且没有出现error提示,说明您的安装成功了。然后您需要依次输入
cd swig
swig -c++ -lua sanguosha.i
得到sanguosha_wrap.cxx.
PS:这里额外说一句,如果您不知道如何使用 terminal,请您先阅读以下有关 terminal 的相关知识。sanguosha.i 文件位于项目根目录下的 swig 文件夹中。整个过程中确保您的每一句指令都是在相应的文件夹下执行的。如果您的神杀文件直接解压缩在您的 user 文件夹下,你可以使用这一串代码。
cd Downloads/swig-3.0.5/ (这里替换为您的版本)
./configure –without-pcre
make
sudo make install
cd swig
swig -c++ -lua ../../../QSanguosha-For-Hegemony/swig/sanguosha.i

开始编译

好了,现在您可以打开您的QtCreator来进行编译了。请您在欢迎界面选择 Open Project, 然后从您的系统中找到 QSanguosha.pro, 然后打开之。这个项目文件位于项目的根目录。

当您打开项目后,确保您的项目使用 clang 编译,并请把您的 configuration 改为 release。


这样完成后,您就可以顺利地完成构建。建议您把构建完成的文件夹移动到根目录。

连接动态库

这一步比较困难但相当重要。打开您的 terminal,移动到您的构建目录并输入
otool -L QSanguosha.app/Contents/MacOS/QSanguosha

您大概会看到
QSanguosha.app/Contents/MacOS/QSanguosha:
./libfmodex.dylib (compatibility version 1.0.0, current version 1.0.0)
(QtDir)/5.3/clang_64/lib/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtQml.framework/Versions/5/QtQml (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtQuick.framework/Versions/5/QtQuick (compatibility version 5.3.0, current version 5.3.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

请注意 ./libfmodex.dylib 这一行。
请您使用 install_name_tool 来修改这个库文件的绝对路径,如下:
install_name_tool -change ./libfmodex.dylib ~/lib/mac/lib/libfmodex.dylib QSanguosha.app/Contents/MacOS/QSanguosha

再次输入
otool -L QSanguosha.app/Contents/MacOS/QSanguosha

如果您看到所有的路径均变为绝对路径,说明您成功了。(~是您的项目目录)
QSanguosha.app/Contents/MacOS/QSanguosha:
~/lib/mac/lib/libfmodex.dylib (compatibility version 1.0.0, current version 1.0.0)
(QtDir)/5.3/clang_64/lib/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtQml.framework/Versions/5/QtQml (compatibility version 5.3.0, current version 5.3.0)
(QtDir)/5.3/clang_64/lib/QtQuick.framework/Versions/5/QtQuick (compatibility version 5.3.0, current version 5.3.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

输入
macdeployqt QSanguosha.app/

有时您的macdeployqt并不在system directories下,这是您需要去您的Qt文件夹寻找这个文件。(Qt/5.4/clang_64/bin/)

输入
otool -L QSanguosha.app/Contents/MacOS/QSanguosha

如果您看到所有的非系统库都在@executable_path中,您应该就完成了。
QSanguosha.app/Contents/MacOS/QSanguosha:
@executable_path/../Frameworks/libfmodex.dylib (compatibility version 1.0.0, current version 1.0.0)
@executable_path/../Frameworks/libfreetype.dylib (compatibility version 1.0.0, current version 1.0.0)
@executable_path/../Frameworks/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.3.0, current version 5.3.0)
@executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore (compatibility version 5.3.0, current version 5.3.0)
@executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.3.0, current version 5.3.0)
@executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui (compatibility version 5.3.0, current version 5.3.0)
@executable_path/../Frameworks/QtQml.framework/Versions/5/QtQml (compatibility version 5.3.0, current version 5.3.0)
@executable_path/../Frameworks/QtQuick.framework/Versions/5/QtQuick (compatibility version 5.3.0, current version 5.3.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

复制resource

将下面的全部文件复制到QSanguosha.app/Contents/MacOS/。这些文件都位于项目的根目录下。
* ai-selector/
* audio/
* developers/
* diy/
* font/
* image/
* lang/
* lua/
* rule/
* skins/
* ui-script/
* qt_zh_CN.qm
* sanguosha.qss

运行

打开您的 .app,这时候您应该就可以运行了。祝您游戏愉快。

用语定义

专用语:在该用语和试图表达同一内容的类似的表述中,只有该用语有效。
承接语:不表达任何意思,仅帮助人类理解和阅读语句。
全局时机:所有角色同时触发的时机,描述时不存在“某角色的某时机”这种说法
局部时机:不是【全局时机】的时机,“某角色的某时机”是合理描述,若未声明角色,表示技能拥有者的该时机

专用语:

所有O:一局游戏中所有是O的对象
玩家:User
角色:Player
你:技能拥有者
其:指代前文提到的唯一角色或前文最后提到的非“你”的角色
E1和E2:E1、E2都是技能/效果的时机
P1和P2:P1 AND P2
主公:身份局中身份为主公的角色
对手:1v1中除你外的角色
A之后:指动作A发生过后的时间段
第I个P:指某角色的第I个阶段P
其他角色:非你的角色
一名角色:任意角色
除P外的阶段:是 NOT P 的阶段
这些O:指代前文最近提及的一些个O
此O:指代前文最近提及的一个O
于O:仅处于O时可以继续执行后续语句。(O类型为时间段)

时机声明(带”*“的是局部时机,支持局部时机的特有语法,同时解释中的时机也专指某人的时机):

所有玩家亮出武将牌后:表示技能/效果时机为【游戏开始前亮出武将牌后】
分发起始手牌前:表示技能/效果的时机为【游戏开始前分发起始手牌前】
游戏开始后:表示技能/效果的时机为【游戏开始后】
*回合开始后:表示技能/效果的时机为【回合开始后】
*P开始后:表示技能/效果的时机为【阶段P开始后】
*P结束后:表示技能/效果的时机为【阶段P结束后】
*P开始前:表示技能/效果的时机为【阶段P开始前】
通则摸牌前:表示技能/效果的时机为【通则摸牌前】
出牌阶段空闲点:表示技能的时机为【出牌阶段的空闲时间点】
出牌阶段空闲点限I次:表示技能的时机为【出牌阶段的空闲时间点】,限制类型:出牌阶段空闲时间点限制,次数限制I
通则弃置前:表示技能/效果的时机为【通则弃置前】
使用O时:表示技能/效果的时机为【使用O时】(O类型为牌)

逻辑用语:

若如此做:若此用语之前的效果没有执行,那么此用语之后的效果也不执行。

承接语:

然后

一个控制用户使用卡牌操作规范的模块构想:


卡牌需要提供的参数:

写在每一个卡牌中:

public:
int get额定使用次数() {return 额定使用次数;}
enum CountType get计数类型() {return 计数类型;}
int get距离限制() {return 距离限制;}
int get目标上限() {return 目标上限;}
bool 能重铸() {return 重铸许可;}
bool 能连横() {return 连横许可;}
bool get合法性(&玩家1, &玩家2) {...}    //函数体中写出判断的具体代码,如果玩家1对玩家2使用此牌合法(不考虑距离)则返回true

private:
int 额定使用次数;  //默认1000,相当于无限制
enum CountType 计数类型    //一定要初始化
int 距离限制; //默认1000,相当于无限制
bool 重铸许可; //默认false
bool 连横许可; //默认false

接下来是模块本体的实现过程:

先扫描所有牌检查可用性,每张卡牌对应执行下面函数,返回false则该卡牌低暗不可选,返回true高亮可选:

bool cardUsable(&玩家, &此牌)
{
    int 额定次数 = 此牌->get额定次数() + 技能修正;
    int 额外次数 = 技能修正;
    if ( (玩家->has无次数限制效果(此牌) != true)
      && (玩家->get额定使用计数(此牌) >= 额定次数)           //计数模块需读取此牌的限制类型并按照计数类型条件计数。
      && (玩家->get额外使用计数(此牌) >= 额外次数) )
        return false;

    bool 存在目标 = false;
    int 距离限制 = 此牌->get距离限制() + 技能修正;
    for (auto &tmp玩家 : 所有玩家) {
        if ( 此牌->get额外距离以及合法性(tmp) == true ) {
            存在目标 = true
            break;
        }

        if ( (玩家->has无距离限制效果(此牌) == false)
          && (玩家:get距离(tmp玩家) >= 距离限制) )
            continue;

        if ( 此牌->get合法性(玩家,tmp玩家) == true ) {
            存在目标 = true;
            break;
        }
    }

    if (存在目标 == false)
        return false;


    if (玩家:被禁止使用(此牌) == true)
        return false;

    return true;
}

当玩家选中一张牌后,选择目标前:

扫描检查所有玩家作为目标的可选性,每个玩家对应执行下面函数,返回false则该玩家低暗不可选,返回true高亮可选:

bood cardTargetChoosable(&玩家, &此牌, Qlist &已选目标, &待选目标)  //待选目标相当于filter里的to_select
{
    if ( 此牌->get额外距离以及合法性(tmp) == true )
        return true;


    int 已选额定目标数 = 0;
    for (auto &tmp目标 : 已选目标) {
        if (tmp目标->hasFlag("额定目标"))
            ++已选额定目标数;
    }
    额定目标 = 此牌->get目标上限 + 技能修正;
    if (已选额定目标数 >= 额定目标)
        return false;

    if ( (玩家->has无距离限制效果(此牌) == false)
      && (玩家:get距离(tmp玩家) >= 距离限制) )
        return false;

    if ( 此牌->get合法性(玩家,tmp玩家) == false ) {
        return false;
}

玩家选择目标的过程中还需要判断是否可以点击确定

bool cardUseFeasible(&玩家, &此牌, Qlist &已选目标)
{
    if (此牌->能重铸() = true)
        return true;
    return (已选目标->empty() == false); //卡牌只要有已选目标就能用
}
国战1.0.0更新内容(持续更新)

Bugs Fixed:

API Changes:

  • 增加Lua函数table:toSet(),返回无重复元素的table对象

  • 以”&”开头的私有牌堆可以在检测时像【木牛流马】牌堆一样视为手牌

  • 修复”使用TargetModSkill增加【顺手牵羊】的额外目标有时不亮将”的bug

  • 修复”锁定视为锦囊时checkTargetModSkillShow返回0”的bug

  • 新增对同一个角色点击多次的卡牌Lua接口

  • 开放Lua读取ServerInfo的接口

  • 升级Qt库支持至最新(5.4.0)

  • 更新freetype至2.5.4,增加debug版库(OSX及Linux使用静态库)

  • 更新fmodex至4.4.49

  • 新增 Room::sendCompulsoryTriggerLog ,能更方便的发送锁定技的 log

  • 修复”CardAsk 时机不能正确调用 CardUsePattern”的 bug

New Features/Enhancements:

有关 git Extensions 的简单使用方法

Git Extensions 是一个可视化的git工具,通过它,你可以轻松的管理git档案库。

下载地址:http://sourceforge.net/projects/gitextensions/ 然后根据你的平台选择下载地址。 注意,gitExtensions 的安装需要 .Net Framework 4.0 的支持。(对于 Windows 来说)

安装完之后,运行之,打开左上角的克隆档案库

然后:

在要克隆的档案库中输入你需要的源码,目的地自己选吧……这个目的地就是所谓的源码目录了。选好之后,点克隆……

待其clone完成后,会弹出一个询问你是否打开档案库的框,当然打开了…… 然后你可以点击上面的按钮来检查更新:(正常情况下,刚刚clone的源码是不需要检查更新的,当然,你也可以随时检查更新……)

然后就可以点拉取了…… 等待拉取完成后,就完成了源码的更新。