当前位置: 永利棋牌 > 儿童文学 > 正文

如何使用Vuex,游戏交互设计师

时间:2019-10-01 13:19来源:儿童文学
1、游戏的核心 前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和Vuex来构建一个简单笔记的单页应用的文章。感觉收获挺多,自己在它的例子的基础上进行了一些优

1、游戏的核心

前言:在最近学习 Vue.js 的时候,看到国外一篇讲述了如何使用 Vue.js 和 Vuex 来构建一个简单笔记的单页应用的文章。感觉收获挺多,自己在它的例子的基础上进行了一些优化和自定义功能,在这里和大家分享下学习心得。

文/小黑

在这篇教程中我们将通过构建一个笔记应用来学习如何在我们的 Vue 项目中使用 Vuex。我们将大概的过一遍什么是 Vuex.js,在项目中什么时候使用它,和如何构建我们的 Vue 应用。

今天主要讲讲游戏交互设计师在项目中的主要职责。

  设计师想要传达的唯一的游戏体验。

这里放一张我们项目的预览图片:

先大概了解一下游戏项目流程中的角色关系和产出:

笔记:【简单来说就是我们想传达的是这个游戏是关于什么样的游戏,比如App store里面的一个游戏《Sprinkle》 ,他给人传达的是你要用不同的方式去灭火,这用行业术语叫“核心说明”。】

图片 1

图片 2

 

项目源码:vuex-notes-app;有需要的同学可以直接下载源码查看。

下面进入主题:一、理论篇

2、游戏中可能出现的核心动态

主要知识点
Vuex状态管理机制的使用
Vue.js 的基础 api
Vue-cli脚手架的安装及使用
vur-router的使用
ES6的语法,这里推荐看下阮一峰的入门教程

游戏交互设计师在项目中主要做什么?

Vuex 概述 在我们迫不及待的开始项目之前,我们最好先花几分钟来了解下 Vuex 的核心概念。

1.策划需求审稿员

(1)领地获取:

Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构。它借鉴了 Flux 和 Redux 的设计思想,但简化了概念,并且采用了一种为能更好发挥 Vue.js 数据响应机制而专门设计的实现。

UI最开始会拿到游戏策划的需求文档,需求文档中主要会描述完整的功能需求。

【通俗讲就是占地为王,通过获取某处地方和消灭某处地方的敌人而获取游戏的胜利,比如App store里面有很多类似的回合制的飞机射击类游戏,这类型也火过一段时间。】

state 这样概念初次接触的时候可能会感觉到有点模糊,简单来说就是将 state 看成我们项目中使用的数据的集合。然后,Vuex 使得 组件本地状态(component local state)和 应用层级状态(application state) 有了一定的差异。

很多小伙伴拿到文档就开始做原型了。但是,等等,建议大家拿到需求文档后,先好好“审稿”,主要查看3点:第一,功能是否必要;

(2)预测类型:

component local state:该状态表示仅仅在组件内部使用的状态,有点类似通过配置选项传入 Vue 组件内部的意思。
application level state:应用层级状态,表示同时被多个组件共享的状态层级。

有一些策划会抱着“功能做大做全总是没错的”的想法来写需求,导致功能庞大繁杂,主次不清。这个时候,UI担任了平衡轻重的角色——

【就是让玩家通过预测游戏的结果而取得游戏晋级,我们可以通过预测做一些棋牌类型的游戏,而这在App store里面貌似还没有找到。】

假设有这样一个场景:我们有一个父组件,同时包含两个子组件。父组件可以很容易的通过使用 props 属性来向子组件传递数据。

从阶段性开发、功能必要性的角度,和策划讨论删减功能,或者延后开发;

(3) 构造:

但是问题来了,当我们的两个子组件如何和对方互相通信的? 或者子组件如何传递数据给他父组件的?在我们的项目很小的时候,这个两个问题都不会太难,因为我们可以通过事件派发和监听来完成父组件和子组件的通信。

从玩家需求的角度,挑出重要功能着重处理,删减非必要需求。

