在具有巨大世界的游戏中正确使用scene2d的舞台

时间:2013-10-31 05:31:55

标签: libgdx scene2d

如果整个“游戏世界”比视口宽几千倍,并且如果我想使用scene2d将游戏对象管理为Actor,我应该创建与全世界一样宽的Stage对象,或者Stage应该是当前视口周围的某个区域而不是整个世界? 换句话说,具有更大宽度和高度的Stage本身是否会消耗更多内存,即使我只在一个小视口大小的部分上渲染对象?

2 个答案:

答案 0 :(得分:13)

我认为你误解了Stage究竟是什么。舞台本身并没有真正的尺寸。您没有指定宽度或高度或Stage,您只需指定视口的宽度和高度。视口就像一个窗口,只显示您的世界的一部分,即场景。 Stage是一个2D场景图,它会随着Actors“增长”。你拥有的Actors越多,你的舞台就越大(记忆力越强),但它并不取决于你的Actors实际上有多远。如果它们非常普及并且您只显示整个Stage的一小部分,那么它将被处理得非常有效,因为场景图将这个巨大的空间细分为能够非常快速地决定是否忽略某个演员,或者在屏幕上画出来。

这意味着Stage实际上正是你需要的这种情况,你应该没有任何问题,FPS和内存明智。 但是当然,如果您的Stage是视口大小的1000倍,并且您知道某些Actors很快就不会显示,那么将它们添加到舞台呢。

答案 1 :(得分:0)

一个阶段只是一个将容纳所有演员的根节点。它的作用是为孩子调用方法(如绘画和行为);因此,只有actor的数量和复杂性才会对内存和帧速率产生影响。


对于您的情况,肯定需要剔除方法。最简单的方法是检查一个actor是否在视口中,如果没有,则跳过绘制他。创建自定义actor并添加以下代码:source

        public void draw (SpriteBatch batch, float parentAlpha) {
            // if this actor is not within the view of the camera we don't draw it.
            if (isCulled()) return;

            // otherwise we draw via the super class method
            super.draw(batch, parentAlpha);
        }    




        Rectangle actorRect = new Rectangle();
        Rectangle camRect = new Rectangle();
        boolean visible;

        private boolean isCulled() {

            // we start by setting the stage coordinates to this
            // actors coordinates which are relative to its parent
            // Group.
            float stageX = getX();
            float stageY = getY();

            // now we go up the hierarchy and add all the parents'
            // coordinates to this actors coordinates. Note that
            // this assumes that neither this actor nor any of its
            // parents are rotated or scaled!
            Actor parent = this.getParent();
            while (parent != null) {
                stageX += parent.getX();
                stageY += parent.getY();
                parent = parent.getParent();
            }

            // now we check if the rectangle of this actor in screen
            // coordinates is in the rectangle spanned by the camera's
            // view. This assumes that the camera has no zoom and is
            // not rotated!
            actorRect.set(stageX, stageY, getWidth(), getHeight());
            camRect.set(camera.position.x - camera.viewportWidth / 2.0f,
                    camera.position.y - camera.viewportHeight / 2.0f,
                    camera.viewportWidth, camera.viewportHeight);
            visible = (camRect.overlaps(actorRect));
            return !visible;
        }


如果您需要进一步提高性能,可以切换到手动确定可见和不可见的内容(例如移动相机时)。这会更快,因为所有那些剔除计算都是在每个帧执行,对于每个演员。因此,尽管做一些数学而不是绘画要快得多,但是大量演员会给出大量不需要的电话。