概述:

flash后台运行帧频低是源自flashplayer插件的问题,为了解决flash在后台运行时少占用些CPU的问题,但却为页游带来了一些麻烦,比如挂机战斗时玩家切换到别的页面去看东西了,就会造成如伤害输出不足,基本停止打怪这样的问题(除非你的战斗逻辑全写在服务端)。

解决方案思路:

起初想利用js的时间间隔相关的方式去实现(setTimeout、setInterval、和支持H5的requestAnimationFrame帧渲染),不过目前很多浏览器对于当前页面最小化或切换了标签进行了优化,不再执行js的这些函数。

360 浏览器 - 非激活无法执行定期执行的函数
           - 切换标签无法执行定期执行的函数

IE         - 非激活无法执行定期执行的函数 
           - 切换标签无法执行定期执行的函数

chrome/ff/opera - 非激活可以执行定期函数
                - 切换标签无法执行定期函数
所以,换了一种思路:

-- 检测flash帧频低:在enterframe 事件里根据距离上一帧的时间间隔来检测(或者连续几帧时间间隔都很长)并切换至【虚拟渲染模式】
      -- 检测flash帧频正常:在js里通过监听页面激活来与flash交互,并切换至【正常渲染模式】,同时在虚拟渲染模式时如果发现距离上一帧时间很短,就恢复至【正常渲染模式】(起到双重保险的作用,确保能够恢复正常)

实现流程:

  1-写一个JS,监听页面激活状态并通知FLASH,FLASH会切入到【正常渲染模式】-- 普通的entreframe事件。

2-初始化flash,以embed方式嵌入js文件,并以字节流方式解成字符串,然后通过调用js的方法eval来动态解析执行这段js代码。

3-首先进入正常的渲染模式,enterframe事件

4-在onEnterframe里,检测距离上一帧的时间是否超过一定范围(比如我的是设定为700),如果是的话就切换至【虚拟渲染模式】,关闭掉游戏的主循环

同时以while形式来确保将一帧执行N次游戏循环,根据计算得来的正确的帧间隔时间。

5-在【虚拟渲染模式】中利用与上一次while的间隔时间以及JS监控到页面被激活主动调用FLASH通知切换至【正常渲染模式】(优先)的双重保险下确保回归正常的enterframe事件中。


范例工程地址(flashbuilder工程):http://pan.baidu.com/s/1slvjnQX   密码:gtmf

代码 - flash-AS3