【在App store里面,有些类似模拟人生那样的模拟游戏,让你通过建造房屋,构造你的个人资产,然后与人家比拼,这种类型的游戏既有战争类型,也有闲暇一点的模拟类型,这种类型的游戏也有一定的吸引力。我们也可以继续关注。】

然而,随着我们项目的增长:

所以看到功能繁杂、重点不清的时候,就要举起你的奥卡姆剃刀来。第二,功能设计是否合理;

(4)收集:

1、保持对所有的事件追踪将变得很困难。到底哪个事件是哪个组件派发的,哪个组件该监听哪个事件?
2、项目逻辑分散在各个组件当中,很容易导致逻辑的混乱,不利于我们项目的维护。
3、父组件将变得和子组件耦合越来越严重,因为它需要明确的派发和监听子组件的某些事件。

策划不可能总是不出错,有时候他们忘了从玩家身份考虑,可能提出一些不合理的功能,就需要UI来把关。

【我们可以设计当玩家收集到符合我们要求的条件时才通关,其中收集的东西可以自己富有创造力去想象,可以是不同种类的水果,不同花色可以构成一块的瓷砖都可以,尽管发挥你的想象力去联想。】

这就是 Vuex 用来解决的问题。 Vuex 的四个核心概念分别是:

这需要经验积累,才能及时对不合理功能做出反应。第三,根据需求,设计更好的方案;

 

The state tree:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
Getters:用来从 store 获取 Vue 组件数据。
Mutators:事件处理器用来驱动状态的变化。
Actions:可以给组件使用的函数,以此用来驱动事件处理器 mutations
如何你暂时还不太理解这个四个概念,不用着急,我们将在后面的项目实战中详细的解释。

UI的重要贡献在于“为游戏提供更好的体验”,所以有时驳回策划需求后,需要从玩家的角度出发,给策划提供一个更合理的解决方案。

3、点子来自哪里

下面这张图详细的解释了 Vuex 应用中数据的流向(Vuex 官方图)

认真过审文档,一方面在需求阶段就优化项目,另一方面提高自己在项目中的话语权,而不仅是作为一个“策划辅助”的身份。

 

图片 3

2.原型、流程图产出者

(1) 玩大量的游戏:

简单解释下:

这应该是大家听的最多的一个职能了。

【这个不用说,App store上无论是免费还是付费的前二十五或者五十名的游戏,你都可以尝试着去发现这个游戏的亮点在哪里,用户可能会喜欢哪个特点,哪项体验。只有体验不同类型的游戏,你联想的时候才会有多种素材和环境供你选择,不然你设计策划出来的游戏就显得有点单调乏味了。】

Vuex 规定,属于应用层级的状态只能通过 Mutation 中的方法来修改,而派发 Mutation 中的事件只能通过 action。

我们用Axure来写交互文档,一般不做流程图,都是通过图文流进行表述(根据每个项目协作方式的不同,写文档的要求会不一样)。

(2)与游戏设计师交流:

从左到又,从组件出发,组件中调用 action,在 action 这一层级我们可以和后台数据交互,比如获取初始化的数据源,或者中间数据的过滤等。然后在 action 中去派发 Mutation。Mutation 去触发状态的改变,状态的改变,将触发视图的更新。

以主页面或功能流程为一个讲述点,会有当前页面/流程的全局讲述、页面布局说明、功能点说明、跳转说明,复杂些的逻辑也会写逻辑图。

【这点不用说了哈】

注意事项

这个是基本职能,很多文章也都有说明,就不讲太细了,大家跟着项目的UI师傅学一学就清楚。

(3) 随时随地的:

数据流都是单向的
组件能够调用 action
action 用来派发 Mutation
只有 mutation 可以改变状态
store 是响应式的,无论 state 什么时候更新,组件都将同步更新

3.交互规范制定

【每个以一个主题设计一个游戏,发掘你身边中没发现过的事物,比如说声音,水声,门声,动物的声音,很多都等待着你去挖掘。】

环境安装
这个应用将使用 webpack 来做模块打包,处理和热重启。使用 Vue 官方提供的脚手架 vue-cli。

