【原神】matlab gui 记录角色等阶天赋

截止于1.6版本,除了主角外,共有33名分别来自蒙德与璃月的角色,在我们玩游戏的过程中,每位角色都需要升级等级、天赋、圣遗物等等,对于一些喜欢全员升级的人来说,有一个小型免费的应用/程序来记录着所有角色的信息并能根据版本迭代更新增加角色,将会是一个很不错的选择。

下面这个是初具规格的“小程序”,根据自行设定的目标值来记录不同角色的等级、天赋、圣遗物是否达到预期的用matlab制作的GUI。

下面有这个“小程序”的资源,以及GUI构建的全过程解析。

下载程序的全部相关资源(对应原神v1.6),建议下载后学习下文

GUI构建目录

1 资源与控件

2 逻辑整理

2.1 列表

2.2 显示角色数据

2.3 加减与点击逻辑判定

2.4 保存与清除

2.5 刷新列表


1 资源与控件

在上面展示的GUI界面中,存在许多个角色,如果仅仅用文字来展示不同的角色,可能不太好看。在该教程中,将使用不同的图片来展示角色头像。角色的图片,可以在原神官网获取,或者下载上方链接资源;另外在GUI交互过程中,需要记录保存信息,教程使用Excel作为储存。如图1所示是ys.xlsx的主要内容(部分),在目前的版本中C、D、H列暂时没用到。

图1 Excel版数据库

从G列开始,到V列为止,默认的基础数据可参考图中第21行(魈),在后续的初始化中可将对应角色的值重置为此。

完成了初始数据和基本图片的部署后,需要打开matlab,在命令行窗口输入guide回车后新建一个空的GUI,并将该GUI存放于与数据和图片同一目录下。然后通过如下图(右)所示的GUI界面,按照图中所示方式摆放控件(或自行摆放),然后双击控件修改字体大小(FontSize)、显示的文字(String)、标签(Tag)等信息;该图中的红框部分是控件对应的Tag标签命名。

这里用到了列表框(listbox)、按钮(pushbutton)、坐标轴(axes)和静态文本(text),这些部分的回调函数会在下一章分别讲述。

2 逻辑整理

基本思路:(1)点击列表→显示头像和右边的控件(仅第一次);(2)点击获取→右边控件可编辑;(3)右边控件修改完成后点击保存→记录进Excel并检测哪些目标已完成;(4)点击清除→初始化右边控件的数据。

2.1 列表

在我们运行程序时,进入的界面应该是只有列表框和刷新列表的按钮,其它都是'visible'属性值为'off'的,在控件很多的时候应该用循环的方式设置。根据需求,在(比如我命名的是launcher)编辑器的launcher_OpeningFcn函数末尾加入两个函数:隐藏右边的控件、给列表赋值。

对控件的visible值做出批量修改

function inhert(e, value)
if ~strcmp(get(e.relics5, 'visible'), value) % 判断需要设置的值是否与原值不同
    % fnc 是所有需要操作visible值的控件对应的tag标签,...是换行继续写
    fnc = {...
        'axes2', 'pushbutton1', 'save', 'gNow', 'gEx', ...
        'gradeText', 'gradeDec', 'grade', 'gradeInc', 'gradeExDec', 'gradeEx', 'gradeExInc', ...
        'funText', 'funDec', 'fun', 'funInc', ...
        'aText', 'aDec', 'a', 'aInc', 'aExDec', 'aEx', 'aExInc', ...
        'eText', 'eDec', 'e', 'eInc', 'eExDec', 'eEx', 'eExInc', ...
        'qText', 'qDec', 'q', 'qInc', 'qExDec', 'qEx', 'qExInc', ...
        'rText', 'relics1', 'relics2', 'relics3', 'relics4', 'relics5'
    };
    for i = 1:numel(fnc)
        % a.b 可以写成 a.('b')
        set(e.(fnc{i}), 'visible', value)
    end
end

 更新listbox

function relist(e)
[x, showstr1] = incode('A3:A35'); % 读取文本给showstr1,这里从图1看是角色名称
showstr2 = incode('G3:G35'); % 读取是否拥有角色 1|0
showstrL = numel(showstr2);
showstr{showstrL} = '';
for i = 1:showstrL % 没有的角色在名字前加'(x)'符号,如 (x)琴
    if showstr2(i)
        showstr{i} = showstr1{i};
    else
        showstr{i} = ['(x)', showstr1{i}];
    end
