Directx11教程(9) 增加一个TimerClass类

本文介绍了一个简单的TimerClass类,用于计算相邻两帧间的时间差,从而实现平滑且与FPS无关的动画效果。通过使用QueryPerformanceCounter函数获取高精度计时器的值,确保了动画的一致性和流畅性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     在上篇教程代码的基础上,我们增加一个TimerClass类,这个类的功能很简单,就是可以计算相邻2帧的时间差。利用这个时间差值,可以实现平滑的动画,使得动画不会因为不同机器fps不同,从而动画效果变快或者变慢。

    我们主要是利用QueryPerformanceCounter函数来查询定时器的计数值。

    如果硬件里有定时器,它会启动这个定时器,之后会不断获取定时器的值,这样的定时器精度,就跟硬件时钟的晶振一样精确的。

TimerClass.h代码如下:

#pragma once
#include <windows.h>

//主要用来计算相邻两帧之间的时间
//可以用来实现平滑的与fps无关的动画。

class TimerClass
    {
    public:
        TimerClass(void);
        TimerClass(const TimerClass&);
        ~TimerClass(void);
        bool Initialize();
        void Frame();

        float GetTime();

    private:
        INT64 m_frequency;
        float m_ticksPerMs;
        INT64 m_startTime;
        float m_frameTime;

    };

TimerClass.cpp代码如下:

#include "TimerClass.h"


TimerClass::TimerClass(void)
    {
    }


TimerClass::TimerClass(const TimerClass& other)
    {
    }


TimerClass::~TimerClass(void)
    {
    }

bool TimerClass::Initialize()
    {
   // 检测系统是否支持高精度计时器.
    QueryPerformanceFrequency((LARGE_INTEGER*)&m_frequency);
    if(m_frequency == 0)
        {
        return false;
        }

   // 得到每毫秒多少个计数器.
    m_ticksPerMs = (float)(m_frequency / 1000);

    QueryPerformanceCounter((LARGE_INTEGER*)&m_startTime);

    return true;
    }

//每个渲染帧都会被调用,从而计算出每帧之间的时间
void TimerClass::Frame()
    {
    INT64 currentTime;
    float timeDifference;


    QueryPerformanceCounter((LARGE_INTEGER*)& currentTime);

    timeDifference = (float)(currentTime - m_startTime);

    m_frameTime = timeDifference / m_ticksPerMs;

    m_startTime = currentTime;

    return;
    }

float TimerClass::GetTime()
    {
    return m_frameTime;
    }

我们在SystemClass.h中增加一些代码,包含TimerClass.h

#include "GraphicsClass.h"
#include "TimerClass.h"

const float PI     = 3.14159265358979323f;

class SystemClass
    { 

        GraphicsClass* m_Graphics;

        //计时器类
        TimerClass* m_Timer;
    };

 

SystemClass.cpp代码如下,我只贴出了修改了代码的函数。

#include "SystemClass.h"


SystemClass::SystemClass(void)
    {
    m_Input = 0;
    m_Graphics = 0;

    m_Timer = 0;

    }

//调用窗口初始化函数和其它一些类的初始化函数
bool SystemClass::Initialize()
    { 

   // 初始化图形对象
    result = m_Graphics->Initialize(screenWidth, screenHeight, m_hwnd);
    if(!result)
        {
        return false;
        }
    // 创建计时器对象.
    m_Timer = new TimerClass;
    if(!m_Timer)
        {
        return false;
        }

    // 初始化计时器对象
    result = m_Timer->Initialize();
    if(!result)
        {
        MessageBox(m_hwnd, L"Could not initialize the Timer object.", L"Error", MB_OK);
        return false;
        }

    return true;
    }

bool SystemClass::Frame()
    {

    m_Timer->Frame();

根据时间来设定摄像机旋转的角度,基本上能保证旋转不会因为fps不同而不同

    //动画,旋转摄像机
    m_Graphics->m_Camera->roll(m_Timer->GetTime()/1000);

    // 执行帧渲染函数.
    result = m_Graphics->Frame();
    if(!result)
        {
        return false;
        }
    return true;
    }

程序执行后,将会发现一个旋转的颜色立方体,你也可以用Q,W,E,A,S,D,Z,X,C控制摄像机,改变观察方向。

程序的截图和上篇教程中的图是一样的。

完整的代码请参考:

工程文件myTutorialD3D11_8

代码下载:

http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip

### C# 中创建和处理动画的方法 在 C# 中,可以通过多种方式实现动画效果。以下是几种常见的方法及其对应的教程示例。 #### 使用 Windows Forms 实现简单的帧动画 Windows Forms 提供了一种简单的方式来通过定时器控件更新界面以模拟动画效果。可以利用 `System.Windows.Forms.Timer` 控件来定期刷新窗体上的绘图区域[^1]。 ```csharp using System; using System.Drawing; using System.Windows.Forms; public class AnimationForm : Form { private int xPosition = 0; // 初始位置 private Timer timer; public AnimationForm() { this.DoubleBuffered = true; // 减少闪烁 timer = new Timer(); timer.Interval = 50; // 设置时间间隔(毫秒) timer.Tick += OnTimerTick; timer.Start(); // 启动计时器 } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics g = e.Graphics; g.FillEllipse(Brushes.Red, xPosition, 50, 50, 50); // 绘制红色圆圈 } private void OnTimerTick(object sender, EventArgs e) { if (xPosition >= ClientSize.Width) // 如果超出边界则重置位置 xPosition = -50; else xPosition += 5; // 增加水平坐标 Invalidate(); // 请求重新绘制窗口 } } static class Program { static void Main() { Application.EnableVisualStyles(); Application.Run(new AnimationForm()); } } ``` 上述代码展示了如何使用 Windows Forms 和计时器组件制作一个移动的小球动画[^2]。 --- #### 使用 WPF 进行动画开发 WPF 是一种更现代化的技术栈,支持基于声明式的 XAML 编写 UI 并内置强大的动画功能。下面是一个基本的例子,展示如何让按钮平滑地改变其大小: ```xml <Window x:Class="WpfAnimationExample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF 动画示例" Height="350" Width="525"> <Grid> <Button Content="点击我!" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="10"> <!-- 定义双击事件触发的动画 --> <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)" From="1.0" To="1.5" Duration="0:0:0.5"/> <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)" From="1.0" To="1.5" Duration="0:0:0.5"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> <Button.RenderTransform> <ScaleTransform ScaleX="1.0" ScaleY="1.0"/> </Button.RenderTransform> </Button> </Grid> </Window> ``` 此代码片段定义了一个当用户单击按钮时会放大并缩小的效果[^3]。 --- #### 使用 DirectX 或 MonoGame 开发复杂的游戏级动画 对于更高性能需求的应用场景,比如游戏开发中的角色动作或粒子特效,可以选择借助第三方库如 **DirectX** 或者跨平台框架 **MonoGame** 来完成复杂的图形渲染任务。这些工具提供了底层硬件加速能力以及丰富的 API 支持高级视觉表现形式[^4]。 由于篇幅原因这里不提供具体实现细节,但推荐查阅官方文档学习更多相关内容。 --- ### 总结 以上介绍了三种不同层次上构建动画的方式:从基础 WinForms 的逐帧控制到中间层 WPF 高度集成化的解决方案再到高端领域内的专业引擎技术选型建议。开发者可以根据项目实际需要选取合适的技术路线实施自己的创意想法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值