很多小团队不重视规范的制定(视觉规范、交互规范、开发规范),觉得写规范很浪费时间,执行规范太过死板。

 

安装 vue-cli** npm install -g vue-cli
注:Node.js >= 4.x, 5.x 最好

但上一个项目的后果告诉我,一个规范可能决定了项目的成败——

4、游戏设计师要做的东西

初始化应用**

我进入团队的时候,项目已经进行了2年多,中间人员变动频繁,功能更改也很多,因为缺乏规范文档,导致了后来的成员难以维护以前的内容、新内容与旧内容冲突或者不一致、组件复用率低导致迭代困难。

笔记:

vue init webpack vue-notes-app
cd vue-notes-app
npm install // 安装依赖包
npm run dev // 启动服务

虽然当时我根据项目存在的问题,编制了一份游戏交互文档,但是因为许多问题存在于底层代码,要解决规范问题约等于推翻重做,基本不太可能了。于是默默留下文档,离开了项目,来到了一个重视规范的团队。

(1)概念文档:【一般1-3页左右,里面提供游戏的描述,包括游戏主题的介绍,目标受众、题材、目标平台等特性清单】

初始化一个项目名为vue-notes-app的应用,并选择使用 webpack 打包方式。在命令行中按照提示选择初始化配置项。其中在选择 JSLint 校验的时候,推荐选择 AirBNB 规范。

上一家公司的项目到现在已经有4年,投入成本几千万,但基本是废了。

(2)提案:【除了要包括概念文档中提到的,还要包括预算和时间估算,竞争性分析和产品发布之后的扩展、游戏模型和概念美工等】

使用你最喜欢的编辑器打开我们刚刚新建的项目,项目的结构大概如下图:

在网易的一位同事跟我说,网易做项目都会有一份成熟的规范文档,项目中所有人共同维护和执行,保证人员更替、内容迭代、增加内容的情况下,项目都能有序进行。

(3)之后就是你要向你的VC或者游戏发行商推销你的游戏了。

图片 4

因为制定交互规范非常重要,所以我决定单独写一篇文章来详细说明。

 

components/ 文件夹用来存放我们的 Vue 组件
vuex/ 文件夹存放的是和 Vuex store 相关的东西(state object,actions,mutators)
build/ 文件是 webpack 的打包编译配置文件
config/ 文件夹存放的是一些配置项,比如我们服务器访问的端口配置等
dist/ 该文件夹一开始是不存在,在我们的项目经过 build 之后才会产出
App.vue 根组件,所有的子组件都将在这里被引用
index.html 整个项目的入口文件,将会引用我们的根组件 App.vue
main.js 入口文件的 js 逻辑,在 webpack 打包之后将被注入到 index.html 中

4.对接视觉设计师设计页面“故事”

5、当前IOS游戏设计的要考虑的问题

功能模块
新增笔记,新增一篇笔记,编辑区显示空的笔记内容
删除笔记,删除一篇笔记之后,编辑区域显示当前笔记类别的第一项
笔记列表切换,分为全部笔记和收藏笔记两种,在切换之后,编辑区域显示当前列表的第一条笔记
收藏笔记,给当前激活的笔记打上收藏的标签

“一个好的游戏界面设计,会让玩家感受到‘故事’。”——这是视觉设计师告诉我的。

项目组件划分
在这个项目中,我们将总共使用四个组件:根组件 App.vue,操作栏组件 Toolbar.vue,别表组件 NotesList.vue,笔记编辑组件 Editor.vue。

产品交互设计师可能比较少接触到这个工作内容,但游戏设计更像设计“一个世界”,界面就是构成这个“世界”的载体,所以游戏页面除了承载功能,还承载了组成世界的“故事”。这也是为什么游戏界面设计更注重“场景化”。

(1)游戏设计和开发时间的预算:

图片 5

所以项目主界面设计的最开始,需要视觉设计师、交互设计师、策划等,一起来构思怎么讲好这个游戏的“故事”。

【一般小公司的预算都在2-3个月之间,特别在中国,不像国外的做产品的,一个游戏从创意到出场要经过以年计算的时间。】

