[转载]AS3程序动画中Timer和Event.ENTER_FRAME之间的区别与选

本文详细解析了Flash中Event.ENTER_FRAME事件与Timer类在动画制作中的应用原理及优缺点,对比了两种方式在不同场景下的表现,为开发者提供了实用的指导。

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

[url]http://www.cnblogs.com/rob0121/articles/1757325.html[/url]

Event.ENTER_FRAME事件做动画的原理
每当Flash运行器执行一次预定屏幕更新检查的时候它调度Event.ENTER_FRAME事件。注册以接收Event.ENTER_FRAME通知的任何函数都被反复执行,在由当前Flash运行器帧速率决定的一个频率下。由任何Event.ENTER_FRAME事件监听器做出的可见变化在它退出之前被描绘,这就是Event.ENTER_FRAME做动画的原理。
Event.ENTER_FRAME事件做动画的缺陷
1,每当想要改变指定的帧速率的时候,我们必须更新基于该帧速率计算速度的所有代码(除非使用基于速度的动画)
2,Flash运行器不总是能到达指定的帧速率,动画变慢。这种变慢甚至因系统负载而不同,帧速率可能只在短时期下降后恢复到它的正常速率。
在一般情况中,用稍有差别的速度播放一个动画是可以接受的,但是,当要求精确控制或者可见精度是有影响的时候,我们必须考虑帧速率的缺陷。此时,我们用基于逝去的时间而不是关联于指定帧来计算移动一个移动的距离更合适(即基于速度的动画)
用Timer做动画的原理
Timer类是一个一般的实用程序类,用于在一个特定的时间间隔后执行代码。每个Timer对象在一个程序员指定的频率下调度TimerEvent.TIMER事件。想要在该频率下执行的函数用Timer对象为TimerEvent.TIMER事件来注册。
帧速率对Timer的影响
尽管Timer类看似提供了一个完全随意的方式来在一个指定时期之后执行一个函数,但可能令人惊奇的是,它任然依赖于Flash运行器的帧速率。对于每次预定屏幕更新检查一个TimerEvent.TIMER事件最多可以产生10次(10倍于帧速率)。例如,给定每秒1帧的一个帧速率,一个TimerEvent.TIMER事件最多(快)只能每100毫秒执行一次,甚至在一个更小的delay值指定给一个Timer对象的时候。在每秒10帧的时候,一个TimerEvent.TIMER事件每秒最多可以发生100次(10毫秒每次)。在每秒100帧的时候,一个TimerEvent.TIMER事件最多每秒可发生1000次(1毫秒每次)。
当一个TimerEvent.TIMER事件设置为运行得比帧速率更不频繁的时候,它将执行于下一次预定屏幕更新的时间间隔之后。为了请求更新于下次预定更新前,使用TimerEvent类的实例方法updateAfterEvent()。
在Timer和Event.ENTER_FRAME之间选择
帧速率受变化的控制:当一个.swf文件被另一个运用程序装载的时候,该运用程序的帧速率可能和.swf文件指定的帧速率有很大的不同(被装在的帧速率被屏蔽,统一用运用程序的帧速率),从而导致.swf的动画播放太快或者太慢。被装载的.swf文件当然可以设置帧速率,但是改变帧速率可能导致在父亲应用程序的不需要的播放行为Timer类提供了一些帧速率的独立性。
使用大量的Timer对象需要更多的内存:在分散动画管理体系结构中,使用一个单独的Timer来控制每个对象动画需要的内存要多于通过类似的Event.ENTER_FRAME实现可能需要的。
使用大量的Timer对象会导致过度的更新请求:在分散动画管理体系结构中,使用一个单独的Timer和updateAfterEvent()相关联来控制每个对象的动画导致了对屏幕的多个独立的请求,有可能导致性能的问题。
基于这些因素,这里是一个推荐的最佳操作:
1,在必须使程序内容的显示同步于手工创建于Flash authoring tool(Flash CS3,Flash CS4等)的基于帧内容的显示的应用程序中,使用Event.ENTER_FRAME
2,在Flash运行器中的帧速率的变动必须被减轻的应用程序中,使用单个的Timer对象来编制所有动画,并使用基于速度的动画
3,当在Flash运行器中的帧速率的变动当做是可以接受的时候,使用Event.ENTER_FRAME(因为使用基于Event.ENTER_FRAME的动画代码一般要比基于Timer的等价物更简单和使用较少的内存)
4,避免使用单个的Timer对象来移动单个的显示对象。只要有可能,使用一个单个的Timer对象来编制所有的动画。另外提示一下,如果你想在不同时间更新不同的对象,单独的Timer对象可能更合适
#include < WiFi.h> #include < PubSubClient.h> #include “esp_camera.h” WiFi配置 const char *ssid = “@PHICOMM_DC”; const char *password = “13625900271”; 阿里云MQTT配置 const char* mqttHostUrl = “k1gy7PGezyP.iot-as-mqtt.cn-shanghai.aliyuncs.com”; const int mqttPort = 1883; const char* mqttUser = “esp32&k1gy7PGezyP”; const char* mqttPassword = “7c816276f8ad52225cc3a9c32dbbeaa62b511f7a6849058514cd4cf2c336c52f”; const char* clientId = “k1gy7PGezyP.esp32|securemode=2,signmethod=hmacsha256,timestamp=1742611788205|”; // 阿里云组包配置 #define PRODUCT_KEY “k1gy7PGezyP” #define DEVICE_NAME “ESP32” #define ALINK_BODY_FORMAT “{”id“:”level“,”version“:”1.0“,”method“:”thing.event.property.post“,”params“:%s}” #define ALINK_TOPIC_PROP_POST “/sys/” PRODUCT_KEY “/” DEVICE_NAME “/thing/event/property/post” // 摄像头配置 #define CAMERA_MODEL_AI_THINKER #define PWDN_GPIO_NUM 32 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 0 #define SIOD_GPIO_NUM 26 #define SIOC_GPIO_NUM 27 #define Y9_GPIO_NUM 35 #define Y8_GPIO_NUM 34 #define Y7_GPIO_NUM 39 #define Y6_GPIO_NUM 36 #define Y5_GPIO_NUM 21 #define Y4_GPIO_NUM 19 #define Y3_GPIO_NUM 18 #define Y2_GPIO_NUM 5 #define VSYNC_GPIO_NUM 25 #define HREF_GPIO_NUM 23 #define PCLK_GPIO_NUM 22 无效 startCameraServer(); // 全局对象 WiFi客户端 espClient; PubSubClient 客户端 (espClient); 无符号 long lastMs = 0; 无效 setup() { 序列号.begin(115200); Serial.setDebugOutput(true); // 初始化摄像头 camera_config_t配置; config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = Y2_GPIO_NUM; config.pin_d1 = Y3_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM; config.pin_pclk = PCLK_GPIO_NUM; config.pin_vsync = VSYNC_GPIO_NUM; config.pin_href = HREF_GPIO_NUM; config.pin_sccb_sda = SIOD_GPIO_NUM; config.pin_sccb_scl = SIOC_GPIO_NUM; config.pin_pwdn = PWDN_GPIO_NUM; config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.frame_size = FRAMESIZE_UXGA; config.pixel_format = PIXFORMAT_JPEG; config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; config.fb_count = 1; 如果 (psramFound()) { config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; } esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf(“相机初始化失败:0x%x”, err); 返回; } 连接WiFi WiFi.begin(ssid, 密码); WiFi.setSleep(false); Serial.print(“连接到 WiFi”); while (WiFi.status() != WL_CONNECTED) { 延迟 (500); 序列号.print(“.”); } Serial.println(“\nWiFi 已连接”); // 启动摄像头服务器 startCameraServer(); Serial.print(“相机准备好了!用途:http:// 英寸); Serial.println(WiFi.localIP()); 初始化MQTT client.setServer(mqttHostUrl, mqttPort); mqttCheckConnect(); } void loop() { 客户端.loop(); 如果 (millis() - lastMs >= 5000) { lastMs = 毫(); 如果 (!client.connected()) { mqttCheckConnect(); } mqttIntervalPost(); } } MQTT连接检查 无效 mqttCheckConnect() { while (!client.connected()) { Serial.println(“正在连接到 MQTT...”); 如果 (client.connect(clientId, mqttUser, mqttPassword)) { Serial.println(“MQTT 已连接”); } else { Serial.print(“失败, rc=”); Serial.print(client.state()); 延迟(2000 年); } } } MQTT数据发送 无效 mqttIntervalPost() { char 参数[32]; 字符 jsonBuf[128]; sprintf(参数, “{”num8“:%d}”, 9); sprintf(jsonBuf, ALINK_BODY_FORMAT, param); client.publish(ALINK_TOPIC_PROP_POST, jsonBuf); Serial.println(“发送的数据: ” + String(jsonBuf)); } 降低代码的功耗
最新发布
03-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值