DIY编程器网

 找回密码
 注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1669|回复: 0
打印 上一主题 下一主题

[待整理] LabWindows/CVI虚拟仪器设计技术场景与游戏设计之: 下雪场景

[复制链接]
跳转到指定楼层
楼主
发表于 2014-10-12 07:21:51 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
4.3 下雪场景
        4.3.1 下雪场景设计方法
        动画场景(背景)在动画以及游戏设计中起到烘托角色和渲染气氛的作用。动画场景分为场景和背景两部分,场景是角色可以穿行其中的活动场面或自然景观;背景是起烘托和渲染作用的角色背后的景色。场景是动画设计过程当中不可缺少的一部分,在某种意义上,场景可以决定整个动画及游戏的风格。场景设计所涉及的面很广,要找到场景与整体风格的切入点,达到情节的和谐统一。
         
        动画场景的创意设计与其他创意设计有相似的过程和方法。在创意前要做周密的设计和准备,即使创意不同凡响,也要使创意循着一个确定目标去发展。动画场景的创意设计是整个动画创意的一部分,应以整体效果为最终目标来思考和把握。实际上,动画场景设计的所有创意要建立在理解动画情境的基础上,动画设计师应不断与程序设计者在整体构思上保持一致,保证创意的完整性和协调性。
         
        从时间上讲,场景艺术也就是时间艺术,在心理空间中营造物理空间的虚拟造型和概念,根据动画及游戏来调节场景的大小、高度等。而动画场景的运动性是建立在时间和空间的基础上的,空间中的角色和物体由于速度的变化而引起的位移和变形,设计者可以充分发挥想象的空间,制造出高水平的视觉效果。
         
        在LabWindows/CVI 程序开发中,场景制作无疑是一个非常重要的环节,对于一些注重细节的用户来说,美观的界面,动态的效果无疑能大大提高软件的亲和力。对于下雪场景大家都不会陌生,用程序代码来控制雪花的下落与堆积也是比较有意思的,其原理并不复杂。先将背景设置为黑色,随机画出许多白点(雪花),然后使这些雪花不断地向下移动,并在底部形成堆积效果,随时间的流失逐渐融化,循环往复,一个下雪场景就完成了。
         
        4.3.2 下雪场景程序设计
        (1)面板设计
        编写一个下雪场景效果程序,背景设置为黑色,随机产生白色的雪花,随时间的流失不断下落,堆积到地上,雪层不断加厚,但雪层也会随之部分融化,产生一种比较逼真的效果。背景采用Canvas 控件,雪花由CanvasDrawPoint 函数实现,雪花下落由异步定时器控制。面板设计如图4-7 所示,面板中主要控件属性设置如表4-5 所示。
       

        图4-7 下雪场景面板

         
        表4-5 控件属性设置表
                               
                                        常量名

                       
                               
                                        控件类型

                       
                               
                                        控件的主要属性

                       
                               
                                        PANEL

                       
                               
                                        Panel

                       
                               
                                        标题:下雪场景回调函数:PanelCB

                       
                               
                                        CANVAS

                       
                               
                                         Canvas

                       
                               
                                        ( 下雪场景背景)

                       
         
        (2)程序源代码
        //头文件声明
        #include "toolbox.h"  
        #include "asynctmr.h"  
        #include <utility.h>  
        #include <ansi_c.h>  
        #include "下雪场景.h"  
        //全局静态变量
        static int TimerID;  
        static int panelHandle;  
        static int Snow[1000][3];  
        static int PWidth;  
        static int PHeight;  
        //声明异步定时器
        int CVICALLBACK timer (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2);  
        //主函数
        int main (int argc, char *argv[])  
        {  
        int i;  
        if (InitCVIRTE (0, argv, 0) == 0)  
        return &ndash;1;  
        if ((panelHandle = LoadPanel (0, " 下雪场景.uir", PANEL)) < 0)  
        return &ndash;1;
        SetCtrlAttribute (panelHandle, PANEL_CANVAS, ATTR_PEN_COLOR, VAL_WHITE);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS, ATTR_PEN_WIDTH, 1);
        GetPanelAttribute (panelHandle, ATTR_HEIGHT, &PHeight);
        GetPanelAttribute (panelHandle, ATTR_WIDTH, &PWidth);
        //用当前时间产生随机数
        SetRandomSeed (0);
        //随机产生雪花
        for (i = 0; i < 1000; i ++)  
        {  
        Snow[0] = (int) (Random(0, 1) * PWidth);  
        Snow[1] = (int) (Random(0, 1) * PHeight);  
        Snow[2] = 10 + (Random(0, 1) * 5);  
        }  
        //装载异步定时器
        TimerID = NewAsyncTimer (0.2, &ndash;1, 1, timer, 0);
        DisplayPanel (panelHandle);  
        RunUserInterface ();  
        //释放异步定时器资源
        DiscardAsyncTimer (TimerID);  
        DiscardPanel (panelHandle);  
        return 0;
        }  
        //面板回调函数
        int CVICALLBACK PanelCB (int panel, int event, void *callbackData,  
        int eventData1, int eventData2)  
        {  
        switch (event)  
        {  
        case EVENT_CLOSE:  
        // 停止异步定时器
        SuspendAsyncTimerCallbacks ();
        // 延时0.2s  
        Delay (0.2);  
        QuitUserInterface (0);  
        break;
        }  
        return 0;  
        }  
        //异步定时器——绘制下雪场景
        int CVICALLBACK timer (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2)  
        {  
        int i;  
        static int OldX;  
        static int OldY;  
        static int colory;  
        static int RGBValue;  
        switch (event)  
        {  
        case EVENT_TIMER_TICK:
        // 禁止弹出运行时错误对话框
        DisableBreakOnLibraryErrors ();  
        for (i = 0; i < 1000; i ++)  
        {
        OldX = Snow[0];  
        OldY = Snow[1];  
        Snow[1] = Snow[1] + Snow[2];  
        if (Snow[1] > PHeight)
        {
        Snow[1] = 0;  
        Snow[2] = 5 + ((double)rand () / RAND_MAX * 50);  
        Snow[0] = (double)rand () / RAND_MAX * PWidth;
        OldX = 0;
        OldY = 0;
        }
        SetCtrlAttribute (panelHandle, PANEL_CANVAS, ATTR_PEN_COLOR, VAL_BLACK);
        // 绘制雪花点
        CanvasDrawPoint (panelHandle, PANEL_CANVAS, MakePoint (OldX, OldY));
        // 设置雪花灰度渐变色阶
        colory = 8 * (Snow[2] -10);
        colory = 60 + colory;  
        RGBValue = MakeColor (colory, colory, colory);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS, ATTR_PEN_COLOR, RGBValue);  
        CanvasDrawPoint (panelHandle, PANEL_CANVAS, MakePoint (Snow[0], Snow[1]));
        }
        break;
        }   
        return 0;   
        }
         
        (3)程序注释
        ① NewAsyncTimer 函数
        创建一个异步定时器并返回异步定时器ID。创建的异步定时器会自动开辟一个新的线程,其默认优先级为THREAD_PRIORITY_HIGHEST ,如需要修改优先级,可调用NewAsyncTimer WithPriority 函数重新设置优先级,异步定时器支持Windows 、real-time (RT) 、Linux 等系统。函数原型为:
        int NewAsyncTimer (double Interval, int Count, int Initial_State, void *Event_Function, void *Callback_Data);
        Interval:指定触发事件时间间隔,以秒计。
        Count :指定异步定时器触发的事件数目。如果输入负值,则异步定时器只有调用DiscardAsyncTimer 或SuspendAsyncTimerCallbacks 函数时才会被终止。如果输入0 则返回一个错误。
        Initial_State :设置异步定时器为运行或暂停状态。可以通过SetAsyncTimerAttribute 函数重新设置状态。
        *Callback_Data :用户定义回调数据。
        返回值:返回异步定时器ID。负值表示产生错误。错误说明如表4-6 所示。
         
        表4-6 异步定时器错误说明表
         
                               
                                        错误码

                       
                               
                                         说明

                       
                               
                                        &ndash;1

                       
                               
                                        系统分配异步定时器资源失败

                       
                               
                                        &ndash;2

                       
                               
                                        没有ID 资源分配给异步定时器

                       
                               
                                        &ndash;3

                       
                               
                                        内存不足

                       
                               
                                        &ndash;4

                       
                               
                                        指定ID 不存在

                       
                               
                                        &ndash;5

                       
                               
                                        调用并初始化异步定时器未完成

                       
                               
                                        &ndash;6

                       
                               
                                        内部错误

                       
                               
                                        &ndash;7

                       
                               
                                        参数传递无效

                       
                               
                                        &ndash;8

                       
                               
                                        仅用于实时系统

                       
                               
                                        &ndash;9

                       
                               
                                        不能设置此属性

                       
         
        *Event_Function :指定用户自定义异步定时器函数名。此参数为AsyncTimerCallbackPtr 函数指针类型,函数定义与普通定时器类似,即:
        int CVICALLBACK FunctionName (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2);
        reserved :保留参数。
        timerId :异步定时器ID,用于产生回调事件。
        event:响应事件,包含EVENT_TIMER_TICK 和EVENT_DISCARD 事件。
        *callbackData :用户定义回调数据。
        eventData1 :为双精度指针变量,指向异步定时器持续运行时间。
        eventData2 :为双精度指针变量,指向异步定时器从上次触发事件到该时间持续时间。
         
        ② DiscardAsyncTimer 函数释放异步定时器资源。函数原型为:
        int DiscardAsyncTimer (int Timer_ID);
        Timer_ID :异步定时器ID。如果输入值为&ndash;1,将释放所有异步定时器资源。注意,创建或释放异步定时器只有当函数执行完毕返回时才能真正完成,否则会有错误产生。
         
        ③ SuspendAsyncTimerCallbacks 函数停止所有异步定时器,直到调用ResumeAsyncTimerCallbacks 函数。函数原型为:
        int SuspendAsyncTimerCallbacks (void);
         
        ④ Delay 函数延时指定时间,以秒计。一般情况下,默认分辨率为1ms 。函数原型为:
        void Delay (double Number_of_Seconds);
        Number_of_Seconds :延时时间。
         
        ⑤ CanvasDrawPoint 函数在Canvas 控件上绘制点图。绘制时使用ATTR_PEN_COLOR 、ATTR_PEN_MODE 和ATTR_PEN_WIDTH 属性。当ATTR_PEN_WIDTH 属性不为1 时,可能出现非圆形点。函数原型为:
        int CanvasDrawPoint (int Panel_Handle, int Control_ID, Point Point);
         
        ⑥ MakeColor 函数利用红、绿、蓝三色合成一个RGB 颜色值。RGB 值是一个4 字节整型数据,用十六进制表示为0x00RRGGBB,RR、GG、BB 分别表示红、绿、蓝三基色。函数原型为:int MakeColor (int Red, int Green, int Blue);
        Red:红色分量值,取值范围为0~255 。
        Green:绿色分量值,取值范围为0~255 。Blue:蓝色分量值,取值范围为0~255 。
         
        ⑦ DisableBreakOnLibraryErrors 函数
        当产生库函数错误时,禁止弹出运行时错误对话框。可以使用SetBreakOnLibraryErrors 函数代替。函数原型为:
        void DisableBreakOnLibraryErrors (void);
        通常情况下,可以通过选择菜单Run→Break on→Library Errors 选择打开或关闭运行时错误对话框。如果需要打开运行时错误对话框,也可采用EnableBreakOnLibraryErrors 或SetBreakOnLibraryErrors 函数。
         
        ⑧ 异步定时器退出问题
        如果将面板回调函数PanelCB 中的SuspendAsyncTimerCallbacks 和Delay 函数删除,在关闭面板时,会弹出运行时错误对话框,如图4-8 所示。从提示内容可以看出,此错误为“NON-FATAL RUN-TIME ERROR”,即非致命运行时错误,并给出错误线程ID。由于异步定时器与用户界面逻辑分布在不同的线程中,会造成主函数main 中的DiscardPanel 已经执行完毕,panelHandle 句柄已经释放,但异步定时器可能只运行了一半,由于异步定时器的特殊性决定了其必须运行完毕才能暂停或终止,因此,错误提示中会出现句柄无效的情况。简单的做法是在timer 回调函数的首行添加DisableBreakOnLibraryErrors 函数,禁止错误对话框弹出。如果想根除错误,需要在面板回调函数PanelCB 首先停止异步定时器并等待其执行完毕,即延时一定时间,如一个Interval 来使另一个线程中的timer 函数执行完毕并成功返回。
         
        由于采用多线程技术,同时跟踪多个并发线程是非常必要的。LabWindows/CVI 提供了线程窗口可随时获得每个线程的详细执行信息。在调试状态下,选择LabWindows/CVI 8.5 下的菜单Run→Threads… (或选择LabWindows/CVI 9.0 下的菜单Window→Threads),弹出线程对话框,
         
        如图4-9 所示。在对话框中显示每个线程ID 以及当前执行的函数,选中要查看的线程后,点击“View”按钮,可定位到当前运行的线程。在菜单Run 下,还可以通过Up Call Stack 、Down Call Stack 以及Call Trace… 菜单查询当前线程信息。
       

        图4-8 运行时错误对话框

             

         图4-9 LabWindows/CVI 8.5 线程对话框

         
        (4)运行效果图
        点击工具栏中的Debug Project 按钮,程序开始运行,其效果如图4-10 所示。
       

        4-10 运行效果图

         

        相关阅读
        《虚拟仪器技术,将“软件就是仪器”进行到底!》
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
收藏收藏 分享分享 支持支持 反对反对
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|文字版|手机版|DIY编程器网 ( 桂ICP备14005565号-1 )

GMT+8, 2025-8-1 20:25 , 耗时 0.103820 秒, 21 个查询请求 , Gzip 开启.

各位嘉宾言论仅代表个人观点,非属DIY编程器网立场。

桂公网安备 45031202000115号

DIY编程器群(超员):41210778 DIY编程器

DIY编程器群1(满员):3044634 DIY编程器1

diy编程器群2:551025008 diy编程器群2

QQ:28000622;Email:libyoufer@sina.com

本站由桂林市临桂区技兴电子商务经营部独家赞助。旨在技术交流,请自觉遵守国家法律法规,一旦发现将做封号删号处理。

快速回复 返回顶部 返回列表