创建 Vuex Store
按照上面我们列出来的功能模块,我们在 Vuex/ 下面建立一个 store.js 文件。

《阴阳师》的界面就很好地传达了它想讲的“故事”,让玩家觉得进入了一个完整的“世界”中。

(2)成本:

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

// 需要维护的状态
const state = {
 notes: [],
 activeNote: {},
 show: ''
};

const mutations = {
 // 初始化 state
 INIT_STORE(state, data) {
 state.notes = data.notes,
 state.show = data.show;
 state.activeNote = data.activeNote;
 },
 // 新增笔记
 NEW_NOTE(state) {
 var newNote = {
 id: +new Date(),
 title: '',
 content: '',
 favorite: false
 };
 state.notes.push(newNote);
 state.activeNote = newNote;
 },
 // 修改笔记
 EDIT_NOTE(state, note) {
 state.activeNote = note;
 // 修改原始数据
 for (var i = 0; i < state.notes.length; i++) {
 if(state.notes[i].id === note.id){
 state.notes[i] = note;
 break;
 }
 };
 },
 // 删除笔记
 DELETE_NOTE(state) {
 state.notes.$remove(state.activeNote);
 state.activeNote = state.notes[0] || {};
 },
 // 切换笔记的收藏与取消收藏
 TOGGLE_FAVORITE(state) {
 state.activeNote.favorite = !state.activeNote.favorite;
 },
 // 切换显示数据列表类型:全部 or 收藏
 SET_SHOW_ALL(state, show){
 state.show = show;
 // 切换数据展示,需要同步更新 activeNote
 if(show === 'favorite'){
 state.activeNote = state.notes.filter(note => note.favorite)[0] || {};
 }else{
 state.activeNote = state.notes[0] || {};
 }
 },
 // 设置当前激活的笔记
 SET_ACTIVE_NOTE(state, note) {
 state.activeNote = note;
 }
};

export default new Vuex.Store({
 state,
 mutations
});

图片 6

【这个相信是最关键的,成本无疑是影响是否启动这个游戏开发的主要因素,一个游戏可能会涉及到1-3游戏程序员和1-2UI和美术,1-2原画,当然,这是相对于中等水平的团队来说,但如果你上线的游戏是否能够受到用户的青睐而收回自己的开发成本,这个就需要你的抉择了】

创建 Vuex Actions
在 Vuex/ 下面建立一个 action.js,用来给组件使用的函数。

《阴阳师》主界面

(3)游戏策划:

function makeAction(type) {
 return ({ dispatch }, ...args) => dispatch(type, ...args);
};

const initNote = {
 id: +new Date(),
 title: '我的笔记',
 content: '第一篇笔记内容',
 favorite: false
};

// 模拟初始化数据
const initData = {
 show: 'all',
 notes: [initNote],
 activeNote: initNote
};

export const initStore = ({ dispatch }) => {
 dispatch('INIT_STORE', initData);
};
// 更新当前activeNote对象
export const updateActiveNote = makeAction('SET_ACTIVE_NOTE');

// 添加一个note对象
export const newNote = makeAction('NEW_NOTE');

// 删除一个note对象
export const deleteNote = makeAction('DELETE_NOTE');
export const toggleFavorite = makeAction('TOGGLE_FAVORITE');
export const editNote = makeAction('EDIT_NOTE');

// 更新列表展示
export const updateShow = makeAction('SET_SHOW_ALL');
创建 Vuex Getters
在 vuex/ 下面建立一个 getter.js 文件,用来从 store 获取数据。

// 获取 noteList,这里将会根据 state.show 的状态做数据过滤
export const filteredNotes = (state) => {
 if(state.show === 'all'){
 return state.notes || {};
 }else if(state.show === 'favorite'){
 return state.notes.filter(note => note.favorite) || {};
 }
};


// 获取列表展示状态 : all or favorite
export const show = (state) => {
 return state.show;
};

// 获取当前激活 note
export const activeNote = (state) => {
 return state.activeNote;
};

图片 7

