Flash定时器

2023-05-16

基于计时器的动画 

     作为计时器动画使用的关键类,不出意料,它就是 flash.utils.Timer。同时我们还需要 

flash.events.TimerEvent  类。 

     使用计时器实际上与使用 enterFrame  没什么两样。只需要我们去创建一个计时器

(Timer),告诉它多久“滴答响”一声,并侦听 TimerEvent.TIMER  事件,就像对 

Event.ENTER_FRAME  事件的侦听一样。哦,还要告诉计时器何时开始!接下来,计时器

就会每隔一段时间广播一个计时事件,它将调用赋给它的函数进行处理。计时器触发的间隔

 

以毫秒为单位,在创建该计时器时指定。让我们来看一个简单的例子(可在 Timer1.as  中找

到): 

package { 

 import flash.display.Sprite; 

 import flash.utils.Timer; 

 import flash.events.TimerEvent; 

  public class Timer1 extends Sprite { 

    private var timer:Timer; 

    public function Timer1() { 

   init(); 

  } 

    private function init():void { 

   timer = new Timer(30); 

   timer.addEventListener(TimerEvent.TIMER, onTimer); 

   timer.start(); 

  } 

    private function onTimer(timer:TimerEvent):void { 

   trace("timer!"); 

  } 

 } 

} 
 重要的部分加粗表示。我们创建一个计时器,告诉它每隔 30  毫秒触发一次,意味着每秒约 

33  次。添加一个事件的侦听器并将它起动。 onTimer  方法与我们以前用的 onEnterFrame 

类似。 

     这是我们所要知道计时器的大部分内容。它还有其它两个漂亮的特征。一个是在创建计

时器时,可以通过第二个参数,repeatCount,告诉它运行的次数。假设我们要让计时器每秒

运行一次,总共执行 5 秒。就可以这样做: 

    timer = new Timer(1000, 5); 

如果没有指定重复的次数,或传入 0,那么计时器将无限地运行。 

     另一个好东西是可以让计时器在某个点上启动或停止,只需要调用 timer.stop  或 

timer.start  即可。在某些例子中,这样做比删除和重新加入事件侦听器更简单一些。 

     与 enterFrame  相比,很多朋友更喜欢使用计时器的原因是,理论上讲,计时器可以让

我们控制动画的速度——这是对于帧的不精确性的一个重大改进。我之所以说“理论上讲”,

是因为这里有些事情需要弄清楚。 

     首先,实际上计时器要依赖于帧频。另一个原因是计时器的事件函数中的代码会增加整

个计时器间隔。稍后我会解释一下第二点。现在,让我们看看计时器是如何与帧频相关联的。

下面是文档类 Timer2.as,使用到我们著名的 Ball  类。

package { 

 import flash.display.Sprite; 

 import flash.utils.Timer; 

 import flash.events.TimerEvent; 

  public class Timer2 extends Sprite { 

    private var timer:Timer; 

    private var ball:Ball; 

    public function Timer2() { 

   init(); 

  } 

    private function init():void { 

   stage.frameRate = 1;   340

   ball = new Ball(); 

      ball.y = stage.stageHeight / 2; 

   ball.vx = 5; 

   addChild(ball); 

   timer = new Timer(20); 

   timer.addEventListener(TimerEvent.TIMER, onTimer); 

   timer.start(); 

  } 

    private function onTimer(event:TimerEvent):void { 

   ball.x += ball.vx; 

  } 

 } 

} 
 这里我们把创建出来的小球放在舞台的左侧。让它以 vx 为 5  的速度穿过舞台。然后设置

一个 20  毫秒的计时器,每秒约调用 50  次。同时设置影片的帧频为 1  就是为了看看帧频

是否会对计时器有影响。 

     测试后,我们会看到小球没有平稳地穿过屏幕,而是每秒钟跳一下  ——  以帧的频率。

每跳一次都会大于 5  像素。为什么呢? 

     回想一下一、二章的动画基础,我们知道模型是需要更新的,所以屏幕要根据新的模型

