cocos2d-js 越来越慢的定时器schedule 制作不变慢的定时器
对于动画控制,可能一点误差,大家不会察觉,但如果多次循环累积或网络同步等,大家就会很清楚意识到schedule的误差问题。
首先做一个例子证明一下:
var InaccuracyTestLayer = cc.Layer.extend({
ctor: function () {
this._super();
var startTime = new Date().getTime();
var count = 0;
this.schedule(function(){
var timePass = new Date().getTime() - startTime;
count++;
var delta = timePass - (count*100);
trace("time pass", timePass, "total delta", delta, "count", count);
}, 0.1);
this.scheduleUpdate();
},
update: function () {
for (var i = 0; i < 100000; i++) {
b = 1/0.22222;
}
}
});
帧频越低,变慢得越快。
time pass, 1481, total delta, 381, count, 11 CCDebugger.js:334
time pass, 1608, total delta, 408, count, 12 CCDebugger.js:334
time pass, 1735, total delta, 435, count, 13 CCDebugger.js:334
time pass, 1861, total delta, 461, count, 14 CCDebugger.js:334
那么尝试一下解决问题?
定时器原理:cocos2d-js底层在每一帧计算中,遍历所有定时器,看是否达到触发时间。如果达到则触发该定时器,并把时间重置为当前时间。好了,问题就在于此,“重置为当前时间”。
看看一个新的定时器:
schedule2: function (callback, interval) {
var then = Date.now();
interval = interval*1000;
this.schedule(function(){
var now = Date.now();
var delta = now - then;
if(delta > interval){
then = now - (delta % interval);
callback.call(this);
}
}.bind(this), 0);
}
这里核心是then=now-(delta%interval),每一次触发的时候,把误差算到下次触发的控制中。
例如60fps,那么schedule2每16ms触发一次,用户设定了100ms的interval,那么将有16*7=112>100,7帧才触发1次用户的定时器。这里累积了12ms误差,把12ms算到then中。
那么下次将有12+16*6=108>100,只需要96ms就触发第2次用户的定时器,这次提前了4ms,弥补了第1次的误差。
这个定时器经得起考验,即使在低帧频情况下,仍然保持稳定。
var BetterScheduleLayer = cc.Layer.extend({
ctor: function () {
this._super();
var startTime = Date.now();
var count = 0;
this.schedule2(function(){
var timePass = Date.now() - startTime;
count++;
var delta = timePass - (count*100);
trace("time pass", timePass, "total delta", delta, "count", count);
}, 0.1);
this.scheduleUpdate();
},
schedule2: function (callback, interval) {
var then = Date.now();
interval = interval*1000;
this.schedule(function(){
var now = Date.now();
var delta = now - then;
if(delta > interval){
then = now - (delta % interval);
callback.call(this);
}
}.bind(this), 0);
},
update: function () {
for (var i = 0; i < 10000000; i++) {
b = 1/0.22222;
}
}
});
输出:
time pass, 3447, total delta, 47, count, 34 CCDebugger.js:334
time pass, 3510, total delta, 10, count, 35 CCDebugger.js:334
time pass, 3637, total delta, 37, count, 36 CCDebugger.js:334
time pass, 3701, total delta, 1, count, 37 CCDebugger.js:334
time pass, 3828, total delta, 28, count, 38 CCDebugger.js:334
time pass, 3955, total delta, 55, count, 39 CCDebugger.js:334
cocos2d-js 越来越慢的定时器schedule 制作不变慢的定时器的更多相关文章
- cocos2d js ClippingNode 制作标题闪亮特效
1.效果图: 之前在<Android 高仿 IOS7 IPhone 解锁 Slide To Unlock>中制作了文字上闪亮移动的效果,这次我们来看下怎样在cocos2d js 中做出类似 ...
- Cocos2d Lua 越来越小样本 内存游戏
1.游戏简介 一个"记忆"类的比赛游戏.你和电脑对战,轮到谁的回合,谁翻两张牌,假设两张牌一样.就消掉这两张牌,得2分,能够继续翻牌,假设两张牌不一样,就换一个人.直到最后.看谁的 ...
- cocos2d js jsb XMLHttpRequest 中文乱码
1.首先讲下怎样使用XMLHttpRequest 下面所说的是在cocos2d-x 2.2.2 或者 2.3 版本号中. 首先要明确cocos2d js事实上分两个版本号,一个是html5的版本号,另 ...
- cocos2d js的一些tip
cocos2d-js-v3.2-rc0 cc.director.end();//退出app cc.Application.getInstance().openURL("http://www. ...
- cocos2dx打飞机项目笔记七:各种回调:定时器schedule、普通回调callFunc、菜单回调menu_selector、事件回调event_selector
各种回调函数的定义: typedef void (CCObject::*SEL_SCHEDULE)(float); typedef void (CCObject::*SEL_CallFunc)(); ...
- cocos2dx基础篇(6) 定时器schedule/update
定时器在大部分游戏中是不可或缺的,即每隔一段时间,就要执行相应的刷新体函数,以更新游戏的画面.时间.进度.敌人的指令等等.cocos2dx为我们提供了定时器schedule相关的操作.其操作函数的定义 ...
- 【js】Leetcode每日一题-制作m束花所需的最少天数
[js]Leetcode每日一题-制作m束花所需的最少天数 [题目描述] 给你一个整数数组 bloomDay,以及两个整数 m 和 k . 现需要制作 m 束花.制作花束时,需要使用花园中 相邻的 k ...
- STM32定时器配置(TIM1-TIM8)高级定时器+普通定时器,定时计数模式下总结
文章结构: ——> 一.定时器基本介绍 ——> 二.普通定时器详细介绍TIM2-TIM5 ——> 三.定时器代码实例 一.定时器基本介绍 之前有用过野火的学习板上面讲解很详细,所以 ...
- cocos2d JS 利用定时器实现-倒计时功能
//创建一个定时器 cc.director.getScheduler().schedule(this, this.updates, 1, cc.REPEAT_FOREVER, 0, false, &q ...
随机推荐
- ExtJS 4.2 教程-07:Ext.Direct
转载自起飞网,原文地址:http://www.qeefee.com/extjs-course-7-Ext-Direct ExtJS 4.2 教程-01:Hello ExtJS ExtJS 4.2 教程 ...
- MVC异步分页
如图: 1: 控制器代码 // // GET: /AjaxUser/ shopEntities shop = new shopEntities(); public ActionResult Index ...
- Docker 常用命令与操作
介绍 此命令集合版本为 1.11.1 及以上 基础类 查看docker信息 # 查看docker版本 docker version # 显示docker系统的信息 docker info # 日志信息 ...
- UEFI与 Legacy BIOS两种启动模式详解
(1). UEFI启动模式 与 legacy启动模式 legacy启动模式: 就是这么多年来PC一直在使用的启动方式(从MBR中加载启动程序),UEFI BIOS作为一种新的BIOS自然也应该兼容这种 ...
- Python Configparser模块读取、写入配置文件
写代码中需要用到读取配置,最近在写python,记录一下. 如下,假设有这样的配置. [db] db_host=127.0.0.1 db_port=3306 db_user=root db_pass= ...
- Zindex和png
Z轴在元素设置position为absolute或relative后被激活,起大小由z-index设置,z-index越大,元素位置越靠上.如果多个元素的z-index值相同,那么html标签中后出现 ...
- 条件随机场(CRF)理论及应用
http://x-algo.cn/index.php/2016/02/15/conditional-random-field-crf-theory-and-implementation/ 条件随机场( ...
- java中两种发起POST请求,并接收返回的响应内容的方式 (转)
http://xyz168000.blog.163.com/blog/static/21032308201162293625569/ 2.利用java自带的java.net.*包下提供的工具类 代码如 ...
- MySQL数据库localhost的root用户登陆遭遇失败
问题:Access denied for user 'root'@'localhost' (using password: YES)打开MySQL目录下的my.ini文件(Linux的话是/etc/m ...
- Cognos11中报XQE-JDB-0004查找驱动程序类错误
1:问题描述,在cognos11中创建了一个数据源连接TestData, 类型为Microsoft SQL Server (OLE DB) 操作如下: 同时配置了jdbc的连接方式,如下图所示 测试数 ...