您当前所在位置: > 爆料站 > 君子堂

Cocos Creator 超简洁代码实现有限状态机 FSM,打造丝滑角色动作

时间:2022-03-13 13:12:28  来源:  作者:网络转载
简洁记账

简洁记账

大小:7.2M更新:2020-12-15

分类:生活实用

引言:本文作者黄聪是一名在校大学生,设计毕设的过程中,他参考《游戏编程模式》一书,摸索出了一套角色动作控制方案。

作为一名在校学生,前段时间在做毕业设计的过程中,我也遇到了很多同学都会遇到的问题:角色的动作逻辑全都写在 Player.ts 里面,当一个玩家脚本需要同时执行多个逻辑的时候(移动控制,动画播放,按键管理等等),无一例外地出现了这样的局面——

我们优雅地判断了按键输入,希望在 WASD 的按键驱动下,让我们的主人公顺理成章地旋转跳跃翻飞升华,于是在判断按键输入的代码块里改变了角色的动作播放,又设置了移动速度,还在某个 update 里面不停地设置他的方向……

光是想想我就已经戴上了痛苦面具!于是我在网上搜索了各路资料,在不懈的努力下最终摸索出了一套方案,思路基于游戏编程模式中的状态模式(State Pattern)。

以下是我在 Cocos Creaotr 2.4.x 用框架实现的角色移动、跳跃、下蹲、跳斩状态之间的切换效果,且 Player.ts 脚本内不再包含状态的行为逻辑。

成品效果,部分素材来源于网络

初试

让我们从零开始。为了保证思路清晰,我们假设现在在做一个 2D 横版闯关游戏,需要让主角对我们的键盘输入做出响应,按下空格键跳跃。这个功能看起来很容易实现:

Player.ts

private _jumpVelocity: number = 100;

onKeyDown(event: any) {

if (cc.macro.KEY.space == event.keyCode) {

this.node.getComponent(Rigibody).setVerticalVelocity(this._jumpVelocity);

}

}

但这有个问题,没有东西可以阻止「空中跳跃」,当角色在空中时疯狂按下空格,角色就会浮空。简单的修复方式是给 Player.ts 增加一个 _onGround 字段,然后这样:

private _onGround: boolena = false;

private _jumpVelocity: number = 100;

onKeyDown(event: any) {

if (cc.macro.KEY.space == event.keyCode) {

if(this._onGround) {

this._onGround = false;

// 跳跃...

}

}

}

意识到了吗?此时我们还没有实现角色的其他动作。当角色在地面上时,我希望按下↓方向键时,角色能够卧倒,松开时又能站起来:

private _onGround: boolena = false;

private _jumpVelocity: number = 100;

onKeyDown(event: any) {

if (cc.macro.KEY.space == event.keyCode) {

if(this._onGround) {

this._onGround = false;

// 如果在地上,就跳起来

}

}

else if (cc.macro.KEY.down == event.keyCode) {

if (this._onGround){

// 如果在地上,就卧倒

}

}

}

onKeyUp(event: any) {

if (cc.macro.KEY.down == event.keyCode) {

// 起立

}

}

新的问题出现了。通过这段代码,角色可能从卧倒状态跳起来,并且可以在空中按方向键趴下,这可不是我们想要的,因此这时候又要加入新的字段……

private _onGround: boolena = false;

private _isDucking: boolean = false;

private _jumpVelocity: number = 100;

onKeyDown(event: any) {

if (cc.macro.KEY.space == event.keyCode) {

if(this._onGround && !this._isDucking) {

this._onGround = false;

// 如果在地上,不在卧倒,就跳起来

}

}

else if (cc.macro.KEY.down == event.keyCode) {

if (this._onGround){

this._isDucking = true;

// 如果在地上,就卧倒

}

}

}

onKeyUp(event: any) {

if (cc.macro.KEY.down == event.keyCode) {

if (this._isDucking) {

this._isDucking = false;

// 起立

}

}

}

但是这样的实现方法很明显有很大问题。每次我们改动代码时,就会破坏之前写好的一些东西。我们需要增加更多动作——滑铲、跳斩攻击、向后闪避等,但若用这种方法,完成之前就会造成一堆漏洞。

有限状态机(FSM)