被刷新。这里时间间隔函数确实将更新了模型并将小球每次移动 5  像素,但是只有在 Flash 

进入新的一帧时才进行刷新。仅仅运行一个函数不会驱使 Flash  进行重绘。 

     幸运的是,Macromedia (现在的 Adobe)  的好人们看到了这个问题并给了我们另一个小

工具:updateAfterEvent。最初是在 Flash MX  中介绍的,现在它是传给计时器事件函数中 

TimerEvent  对象的一个方法。就像它的名字一样,在事件之后刷新屏幕的。当然,由于它

是 TimerEvent  类的一个方法,所以只有在收到一个事件后才能被调用。(事实上,它也是 

KeyboardEvent  和 MouseEvent  的方法,因此也能在这些处理函数中调用。) 

这样一来,我们可以修正一下 onTimer  事件: 

private function onTimer(event:TimerEvent):void { 

  ball.x += ball.vx; 

 event.updateAfterEvent(); 

} 
 现在一切有所好转了。非常流畅。但是如果您意识到小球应该每秒更新 50  次,我们看到的

基本上应该是一个 50 fps  的动画。这就意味着小球的运动应该比第四章创建的 fps  小于 

50  的 enterFrame  事件的例子更为流畅。但是实际的运动更为缓慢。 

     问题出来了,计时器在某种程度上要依赖于帧频。通过我的测算,在帧频为 1 fps  时,

我们所得到的计时器运行的最快间隔大约为 100  毫秒。 

     我已经听到了嘲笑:每帧只得到了 10  次间隔。所以,试将帧频改为 5。它允许每秒更

新 50  次。在我看来,仍然不是很流畅。如果不大于每秒 10  帧的话是不会达到真正流畅的

效果。因此,我们可以看到使用计时器并不能完全让我们从帧频的铐链中解脱出来。 

     下一个问题是计时器内部是怎样工作的,它会对计时的精确度产生多大的影响。当 

timer.start()  被调时,实际上发生了什么,Flash 等待一段指定的时间,然后广播事件,运行

与该计时器相关的处理函数。只有当函数执行完成后计时器才开始定时下一次计时。看一个

例子,假设我们有一个每 20  毫秒运行一次计时器。假设在处理函数中有大量的代码需要执

行 30  毫秒。下一轮定时只有在所有的代码都运行完成后才开始。这样一来,我们的函数会

在大约每 50  毫秒调用一次。因为在用户的机器上没法精确地知道代码会运行多快,所以多

数情况下,计时器动画不会比帧动画精确多少。 

    如果您需要真正的精确,那么基于时间的动画则是我们的必经之路。 

    341

基于时间的动画 

     如果要让动画中物体的速度是一致的,那么基于时间的动画就是我们要使用的方法。这

种方法在一些游戏中比较常用。我们知道,帧和计时器动画都不能以特定的速率播放。一个

复杂的动画在一台又老又慢的电脑上运行可能要比最初设计的速度慢上许多。我们马上会看

到,使用基于时间的动画无论最终动画运行的帧频如何,都将获得可靠的速度。 

     首先要改变考虑速度的方法。到目前为止,在我说 vx = 5  时,我们使用的单位是像素

每帧(pixels per frame)。换句话讲,每进入新的一帧物体都将在 x  轴上运动 5  像素。在计

时器动画中,当然,就应该是每次定时间隔移动 5  像素。 

     对于时间动画,我们将使用真正的时间单位,如秒。由于我们是处理完整的一秒,而非

其中的一部分,因此这个速度值就要更大一些。如果某个物体的速度是每帧 10 像素,每秒 

30  帧的速度运动,大约每秒 300  像素。比如下面这个例子,我从第六章的 Bouncing2.as  文

档类中截取了一部分并进行了一些变化,见下面粗体部分(也可在 TimeBased.as 中找到):