end
% 在列表框展示所有角色名称,注意是cellstr()
set(e.listbox1, 'String', cellstr(showstr))

 读取Excel数据

function [num, txt, raw] = incode(position)
% 返回的txt是cell
[num, txt, raw] = xlsread('ys.xlsx','Sheet1',position);

 根据上面的自定义函数,可以得到launcher_OpeningFcn函数

function launcher_OpeningFcn(o, d, e, varargin)
e.output = o;
guidata(o, e);
% 打开launcher执行
inhert(e, 'off'); % 隐藏控件
relist(e); % 给列表框获取角色名称

2.2 显示角色数据

在打开launcher后可以得到角色列表,然后需要点击角色的时候显示控件和控件的内容,这个时候需要编辑的则是listbox1_CallBack函数

function listbox1_Callback(o, d, e)
inhert(e, 'on'); % 显示控件
index = get(e.listbox1, 'Value'); % 获得回调位置,返回一个数(1, 2, 3, ...)
% 显示右边的图
[x, filename] = incode('F3:F35');
img = imread(['roles/', filename{index}]);
axes(e.axes2), imshow(img)
% 更新右边的数据
renew(e, index)
% 更新已完成
gradeComplete(e);
funComplete(e);
aComplete(e);
eComplete(e);
qComplete(e);
relicsComplete(e);

 更新右边数据的renew函数

function renew(e, index)
line = num2str(index+2);
data = incode(['G', line, ':V',  line]);
area = {
    'pushbutton1', '', 'fun', 'grade', 'a', 'e', 'q', ...
    'relics1', 'relics2', 'relics3', 'relics4', 'relics5', ...
    'aEx', 'eEx', 'qEx', 'gradeEx'
};
% 更新按钮
tag = {'获取', '清除'};
set(e.pushbutton1, 'String', tag{data(1)+1})
%更新右边控件数据
relics_txt = {'花', '羽', '沙', '杯', '冠'};
L = numel(area);
for i = 3:L
    if i >= L-8 && i <= L-4 % 圣遗物部分(R)
        if data(i)
            set(e.(area{i}), 'String', relics_txt{i-L+9})
        else
            set(e.(area{i}), 'String', 'x')
        end
    else
        set(e.(area{i}), 'String', num2str(data(i)))
    end
end

检测是否达到预计值的Complete函数 

function setCBG(o, t) % 设置静文本背景
switch(t)
    case 1
        set(o, 'BackgroundColor', 'green')
    otherwise
        set(o, 'BackgroundColor', '0.94,0.94,0.94')
end

function gradeComplete(e) % 等阶完成否
g = get(e.grade, 'string');
ge = get(e.gradeEx, 'string');
setCBG(e.gradeText, strcmp(g, ge) && ~strcmp(g, '0'))

function funComplete(e) % 好感完成否
setCBG(e.funText, strcmp(get(e.fun, 'string'), '10'))

function aComplete(e) % A完成否
a = get(e.a, 'string');
ae = get(e.aEx, 'string');
setCBG(e.aText, strcmp(a, ae) && ~strcmp(a, '1'))

function eComplete(v) % E完成否
e = get(v.e, 'string');
ee = get(v.eEx, 'string');
setCBG(v.eText, strcmp(e, ee) && ~strcmp(e, '1'))

function qComplete(e) % Q完成否
q = get(e.q, 'string');
qe = get(e.qEx, 'string');
setCBG(e.qText, strcmp(q, qe) && ~strcmp(q, '1'))

function relicsComplete(e) % 圣遗物完成否
r1 = get(e.relics1, 'string');
r2 = get(e.relics2, 'string');
r3 = get(e.relics3, 'string');
r4 = get(e.relics4, 'string');
r5 = get(e.relics5, 'string');
setCBG(e.rText, strcmp([r1, r2, r3, r4, r5], '花羽沙杯冠'))

2.3 加减与点击逻辑判定