经历了上述的挫败后,我痛定思痛,把桌面清空,留下纸笔,开始画流程图。我给角色的每个行为都画了一个盒子:站立、跳跃、卧倒、跳斩……当角色响应按键时,画一个箭头,连接到它需要切换的状态。


如此,就建立好了一个有限状态机,它的特点是:

拥有角色所有可能状态的集合。在这里,状态有站立、卧倒、跳跃以及跳斩。

状态机同一时间只能处于一个状态。角色不可能同时处于站立和卧倒状态,这也是使用 FSM 的理由之一。

所有的按键输入都将发送给状态机。在这里就是不同按键的按下和弹起。

每个状态都有一系列的状态转移、转移条件和输入与另一个状态相关。当处于这个状态下,输入满足另一个状态的条件,状态机的状态就切换到目标的状态。

这就是状态机的核心思维:状态、输入、转移。

枚举与分支

回来分析之前的代码存在的问题。首先,它不合时宜地捆绑了一大堆 bool 变量:_onGround 和 _isDucking 这些变量似乎不可能同时为真或假,因此我们需要的其实是枚举。类似这样:

enum State {

STATE_IDLE,

STATE_JUMPING,

STATE_DUCKING,

STATE_DIVING

};

这样一来不需要一堆字段,我们只需要根据枚举进行对应的判断:

onKeyDown(event: any) {

switch(_state) {

case State.STATE_IDLE:

if(cc.macro.KEY.space == event.keyCode){

_state = STATE_JUMPING;

// 跳跃...

}

else if (cc.macro.KEY.down == event.keyCode) {

_state = STATE_DUCKING;

// 卧倒...

}

break;

case State.STATE_JUMPING:

if (cc.macro.KEY.down == event.keyCode) {

_state = STATE_DIVING;

// 跳斩...

}

break;

case State.STATE_DUCKING:

//...

break;

}

看起来也就改变了一点点,但是比起之前的代码有了很大的进步。我们在条件分支进行了区分,将某个状态中运行的逻辑聚合到了一起。

这是最简单的状态机实现方式,但是实际问题没有这么简单。我们的角色还存在着按键蓄力,松开时进行一段特殊攻击。现在的代码没有办法很清晰地胜任这样的工作。

还记得一开始画的状态机流程图吗?每一个状态方盒子给了我一些灵感,于是我开始尝试,用面向对象的思想去设计状态机。

状态模式

即使 switch 可以完成这些需求,但就像我们用起来的那样:崎岖且繁琐。因此我决定去使用游戏编程模式中的思想,让我们能使用简单的接口去完成复杂的逻辑工作,目标还是老样子:高内聚,低耦合。

状态接口

将状态封装成一个基类,用于控制某个状态相关的行为,并让状态记住自己所依附的角色信息。

这么做的目的很明确:让每个状态拥有相同的类型与共性,方便我们集中管理。

/**状态基类,提供状态的逻辑接口 */

export default class StateBase {

protected _role: Player | null = null;

constructor(player: Player) {

this._role = player;

}

//start------------虚方法-----------

/**进入该状态时被调用 */

onEnter() { }

/**该状态每帧都会调用的方法 */

onUpdate(dt: any) { }

/**该状态监听的键盘输入事件 */

onKeyDown(event: any) { }

/**该状态监听的键盘弹起事件 */

onKeyUp(event: any) { }

/**离开该状态时调用 */

onExit() { }

//end--------------虚方法------------

}

为每个状态写一个类

对于每个状态,我们定义一个类的实现接口。

它的方法定义了角色在这个状态的行为。换句话说,从之前的 switch 中取出每个 case,将它们移动到状态类中。

export default class Player_Idle extends StateBase {

onEnter(): void { }

onExit(): void { }

onUpdate(dt: any): void { }

onKeyDown(event: any): void {

switch (event.keyCode) {

case cc.macro.KEY.space:

// 跳跃状态

break;

case cc.macro.KEY.down:

// 卧倒状态

break;

}

}

onKeyUp(event: any): void { }

}

要注意,这里就已经把原本写在 Player.ts 中的 Idle 状态逻辑移除,放到了 Player_Idle.ts 类中。这样非常的清晰——在这个状态内只存在我们需要他判断的逻辑。


状态委托

接下来,重新构建角色内原来的逻辑,放弃庞大的 switch,通过一个变量来存储当前正在执行的状态。

export default class Player {

protected _state: StateBase | null = null; //角色当前状态

constructor() {

onInit();

}

onInit() {

this.schedule(this.onUpdate);

}

onKeyDown(event: any) {

this._state.onKeyDown(event);

}

onKeyUp(event: any) {

this._state.onKeyUp(event);

}

onUpdate(dt) {

this._state.onUpdate(dt);

}

}

为了「改变状态」,我们只需要将 _state 指向不同的 StateBase 对象,这样就实现了状态模式的全部内容。

将状态存在哪里?

又一个小细节:上面说到,为了「改变状态」,我们需要将 _state 指向新的状态对象,但是这个对象从哪里来呢?

我们知道一个角色有多个属于它的状态,而这些状态不可能是游离态存在内存中,我们必须用某些方式把这个角色的所有状态管理起来,我们或许可以这样做:找个人畜无害的位置,添加一个静态类,存储玩家的所有状态:

export class PlayerStates {

static idle: IdleState;

static jumping: JumpingState;

static ducking: DuckingState;

static diving: DivingState;

//...

}

这样玩家就可以切换状态:

export default class Player_Idle extends StateBase {

onEnter(): void { }

onExit(): void { }

onUpdate(dt: any): void { }

onKeyDown(event: any): void {

switch (event.keyCode) {

case cc.macro.KEY.space:

// 跳跃状态

this._role._state = PlayerStates.JumpingState;

break;

case cc.macro.KEY.down:

// 卧倒状态

this._role._state = PlayerStates.DuckingState;

break;

}

}

onKeyUp(event: any): void { }

}

这有问题吗?没有问题。但现在优化到了这一步,我不甘心这么做,因为这依旧是一个耦合较高的实现方法。这样的实现方式意味着每个角色都需要一个单独的类来存放状态合集,当一个游戏中存在多个角色,多个职业的时候,这个做法就相当繁琐。

那么这个问题有没有突破口呢?当然有,用容器装起来!既解决了耦合问题,也保留了之前的方式的所有灵活性,只需要往容器中注册一个状态就可以了。

protected _mapStates: Map<string, StateBase> = new Map();   //角色状态集合

将现有的代码模块化

现在整理一下我们所实现的部分:

多个状态继承自一个状态基类,实现相同的接口。

角色类中定义了该角色当前状态的变量 _state 。

用一个容器 _mapStates 存储某个角色的状态合集。

我觉着功能已经差不多完善了,将处理状态相关的变量聚合到一个类中,将角色类彻底放空,同时像一般的管理器一样,实现对于状态类的增删查改,画个框架图便于理解。


Animator.ts

/**动画机类,用于管理单个角色的状态 */

export default class Animator {

protected _mapStates: Map<string, StateBase> = new Map();   //角色状态集合

protected _state: StateBase | null = null;                  //角色当前状态

/**

* 注册状态

* @param key 状态名

* @param state 状态对象

* @returns

*/

regState(key: string, state: StateBase): void {

if ('' === key) {

cc.error('The key of state is empty');

return;

}

if (null == state) {

cc.error('Target state is null');

return;

}

if (this._mapStates.has(key))

return;

this._mapStates.set(key, state);

}

/**

* 删除状态

* @param key 状态名

* @returns

*/

delState(key: string): void {

if ('' === key) {

cc.error('The key of state is empty');

return;

}

this._mapStates.delete(key);

}

/**

* 切换状态

* @param key 状态名

* @returns

*/

switchState(key: string) {

if ('' === key) {

cc.error('The key of state is empty.');

return;

}

if (this._state) {

if (this._state == this._mapStates.get(key))

return;

this._state.onExit();

}

this._state = this._mapStates.get(key);

if (this._state)

this._state.onEnter();

else

cc.warn(`Animator error: state '${key}' not found.`);

}

/**获取状态机内所有状态 */

getStates(): Map<string, StateBase> {

return this._mapStates;

}

/**获取当前状态 */

getCurrentState(): StateBase {

return this._state;

}

/**当前状态更新函数 */

onUpdate(dt: any) {

if (!this._state) {

return;

}

if (!this._state.onUpdate) {

cc.warn('Animator onUpdate: state has not update function.');

return;

}

this._state.onUpdate(dt);

}

}

接下来在角色类中只需要定义一个 Animator 类的变量,并向其中注册我们需要的状态,再继续执行之前的逻辑代码:

Player.ts

export default class Player {

private _animator: Animator| null = null;

onInit() {

// 状态机注册

this._animator = new Animator();

if (this._animator) {

this._animator.regState('Idle', new IdleState(this));

this._animator.regState('Jumping', new JumpingState(this));

this._animator.regState('Ducking', new DuckingState(this));

this._animator.regState('Diving', new DivingState(this));

}

// 按键响应事件绑定

cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this);

cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this);

this.schedule(this.onUpdate);

}

