精华内容
下载资源
问答
  • 游戏界面设计

    2007-09-13 09:29:09
    一款游戏界面设计,组件是可以添加的
  • 游戏界面设计 PAGE 8 游戏界面设计 目 录 TOC \o "1-3" \h \z \u 一打开文件 2 二创建人物角并且使之与场景融合 3 一人物 3 三环境渲染 4 一气氛加强 4 \t "/s/_blank" Ps设计游戏界面实例 本次的目标与要求 网游...
  • 游戏界面设计psd

    2013-02-05 11:31:40
    游戏界面设计psd,游戏的必须,难得的制作
  • 资源名称:创意UI Photoshop玩转游戏界面设计资源截图: 资源太大,传百度网盘了,链接在附件中,有需要的同学自取。
  • 火龙果软件工程技术中心 摘要:从计算机游戏界面的概念入手,阐述了游戏界面设计中交互性的概念、组成、作用及意义;通过人机界面的两个组成部分:软件界面和硬件界面,重点论述了游戏界面交互性设计的规律和原则,...
  • Android平台连连看游戏界面设计.pdf
  • 《创意UI Photoshop玩转游戏界面设计》由具有多年从业经验的专业设计师总结设计方法,筛选游戏UI设计中热门的游戏案例编写而成。全书分为5章,每章都包含丰富的游戏界面设计知识和设计制作的详细讲解。从“揭开游戏...
  • C++/QT 贪吃蛇小游戏 界面设计

    千次阅读 多人点赞 2020-03-22 10:05:28
    C++/QT 贪吃蛇小游戏 界面设计 前言:本文所写的贪吃蛇是笔者初学QT练手的小项目,做出来的界面较为粗糙。由于很久没有接触C++,程序中类封装的不是很规范。写这篇文章,权当是记录生活了,手动狗头。还有就是写的...

    C++/QT 贪吃蛇小游戏 界面设计

    前言:本文所写的贪吃蛇是笔者初学QT练手的小项目,做出来的界面较为粗糙。由于很久没有接触C++,程序中类封装的不是很规范。写这篇文章,权当是记录生活了,手动狗头。还有就是写的比较啰嗦,建议跳跃性阅读。文章末尾附代码文件下载链接

    概述:一张16格x16格地图,初始长度为2格,宽度为1格的Snake,地图中随机合法位置刷新食物;

    游戏规则:

    • 玩家使用上下左右(或者WSAD)控制Snake的前进方向;

    • Snake成功吃到食物后长度加1;

    • 吃到自己身体或撞到地图边界死亡;


    设计思路

    关于Size:地图为16格x16格,实际编程窗口中取:1格=30x30像素,即地图尺寸为480x480像素

    关于地图:使用QT绘制组件QPainter绘制480x480的浅灰色填充矩形

    定义MyWin类(继承QWidget基类),用于创建窗口以及按钮、标签、画布等子控件,包含以下变量及成员:

    • MyWin(),默认构造函数
    • ~Mywin(),默认析构函数
    • void paintEvent(QPaintEvent*),绘图事件重写
    • void keyPressEvent(QKeyEvent* event),键盘监听事件重写
    • QTimer* timer,定时器,核心部件,可以定时发出信号,完成程序界面刷新动作
    • Snake* m_snake,生成Snake类对象,即初始化一条蛇,根据对象的信息在地图中进行绘制
    • QLabel*,QPushButton*等子控件,用于界面功能设计

    定义Snake类,用于生成一条蛇,包含以下变量及成员:

    • Vector<Vector> snake_node变量,存储Snake身体结点;例如:[[2,2],[2,3],[3,3]…]

    • char direction变量,Snake当前方向,‘U’==Up,‘D’=Down,‘L’=Left,‘R’=Right

    • int head_x,head_y,蛇头坐标

    • int score,游戏得分,成功吃下一个食物,得分加 1

    • int snake_length,蛇身长度

    • moveSnake()函数,判断移动是否合法,并相应改变Snake的身体结点坐标,

    • Vector mapFlag(256,1),定义一个二维数组mapFlag,大小为16x16,与地图相对应。遍历数组,将Snake身体所处的结点标为 0,当蛇头移动至被标记为 0 的结点,即吃到自己身体,游戏结束。

      同时,将食物结点标为2,当蛇头移动至标为 2 的结点时,即吃到食物。

    定义Food类,用于生成食物,包含以下变量及成员:

    编写Food类,写到一半发现,Food类中变量成员太少了,单独开.h .cpp文件简直是可耻的浪费,于是干脆把变量成员都塞到Snake类里了,不建议这样写,因为不利于阅读以及后期维护(我就默默偷懒了)

    • int food_x,food_y,食物坐标
    • void newFood(),生成新的食物

    第一步 界面设计

    1. 创建顶级窗口:
      • 实例化继承于QWidget的MyWin类对象,生成一个800x600空窗口,标题设置为[贪吃蛇]
    2. 往顶级窗口中添加内容:
      • 重写绘画事件paintEvent,使用QPainter控件在顶级窗口中绘制480x480的浅灰色填充矩形,起点为(80,60),地图绘制完成。
      • 调用QLabel,QPushButton等控件,设置字体,控件位置,文本内容(按钮的点击响应事件暂时放一边,先设计好外观),完成以上步骤后界面如下

    第二步 蛇的绘制&食物的绘制

    1. 蛇的绘制:

      • 蛇身体的绘制,Snake类中变量vector<vector> snake_node存储的是蛇身体结点的坐标,数组初始化为[ [0,1], [1,1] ]。绘制第一个结点[0,1]时,要清楚地图尺寸为16x16格,1格为30像素

        要想绘制结点[0,1]即图中绿色部分,首先需要获得绿色区域左上角的坐标,根据映射关系可以得到,左上角横坐标 = 80 + 30 * 0;纵坐标 = 60 + 30 * 1;(80,60分别是顶级窗口左上角到地图左上角的横纵距离,计算时要代入),所以绿色区域左上角的像素坐标为(80, 90),使用以下语句即可填充此区域:

        painterSnakeBody.drawRoundedRect(80, 90, single_size, single_size, 10, 10)
        

        painterSnakeBody是绘画控件对象;drawRoundedRect是画圆角矩形函数;80,90为矩形左上角坐标;single_size为30,是每1格的像素长度;最后两个参数10表示矩形圆角的弯曲程度。

        遍历snake_node数组,并按上述步骤操作,即可画出蛇的所有身体。

      • 蛇头的绘制,绘制步骤相同,但蛇身结点使用黑色绘制,蛇头使用红色绘制

      • 蛇眼睛的绘制,眼睛的绘制区域与蛇头区域相同,不同的是眼睛的部位需要视情况而定,将头结点那格区域(30x30像素)放大如下:

        如图所示:1,2,3,4分别为眼睛可以放置的位置,当蛇向上移动时,即蛇头向上,眼睛的绘制区域应该为1,2;蛇头向右时,眼睛绘制区域为2,4;蛇头向下时,眼睛绘制区域为3,4;蛇头向左时,眼睛绘制区域为1,3;根据不同情况,在相应位置绘制直径为3的白色圆形,具体坐标的映射计算就不再赘述,代码如下:

        painterSnakeEye.drawEllipse(site_x, site_y, 6, 6);
        
    2. 食物的绘制:

      • 食物的绘制,与身体绘制方式一致,颜色选用绿色。完成以上步骤效果如下(蛇初始长度为2):

    第三步 地图刷新机制

    1. 创建定时器对象:

      定时器QTimer介绍:QT中的一个控件,初始化时调用timer->start( T )函数,T可以传入单位为毫秒的参数,比如1000,则定时器timer的功能就是每1000ms发出一个超时信号,不断循环这个操作,直到程序退出或对象调用stop()函数(笔者对定时器了解不深,这段概括可能不够严谨,具体事项请阅读QT官方说明文档)

      QTimer* timer = new QTimer(this);
      

      设置超时周期:

      timer->start(1000);
      
    2. 信号与槽

      • 将每次定时器发出的超时信号作为信号函数,以此触发槽函数。在槽函数中,即新的周期开始时,我们需要更新绘图事件,按照新周期当前snake_node结点坐标和食物坐标重新绘制蛇与食物,这样便可以达到蛇在移动的视觉效果;我们还需要更新界面上游戏得分标签子控件。

        (void)connect(timer, &QTimer::timeout, [=](){
        
        ​	update();
        
        ​    label_score_2->setText(QString::number(m_snake->score));
        
          });
        

        上述代码中,connect()函数功能是将信号与槽连接起来,在QT早期版本,connect不支持Lambda表达式的使用,所以传入参数形式如:connect(信号发出者,信号,信号接收者,槽);在新版QT中,加入了Lambda表达式的使用,所以connect的传入参数中可以直接编写槽函数,并且可以省略信号接收者参数。针对上述代码,我们逐句分析理解:

        • 参数timer是定时器,即信号发出者;
        • timeout表示超时信号,加上作用域QTimer,表示为定时器发出的超时信号,记得开头要加上取地址符,参数需要传入的是函数地址;
        • [=](){}是lambda表达式格式,[]是lambda引出符,编辑器会根据引出符来判断接下来的代码是否为lambda表达式,[]中传入的=符号表示值传递方式为捕捉父作用域的变量(说实话笔者不是太理解,改天花时间认真学习一下)
        • update()功能是再次调用绘图事件,重新绘画蛇及食物
        • label_score_2是界面上用来显示游戏得分的一个标签;setText()函数可以设置标签文本内容;QString::number可以将整型转换为QString类型,也就是QT中的字符串;m_snake是在窗口类MyWin下实例化Snake类的一个对象,即Snake *m_snake = new Snake;score是当前对象拥有的属性,即当前游戏得分;

        所以这段代码的意思就是:定时器发出超时信号,执行绘图事件,更新地图,游戏得分标签更新。

    3. 蛇的移动

      • 仅仅是每周期执行绘图事件,刷新地图是没有办法让蛇移动起来的。要知道,之前定义的snake_node数组中存放着蛇的全部结点坐标,绘图事件是根据snake_node数组来绘制蛇的,因此只有让snake_node数组发生变化并每周期绘制一次才能达到蛇移动的效果,因此可以理解移动蛇实际上是对snake_node数组进行操作。状态A移动至状态B后snake_node数组的变化,如下图所示:

        每次蛇的移动都可以看作为,snake_node数组删除第一对坐标[0,1],并添加新坐标[2,1],代码如下:

        snake_node.erase(snake_node.begin());
        snake_node.push_back([2,1]);
        

        .erase()函数功能即删除数组成员,.begin()是返回数组第一位成员的迭代器,组合起来便是删除第一队结点坐标[0,1];

        .push_bakc()是向数组最后添加一位成员;实际上push_back()不支持上述表达式中的语法,这样写是为了更加容易理解,编程时需要先定义一个一维数组temp_node,将2,1塞进一维数组后,再执行push_back(temp_node)将[2,1]添加进去,代码如下:

        vector<int> temp_node = { 2,1 };
        snake_node.push_back(temp_node);
        

        每周期开始时执行这样的数组操作,再调用绘图事件绘制,刷新地图和标签,实现效果如下:

    第四步 键盘控制移动

    1. 加入键盘监听事件

      • 为了实现程序运行过程中能够实时循环接收键盘输入的内容,我们重写QT键盘监听事件,先在窗口类MyWin中声明,再在类外实现,键盘事件实现代码如下:

        void MyWin::keyPressEvent(QKeyEvent* event)
        {
          switch (event->key())
          {
          // 键盘的方向键'上'或大小写'w/W'
          case Qt::Key_Up:
          case 'w':
          case 'W':
          if (m_snake->direction == 'D') break;
          m_snake->direction = 'U';
          break;
            
          // 键盘的方向键'下'或大小写's/S'
          case Qt::Key_Down:
          case 's':
          case 'S':
          if (m_snake->direction == 'U') break;
          m_snake->direction = 'D';
          break;
            
          // ······省略左右操作
            
          default:
          break;
          }
        }
        

        上述代码中,void MyWin::keyPressEvent(QKeyEvent* event)即键盘事件函数的实现,注意在keyPressEvent前要加上作用域MyWin;

        event->key()即键盘监听事件程序从键盘获取的内容,比如我们按下键盘上的字母’T’,那么event->key()的值就是’T’(至于函数这个实时不断获取功能是怎样实现的,笔者也是比较好奇,有机会可以学习一下)。

        综上,当我们在键盘上按下了字母’W’,即希望蛇向上移动,代码进入Switch第一段分支语句,这里我们需要做个判断,如果当前蛇的方向是向下的(Down),那么我们执行向上操作显然是非法的(总不能让蛇原地转头吧),因此操作非法时,直接break,退出这一次键盘监听程序,忽略本次操作;若合法,将对象m_snake的方向赋值为上’U’(Up),然后退出这一次键盘监听程序。m_snake->direction即对象m_snake拥有的属性direction,direction的值即当前蛇的朝向。

        我们总共需要4段分支语句,分别判断输入的上下左右,这里代码比较长,且逻辑重复性高,就不贴出来了,只贴了上下判断的分支语句。

    2. 控制蛇的移动

      • 现在我们已经可以接收键盘输入的内容,要做的就是编写移动函数moveSnake(),实现根据键盘输入的内容而为snake_node数组添加相应的结点,函数实现如下:

        int Snake::moveSnake()
        {
          // 根据方向移动蛇头
          if (direction == 'U') head_y--;
          else if (direction == 'D') head_y++;
          else if (direction == 'L') head_x--;
          else head_x++;
        
          // 若移动不合法,吃到自己或撞墙
          int head_site = 16 * head_y + head_x;
          if(head_x < 0 || head_x>15 || head_y < 0 || head_y>15 || mapFlag[head_site]==0) 	{
            return 0;
          }
        
          // 将蛇尾对应标志地图置为1,蛇头置为0
          int temp_site = snake_node[0][1] * 16 + snake_node[0][0];
          mapFlag[temp_site] = 1;
          mapFlag[head_site] = 0;
        
          // 将蛇头加入数组,并删除蛇尾
          vector<int> temp_node = { head_x,head_y };
          snake_node.push_back(temp_node);
          snake_node.erase(snake_node.begin());
          return 1;
        }
        

        上述代码第一段,根据当前蛇的朝向来改变头结点的坐标,示例如下:

        若当前头结点坐标为[3, 3],且蛇当前朝向上边,所以下一周期头结点的位置即为[3, 3 - 1];

        若当前头结点坐标为[3, 3],且蛇当前朝向下边,所以下一周期头结点的位置即为[3, 3 + 1];

        以此类推,可以得到蛇头下一周期的坐标。

        代码第二段,如果第一段计算出的坐标超出了16x16,或者在标志地图上对应的标志为0(表示该坐标处有蛇的身体),就说明蛇撞到了墙或者吃到了自己,直接返回0,表示蛇已经死亡。

        代码第三段,将蛇尾的区域对应的标志地图赋值为1,表明该区域已经没有蛇身体了,已经是空白区域了;再将蛇头即将进入的区域赋值为0,表示蛇已经进入该区域了;

        代码第四段,即snake_node数组操作,删除第一位,数组末尾添加一位,并返回1,表示移动成功;

        至此,我们就实现了控制蛇移动的功能,效果如下:

    第五步 食物生成&吃掉食物

    食物的生成相对较于简单,只需要注意几点:1)食物的生成应当是随机的;2)一次只能生成一颗食物,在已有食物被吃掉之前不能触发生成函数;3)食物需要生成在地图中合法位置,不允许生成在蛇的身体上。

    1. 随机生成机制

      • 一开始的想法很简单,地图是16格x16格,所以先在[0, 15]区间内取个随机数当作 X,再次取个数当作 Y,这样不就有了一个随机坐标,当作食物坐标就行了。如果随机取的坐标不合法,就舍去重新再随机一个。写到一半突然想起来,这样的效率太低了,到最后蛇的身体快占满地图的时候,这时想要随机取出一个合法的坐标,概率太低了。所以想了想换成了下面的生成机制。

        地图16x16总共256格合法位置可以生成食物,当地图中有了蛇的身体,合法区域会随之减少,例如现在蛇的长度为50格长,那么还剩下206格合法位置可以刷新食物,因此在[0, 205]区间内随机取值,无论随机数是多少,必然得到的都是一块合法的区域

    2. 食物生成代码

      void Snake::newFood()
      {
        // 食物随机刷新机制如下:
        // 标志地图为256大小的数组,地图中空白区域对应数组中的标志为0,蛇身区域为1,食物为2
        // 每次将数组大小256减去蛇身长度,得到余留空白区域的大小,以此大小为范围取随机数
        // 例如蛇身长度为250,说明余留空白区域大小为6,随机数只需在[0,5]范围内取值即可
        // 例如随机数取值为4,遍历标志地图数组,找到第4个空白区域,并刷新食物
        srand((unsigned)time(NULL));
        int site_food = rand() % (256 - snake_length);
        int i = 0;
        for (; i < 256; i++) {
          if (mapFlag[i] == 1) {
            site_food--;
            if (site_food == -1) break;
          }
        }
        food_x = i % 16;
        food_y = i / 16;
        mapFlag[i] = 2;
      }
      

      找到合法位置后,将该位置对应的标志地图赋值为2,表示该位置是食物;并对食物的坐标进行修改。

    3. 吃掉食物

      • 与移动到空白区域不同,蛇头移动到食物区域时,对蛇的moveSnake()函数要进行部分修改。当蛇吃到食物时,进行以下操作:

        • 蛇的长度snake_length加 1;
        • 游戏得分score加 1;
        • 在snake_node数组末尾加上下一组坐标,但并不需要删除数组的第一组坐标,因为蛇吃完食物后身体长度加 1,实际尾巴并没有发生移动;
      • 在moveSnake()函数中增加以下代码:

        // 若遇见食物,进行吃食物操作
          if (mapFlag[head_site] == 2) {
            mapFlag[head_site] = 0;
            vector<int> temp_node = { head_x,head_y };
            snake_node.push_back(temp_node);
            snake_length++;
            score++;
            return 2;
          }
        

        返回值为 2,表示这次移动吃到了食物,告诉对象m_snake调用生成新食物函数newFood();

        实现以上功能,效果如下:

    拓展1 调节速度机制

    至此,贪吃蛇简单的核心功能已经全部完成,剩下的就是些修修补补的工作。

    实现贪吃蛇速度调节功能,其实很简单,之前我们定义的定时器使用函数timer->start(T)时,传入的参数是T=1000,即1000ms刷新一次,如果我们将T改为500,即1s内刷新两次,也就是蛇1s内移动两格,速度就是之前的两倍。因此要想实现多级速度调节,我们只需要将 ( T ) 改为 ( 1000 / game_speed ),game_speed数据类型为整形,取值为[ 1, 2, 4 ,8 ],因此现在传入的参数可以是[ 1000, 500, 250, 125 ],对应着四种速度。

    再设计两个按钮,分别对应着 ’ - ’ 和 ’ + ’ ;按下减速按钮时,将game_speed的值翻倍,并重新调用start()函数,当按下加速按钮时,将game_speed的值除2,并调用start()函数;对应减速按钮的点击事件代码如下:

    // 按钮事件:减速按钮
      (void)connect(button_speed_sub, &QPushButton::clicked, [=]() {
        if (game_speed > 1)
        {
          game_speed = game_speed / 2;
          // 显示当前速度的标签
          label_cur_speed_2->setText("x" + QString::number(game_speed));
          
          timer->start(1000 / game_speed);
        }
        });
    

    我这里设置的game_speed的最小值为1,最大值为8,所以会有上下限的判断;当然也有其他很多思路,比如给T设定一个初始值,每次按下加速按钮时,T就加上200;每次按下加速按钮时,T就减去200(注意判断小于0);

    效果展示:

    拓展2 游戏暂停

    相同的,实现暂停游戏也很简单。用到定时器中的一个函数timer->stop(),即定时器停止函数;

    这边的逻辑部分需要注意一下,当按下”暂停游戏“按钮时,游戏暂停,并且”暂停游戏“字样应当改为”继续游戏“;相反,当按钮”继续游戏“时,字样也应当发生改变;要实现单个按钮状态的切换,我在网上没有找到好的方法,智能曲线救国,在程序中加了个标志位:

    // 0:表示游戏正在运行 1: 表示游戏正在暂停
    	int pause_flag;
    

    因此,暂停按钮的点击事件部分可以这样写:

      // 游戏暂停按钮响应事件
      (void)connect(button_game_pause, &QPushButton::clicked, [=]() {
        // 根据暂停标志得知当前游戏状态
        // 从而切换该按钮的状态
        switch (pause_flag)
        {
        case 0:
          timer->stop();
          pause_flag = 1;
          button_game_pause->setText(QString::fromLocal8Bit("继续游戏"));
          break;
          
        case 1:
          timer->start(1000 / game_speed);
          pause_flag = 0;
          button_game_pause->setText(QString::fromLocal8Bit("暂停游戏"));
          break;
          
        default:
          break;
        }   
        });
    

    效果展示:

    拓展3 重新开始

    在原窗口实现重新开始功能的思路如下:

    1. 重新实例化一个对象,即m_snake = new Snake;
    2. 初始化各项变量,例如游戏速度,暂停标志,游戏得分标签等等

    实现代码如下:

      // 重新开始按钮响应事件
      (void)connect(button_restart, &QPushButton::clicked, [=]() {
        // 重新实例化
        m_snake = new Snake;
        game_speed = 1;
        pause_flag = 0;
        
    	// 速度标签重置
        label_cur_speed_2->setText("x" + QString::number(game_speed));
        // 得分标签重置
        label_score_2->setText(QString::number(m_snake->score));
        // 暂停标志重置
        pause_flag = 0;
        // 将暂停按钮重置
        button_game_pause->setText(QString::fromLocal8Bit("暂停游戏"));
        // 重新绘制
        update();
        // 启用定时器
        timer->start(1000 / game_speed);
        });
    

    效果展示:

    拓展4 非法输入过滤

    在调试程序的时候,发现了一个非常有趣的问题,如下:

    不知道大家有没有看清楚蛇是怎么死的,它原地掉头把自己咬到了(可以看到蛇死的时候,眼睛是向左边的)。当时出现这个bug的时候很懵逼,明明写了程序判断,当蛇朝向右边时,向左移动是非法操作,是不执行任何操作的,那为什么会出现这个问题呢?

    其实,在那个周期内,我迅速的按了 ’ W ’ ,’ A ’ 两个键,即先向上再向左;这时程序先判断,发现向上移动合法,于是将蛇的方向改为了向上 ’ U ',还没等到下一周期,蛇头还未发生移动(蛇每周期移动一格),这时程序又接收到了向左的操作,因为当前方向已经改成了向上,所以此时向左也是合法操作,于是又将蛇的朝向改为了向左,等于在一周期内发生了两次转向操作,并且都是合法的,于是到了下一周期,执行moveSnake函数的时候,蛇头直接咬到了自己。

    问题的缘由弄清楚,那么怎么避免单周期内多次操作呢?

    我的做法是:为每个周期加个标志,即定义int step_count = 1;比如定时器第一次循环的时候,step_count的值为 1,可以认为当前周期叫做 ’ 1 ’ 周期,第二次循环的时候,step_count的值加 1,所以第二周期可以叫做 ’ 2 ’ 周期,以此类推,每周期开始时将step_count的值加 1,表示为该周期的标识;

    再添加一个标志位step_key_input,当键盘输入时,将当前周期的标识赋值给step_key_input,下次键盘输入时,判断step_key_input是否等于step_count,如果等于说明在这个周期内,已经有过一个合法输入了,本次操作不执行。

    举个例子:就类似上面出错的情景,在定时器循环的第3个周期,step_count = 3,蛇朝向左边,这时我们输入向上操作,于是step_key_input = 3,当前朝向被修改为向上;紧接着,我们又输入了向左操作,由于此时的step_count = step_key_input = 3,所以本次向左操作被视为非法操作,故不执行。在当前周期内,只允许1个合法操作,这样就可以避免上述bug的发生。

    关于这个问题,肯定有很多不同的解决思路,上述方法只能说是解决问题,算不上是最优方案,还是要多思考,多学习。最后附一张菜鸡截图:

    附代码文件:

    笔者环境是VS2019社区版+QT5(注意:QT4可能不兼容,特别是connecct函数那部分),与在QT中直接编译可能会有些不同,代码应该是没有问题的;建议无论是使用VS还是QT,先创建QT界面项目,然后用下面的文件将项目中的替换掉,否则可能无法运行。

    C++/QT 贪吃蛇简陋小游戏
    百度网盘链接(提取码:aciq)

    展开全文
  • 使用相对布局 实现猜拳游戏界面设计
  • 风暴英雄游戏UI分析/game/259/36133259.shtml游戏背景/game/259/36133259.shtml风暴/game/259/36133259.shtml英雄/game/259/36133259
  • 格式塔心理学下的手机游戏界面设计 摘要格式塔心理学是研究视知觉的理论而在手机游戏界面设计中视觉占据主导地位文章对格式塔心理学的相关文献进行分析和整理依据其相关原理与法则并对几款优秀的手机游戏界面设计...
  • 游戏界面设计是对与游戏用户具有交互功能的视觉元素进行规划设计的活动. 目前存在一些应用框架对游 戏界面进行设计的技术, 但它们都存在着与三维游戏场景接口不一致、设计复杂、不易扩展和维护等缺陷. 因此, 提 出了...
  • 游戏界面设计GUI

    千次阅读 2019-11-04 13:15:19
    区别 NGUI:Unity的插件,由外部公司...GUI是指那些显示在屏幕上给予用户提示的界面,这些界面不会与游戏内容产生互动或者影响。 GUI用的是屏幕坐标系,都是2D效果。 主要API 所有代码都要写在OnGUI()方...

    区别

    1. NGUI:Unity的插件,由外部公司开发的。(因开发人员离开Unity,继续开发NGUI,所以NGUI现在仍在更新)
    2. UGUI:Unity吸收NGUI的开发公司,为Unity新增原生的UGUI。

    什么是GUI

    1. GUI是指那些显示在屏幕上给予用户提示的界面,这些界面不会与游戏内容产生互动或者影响。
    2. GUI用的是屏幕坐标系,都是2D效果。

    主要API

    1. 所有代码都要写在OnGUI()方法中。在界面变动时每帧都会进行一次擦除、一次重绘。
    2. 流式布局:GUILayout.xxx(自左向右、自上向下顺序排列布局)
    3. 块布局:GUI.xxx(固定在某个位置)
    4. 文本框:GUILayout.TextField(文本框内容, GUI布局的规格参数);(返回值为当前文本框的内容)
    5. 按钮:GUILayout.Button(文本框内容, GUI布局的规格参数);(默认值为false,点击后返回值为true)
    6. 世界坐标转化为屏幕坐标:Camera.main.WorldToScreenPoint(世界坐标位置);
    7. GUI绘制图形:GUI.DrawTexture(new Rect(图形x坐标,图形y坐标,图形宽度,图形高度),图形对象);

    GUI文本框 源码

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class GUITest : MonoBehaviour
    {
        //设置变量,用于存储文本框内容
        string s1,s2 ;
        int i;
        private void Start()
        {
            s1 = "click";
            s2 = "";
            i = 0;
        }
        //调用GUI方法,每帧都会进行一次擦除、一次重绘
        private void OnGUI()
        {
            //s = GUILayout.TextField(s, GUILayout.Width(100));
            //print(s);
    
            //判断按钮是否激活,松开时返回true,其他状态返回false
            if (GUILayout.Button(s1, GUILayout.Width(100)))
            {
                i++;
                s2 = "click-" + i;
            }
            //流布局绘制文本框
            GUILayout.TextField(s2, GUILayout.Width(100));
        }
    }
    

    GUI血条效果 源码

    在unity中上传血条图片
    在这里插入图片描述

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class GUIHealth : MonoBehaviour
    {
        //定义图片对象,在unity上传图片
        public Texture2D health;
        private float speed;
        private Vector3 headPos;
        // Start is called before the first frame update
        void Start()
        {
            speed = 5;
        }
    
        // Update is called once per frame
        void Update()
        {
            //物体按键移动
            transform.Translate(Vector3.right * Time.deltaTime * speed * Input.GetAxisRaw("Horizontal"));
            transform.Translate(Vector3.forward * Time.deltaTime * speed * Input.GetAxisRaw("Vertical"));
    
            //获取物体头顶的位置
            //将世界坐标系转到屏幕坐标系
            headPos = Camera.main.WorldToScreenPoint(transform.position + Vector3.up*1.5f);
        }
    
        private void OnGUI()
        {
            //GUI绘制血条图形
            GUI.DrawTexture(new Rect(headPos.x-64, Screen.height - headPos.y, 128,8), health);
        }
    }
    

    在这里插入图片描述

    展开全文
  • 游戏界面设计的原则

    千次阅读 2011-11-14 23:14:38
    游戏界面是什么呢?对于这个问题,也许一百个人能有一百个答案,对于我而言,如果把游戏整体比喻为一个人,那么程序部分则是筋骨、美术资源自然就是肌肤、而游戏性则是这个人的气质。而我们谈论的游戏界面自然是容貌...

    游戏界面是什么呢?对于这个问题,也许一百个人能有一百个答案,对于我而言,如果把游戏整体比喻为一个人,那么程序部分则是筋骨、美术资源自然就是肌肤、而游戏性则是这个人的气质。而我们谈论的游戏界面自然是容貌了。
        在茫茫人海中,有些人我们只一眼就能留下深刻的印象,甚至多年后也难以忘怀,为什么呢?很大程度则就是容貌导致的。无论是美貌,还是恶容,都会让人留下深刻的印象,甚至是难以忘却的永久性记忆。同样的,游戏的界面也具有这个意义。
        从玩家第一次启动游戏,由登陆界面,再到游戏界面,短短数分钟很难让其对游戏本身的优劣进行评定,但却足以给玩家留下第一印象。这个第一印象在很大程度上会影响玩家对游戏的其它评定。
        世上没有绝对的公平,所以当玩家对一款游戏进行评定的时候,或多或少都受了第一印象的影响。若他一开始对界面产生了好感,对界面的布局产生了共鸣,那么在其后的其它项评定后,他的内心就会趋向认同,即便是后来发现了一些游戏的缺陷,也会被淡化,对游戏的评定会缓慢的由认同转变为否定,若期间发现了游戏的闪光点,则会得出最终的认同评定;反之,若一开始的界面让玩家感觉到不适,其后的操作也感到厌恶,那么在他的内心会对游戏首先趋向否定,即便是其后发现了游戏中很多闪光的地方,也会由否定慢慢转变为认同,若期间发现了游戏的其它缺点则直接否定掉整款游戏。可见,游戏的界面对玩家的影响是何其深远!
        但遗憾的是,目前国内很少有研发公司重视这个方面:在很多时候,界面设计被忽略。平庸化,同质化,这就是为什么有些游戏花费了N年研发,但刚上市没多久,就被玩家迅速抛弃的原因。同样的,有些游戏仅花费几个月时间抄袭的,但由于在界面设计上相对出彩,意外的获得了巨大的成功。这样的例子很多,大家有心可以留意下。当很多研发者满腹委屈,高喊理解万岁的时候,他们却从来没认真想过问题的核心在哪里?玩家为什么在还没了解游戏时就集体投了否定票?甚至把一切责任归咎于无辜的万千玩家:认为之所以会这样,是大部分玩家素质过低造成的。


    一、 界面设计的原则

    1. 直观:尽量少用图标多用文字,图标用得越多界面设计越难令玩家理解。
    2. 通俗:用词要大众化,令玩家容易接受,不用生僻词,以及专业术语。
    3. 按钮图标:按钮设计要有凸出感,醒目一些,让玩家易接受
    4. 显示优先:显示的层次要清楚

    (1) 生命,魔法,以及一些常用功能
    (2) 常用操作(重要操作),如吃物品的快捷键,技能施放等。
    (3) 空间优先(有限的空间放入更多功能)
    (4) 符合玩家的一般习惯(WIN的习惯,WORD的习惯等)

    5. 可扩充性:网络游戏需要不断添加新功能等等,对界面的需求会不断增加。需要预先考虑好扩充性
    6. 游戏种类:游戏的性质对界面的要求

    (1) 回合制:全屏界面对游戏影响不是很大
    (2) 即时制:尽量不出现全屏界面,能透明的要透明,减少对屏幕的影响

    心得:设计界面的时候要考虑资源的通用性,能统一规格(大小)的界面最好统一它,制作的时候会省好多事,不容易出错。

    二、 界面文档一般格式

    界面设计需要交给美术,程序去实现,以下是一般的实现方式

    美术部分
    1. 界面示意图:告诉他界面该如何布局,常用表达方式实心框,虚线框,双线框,黑线框分别代表按钮的不同形式以及不同显示方式。这些需要在后面标明
    2. 如何确定界面大小:用原图做(示意),根据功能的位置放置。考虑到以后的影响(如聊天遮挡按钮,等等类似问题)
    3. 特别注意:需要考虑到游戏设计对游戏的影响,如人名输入框的大小一定要大于最大人名数量,负责就出现冒行等问题。
    4. 按钮及状态

    (1) 替换显示:帮派入帮、不入帮与帮主的不同显示界面
    (2) 发亮显示:有新消息界面就闪光来提示玩家
    (3) 界面转换:好友与仇人名单的界面转换。

    程序部分
    1. 显示内容:需要说明,确认大小以后标示明白
    2. 触发条件:NPC对话,点选物品,点按钮等
    3. 界面关闭:关闭的条件(被攻击,自己点选等等)
    4. 注:界面、按钮的功能(弹出新界面后是重叠显示还是关闭老界面来显示);界面的操作以及相关的提示(升级、成功是否提示等),其中的成功的提示做还是不做这个很重要(关乎玩家的心理,需要从实践中找感觉)
    5. 另:有快捷键的话,需要标明快捷键

    界面设计意图中的方方面面的东西需要程序容易实现。

    各种设计的小细节方面:
    《征服》的聊天模式转换方面,目前的现状是根据设计需要(符合以上要点)以及界面的总体布局造成的。

    讨论:
    做界面以前先考虑一下游戏的风格,按钮的用字,显示位置一定要大,明了。

    首先将游戏功能分类清楚,然后再做界面。尽量考虑资源的通用性。
    将一些功能性界面放NPC身上,主界面尽量简练,精致

    展开全文
  • 简单的游戏界面设计

    千次阅读 2015-02-13 22:43:02
    先看效果 自己做那还是游戏啊 失败失败 自己只有一点点图片 图片多可以自己去替换下面的文件夹中的图片 主要的代码 using UnityEngine; using System.Collections; public class AA : MonoBehaviour { // Use ...

    先看效果 自己做那还是游戏啊 失败失败
    这里写图片描述

    自己只有一点点图片 图片多可以自己去替换下面的文件夹中的图片
    这里写图片描述

    主要的代码
    using UnityEngine;
    using System.Collections;
    public class AA : MonoBehaviour {
        // Use this for initialization
        private Texture2D bg;
        private Texture2D title;
        private Object[] tex;
        private int x,y,nowFran,mFramCount;
        private float fps=5;
        private float time=0;
        void Start () {
    
            bg=(Texture2D)Resources.Load("bg/0");
            title=(Texture2D)Resources.Load("title/0");
            tex=Resources.LoadAll("tex");
            x=Screen.width;
            y=200;
        }
    
        // Update is called once per frame
        void OnGUI () {
            GUI.DrawTexture(new Rect(0,0,Screen.width,Screen.height),bg);
            GUI.DrawTexture(new Rect(Screen.width-title.width>>1,30,title.width,title.height),title);
            DrawAnimation(tex,new Rect(x,y,40,60));
            x--;
            if(x<-42){
                x=Screen.width;
            }
            GUI.Button(new Rect(330,300,100,30),"StartGame");
            GUI.Button(new Rect(330,340,100,30),"Load");
            GUI.Button(new Rect(330,380,100,30),"About");
            GUI.Button(new Rect(330,420,100,30),"Exit");
        }
        void DrawAnimation(Object[] tex,Rect rect){
            GUI.DrawTexture(rect,(Texture2D)tex[nowFran]);
            time+=Time.deltaTime;
            if(time>1/fps){
                nowFran++;
                time=0;
                if(nowFran>=tex.Length){
                    nowFran=0;
                }
            }
        }
    }
    展开全文
  • 游戏界面设计,代码正在完善,JS没有效果
  • 一款游戏中心App UI界面设计 sketch素材下载 App Store UI界面设计、app ui 设计、sketch、UI APP、ui界面设计、游戏列表、游戏界面设计
  • 游戏界面交互设计.ppt

    2020-10-31 00:26:08
    游戏界面交互设计.ppt
  • 我发现界面设计是创造游戏最困难的阶段之一。如今市面上充斥着各种不同的屏幕,而在这些较小的屏幕空间里,设计师更是需要谨慎思考每个屏幕的像素问题。最近,我们重新设计了一款即将发行的游戏的整个界面——因为...
  • 游戏app ui界面设计 .xd素材下载 app ui界面、ui界面设计、xd、游戏app ui
  • 学习情景2 手机游戏迷失森林设计和开发;学习任务1;学习单元一 手机游戏设计;手机游戏特征;传统手机存在以下弊端 ;...学习单元二 游戏界面设计 ;建立应用程序 ;Canvas类;Graphics类 ;坐标设置 ;颜色设置
  • 【C语言】游戏菜单界面设计游戏整合

    千次阅读 多人点赞 2020-04-22 15:53:23
    游戏菜单界面设计游戏整合 旧文档 2019.11 小时候一直觉得4399小游戏的那些游戏菜单好low,现在做完我的菜单界面回去去看看感觉还不错。。。 菜单制作过程 完整代码 https://paste.ubuntu.com/p/HZBWXMWT8K/ ...
  • 游戏工具界面的开发一般采用MFC或自己封装的API函数库的方式。但自己封装的API的难度比较大,所以一般在游戏工具界面开发的时候采用MFC,由于MFC是已经封装起来的一套完整的基础库,所以使用很方便且灵活。
  • [UI参考]_游戏界面UI设计素材

    热门讨论 2011-10-20 16:12:55
    UI设计 [UI参考]_游戏界面UI设计素材 [UI参考]_游戏界面UI设计素材 [UI参考]_游戏界面UI设计素材
  • 游戏app 用户界面ui设计 .psd素材下载 PSD、ui界面设计游戏app设计、用户界面
  • 简单的C++游戏载入界面设计-附件资源
  • 深色风格游戏平台网页界面设计 .xd素材下载 xd、游戏网页模板、网页模板、网页界面模板
  • iOS游戏社区的未来主义界面设计.psd素材下载 ios app design、PSD、地图导航界面、界面设计

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 117,924
精华内容 47,169
关键字:

游戏界面设计