package
{import flash.display.Sprite;import flash.display.Stage;import flash.events.Event;import flash.events.MouseEvent;import flash.external.ExternalInterface;import flash.text.TextField;import flash.utils.ByteArray;import flash.utils.clearTimeout;import flash.utils.getTimer;import flash.utils.setTimeout;[SWF(width="1024",height="576",frameRate="60")]public class testBackRender extends Sprite{// 嵌入的JS文件,以字节流方式[Embed(source = "render.js",mimeType = "application/octet-stream")]// 绑定的类private var jsClass:Class;/*** 游戏主循环总执行次数 */        private var f:int = 0;/*** 虚拟渲染时的方法 */      private var vf:Function;/*** 虚拟渲染时用到的setTimeout记录值 */       private var vfi:*;/*** 是否真实渲染模式(enterframe),否则的话采用while虚拟执行游戏主循环*/     private var isRealRender:Boolean = true;/*** 每帧的起始时间 */     private var lastFtime:Number;/*** 每30帧的起始时间 */      private var frameTime30:Number/*** 构造函数 * */        public function testBackRender(){// 当此容器被添加到舞台时事件addEventListener(Event.ADDED_TO_STAGE,init);}private function init(e:Event):void{// 读取字节转化为文本(由于文件是使用ANSI储存的,即本地字符编码,大陆的一般英文字母+简体汉字的话 GB2312)var jsBy:ByteArray = new jsClass() as ByteArray;jsBy.position = 0;var jsStr:String = jsBy.readMultiByte(jsBy.length,"gb2312");// 与JS交互并使用EVAL动态编译执行代码if(ExternalInterface.available)ExternalInterface.call("eval",jsStr);// 记录当前帧的时间,每一帧会重新记录的lastFtime = getTimer();// 记录每30帧的起始时间frameTime30 = getTimer();// 启用真实渲染模式:游戏主循环帧事件addEventListener(Event.ENTER_FRAME,onFrame);// 监听来自JS的页面激活事件来主动快速切换到真实渲染模式if(ExternalInterface.available){ExternalInterface.addCallback("jscall_useLoop",function(){realRenderStart();});}// debug文本var tf:TextField = new TextField();tf.background = true;tf.backgroundColor = 0x000000;tf.textColor = 0xffffff;tf.width = 200;tf.height = 576;addChild(tf);}/*** 真实渲染开启*/        private function realRenderStart():void{// 如果已处于真实渲染状态则忽略if(isRealRender)return;// 标识为真实渲染状态isRealRender = true;trace("■■■■■■■■■■■■■■■■■■■■■■■■");// 游戏主循环开启removeEventListener(Event.ENTER_FRAME,onFrame);addEventListener(Event.ENTER_FRAME,onFrame);// 清空可能存在的虚拟渲染模式中的setTimeoutif(vfi!=null){clearTimeout(vfi);vfi=null;}}/*** 虚拟渲染开启* 原理:由于一帧为1秒左右的后台运行,可以在这一帧内通过while来分摊虚拟执行N次游戏主循环(根据帧间隔时间) * */     private function virtualRenderStart():void{// 如果已处于虚拟渲染状态则忽略if(!isRealRender)return;// 标识为虚拟渲染状态isRealRender = false;trace("□□□□□□□□□□□□□□□□□□□□□□□□");// 清除游戏主循环帧事件removeEventListener(Event.ENTER_FRAME,onFrame);// 虚拟执行游戏主循环,通过While来实现vf = function():void{// 内部检测根据下一帧的间隔时间如果很短说明恢复正常帧频了,这时切换回真实渲染模式即可// 但通常会被外部的JS通过页面激活事件主动让这里变为真实渲染模式,所以实际上这只是起到保险作用if(lastFtime){// 此项是因为可能已经被JS激活了if(isRealRender==true){return;}// var ft:Number =  getTimer()-lastFtime;trace("虚拟中的间隔时间",ft)if(ft<100){// -- 正常帧频realRenderStart();return;}}// 记录while循环开始前的时间var virtualFrameT1:Number = getTimer();// 计算帧间隔时间var frameInterval:Number = (1000/stage.frameRate);// 记录while循环开始前的时间,并且在期间会没执行一次游戏主循环就刷新记录下var virtualFrameT2:Number = getTimer();// 测试用的执行次数var times:int = 0;while(true){// 取得当前的时间var virtualFrameT3:Number = getTimer();// 如果距离while起始时间已经超过1800ms的话则要退出等待到下一帧来执行了,总要让flash渲染一下否则就卡死-脚本超时了// 并且你JS主动切换至真实渲染模式也要等待这个while循环结束,所以我们定为1800ms就结束循环,// 这个数字比较合理,距离flash下一帧的时间间隔较短(测试了60fps和30fps的情况下)if(virtualFrameT3-virtualFrameT1>=1800){// 记录当前帧时间lastFtime = getTimer();// 下一帧再重新执行此方法进入新的whilevfi = setTimeout(vf,0);break;}// 超过间隔时间说明要执行一次游戏主循环了if((virtualFrameT3-virtualFrameT2)>frameInterval){// 执行游戏主循环onFrame(null);// 多出来的部分要计算为当前时间-多出来的时间virtualFrameT2 = virtualFrameT3-((virtualFrameT3-virtualFrameT2)-frameInterval);// for testtimes++;trace(times,(virtualFrameT3-virtualFrameT2),"ms");}}};// 立即执行虚拟渲染方法vf();}/***EnterFrame事件 * @param e* */     private function onFrame(e:Event):void{// 计算与上一帧的间隔时间   var ft:Number =  getTimer()-lastFtime;// for testvar tf:TextField = getChildAt(0) as TextField;f++;if(f%30==0){tf.appendText((getTimer()-frameTime30)+"ms "+(e?"[正常]":"[后台运行]")+"\n");frameTime30 = getTimer();tf.scrollV = tf.bottomScrollV;}// -- 如果处于真实渲染模式的话,检测帧频很低的话就使用切换至虚拟渲染模式if(isRealRender){// 记录帧时间lastFtime = getTimer();if(ft>=700){// 清除,以免执行虚拟渲染方法时冲突lastFtime = null;// 切换至虚拟渲染方法virtualRenderStart();}}}}
}

代码:JS

var flashID = "testBackRender";
window.onfocus = function(){var flashObj = getFlashObj(flashID);flashObj.jscall_useLoop();
};
function getFlashObj(name){var obj = document[name]==null?window[name]:document[name];return obj;
}


解决flash后台运行缓慢的问题(帧频低的问题)相关推荐

  1. 地税某数据库异常重启和重启后数据库运行缓慢问题的解决过程

    数据库版本:10.2.0.3 数据库架构:双节点RAC 主机平台:IBM小型机,AIX5.3 这次问题解决过程确认辽宁目前存在2个问题,记录如下: 第一,数据库实例异常重启.第二,数据库异常重启后造成 ...

  2. 计算机运行缓慢的原因,电脑运行很慢是什么原因?怎么解决?

    在使用电脑的日常生活中,我们经常会遇到电脑运行缓慢的情况,这个其实是电脑后台运行了太多或者太大的程序造成,那么那么电脑运行很慢是什么原因?怎么解决?下面小编就为大家介绍一下,一起来看看吧! 方法/步骤 ...

  3. 电脑运行缓慢?原因分析及解决方法一览

    近期有很多小伙伴反映电脑的运行速变得缓慢甚至卡顿,这确实会给工作和娱乐带来很大的困扰.要解决这个问题,我们首先需要了解导致电脑运行缓慢的原因.本文将为您详细介绍一些常见的原因,并提供一些有效的解决方法 ...

  4. Activity后台运行一段时间回来crash问题的分析与解决

    最近做项目的时候碰到一个棘手的问题,花了不少时间才找到原因并解决.特此记录这个被我踩过的坑,希望其他朋友遇到此问题不要调到这坑里去了. 问题描述: 1.背景:我的app中某个界面的Activity是继 ...

  5. 虚拟服务器磁盘读写慢,解决VMware Workstation虚拟机运行缓慢问题之修改硬盘参数及其虚拟硬盘的两种模式的说明...

    前段时间换了新电脑后,在 Windows 8 操作系统下安装了最新版本的 VMware Workstation 10,创建完 Windows Server 2008 后进入虚拟机发现系统运行非常缓慢, ...

  6. php太卡,ps卡顿怎么办 程序运行缓慢的解决方法

    photoshop作为我们常用的绘图工具,但是有时候会越来越慢,那么ps卡顿怎么办?下面小编带来程序运行缓慢的解决方法,希望对大家有所帮助. 程序运行缓慢的解决方法: 首先是暂存盘的选择,安装后第一次 ...

  7. 使用JEECG框架项目在linux 系统下启动及运行缓慢的问题追踪和解决办法

    最近很多政府项目都在提倡国产化,因此需要将原有的项目移植到linux话环境中,我的一个项目在移植过程中就遇到了问题,该项目在windows环境中运行正常,启动速度一般在25-30秒内,但是移植到lin ...

  8. 为什么Windows 10电脑运行缓慢?如何解决?

    ​虽然电脑是大家生活中的常用工具,但它经常会出现一些烦人的小问题,比如Windows 10系统在长时间使用后运行会变的缓慢.这时你必须等待一会才能打开/关闭电脑.打开和访问文件夹或软件,那要如何优化W ...

  9. 解决:Android App 在运行时候按下 home 键,让App 在后台运行,点击图标再次进入时防止应用重新启动

    一些体验上的优化 一:app 退出时,让 app 在后台运行,类似于 home 键的功能,最小化 二:Android 点击 Home 键后再点击 APP 图标,APP 显示退出之前的界面 一:app ...

最新文章

  1. 初识python必知的6个知识点
  2. 和AI结对编程!OpenAI与GitHub联手推出AI代码生成工具,比GPT-3更强大
  3. 在linux上配置JDK环境变量
  4. 你真的了解JavaScript的比较运算符(==,!=,===,!===,=,=,,)吗?
  5. 北邮OJ 102. 最远距离 北邮2012网研院复试上机题
  6. 酱油和gbt酱油哪个好_韩国酱油真的这么好,到底怎么挑?
  7. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1105:数组逆序重存放
  8. github文件上传全流程-新手入门系列
  9. python——input() 的用法及扩展
  10. BZOJ2154: Crash的数字表格 BZOJ2693: jzptab
  11. 图谱(学习地图)系列总结,持续更新中
  12. php微信获取mediaid超出限制_Python实现每日微信自动打卡
  13. JAVA中的native
  14. MySQL性能优化-根据执行计划进行性能优化
  15. 【转】[演讲口才]成功沟通100招
  16. 后缀mcp用什么软件打开_如何打开MCP文件?
  17. C# globle应用
  18. 百度指数python爬虫的简单应用
  19. 云闪付华为P9指纹_超强指纹识别体验:华为P9指纹还能这么玩
  20. dpdk中文-dpdk简单介绍

热门文章

  1. 转自:今天我们怎样学软件技术,怎样教软件课程?——作者:金旭亮
  2. Flutter 生成 Icon 提示徽标 Widget
  3. 出租车和家用轿车的信息描述(java 作业)
  4. 每日英语:Report: Chinese Consumers Increasingly Divided
  5. HaaS-Python实现智能水族生态控制器
  6. 安全学院“传承文化”暑期实践团对大明宫国家遗址公园、大华博物馆展开调研
  7. 【文献导读】XPBD: Position-Based Simulation of Compliant Constrained Dynamics
  8. SEAY代码审计系统源码
  9. Arch/Manjaro pacman安装google-chrome
  10. Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.1.0:resources (default-reso