深入理解LayaAir引擎架构和实现原理(三)引擎渲染主循环与AOP介入控制

最近完善了下LayaTree,顺便看了看Laya引擎源码的主循环和渲染部分。这节的话,来聊聊Laya引擎的渲染主循环,以及如何在外部暂停和单帧步进调试。

1.引擎启动入口

工程的入口文件一般为Main.ts,这里面不仅需要处理项目相关的逻辑初始化,也会调用Laya3D.init()进行Laya引擎的初始化。
在init中,可以看到创建了两个画布,mainCanvas是引擎的主画布,所有游戏内的canvas和webgl渲染都用这个画布。canvas是一个全局离线画布,不会加到DOM上,主要用来测量字体、获取image数据。

  • 主画布

    同样在初始化中还创建了渲染器Render,它是一个管理渲染的单例。

2.渲染结构

Rander


来看Rander的构造函数发现,游戏渲染的主循环是通过window.requestAnimationFrame不断loop实现的,是程序的主要更新源头。
需要注意的是window.requestAnimationFrame原生的浏览器重绘接口函数都不兼容时。Laya引擎会使用setTimeout代替。

        win.requestAnimationFrame = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || win.msRequestAnimationFrame || function (fun: any): any {
            return win.setTimeout(fun, 1000 / 60);
        }

initRender()为画布初始化函数,创建和保存了WebGL上下文环境。如需更改canvas的参数,如设置是否抗锯齿,请在初始化引擎之前设置。

Stage

Stage是一个单例舞台类,显示列表的根节点,所有显示对象都在舞台上才能被显示。Stage中的_loop()函数就是帧循环函数,函数内部调用render函数用于渲染当前context渲染上下文和更新逻辑。

这边主要的功能是:清空画布——提交渲染——更新逻辑。引擎内所有的计时器timer都是在这里更新的。其中super.render(context, x, y); 属于stage的父类Sprite类的方法,渲染具体实现的地方。与其他引擎不同的是,Laya的帧率只有两种,高帧率模式固定60帧,低帧率模式
为双帧处理一次渲染,固定30帧。

Sprite

Stage的父类是Sprite。 Sprite是基本的显示图形的显示列表节点。默认没有宽高,默认不接受鼠标事件。通过graphics可以绘制图片或者矢量图,支持旋转,缩放,位移等操作。同时也是容器类,可用来添加多个子节点。LayaAir引擎API设计精简巧妙。核心显示类只有一个Sprite。Sprite针对不同的情况做了渲染优化,所以保证一个类实现丰富功能的同时,又达到高性能。

Sprite的renders函数对renders数组(RenderSprite数组)中的第this._renderType个RenderSprite精灵进行渲染(调用_fun函数),_fun函数是RenderSprite类的方法,定义了属于不同类型的不同的渲染方式,里面都是通过调用Context类的方法进行绘制的
需要注意的是RenderSprite在Laya.init初始化的时候就已经创建了,默认是预创建了8192*2个精灵渲染器。它的渲染_fun类型会根据传入的Sprite的_renderType决定渲染方式。

Context

Context扩展类主要用来进行绘制。

流程图

3.AOP介入

面向切面编程

面向切面编程(AOP是Aspect Oriented Program的首字母缩写), 是通过预编译方式和运行期动态代理的方式实现不修改源代码的情况下给程序动态统一添加功能的技术。比如装饰器就是在预编译阶段执行的,本文介绍的控制游戏主流程的方法是在运行时执行的。

AOP面向切面编程是针对业务处理过程中的切面进行提取,它所面对的是处理过程中某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。所以可以在不修改Laya引擎的情况下实现功能。

实现AOP介入控制Laya游戏暂停和单步运行的代码

// 注入脚本的代码
export default function () {
    // 检测是否包含Laya变量
    var isLayaGame = true;
    try {
        var layaGame = Laya;
    } catch (e) {
        isLayaGame = false;
    }


    if (isLayaGame) {
        // laya 暂停状态
        window.layaStatePause = false;

        // laya 需要单步次数
        window.layaStepCount = 0;

        let rawRequestAnimationFrame = window.requestAnimationFrame;

        let renderRec = null;

        function loopCheck(stamp) {
            if (renderRec != null) {
                window.requestAnimationFrame(renderRec);
            }
        }

        window.requestAnimationFrame = function (render) {
            if (renderRec == null) {
                renderRec = render;
            }

            if (window.layaStatePause) {
                if ( window.layaStepCount > 0) {
                    window.layaStepCount -= 1;
                    rawRequestAnimationFrame(renderRec);
                } else {
                    rawRequestAnimationFrame(loopCheck);
                }
            } else {
                rawRequestAnimationFrame(renderRec);
            }
        };
    }
}

运行效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring是一个开源的Java框架,它提供了大量的功能和特性来简化Java应用程序的开发。下面我将分别解释ioc和aop的概念,并介绍一下aop原理。 1. ioc(Inversion of Control,控制反转):ioc是Spring框架的核心概念之一。它通过将对象的创建、依赖关系的管理和对象的生命周期交给容器来管理,实现了对象之间的解耦和灵活性。在传统的开发方式中,对象之间的创建和依赖关系需要由开发者手动管理,而在使用ioc容器后,只需要通过配置文件或注解来描述对象之间的依赖关系,容器会负责创建和管理这些对象。 2. aop(Aspect-Oriented Programming,面向切面编程):aop是一种编程范式,它的目标是将程序中的横切关注点(如日志记录、事务管理等)与核心业务逻辑分离开来,使得代码更具可维护性和可重用性。在Spring中,aop可以通过使用代理模式和动态代理来实现。它可以在不修改原有代码的情况下,通过在特定的切点上织入切面逻辑,从而实现对横切关注点的控制和管理。 3. aop原理:Spring框架使用动态代理来实现aop。在运行时,Spring会根据配置或注解,动态地为目标对象生成一个代理对象,并将切面逻辑织入到目标对象的方法执行前、执行后或异常处理等关键点。代理对象在执行方法时,会自动触发切面逻辑的执行。这使得开发者可以专注于核心业务逻辑的编写,而无需关注横切关注点的处理。 总结:Spring框架通过ioc和aop的结合,实现了面向对象编程的灵活性和重用性,使得开发者能够更加专注于核心业务逻辑的开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值