使用Qt动画框架设计角色的二维动画

使用Qt动画框架设计角色的二维动画

Qt的动画框架是Qt4.6新添加的一个重要的特性,有了它,开发人员可以制作激动人心的动画界面,而不必局限于单调的固定窗口了,可以说,Qt动画框架是其它界面库少见的功能,它带来的是Qt的一大优势。最近我花了大概三、四天的时间研究Qt动画框架的内容,这让我感到Qt人员精心的设计给了我们一套非常规范并且易懂的代码,如果另外的一名开发者也对Qt动画框架有所了解,那么他可以毫不费力地看懂我的代码,并且从代码中了解设计思想。

演示程序的下载地址:这里

源代码的下载地址:这里

下面是程序的截图:



这里我使用了大家非常熟知的初音ミク来演示,我们可以通过【w】【s】【a】【d】键控制它的行动,不过呢,这个程序还是有一些小问题的,以后有时间再来改进。

该如何介绍呢?首先为了了解角色动画是如何进行的,还是了解一下Qt状态机框架。这里是英文的介绍,而这里呢,是英文介绍的翻译。

在初步了解Qt状态框架之后,我介绍一下最简单的二维动画:行走动画。其实演示程序所用的是初音ミク的行走图:如下图所示:


我们应用Qt的图形 – 视图框架(Graphics – View Framework)来绘制二维图形,这很简单。在成功之后我就想,如何才能让初音ミク动起来呢?在多天的尝试和失败后,我绘制了一个有限状态图。


在这个图中,站立和行走是状态机中的两个状态,它们之间可以相互转换。这样的转换通过按键的响应来完成。在Qt中有一个专门负责按键响应并且用于状态之间转换的类:QKeyEventTransition。它通过绑定一个QWidget来获取它的按键事件,并且一旦满足相应的按键条件就开始进行状态之间的转换。所以角色的行走动画可以这样制作:首先角色处于站立状态,当它捕获到了上下左右键,一个 QkeyEventTransition的对象指针负责将其转换成行走状态。转换附带了两个动画,一个是角色的帧动画,也就是初音ミク的一帧一帧的运动,另一个是角色的位置动画,让角色的位置发生变化。不可能让我们的ミク原地踏步吧!转换完毕后角色实际上进入了行走的状态,通过设定另外一个QAbstractTransition的指针来让角色从行走状态迅速地回到站立状态,这样就可以等待下一次按键的响应。

在我的实现中,让Character类来实现这样的功能,它是GameObject的子类,而GameObject类则是所有游戏对象的基类。一般来说角色(Character)基本上都有行走的功能,而同属于GameObject的其它物体则没有,比如说树木。

下面是Character.h的内容:

#ifndef CHARACTER_H
#define CHARACTER_H
#include <QRect>
#include <QKeyEventTransition>
#include <QPropertyAnimation>
#include <QWidget>
#include "GameObject.h"
/*---------------------------------------------------------------------------*/
class Character: public GameObject
{Q_OBJECTQ_PROPERTY( QRect FrameRect READ FrameRect WRITE setFrameRect )
public:explicit Character( const QString& fileName, GameObject* parent,QWidget* pWidget = 0 );// QGraphicsItem必须实现的函数QRectF boundingRect( void ) const;void paint( QPainter* pPainter, const QStyleOptionGraphicsItem* pOption,QWidget* pWidget = 0 );// 子类需要实现的函数virtual void Init( void );
public slots:void SlotSetDirection( void );
protected:// 枚举enum Direction// 即控制的按键{_Up_            = Qt::Key_W,_Down_          = Qt::Key_S,_Left_          = Qt::Key_A,_Right_         = Qt::Key_D};// 本类的函数void SetDirection( int dir );void SetFrameAnimation( int dir );void SetPosAnimation( int dir );// 本类的成员以及读/写函数DECLRARE_PROPERTY_WITH_GETTERS_AND_SETTERS( QRect, FrameRect )DECLRARE_PROPERTY_WITH_GETTERS_AND_SETTERS( int, AnimateTime )QState                     *m_pStandState, *m_pWalkState;QPropertyAnimation*         m_pPA;QPropertyAnimation*         m_pFPA[4];QWidget*                    m_pWidget;
};
/*---------------------------------------------------------------------------*/
#endif // CHARACTER_H

下面是Character.cpp的内容:

#include <QDebug>
#include <QPoint>
#include <QPainter>
#include <QEasingCurve>
#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <QParallelAnimationGroup>
#include "Character.h"
/*---------------------------------------------------------------------------*/
Character::Character( const QString& fileName, GameObject* parent,QWidget* pWidget ): GameObject( parent )
{m_AnimateTime = 1000;// 即1秒m_pWidget = pWidget;m_Image.load( fileName );       // 载入图片m_FrameRect.setRect( 0, 0, m_Image.width( ) / 4, m_Image.height( ) / 4 );SetDirection( _Right_ );        // 朝向右Init( );
}
/*---------------------------------------------------------------------------*/
void Character::paint( QPainter* pPainter, const QStyleOptionGraphicsItem* pOption,QWidget* pWidget )
{pPainter->drawPixmap( QPoint( 0, -16 ), m_Image, m_FrameRect );GameObject::paint( pPainter, pOption, pWidget );
}
/*---------------------------------------------------------------------------*/
QRectF Character::boundingRect( void ) const
{return QRect( 0, -16, 32, 48 );// 没有其它特殊的效果将返回帧框
}
/*---------------------------------------------------------------------------*/
void Character::SetDirection( int dir )
{int rectY = 2;switch ( dir ){case _Up_: rectY = 3; break;case _Down_: rectY = 0; break;case _Left_: rectY = 1; break;case _Right_: rectY = 2; break;}m_FrameRect = QRect( m_FrameRect.x( ),rectY * m_Image.height( ) / 4,m_FrameRect.width( ),m_FrameRect.height( ) );
}
/*---------------------------------------------------------------------------*/
static qreal OneEasingFunction( qreal progress )
{Q_UNUSED( progress )return 1.0;
}
/*---------------------------------------------------------------------------*/
void Character::SetFrameAnimation( int dir )
{int rectY = 2;switch ( dir ){case _Up_: rectY = 3; break;case _Down_: rectY = 0; break;case _Left_: rectY = 1; break;case _Right_: rectY = 2; break;}QRect rect[4];QEasingCurve curve( QEasingCurve::Custom );curve.setCustomType( OneEasingFunction );for ( int i = 0; i < 4; ++i ){rect[i] = QRect( m_FrameRect.width( ) * i, rectY * m_Image.height( ) / 4,m_FrameRect.width( ), m_FrameRect.height( ) );}for ( int i = 0; i < 4; ++i ){m_pFPA[i]->setStartValue( rect[i] );m_pFPA[i]->setEndValue( rect[( i + 1 ) % 4] );m_pFPA[i]->setEasingCurve( curve );m_pFPA[i]->setDuration( m_AnimateTime / 4 );}
}
/*---------------------------------------------------------------------------*/
void Character::SetPosAnimation( int dir )// 设定位置动画
{QPointF point = pos( ), deltaPt;switch ( dir ){case _Up_:deltaPt = QPointF( 0.0, -32.0 ); break;case _Down_:deltaPt = QPointF( 0.0, 32.0 ); break;case _Left_:deltaPt = QPointF( -32.0, 0.0 ); break;case _Right_:deltaPt = QPointF( 32.0, 0.0 ); break;}m_pPA->setStartValue( point );point += deltaPt;m_pPA->setEndValue( point );
}
/*---------------------------------------------------------------------------*/
void Character::SlotSetDirection( void )
{QKeyEventTransition* eventTrans =qobject_cast<QKeyEventTransition*>( sender( ) );SetDirection( eventTrans->key( ) );SetFrameAnimation( eventTrans->key( ) );SetPosAnimation( eventTrans->key( ) );
}
/*---------------------------------------------------------------------------*/
void Character::Init( void )
{// 初始化站和走的状态m_pStandState = new QState( &m_Machine );m_pWalkState = new QState( &m_Machine );// 初始化和设定帧动画QSequentialAnimationGroup* pFSAG = new QSequentialAnimationGroup( this );for ( int i = 0; i < 4; ++i ){m_pFPA[i] = new QPropertyAnimation( this, "FrameRect", this );pFSAG->addAnimation( m_pFPA[i] );}// 初始化和设定位置动画m_pPA = new QPropertyAnimation( this, "pos", this );m_pPA->setDuration( m_AnimateTime );// 设定一个并发的动画组,同时调用这两个动画QParallelAnimationGroup* pPAG = new QParallelAnimationGroup( this );pPAG->addAnimation( pFSAG );pPAG->addAnimation( m_pPA );QKeyEventTransition* pKeyPressTrans[4];QKeyEventTransition* pKeyReleaseTrans[4];int keys[4] = { _Up_, _Down_, _Left_, _Right_ };for ( int i = 0; i < 4; ++i ){pKeyPressTrans[i] = new QKeyEventTransition( m_pWidget,QEvent::KeyPress,keys[i],m_pStandState );pKeyPressTrans[i]->setTargetState( m_pWalkState );pKeyPressTrans[i]->addAnimation( pPAG );// “站立?行走”转换需要动画connect( pKeyPressTrans[i], SIGNAL( triggered( ) ),this, SLOT( SlotSetDirection( ) ) );// 触发转换的时候调用槽pKeyReleaseTrans[i] = new QKeyEventTransition( m_pWidget,QEvent::KeyRelease,keys[i],m_pWalkState );pKeyReleaseTrans[i]->setTargetState( m_pStandState );}// 启动有限状态机m_Machine.setInitialState( m_pStandState );m_Machine.start( );
}