onEnter(params?: any) { }

onUpdate(dt: any) {

this._animator.onUpdate(dt);

}

onKeyDown(event: any) {

let state = this._animator.getCurrentState();

if (state) {

state.onKeyDown(event);

}

}

onKeyUp(event: any) {

let state = this._animator.getCurrentState();

if (state) {

state.onKeyUp(event);

}

}

}

当然,可以选择做一些拓展的工作,让状态机也被管理起来:

AnimatorManager.ts

/**动画机管理器 */

export default class AnimatorManager {

//单例

private static _instance: AnimatorManager | null = null;

public static instance(): AnimatorManager {

if (!this._instance) {

this._instance = new AnimatorManager();

}

return this._instance;

}

private _mapAnimators: Map<string, Animator> = new Map<string, Animator>();

/**

* 获取动画机,若不存在则新建并返回

* @param key 动画机名

* @returns 动画机

*/

getAnimator(key: string): Animator | null {

if ("" == key) {

cc.error("AnimatorManager error: The key of Animator is empty");

}

let anim: Animator | null = null;

if (!this._mapAnimators.has(key)) {

anim = new Animator();

this._mapAnimators.set(key, anim);

}

else {

anim = this._mapAnimators.get(key);

}

return anim;

}

/**

* 删除动画机

* @param key 动画机名

*/

delAnimator(key: string) {

this._mapAnimators.delete(key);

}

/** 清空动画机 */

clearAnimator() {

this._mapAnimators.clear();

}

/**动画机状态更新 */

onUpdate(dt: any) {

this._mapAnimators.forEach((value: Animator, key: string) => {

value.onUpdate(dt);

});

}

}

这样角色类的 new 操作就被集中到了管理类,在 Player.ts 中也就不需要再 new 了:

// 状态机注册

this._animator = AnimatorManager.instance().getAnimator("player");

if (this._animator) {

this._animator.regState('Idle', new IdleState(this));

this._animator.regState('Jumping', new JumpingState(this));

this._animator.regState('Ducking', new DuckingState(this));

this._animator.regState('Diving', new DivingState(this));

}

成品

最终的角色状态切换效果通过如下代码实现,干净整洁:

注:this.getController() 为控制移动的模块,与该系统无关

即使状态机有这些常见的扩展,它们也受到一些限制。这里只是记录下我的解决方式,意为抛砖引玉,欢迎大家点击文末【阅读原文】到论坛专贴一起交流!


来源:COCOS
原文:https://mp.weixin.qq.com/s/st0KdsRpSb-ekoJNcp_Ruw


资源转载网络,如有侵权联系删除。
相关下载

玩家评论

百度地图“实时公交”升级:布局更简洁拥堵情况一目了然

  3月3日消息, 百度地图宣布“实时公交”功能升级:布局更简洁,关键信息更清晰,道路的拥堵情况也能看得清清楚楚。   从官方晒图来看,用户在百度地图APP可以看到详情>>

阅读: 0
日期: 2022-03-05
无线更简洁:苹果在AppleStore采用MagSafe展示架

  外媒 9to5mac 报道称,苹果开发出了一种全新的 iPhone 展示解决方案,尤其是突出展示 MagSafe 无线充电功能,不再有充电线缆,消除了杂乱感,可以让顾客感觉 iPhone 悬浮在空中详情>>

阅读: 4
日期: 2021-08-03
QQ音乐内测“简洁模式”,此前已发布简洁版App

  腾讯近日推出了 QQ 音乐简洁版 ,仅保留音乐 App 必须功能,去除类似“主题皮肤”“社区”等次要功能,大家应该都已经知道了。   据网友 @贾贵贾队详情>>

阅读: 4
日期: 2021-07-29
QQ音乐简洁模式内测怎么申请 QQ音乐简洁模式有什么不同

QQ音乐功能十分全面,也正是因为如此导致QQ音乐的安装包非常占据内存空间,并且很多网友表示QQ音乐很多功能都用不上。不过近日腾讯推出了QQ音乐简洁模式,此次内测开启,还是挺值得详情>>

阅读: 4
日期: 2021-07-28
QQ音乐简洁版怎么设置?qq音乐简洁版体验测评

前段时间QQ音乐“简洁版”的功能大家体验到吗,界面没有花里胡哨,而且没有广告,看起来就很舒服,不过近日qq音乐下架了这个功能,上线了一款QQ音乐简洁版的APP,而且只有39.11MB,这个大详情>>

阅读: 6
日期: 2021-07-22
原神最简洁钟离攻略

  原神开启1.5版本玉扉绕尘歌,钟离也迎来了复刻UP池,下面一起随小编来了解一下在原神新版本玉扉绕尘歌中钟离将有怎样的提升和出彩的表现吧。   角色:钟详情>>

阅读: 10
日期: 2021-04-27
模拟人生4艺术风简洁挂画MOD v1.0 evi版

MOD介绍 模拟人生4艺术风简洁挂画MOD是论坛大神“evi”为模拟人生4游戏制作的MOD,使用之后将可以让玩家获得一个很好看详情>>

阅读: 3
日期: 2021-04-17
ZorinOS16Beta发布:界面更简洁应用更丰富

如果你正准备从 Windows 10 迁移到 Linux 平台,那么 Zorin OS 是非常不错的选择。该发行版提供了熟悉的用户界面,并预装了大量的实用工具。今天,Zorin OS 16 Beta 版本发布了详情>>

阅读: 6
日期: 2021-04-16
模拟人生4男性黑白色简洁t恤MOD v1.0 Birba32版

MOD介绍 模拟人生4黑白色简洁t恤MOD是论坛大神“Birba32”为模拟人生4游戏制作的MOD,使用之后将可以让玩家获得一个很详情>>

阅读: 3
日期: 2021-01-26
模拟人生4女性简洁夏季服装MOD v1.0 Camuflaje版

MOD介绍 模拟人生4简洁夏季服装MOD是论坛大神“Camuflaje”为模拟人生4游戏制作的MOD,使用之后将可以让玩家获得一个很详情>>

阅读: 7
日期: 2020-12-17
Steam更换网页端登录界面 UI风格更简洁,有现代气息

今日,Steam更换了网页端的账号登陆界面。新的界面更加简洁明了,更有现代气息了。以前的老版登录界面是左输入、右提示。新版登录界面则是登录或下载Stea详情>>

阅读: 6
日期: 2020-10-21
Steam更换网页端登录界面UI风格更简洁,有现代气息

Steam更换网页端登录界面 UI风格更简洁,有现代气息 2020-10-21 14:29:08来源:游戏下载编辑:松鼠骑士评论(0) 详情>>

阅读: 13
日期: 2020-10-21
XboxOne主机10月份UI更新上线大小为6G,界面更简洁

Xbox One主机10月份UI更新上线 大小为6G,界面更简洁 2020-10-15 17:15:25来源:游戏下载编辑:松鼠骑士评论(0) 详情>>

阅读: 20
日期: 2020-10-15
Xbox One主机10月份UI更新上线 大小为6G,界面更简洁

根据外媒GameSpot的消息,微软已为Xbox One带来了10月份的UI更新,本次更新大小为6GB。这次更新给Xbox One带来了新鲜的观感和体验,加入个人简介(profile)的详情>>

阅读: 4
日期: 2020-10-15
超神英雄,简洁精致的MOBA游戏

说到MOBA游戏,恐怕在座的各位玩家绝对不会感到陌生,毕竟从Dota到英雄联盟,这种紧张刺激的游戏模式已经吸引了一大票粉丝。今天我们要介绍的是一款比较小众的MOBA游戏,超详情>>