package { 

 import flash.display.Sprite; 

 import flash.events.Event; 

 import flash.utils.getTimer; 

  public class TimeBased extends Sprite { 

    private var ball:Ball; 

    private var vx:Number; 

    private var vy:Number; 

    private var bounce:Number = -0.7; 

    private var time:Number; 

    public function TimeBased() { 

   init(); 

  } 

    private function init():void { 

   stage.frameRate = 10; 

   ball = new Ball(); 

      ball.x = stage.stageWidth / 2; 

      ball.y = stage.stageHeight / 2; 

   vx = 300; 

   vy = -300; 

   addChild(ball); 

   time = getTimer(); 

   addEventListener(Event.ENTER_FRAME, onEnterFrame); 

  } 

    private function onEnterFrame(event:Event):void { 

      var elapsed:Number = getTimer() - time; 

   time = getTimer(); 

      ball.x += vx * elapsed / 1000; 

      ball.y += vy * elapsed / 1000; 

   var left:Number = 0; 

      var right:Number = stage.stageWidth; 

   var top:Number = 0; 

   var bottom:Number = stage.stageHeight; 

      if (ball.x + ball.radius > right) { 

        ball.x = right - ball.radius; 

    vx *= bounce;   342

      } else if (ball.x - ball.radius < left) { 

    ball.x = left + ball.radius; 

    vx *= bounce; 

   } 

      if (ball.y + ball.radius > bottom) { 

        ball.y = bottom - ball.radius; 

    vy *= bounce; 

      } else if (ball.y - ball.radius < top) { 

    ball.y = top + ball.radius; 

    vy *= bounce; 

   } 

  } 

 } 

} 
 如上所描述,我改变了对速度的计算,让它们使用固定的值,而非随机值。然后我创建了一

个名为 time  的变量,让它等于 flash.utils.getTimer  函数的结果。getTimer  函数非常简单。

它返回影片已经运行了的毫秒数  ——  这就是它全部的工作。我们没有办法清除它,重启它,

改变它,等等。它只是一个计数器。 

     看起来它似乎用处不大,但是如果先调用一次 getTimer  将值保存起来,稍后再调用它

一次,将两个结果相减,我们就能知道确切的—— 毫秒  ——这两次调用之间经过了多少时

间。 

     这就是策略:在每帧的开始时调用 getTimer  计算与上一帧间隔了多长时间。如果将它

除以 1,000,我们将得到以秒为单位的间隔时间,这是个以秒为单位的分数。由于我们的 vx 

和 vy  现在是以像素每秒来计算的,因此可以让它们去乘以这个分数,这样就知道要对物体

移动多少了。同样,不要忘记重新设置 time  变量的值,以便让下一帧进行计算。 

     测试一下,我们将看到小球移动的速度几乎与最初的速度相同!但是真正令人激动的是

我们可以以任何帧频来发布这个影片,它仍然可以以同样的速度运动!通过修改 

stage.frameRate  的值,试验一下高到 1,000 fps,低到 10 fps,你会看到小球的速度是相同

的。当然,较高的频率会让动画更加流畅,而较低的频率则会十分不连贯,但是速度是一致

的。 

     大家可以把这个技术应用在本书任何一个包含速度的例子中。如果这样的话,还需要将

相似的技术应用在加速度或外力上,如重力,因为它们也是基于时间的。加速度肯定要比转

前要大很多,因为加速度被定义为速度对时间的变化率。例如,重力大约为 32 英尺/秒/

秒。 

     如果在一个 30 fps 帧的动画中,重力为 0.5  的话,那么现在就应该是 450。计算方法 

0.5 * 30 * 30。然后像这样将它加入: 

          vy += gravity * elapsed / 1000; 

在最后一个例子中加入 450  重力后测试一下。我们会看到它与帧动画中加入重力 0.5  的效

果是相同的。使用这种技术的一个技巧是将帧频设置得非常高,如 100。虽然没有机器能够