注意,在我的草图中还有一点,就是当转换被触发(triggered)时,会向Character类实例发送一个信号,通过SlotSetDirection()槽函数接收,用来针对不同的按键来设定不同的帧显示和进行不同的位置移动,也可以说槽函数设定了角色的朝向(帧框)、帧动画和位置动画。

程序运行基本正常,只是会出现“QEasingCurve: Invalid curve type 45”这样的错误(控制台下),看来是我自定义的插值函数搞的鬼。虽然我在论坛上提问了,但是目前还是没有人知道,这个问题就不了了之了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/41772.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity 3d人形动画 一边走一边吹泡泡

资源下载并导入&#xff1a; Robot Kyle 导入标准资源库并修改资源库过时的错误 >>点击此处查看教程 这样就解决了 我们都知道&#xff0c;标准资源包里的人物&#xff0c;是自带脚本的。 而这些脚本&#xff0c;也可以应用到这个没有脚本的机器人上面&#xff0c;只需要…

unity人物基础动画应用。行走、待机之类的简单动画切换。

[TOC]unity人物基础动画应用 1.将动画或带有动画的&#xff0c;模型导入到unity 直接将项目拖入资源层级就好。这里推荐一个网站&#xff0c;可以给导入网站的模型自动绑骨&#xff0c;并且可挑选动画下载。网站自身也带有很多模型可以直接下载。免费又好用&#xff0c;就是可…

Unity中制作动画

1.创建一个 Cube 模型 2. 点击 Window->Animation->Animation 按钮&#xff0c;打开动画编辑面板(快捷键Ctrl6) 3. 点击 Create 按钮&#xff0c;保存新建的动画文件&#xff0c;我命名为“Cube.anim”创建好界面如下 4.点击 Add Preoperty&#xff0c;选择合适的想要改变…

unity人物素材制作动作,导入unity行走、跑步动画,并用Animator Controller加脚本进行控制

初学Unity的关于制作人物动作、导入unity动画、控制人物移动的简单小结 因为网上的关于人物动画制作、导入、控制运动的文章都不太全面&#xff0c;所以自己制作了一个小结来总结一下&#xff0c;这是我当前做出来的效果图&#xff0c;穿墙效果还未改&#xff0c;这里可以通过…

Unity制作的照片墙效果

使用Unity3D制作的照片墙效果。支持发布PC、Android、Web等多平台使用。 效果上图 点选其中一张图时 参数调节 工程地址&#xff1a;https://download.csdn.net/download/Highning0007/87337607

Unity制作简单的精灵图动画(新手向)

使用精灵图制作动画步骤&#xff1a; 1.精灵图准备 2.制作动画 一、精灵图导入与切割 第一种情况&#xff1a;导入的是已经切割好的精灵图&#xff0c;请直接跳动到二 第二种情况&#xff1a;导入的是需要切割的精灵图&#xff0c;需要切割&#xff0c;切割步骤&#xff1…

unity程序动画

文章目录 Unity 程序动画讲解 一、程序动画是什么&#xff1f;二、使用步骤1.建立模型2.骨骼建立3.代码部分4.角色身体的位置适配 总结 Unity 程序动画讲解 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、程序动画是什么&#xff1f; 程序动画就是…

Unity | 从建模到蒙皮动画的整个过程

目录 一、顶点数组、索引数组及UV数组 二、Mesh、MeshFilter、MeshRenderer及SkinnedMeshRenderer 1. Mesh 2. MeshFilter 3. MeshRenderer 4. MeshRenderer与SkinnedMeshRenderer&#xff08;蒙皮网格&#xff09; 三、Unity中相关组件 1. mesh和material 2. sharedM…

虚幻——动画蓝图、状态机制作人物走跑跳动作