【这个游戏的策划显得很重要,因为影响到这个游戏是否好玩和可玩性如何,直接影响这个游戏的收益,所以游戏策划这块出来的新意很重要,尽管有时候我们无法全部创新,但也可以微创新,呵呵,这个词最近很热门。】

以上就是我们 Vuex 的所有逻辑了,在定下了我们需要完成的功能之后,接下来就是只需要在组件中去调用 action 来实现对应的功能了。

《阴阳师》神龛

 

路由配置 在这里我们将使用 vue-router 来做路由,引用 bootstrap 样式。

图片 8

好了,今天看到这就写到这了,欢迎大家拍砖,也希望大家有什么好的建议发表一下,可以交流下。

index.html

《阴阳师》百鬼夜行转化交互文档为视觉需求文档

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8">
 <title>vuex-notes-app</title>
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
 </head>
 <body>
 <div id="app"></div>
 <!-- built files will be auto injected -->
 </body>
</html>

视觉设计师一般工作量都很大,没有时间细看交互设计文档,所以需要交互设计师将交互文档转化为“GUI设计需求表”,将每一个需要视觉设计的内容整理成表格,注明大小规范、数量、需求等,供视觉设计师快速产出。视觉创意方案

所有的入口逻辑我们都将在 main.js 中编写

是的,交互设计师除了有严谨的逻辑,还需要有足够的创意。

main.js

在我们的项目里,很多小内容需要创意化设计时,都需要交互设计师先提出方案,再由视觉设计师进行细化。

import Vue from 'vue';
import App from './App';

import VueRouter from 'vue-router';
import VueResource from 'vue-resource';

// 路由模块和HTTP模块
Vue.use(VueResource);
Vue.use(VueRouter);

const router = new VueRouter();

router.map({
 '/index': {
 component: App
 }
});

router.redirect({
 '*': '/index'
});

router.start(App, '#app');

所以随时准备打开你的脑洞!

根组件 App.vue

5.对接程序功能逻辑对接

<template>
 <div id="app" class="app">
 <toolbar></toolbar>
 <notes-list></notes-list>
 <editor></editor>
 </div>
</template>

<style>
 html, #app {
 height: 100%;
 }

 body {
 margin: 0;
 padding: 0;
 border: 0;
 height: 100%;
 max-height: 100%;
 position: relative;
 }
</style>

<script>
 import Toolbar from './components/Toolbar';
 import NotesList from './components/NotesList';
 import Editor from './components/Editor';
 import store from './vuex/store';
 import { initStore } from './vuex/actions';

 export default {
 components: {
 Toolbar,
 NotesList,
 Editor
 },
 store,
 vuex: {
 actions: {
 initStore
 }
 },
 ready() {
 this.initStore()
 }
 }
</script>

交互设计文档会直接对接给下游的开发部门,需要交互设计师和开发部门讲解功能的交互流程,详细说明功能的每一个支线和所有存在的状态。

在根组件中引用了三个子组件:Toolbar.vue, NotesList.vue, Editor.vue。

交互设计师在审核和对接需求文档时,已经对功能逻辑比较清晰,所以有一些前期开发要注意的问题,也需要及时知会开发部门。

注意:我们在配置里面加入了 vuex 这么一个选项,这里用来将我们 action 里面定义的方法给暴露出来,我们在根组件中只做了一件事情,那就是初始化模拟数据,因此我们在组件生命周期的 ready 阶段调用了 actions 里面的 initStore 来初始化我们的 store 里面的 state

在整理交互文档的时候,发现需要配置为复用的控件,也需要及时整理进交互设计规范,告知视觉设计师和开发部门,能大大提升开发效率,降低后期迭代成本。界面拼接

Toolbar.vue

大家应该都发现了,开发部门拼界面基本很难讲位置拼准确,所以在网易游戏的项目里,在开发工具里(cocos、unity、U3D等)拼界面的事情是由交互设计师做的。因此交互设计师也需要具备开发工具基本功能常识。功能测试

