使用场景2D的舞台在一个拥有巨大世界的游戏中的正确方法

8
如果整个“游戏世界”比视图窗口宽度大数千倍,而我想使用scene2d将游戏对象管理为Actor,那么我应该创建宽度与整个世界相同的Stage对象,还是Stage应该是围绕当前视口的某个区域而不是整个世界?换句话说,即使我只在小视口大小的部分上渲染对象,具有更大宽度和高度的Stage会消耗更多的内存吗?
2个回答

14
我认为你误解了Stage的实际意义。一个Stage本身并没有尺寸大小。你不需要指定Stage的宽度或高度,只需要指定视口的宽度和高度。视口就像一个窗口,它只展示你的世界(场景)的一部分。一个Stage是一个2D场景图,它会随着Actors的增多而“增长”。你拥有的Actor越多,你的Stage就越大(在内存方面),但这并不取决于你的Actor有多么分散。如果它们相距甚远,而你只显示整个Stage中的很小一部分,那么这将非常高效,因为场景图会将这个巨大的空间划分成子空间,能够非常快速地决定是否忽略某个Actor或者将其绘制到屏幕上。
这意味着一个Stage实际上正是你在这种情况下所需要的,FPS和内存方面都应该没问题。但是,如果你的Stage比视口大很多倍,同时你知道某些Actor不会立即显示,那么不将它们添加到Stage中可能是有意义的。

0

一个舞台只是一个根节点,用于容纳所有的演员。它的作用是调用其子节点的方法(如绘制和行动);因此,只有演员的数量和复杂度会对内存和帧率产生影响。


针对您的情况,肯定需要一个剔除方法。最简单的方法是检查演员是否在视口中,如果不在,则跳过绘制。创建一个自定义演员并添加此代码: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;
        }


如果您需要进一步提高性能,可以手动决定什么是可见的,什么不可见(例如在移动相机时)。这将更快,因为所有那些剔除计算都在每个帧中执行,对于每个Actor。因此,尽管进行一些数学运算比绘图要快得多,但大量的演员会产生大量不必要的调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接