一、名词解释 序列——一段动作。 混合空间——混合不同的动作。将多个序列排序播放。 动画蓝图——根据状态播放不同的动画。 二、混合空间制作走跑动作 由于走和跑的动作比较连续&#xff0c;并且都是由速度控制&#xff0c;所以要把待机、走、跑这三个动作混合在一起。 1.创…

Unity UI 做 图表动画

UI分为三张图片&#xff0c;背景图&#xff0c;前景橘色&#xff0c;前景蓝色&#xff0c;三张图片大小一致&#xff0c;前景就是没有图片的image&#xff0c;填充的颜色。形状是通过shader改变的。 这是一个图标的基本结构&#xff0c;center是中心点&#xff0c;1、2、3...是…

广告中oCPX到底是如何进行优化的?

自从Facebook引入oCPM出价以来&#xff0c;国内的头条广告、微信广点通、百度信息流都陆续推出了自己的oCPX出价&#xff0c;oCPX出价已经成为主流广告投放平台的标配。 简单而言&#xff0c;oCPX是一种出价机制&#xff0c;允许广告主按照转化行为成本出价&#xff1b;假设对…

文字转语音神器!

大家好&#xff0c;我是懂王。 经常刷短视频的兄弟应该知道&#xff0c;有很多短视频的字幕都是用机器人语音来制造的&#xff0c;类似于手机上的 AL 助手语音&#xff0c;不过声音比 siri 和小爱同学要难听一点。 虽然这种机器声音听起来略带生硬&#xff0c;然而对于视频创…

语音转文字怎么转?分享这些实用软件

在参加日常工作会议时&#xff0c;有时候大家记录的速度跟不上对方的语速&#xff0c;会导致会议记录不完整&#xff0c;影响到工作效率。有些小伙伴就把会议内容进行录音&#xff0c;待会后再将录音文件进行整理&#xff0c;这样做既方便快捷&#xff0c;同时能提高工作效率。…

chrome文字转语音(tts)

文章目录 一、文章参考二、TTS (Text-To-Speech) 是文本转语音2.1 概念2.2 windows 操作系统2.3 验证是否有Windows TTS&#xff08;语音转文本&#xff09; 三、chrome 文字转语音3.1 Web Speech相关的API实际上有两类3.2 语音合成Speech Synthesis API3.2.1 SpeechSynthesisU…

在线文字转成语音怎么转

很多小伙伴在办公或学习中&#xff0c;经常或需要浏览大量资料。随着时间越来越长&#xff0c;我们的眼睛就会多度疲劳。为了不戴上眼镜&#xff0c;我们只能改变当前的方式&#xff0c;也就是把文字变成语音去听&#xff0c;而不是去看。那么就有小伙伴想问了在线文字转成语音…

体验最佳的一个TTS文字转语音工具

文本转语音 (TTS) 技术在当今的数字世界中变得越来越流行&#xff0c;其应用范围从语音导航到教学视频、教育和娱乐。 TTS 技术允许用户将文本转换为语音&#xff0c;使其成为一种极其方便、高效和灵活的交流方式。 个人的使用场景是抖音短视频语音配音和电影解说&#xff0c;…

一个在线文字转语音工具

一个在线文字转语音工具 因为参加比赛过程中要频繁使用文字转语音的功能&#xff0c;遂写了这个工具&#xff0c;暂时先用着。 工具基于百度API &#xff0c; 目前只支持 1K 以内的文字转语音。 后续版本拟增加讯飞接口&#xff0c;批量转换&#xff0c;语音识别&#xff0c;在…

SpeechSynthesisUtterance文字转语音播报

一、介绍 SpeechSynthesisUtterance是HTML5中新增的API,用于将指定文字合成为对应的语音.也包含一些配置项,指定如何去阅读(语言,音量,音调)等 二、基本属性 var speech new SpeechSynthesisUtterance() speech.lang 获取并设置话语的语言&#xff08;en-US、zh-CN&#x…

文字转语音功能

大家有没有为如何找到一款文字转语音功能还能免费使用&#xff0c;操作简单的网站而苦恼&#xff0c;这边为大家强烈推荐一款操作简单而且免费使用的网站 96编辑器里的文字转语音功能 什么是文字转语音&#xff1f; 顾名思义&#xff0c;文字转语音是将文字转化成语音的形式&…

TTS Text-to-speech(文字转语音)服务

目录 中文帮助文档&#xff1a; 创建语音资源&#xff1a; 填写注册信息&#xff1a; 转到资源服务 编写测试代码(C#)&#xff1a; C#需要的包【NuGet搜索&#xff1a;CognitiveServices】 视频连接&#xff1a; 官网链接&#xff1a;Speech Studio - Microsoft Azure &am…