与真正的帧频相吻合,但是基于时间的动画将保证每个人看到的影片运行得都是最流畅

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flash定时器 的相关文章

  • Hive知识点汇总

    HIVE 一 Hive的优化 数据倾斜 xff1a shuffle之后Key的分布不均导致分配到Reduce端的数据不均匀 xff0c 出现个别Reduce的数据过大 xff0c 执行时间过长而出现的现象 1 数据倾斜产生的原因 xff1a
  • CentOS7安装与克隆

    CentOS7安装与克隆 一 新建虚拟机及其配置二 配置虚拟网络编辑器三 安装CentOS 7四 一些工具的安装五 虚拟机克隆六 虚拟机克隆后的配置七 配置ssh免密登陆八 批处理脚本与集群分发脚本1 将家目录配置进环境变量2 批处理脚本3
  • NGINX ./configure详解

    在 34 configure 34 配置中 xff0c with 34 表示启用模块 xff0c 也就是说这些模块在编译时不会自动构建 without 34 表示禁用模块 xff0c 也就是说这些模块在编译时会自动构建 xff0c 若你想N
  • Linux下Nginx安装使用

    一 下载解压nginx span class token comment 进入要放安装包的目录 span span class token builtin class name cd span opt software span class
  • java Collections类 详解

    目录 一 前言 二 Collections类简介 三 Collections类常用方法演示 1 static void reverse List list 代码演示 2 static void shuffle List list 代码演示
  • Activity onNewIntent注意事项

    数据上报发现 xff0c onNewIntent 以后 xff0c onResume和onPause可能不会执行 xff0c 直接执行onStop
  • Python+OpenCV实用案例应用教程:人脸检测和识别

    计算机视觉使很多任务成为现实 xff0c 其中两项任务就是人脸检测 xff08 在图像中定位人脸 xff09 和人脸识别 xff08 将人脸识别为特定的人 xff09 OpenCV实现了一些人脸检测和识别的算法 从安全到娱乐 xff0c 这
  • 基数排序 详细讲解

    1 基数排序 桶排序 介绍 基数排序 xff08 radix sort xff09 属于 分配式排序 xff08 distribution sort xff09 xff0c 又称 桶子法 xff08 bucket sort xff09 或b
  • CentOS7安装docker后服务启动不了

    问题排查 运行yum install docker后 xff0c 安装完成docker 运行 docker info 命令测试docker是否正常 则提示以下错误 xff1a Cannot connect to the Docker dae
  • Linux命令+shell脚本大全:处理损坏的包依赖关系

    有时在安装多个软件包时 xff0c 某个包的软件依赖关系可能会被另一个包的安装覆盖掉 这叫作 损坏的包依赖关系 xff08 broken dependency xff09 如果系统出现了这个问题 xff0c 先试试下面的命令 xff1a y
  • 世界上最简单的无锁哈希表

    英文原文 xff1a preshing xff0c 感谢 64 浅水清流 的热心翻译 如果其他朋友也有不错的原创或译文 xff0c 可以尝试推荐给伯乐在线 以下是译文 无锁哈希表 xff08 Lock Free Hash Table xff
  • nginx ssl及http自动跳转到https配置

    1 Nginx路径配置 如下请求地址 http x x x x 8080 api base test 此时 zo java这个应用接收到的地址是 xff1a http x x x x 8080 api base test location
  • 视图绑定.

    在大多数情况下 xff0c 视图绑定会替代 findViewById 视图绑定功能可按模块启用 要在某个模块中启用视图绑定 xff0c 请将 viewBinding 元素添加到其 build gradle 文件中 xff0c 如下例所示 x
  • 优秀程序员的故事

    A君默默的工作了3年 xff0c 从项目初立 xff0c 到遍地开花 工作不忙 xff0c 工资没长 新领导来了 xff0c 下个版本重新开发 xff0c A君继续维护老版本 新招了一批人 xff0c 加班加点干了半年多 直到版本发布 xf
  • Synchronized锁

    1 Synchronized基本特性回顾 应用场景 xff1a 多线程环境下保证线程的安全性 使用方式 xff1a 1 xff09 Synchronized加在普通方法上 xff0c 使用的是this锁 xff0c 也就是当前对象 2 xf
  • HC-05无底板蓝牙模块连接51单片机,配置,安卓连接传输数据测试程序

    买个蓝牙模块以为是HC 06 xff0c 没有底板 xff0c 测试半天反应 xff0c 后面才发现是HC 05 xff0c HC 05和HC 06的测试方法稍有不同 一 HC 05蓝牙模块连线 先上一个自己的接线 xff08 有点丑 xf
  • java.io.StreamCorruptedException: invalid stream header: 异常

    使用java的对象流出现java io StreamCorruptedException invalid stream header异常 原因是数据发送端发送对象到接收端 接收端对于同一个输入流创建了不同的对象输入流 xff0c 而后用不同
  • insmod: ERROR: could not insert module xxxxx.ko: Unknown symbol in module

    有可能是该模块的相关依赖没有加载 先执行命令 xff1a modinfo xxxx ko 查看 depends xff1a 所依赖的模块 先加载依赖模块 xff0c 然后加载xxxx ko模块
  • Mondo Rescue ---FATALERROR--- Failed to generate boot+data disks

    使用Mondo Rescue制作CentOS7的IOS镜像的时候报错 Mindi failed to create your boot 43 data disks Fatal error Failed to generate boot 43
  • 【Git】常用命令commit提交,push推送,merge,添加分支branch

    一 常用操作 xff1a 1 添加跟踪文件 git add 或 git add A 根据ignore的配置 xff0c 添加跟踪文件 xff0c 其中的 或 A表示添加所有更改过的文件 2 查看状态 git status 3 提交到本地 x