<template>
 <div id="toolbar">
 <i class="glyphicon logo"><img src="../assets/logo.png" width="30" height="30"></i>
 <i @click="newNote" class="glyphicon glyphicon-plus"></i>
 <i @click="toggleFavorite" class="glyphicon glyphicon-star" :class="{starred: activeNote.favorite}"></i>
 <i @click="deleteNote" class="glyphicon glyphicon-remove"></i>
 </div>
</template>

<script>
import { newNote, deleteNote, toggleFavorite } from '../vuex/actions';
import { activeNote } from '../vuex/getters';

export default {
 vuex: {
 getters: {
 activeNote
 },
 actions: {
 newNote,
 deleteNote,
 toggleFavorite
 }
 }
}
</script>

<style lang="scss" scoped>
 #toolbar{
 float: left;
 width: 80px;
 height: 100%;
 background-color: #30414D;
 color: #767676;
 padding: 35px 25px 25px 25px;

 .starred {
 color: #F7AE4F;
 }

 i{
 font-size: 30px;
 margin-bottom: 35px;
 cursor: pointer;
 opacity: 0.8;
 transition: opacity 0.5s ease;

 &:hover{
 opacity: 1;
 }
 }
 }
</style>

开发完成后,需要交互设计师对功能进行测试和反馈,保证开发结果。

在这里,我们用到了 Vuex 的一个案例就是我们需要知道当前的激活的笔记是否是收藏类别的,如果是,我们需要高亮收藏按钮,那么如何知道呢?那就是通过 vuex 里面的 getters 获取当前激活的笔记对象,判断它的 favorite 是否为 true。

6.项目迭代

始终牢记一个概念,vuex 中数据是单向的,只能从 store 获取,而我们这个例子中的 activeNote 也是始终都在 store.js 中维护的,这样子就可以给其他组件公用了

一个项目是需要进行反复的迭代的。

// 需要维护的状态
const state = {
 notes: [],
 activeNote: {},
 show: ''
};
NotesList.vue
<template>
 <div id="notes-list">
 <div id="list-header">
 <h2>Notes | heavenru.com</h2>
 <div class="btn-group btn-group-justified" role="group">
 <!-- all -->
 <div class="btn-group" role="group">
 <button type="button" class="btn btn-default"
 @click="toggleShow('all')"
 :class="{active: show === 'all'}">All Notes</button>
 </div>

 <!-- favorites -->
 <div class="btn-group" role="group">
 <button type="button" class="btn btn-default"
 @click="toggleShow('favorite')"
 :class="{active: show === 'favorite'}">Favorites</button>
 </div>
 </div>
 </div>

 <!-- 渲染笔记列表 -->
 <div class="container">
 <div class="list-group">
 <a v-for="note in filteredNotes"
 class="list-group-item" href="#"
 :class="{active: activeNote === note}"
 @click="updateActiveNote(note)">
 <h4 class="list-group-item-heading">
 {{note.title.trim().substring(0,30)}}
 </h4>
 </a>
 </div>
 </div>
 </div>
</template>

<script>
 import { updateActiveNote, updateShow } from '../vuex/actions';
 import { show, filteredNotes, activeNote } from '../vuex/getters';

 export default {
 vuex: {
 getters: {
 show,
 filteredNotes,
 activeNote
 },
 actions: {
 updateActiveNote,
 updateShow
 }
 },
 methods: {
 toggleShow(show) {
 this.updateShow(show);
 }
 }
 }
</script>

在功能迭代层面上,除了策划提出的新增需求,交互设计师需要不断体验游戏,对其中不够合理的内容提出迭代需求。

笔记列表组件,主要有三个操作

迭代的时候,并不是以“这里不好看/不好用”的目的来迭代,这样子容易造成视野陷入细节中出不来,甚至偏离了迭代目标。

渲染笔记
切换渲染笔记
点击列表 title,切换 activeNote

好的迭代是提出“想达到什么目的”,根据目标对一整个功能进行优化。

我们通过 getters 中的 filteredNotes 方法获取笔记列表

迭代方案出来后,再让用户体验的同学帮忙对新方案进行测试和评估。

编辑:儿童文学 本文来源:如何使用Vuex,游戏交互设计师

关键词: