4.帧循环(游戏主循环),schedule
1 概述
游戏乃至图形界面的本质是不断地绘图,然而绘图并不是随意的,任何游戏都需要遵循一定的规则来呈现出来,这些规则就体现为游戏逻辑。游戏逻辑会控制游戏内容,使其根据用户输入和时间流逝而改变。因此,游戏可以抽象为不断地重复。
2 以下动作:
A 处理用户输入
B 处理定时事件
C 绘图
游戏主循环就是这样的一个循环,它会反复执行以上动作,保持游戏进行下去,直到玩家退出游戏。
CCDirector::mainLoop()方法,这个方法负责调动定时器,绘图,发送全局通知,并处理内存回收池。该方法按帧调用,每帧调用一次,而帧间间隔取决于两个因素,一个是预设的帧率,默认为60帧每秒:另一个是每帧的计算大小。当逻辑处理与绘图计算过大时,设备无法完成每秒60次绘制,此时帧率就会降低。
3 实现
mainLoop()方法是定义在CCDirector中的抽象方法,它的实现位于同一个文件中的CCDisplayLinkDirector类。代码如下:
上述代码主要包含如下3个步骤。
判断是否需要释放CCDirector,如果需要,则删除CCDirector占用的资源,通常,游戏结束时才会执行这个步骤。
调用drawScene()发方法,绘制当前场景并进行其他必要的处理。
弹出自动回收池,使得这一帧被放入自动回收池的对象全部释放。
在主循环中drawScene(),主要进行3个操作:
调用了定时调度器的update方法,引发定时器事件。
如果场景需要被切换,则调用setNextStage方法,在显示场景前切换场景。
调用当前场景的visit方法,绘制当前场景。
4 定时器
Schedule.h |
#ifndef __Schedule_H__ #define __Schedule_H__ #include "cocos2d.h" USING_NS_CC; class Schedule :public CCLayer { public: static CCScene * scene(); CREATE_FUNC(Schedule); bool init(); void update(float) override; void mySchedule(float dt); }; #endif |
Schedule.cpp |
#include "Schedule.h" #include "AppMacros.h" CCScene *Schedule::scene() { CCScene * scene = CCScene::create(); Schedule * layer = Schedule::create(); scene->addChild(layer); return scene; } bool Schedule::init() { CCLayer::init(); //scheduleUpdate(); //unscheduleUpdate(); //scheduleOnce(schedule_selector(Schedule::mySchedule), 2); schedule(schedule_selector(Schedule::mySchedule)); //功能等同scheduleUpdate();回调函数可以自定义 //schedule(schedule_selector(Schedule::mySchedule), 3); //CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay); //schedule(schedule_selector(Schedule::mySchedule),1,10,4); //4s以后,每隔1s执行一次回调,共执行10次 CCSprite * spr = CCSprite::create("p_2_01.png"); spr->setPosition(ccp(100,winSize.height / 2)); addChild(spr); spr->setTag(100); //CCMoveBy * by = CCMoveBy::create(2, ccp(300, 0)); //CCMoveBy * by1 = (CCMoveBy *)by->reverse(); //CCSequence *seq = CCSequence::create(by, by1, NULL); //spr->runAction(CCRepeatForever::create(seq)); return true; } void Schedule::update(float dt) { CCLOG("dt = %g",dt); static int i = 0; i++; if (i == 120) { //结束定时器 unscheduleUpdate(); CCLog("schedule is over"); } } void Schedule::mySchedule(float dt) { CCSprite * spr = (CCSprite *)getChildByTag(100); float v = 300 / 2; static int count = 0; count++; static bool flag = true; if (flag) { if ((spr->getPositionX() + v*dt) < 400) { spr->setPositionX(spr->getPositionX() + v*dt); } else { flag = !flag; } } if (!flag) { if ((spr->getPositionX() - v*dt) > 100) { spr->setPositionX(spr->getPositionX() - v*dt); } else { flag = !flag; } } if (count == 1000) { unschedule(schedule_selector(Schedule::mySchedule)); } } |
运行结果: |
5 定时器Schedule
A 帧循环定时器
scheduleUpdate();//帧循环定时器,每一帧都会被调动,对实时性要求非常高的,比如碰撞检测 void update(float delta); unscheduleUpdate();//关闭定时器 |
B 一次性定时器
参数解析:
scheduleOnce(SEL_SCHEDULE selector, float delay) //第一个参数表示要回调的函数,第二个参数表示延时 |
typedef void (CCObject::*SEL_SCHEDULE)(float); #define schedule_selector(_SELECTOR) (SEL_SCHEDULE)(&_SELECTOR); |
scheduleOnce (schedule_selector(Schedule::updateOnce),2); void updateOnce(float delta); |
C 自定义定时器
自定义定时器有3个重载函数,底层都默认调用了scheduleSelector,它的几个参数分别表示,scheduleSelector回调函数,interval时间间隔,repeat重复次数,delay延时执行。
void CCNode::schedule(SEL_SCHEDULE selector) { this->schedule(selector, 0.0f, kCCRepeatForever, 0.0f); } /本质同scheduleUpdate 但是可以自己写回调函数 void CCNode::schedule(SEL_SCHEDULE selector, float interval) { this->schedule(selector, interval, kCCRepeatForever, 0.0f); } void CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay){ m_pScheduler->scheduleSelector(selector, this, interval , repeat,delay, !m_bRunning); } |
D 定时器停止
void CCNode::unschedule(SEL_SCHEDULE selector); void CCNode::unscheduleAllSelectors(); |
注意:多个定时器,可并存,可彼此开始与停止。
4.帧循环(游戏主循环),schedule相关推荐
- 游戏主循环(Game Loop)的详细解析
译自:https://dewitters.com/dewitters-gameloop/ 一. 引言 游戏主循环是每个游戏的心跳,输送着整个游戏需要的养分.不幸的是没有任何一篇好的文章来指导一个菜鸟游 ...
- 游戏主循环基础例子 GameLoop
游戏主循环基础例子 GameLoop 这里比较简单,直接发代码好了 import timefrom loguru import loggerfrom core import GetDeltaTime, ...
- 游戏主循环(Game Loop)详解
每一个复杂的应用程序的核心都是一个循环(Loop) - 贯穿于一个应用程序生活周期的是一部分代码不断的重复执行时间.这个循环(Loop),可以就说是主循环.主循环的主要作用是:协调程序的行为(事件)和 ...
- cocos2d-x游戏开发(四)游戏主循环
欢迎转载:http://blog.csdn.net/fylz1125/article/details/8518737 终于抽时间把这个游戏写完了.由于没有自拍神器,所以把它移植到了Android上,用 ...
- [摘抄]游戏主循环逻辑
1. 最简单的情况 1 bool game_is_running = true; 2 while(game_is_running) 3 { 4 update_game(); // 逻辑帧 5 disp ...
- U-boot主循环main_loop分析
2019独角兽企业重金招聘Python工程师标准>>> 原文在我博客:http://blog.csdn.net/andy_wsj/article/details/8614905 最近 ...
- java实现游戏的循环及游戏帧数处理
引言: 制作游戏对游戏的循环处理无疑是重要的,只有处理对游戏的循环,才不会出现游戏的卡顿现象.我们知道游戏中的动画是由一帧帧的静止的画面形成的,那么如果每一帧的画面因为机器处理的不同使得渲染时间不同, ...
- 辛巴学院-Unity-剑英的c#提高篇(一)主循环
这是测试版 辛巴学院:正大光明的不务正业. 最近刚刚离开了我服务了三年多的公司,因为一个无数次碰到的老问题,没钱了. 之前不知道做什么好的时候,机缘巧合之下和哒嗒网络的吴总聊了一下,发现了vr gam ...
- C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例
C#开发Unity游戏教程循环遍历做出判断及Unity游戏示例 Unity中循环遍历每个数据,并做出判断 很多时候,游戏在玩家做出判断以后,游戏程序会遍历玩家身上大量的所需数据,然后做出判断,即首先判 ...
最新文章
- 802.1x------2
- UVA10341解方程(二分)
- 找呀志_ContentResolver操作ContentProvider数据
- 利旧IBM X3650m2 安装esxi5.1提供云桌面(备忘)
- zk框架_ZK Web框架思想
- 【Python AsciiArt】利用命令行打印出字符图案
- URL不能过长,否则summit方法提交失败
- goldengate for mysql_GoldenGate for mysql to mysql:单向同步
- 加强的alert confirm js自定义对话框 多个按钮 ICO自定义
- 4.设计包(design package)
- Win10窗口拖动时自动最大化的问题,屏幕显示绿框,中间显示1
- 新书推荐——Linux系统管理与服务器配置
- 维基百科英文语料库下载地址
- 算法工程师面试基础题目及答案
- 基于labview的打地鼠游戏制作
- 看着2022年世界杯,我无比怀念98世界杯
- WebApp - 微信浏览器解决安全提示“防盗号或诈骗,请不要输入QQ密码”
- C#开发斑马RFID打印机zt410
- 计算机基础的课程标准,《计算机基础》课程标准
- 2021-03-17
热门文章
- 给书配代码-电力经济调度(3):计及网络安全约束的经济调度模型
- 爬虫实战:要不是热爱学习,谁会爬小姐姐。分析Ajax来爬取今日头条街拍美图(python)
- python打包exe 之打包sklearn模型中的各种坑及其解决方法。
- JavaScript实现判断整数是否为2的幂isPowerOfTwo算法(附完整源码)
- wxWidgets:wxDialog类用法
- boost::spirit模块实现一个复数微生成器的测试程序
- boost::mpl模块at相关的测试程序
- boost::gil模块数字扩展中的 resample_pixels() 示例
- boost::enable_current_exception用法测试程序
- boost::callable_traits添加member_cv的测试程序