随机推荐

  • Python项目打包成wheel笔记

    详情参考 xff1a https setuptools readthedocs io en latest setuptools html Python项目可以使用命名 pip install 包名 安装Python包 xff0c 可以将自己
  • CentOS 网桥配置,静态IP配置

    1 网桥配置 CentOS 网络配置文件在以下目录 ls etc sysconfig network scripts 假设配置文件为ifcfg enp1s0 cp etc sysconfig network scripts ifcfg en
  • UEFI启动,安装CentOS7报错tsc: Fast TSC calibration failed

    安装CentOS7系统报错 tsc Fast TSC calibration failed 多的不说 xff0c 选择Boot启动时有 USB SanDisk和UEFI xff1a SanDisk xff0c Partition 4 xff
  • Linux_Linux命令行提示符配置

    源址 xff1a http liuhongjiang github io hexotech 2013 01 16 shell prompting linux下shell提示符可以任意配置的 首先看看bash的配置文件 xff0c 一般在用户
  • Redis_RedisCluster set 方法跟踪纪要

    最近在使用 JedisCluster 时 对 集群模式下的 Redis key 的设置策略比较感兴趣 xff0c 跟踪了一下执行 set 方法的 主要源码 xff0c 特此记录一下 跟踪的源码版本 pom xml lt dependency
  • iOS开发之配置POST网络请求

    本文主要是讲一下我们在请求网络的时候如何去配置相关的参数然后成功得到响应 那本文以请求百度的API中图像识别为例来说一下该如何去配置 目的需求 我需要把一张包含二维码的图片通过百度的图像识别接口来判定是否包含二维码 准备工作 1 gt 装有
  • android-studio导入时底层编译工具缺失提示奇怪错误No toolchains found in the NDK toolchains folder for ABI with prefix:

    因为androidstudio的ndk升级不完整导致 xff0c 可以升级as的ndk xff0c 也可以修改ndk的配置 xff0c 设置成自己完整的ndk Error A problem occurred configuring pro
  • windows下查找一个目录下所有文件内容

    遇到这个问题的背景是我反编译了一个apk xff0c 得到了它的source code 我在jd gui中查找一个String时 xff0c 发现查找结果严重不全 xff0c 于是我想 xff0c 如果不用jd gui自带的搜索功能 xff
  • 使用yum命令创建缓存时报错:Peer cert cannot be verified or peer cert invalid

    背景 使用yum创建cache时 xff0c 总是一直报错 xff0c 排查 根据报错提示 xff0c 说的是证书的问题 xff0c 于是一直在纠结证书 因为有使用到代理 xff0c 还以为是代理哪里又出了问题 使用其他客户端执行该命令 x
  • angularjs+文件上传 http头content-type字段变化

    注 xff1a 1 文件上传必须采用Content Type multipart form data boundary 61 WebKitFormBoundarypHkhXOMllLo8SW36 2 angularjs默认的 http服务是
  • Android7.1悬浮窗自动消失解决办法

    问题描述 日前在做一个悬浮窗需求悬浮窗 xff0c 在Android 7 1模拟器上悬浮窗会显示几秒钟就自动消失 问题分析 发现问题后首先查看日志 xff0c 没有发现异常 然后翻看代码是否有remove掉悬浮窗的地方 xff0c 也没有出
  • 百度2014移动研发笔试题目

    答案仅供参考 一 简答题 1 简述计算机的存储系统分为哪几个层次 xff0c 为什么这样的分层能够提高程序的执行效率 所谓存储系统的层次结构 xff0c 就是把各种不同存储容量 存取速度和价格的存储器按层次结构组成多层存储器 xff0c 并
  • Windows环境下下载并安装VMware Workstation Pro 17

    VMware Workstation是一款能够在Windows环境下运行的虚拟机软件 xff0c 它可以在操作系统之上再虚拟一个或多个操作系统 xff0c 使你能够在一台电脑上模拟出多台电脑的场景 这次发布的17版本支持自动启动虚拟机 xf
  • Ubuntu 22.04下载安装VMware Workstation Pro 17

    Ubuntu 22 04下载安装VMware Workstation Pro 17 一 下载 打开浏览器 xff0c 访问VMware的官方网站 xff1a https www vmware com 页面打开后 xff0c 点击菜单中的 A
  • CentOS开启SSH免密登录

    CentOS开启SSH免密登录 要实现SSH免密登录 xff0c 首先需要准备一组公钥和私钥 将公钥放到服务器上 xff0c 将私钥放到客户机上 当客户机连接服务器时 xff0c 服务器会根据自身的公钥校验客户机的私钥 xff0c 如果校验
  • Ubuntu开启SSH免密登录

    Ubuntu开启SSH免密登录 要实现SSH免密登录 xff0c 首先需要准备一组公钥和私钥 将公钥放到服务器上 xff0c 将私钥放到客户机上 当客户机连接服务器时 xff0c 服务器会根据自身的公钥校验客户机的私钥 xff0c 如果校验
  • CentOS Stream 9 编译安装6.1内核

    CentOS Stream 9 编译安装6 1内核 一 下载内核源码 打开浏览器 xff0c 访问Linux内核的官方网站 xff1a https www kernel org 在官网首页能够看到许多不同的内核版本 xff0c 位于右边的黄
  • Windows 11安装Visual Studio 2022

    Windows 11安装Visual Studio 2022 一 下载 打开浏览器 xff0c 访问Visual Studio的官方网站 xff1a https visualstudio microsoft com 将页面向下拉动 xff0
  • CentOS Stream 9编译安装Redis 7

    CentOS Stream 9编译安装Redis 7 一 下载 1 访问Redis官方网站 xff1a https redis io xff0c 点击菜单栏右侧的 Download 进入下载页面 2 在下载页面的左侧可以看到Redis相关信
  • Flash定时器

    基于计时器的动画 作为计时器动画使用的关键类 xff0c 不出意料 xff0c 它就是 flash utils Timer 同时我们还需要 flash events TimerEvent 类 使用计时器实际上与使用 enterFrame 没