由于教程存在多组加减逻辑,这里以A技能的举例(前面某个图的aText, a, aEx等);圣遗物R中,以“花”为例。

function aDec_Callback(o, d, e) % A--
if strcmp(get(e.pushbutton1, 'string'), '清除') %判断是否拥有角色,没有不可编辑,下同
    n = str2num(get(e.a, 'String'));
    if n > 1 % 下限是1
        set(e.a, 'String', n-1)
    end
end

function aInc_Callback(o, d, e) % A++
if strcmp(get(e.pushbutton1, 'string'), '清除')
    n = str2num(get(e.a, 'String'));
    if n < 10 % 上限是10
        set(e.a, 'String', n+1)
        if str2num(get(e.aEx, 'String')) < n+1 % 如果期望值小于当前值
            set(e.aEx, 'String', n+1) % 跟着+1
        end
    end
end

function aExDec_Callback(o, d, e) % AEx--
if strcmp(get(e.pushbutton1, 'string'), '清除')
    n = str2num(get(e.aEx, 'String'));
    if n > str2num(get(e.a, 'string')) % 下限不低于当前值
        set(e.aEx, 'String', n-1)
    end
end

function aExInc_Callback(o, d, e) % AEx++
if strcmp(get(e.pushbutton1, 'string'), '清除')
    n = str2num(get(e.aEx, 'String'));
    if n < 10 % 上限10
        set(e.aEx, 'String', n+1)
    end
end

function relics1_Callback(o, d, e) % 花
if get(e.relics1, 'string') == 'x'
    set(e.relics1, 'string', '花')
else
    set(e.relics1, 'string', 'x')
end
% 或者写成
% set(e.relics1, 'string', {'花', 'x'}{get(e.relics1, 'string') == 'x'})

2.4 保存与清除

为了保证GUI的运行速度,没有在按钮中加入保存的功能,而是单独设置了一个保存的按钮,完成修改后点击保存,保存的同时也要更新一下哪些已经达到目标值。

function save_Callback(o, d, e)
if strcmp(get(e.pushbutton1, 'string'), '清除') %拥有角色才能保存
    used = {'fun', 'grade', 'a', 'e', 'q', 'relics1', 'relics2', 'relics3', 'relics4', 'relics5', 'aEx', 'eEx', 'qEx', 'gradeEx'};
    N = numel(used);
    data(N) = 0;
    for i = 1:N
        if i >= N-8 && i <= N-4
            if get(e.(used{i}), 'string') == 'x' %检查圣遗物拥有状态
                data(i) = 0;
            else
                data(i) = 1;
            end
        else
            data(i) = str2num(get(e.(used{i}), 'string'));
        end
    end
    line = num2str(2 + get(e.listbox1, 'value')); %得到当前角色在Excel的行
    recode(['I', line, ':V', line], data); %写入到Excel
    % 刷新完成度
    gradeComplete(e);
    funComplete(e);
    aComplete(e);
    eComplete(e);
    qComplete(e);
    relicsComplete(e);
end

function recode(position, value) %写入数据
xlswrite('ys.xlsx', value, 'Sheet1', position);

有获取就有清除(虽然听起来好鸡肋,但是为了更合理),获取与清除在一个角色下是同一个按钮,需要读取按钮的状态来决定是什么操作。获取是写入文件,拥有角色;清除是初始化角色的数据并刷新。

function pushbutton1_Callback(o, d, e)
index = get(e.listbox1, 'value');
if strcmp(get(e.pushbutton1, 'string'), '清除')
    % 清除角色数据
    set(e.pushbutton1, 'String', '获取')
    initMtx = [0,0,1,0,1,1,1,0,0,0,0,0,1,1,1,0];
    recode(['G', num2str(2+index)], initMtx);
    renew(e, index); %刷新右方数据
    gradeComplete(e); %检测完成度/或者说是重置
    funComplete(e);
    aComplete(e);
    eComplete(e);
    qComplete(e);
    relicsComplete(e);
else
    recode(['G', num2str(2+index)], 1);
    set(e.pushbutton1, 'String', '清除')
end

2.5 刷新列表

点击刷新列表后,更新列表框中的角色信息,只需要如2.1的更新listbox即可。

function refresh_Callback(o, d, e)
relist(e);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值