阅读: 11
日期: 2020-08-13
模拟人生4女性简洁的运动内衣MOD v1.0 Saliwa版

MOD介绍 模拟人生4女性简洁的运动内衣MOD是论坛大神“Saliwa”为模拟人生4游戏制作的MOD,使用之后将可以让玩家获得一详情>>

阅读: 8
日期: 2020-08-01
杨幂黑色长发 简洁搭配更休闲!

原标题:杨幂黑色长发 简洁搭配更休闲! 游戏网 详情>>

阅读: 8
日期: 2020-07-31
西窗烛app:一款界面排版简洁的诗词欣赏app

  西窗烛app是一款能够让用户感受到诗词之美的软件,西窗烛app中的排版简洁素雅,让用户在使用的过程中,不会让双眼感到不适。      在西窗烛app中,每天都会为用户推详情>>

阅读: 13
日期: 2020-07-17
模拟人生4女性简洁彩色短袖MOD v1.0 GossipGirl版

MOD介绍 模拟人生4女性简洁彩色短袖MOD是论坛大神“GossipGirl”为模拟人生4游戏制作的MOD,使用之后将可以让玩家获得详情>>

阅读: 10
日期: 2020-07-13
网页端GooglePhotos改版:弃用汉堡菜单布局更简洁

  上月,谷歌重新设计了 Photos 应用程序,引入了全新的用户界面和一些新的功能。现在,网页端 Google Photos 也获得了改版,移除了此前的汉堡菜单,使用侧边栏替代导航,并包含了详情>>

阅读: 10
日期: 2020-07-08
Win10全新“开始”菜单曝光:更简洁、更时尚

  为了让Windows 10看起来更时尚,微软一直没有停止对它的改造。  据外媒报道称,今天早些时候微软365在Facebook上分享了Windows 10的新开始菜单,色泽上这次新的UI改造旨在详情>>

阅读: 13
日期: 2020-06-24
夏季男士简洁搭配!年年流行的穿法!_风格

原标题:夏季男士简洁搭配!年年流行的穿法! 我们都知道,男人的穿搭常常被女人诟病!尤其是在夏天!不是被吐槽长袖短裤椰子鞋,就是被吐槽汗衫短裤凉拖鞋!究其详情>>

阅读: 13
日期: 2020-04-08
精致少年蔡徐坤运动帽衫简洁搭配更清新!_休闲

原标题:精致少年蔡徐坤 运动帽衫简洁搭配更清新! 蔡徐坤与虚拟人物共同登《Wonderland.》创刊封面,一头金发的蔡徐坤身穿帽衫搭配灯芯绒休闲西服展详情>>

阅读: 7
日期: 2020-04-01
《英雄联盟》客户端视觉升级,全新界面更简洁_进行

原标题:《英雄联盟》客户端视觉升级,全新界面更简洁 IT之家3月9日消息 根据《英雄联盟》官方的消息,官方即将上线新版的客户端界面,相比之前更加简洁详情>>

阅读: 11
日期: 2020-03-10
郑秀晶简洁风格造型微卷长发的美丽“水晶”_Kwak

原标题:郑秀晶简洁风格造型 微卷长发的美丽“水晶” 郑秀晶 《OK!精彩》3月电子刊封面大片, 独有风格的女孩, 简洁风格造型, 单色系套装搭配, 微详情>>

阅读: 16
日期: 2020-03-06
《集合啦!动物森友会》限定版Switch公布 简洁配色还原游戏风格

  《集合啦!动物森友会》限定版Switch公布,底座采用了米白色底色+海岛主题图案的设计方式,Joy-Con为双色的设计,机身背部绘制游戏的各种图标,该主机日版预计3月20日发售,售价359详情>>

阅读: 21
日期: 2020-01-31
【A软推一推】诗鲸简洁呆萌的诗词应用

在上期的A软推一推给大家推荐了SpaceFM 用音乐确认同类,那么今天牛游戏小编为大家推荐诗鲸 简洁呆萌的诗词应用。诗鲸是一款学习教育类app,以最简洁的方式呈现古诗词的学习详情>>

阅读: 16
日期: 2020-01-15
简洁,干净,上档次的会议室还得靠液晶拼接屏结合无线传屏来设计

原标题:简洁,干净,上档次的会议室还得靠液晶拼接屏结合无线传屏来设计 简洁,干净,上档次的会议室还得靠液晶拼接屏结合无线传屏来设计 小编先带大详情>>

阅读: 30
日期: 2019-10-02
有哪些简洁的人生建议?

有哪些简洁的人生建议? 详情>>

阅读: 27
日期: 2019-09-19
LOL:LPL战队TOP正式更名为滔博电竞,全新LOGO简洁大方!

北京时间5月15日晚TOP电子竟技俱乐部官博发布公告,TOP进行了品牌升级后,现更名为滔搏电子竞技俱乐部,英文简写为TES,并公布了全新的队标LOGO。微博正文内容:【俱乐部更名公告】致详情>>

阅读: 76
日期: 2019-09-15
徐璐身穿灰绿色西装套装,简洁清爽、身材纤细,气质当真好

原标题:徐璐身穿灰绿色西装套装,简洁清爽、身材纤细,气质当真好 小密语录:恋爱让人春风满面尽显甜蜜,瑜伽则让人获得好身材变成女神 徐璐曾经出演《海详情>>

阅读: 25
日期: 2019-09-11
简洁日程管理

详情>>

阅读: 0
日期: 2019-09-07
大咖解读BOSCore:保持简洁,为行业做出改变

原标题:大咖解读BOSCore:保持简洁,为行业做出改变 5月27日BOSCore又有大动作,先是团队迎来两位重量级的大咖,火币矿池CEO曹飞和EOSBIXIN的CEO超级君官宣加入BOSCor详情>>

阅读: 14
日期: 2019-06-02
好用简洁的手机日历-手机简洁日历下载

Game234游戏门户为大家带来好用简洁的手机日历,现在手机日历软件非常的多,但是许多这类软件都喜欢在里面打广告,弄的界面乱七八糟,今天小编就要为大家推荐一些手机日历软件,这些软件界面简洁好用,喜欢的详情>>

阅读: 26
日期: 2019-03-17
简洁经验分享 云渺净副本5S通关小技巧

简洁经验分享 云渺净副本5S通关小技巧, 前言:云秒净是我们家族日常本 每周1次南土 其他全是云秒净 所以研究出适合我们家族的云秒净达成条件 供参考 队伍组成 3... 详情>>

阅读: 5
日期: 2019-01-29
简洁类型的软件有哪些_简洁类型的软件那些好用_简洁类型的软件推荐下载

现在我们生活中充斥这各种各样的应用,而且这其中有的软件已经高达了一G左右的内存,有时候会让手机吃不消!,那么就和小编来一起看看那些简洁的软件吧!TOP1:WiFi免费助手(游戏评分:9)WiFi免费助详情>>

阅读: 7
日期: 2019-01-27
阴阳师御魂强化最简洁明了的攻略流程 萌新必读

阴阳师御魂强化最简洁明了的攻略流程 萌新必读介绍了Helloeveryone.阴阳师手游在真正成熟起来之后又被玩家们戏称为御魂师,的确在游戏中,哪怕你拥有再强大的式神,... 详情>>

阅读: 2
日期: 2018-11-16
新老iPad Pro真机对比图赏 没了Home键造型更简洁

新款iPad Pro发布:超窄边框 A12X处理器 6499元起 新iPad Pro实物模型曝光:边框...单机游戏 游戏资讯 游戏评测 游戏下载 单机排行榜 游戏专区 游戏攻略 发售表 ... 详情>>

阅读: 6
日期: 2018-11-06
LOL设计师:暂不添加新符文 S9更加简洁

随着S9季前赛将在10月上线测试服,在刚结束的周末中,英雄联盟的游戏玩法制作人负责人RiotScruffy,分享了S9季前赛的一些改动内容,其中就包括符文系统的改动。新符文... 详情>>

阅读: 16
日期: 2018-09-12
御龙在天什么职业好简洁一点

小编为您搜罗的答案:楼上的是各种职业都有啊,你要说非RMB玩家,我建议是霸刀银枪扇子,这三个,扇子比较稳定,不死之身。但是输出技能少,要说国战人头不好强啊,但是要单P,那你就无敌了,还有霸刀,霸刀详情>>

阅读: 0
日期: 2018-09-12
精彩推荐