8
\$\begingroup\$

Is there a method to know if a sprite has left the camera of the stage? or I have to do my operations? :P

\$\endgroup\$

4 Answers 4

5
\$\begingroup\$

The Camera class contains a Frustum object with the public method pointInFrustum (Vector3 point) which returns true if your sprite is within the frustum of the camera . You can also have a look at the user wiki for other culling techniques. http://code.google.com/p/libgdx-users/wiki/Culling

\$\endgroup\$
2
  • 2
    \$\begingroup\$ pointInFrustum(point) returns true if the specified point is within the frustum, not a Sprite. The Sprite could have its own width and height so it can't be checked to be inside the screen using that method directly. \$\endgroup\$
    – arielsan
    Commented Mar 6, 2012 at 13:26
  • \$\begingroup\$ @arielsan As long as you can check if a point is inside the frustum, you can simply check if all four points of a sprite are in a frustum. \$\endgroup\$ Commented Jul 26, 2018 at 10:33
3
\$\begingroup\$

If you are creating a 2D game with tiles you can easily implement your own culling which is a lot cheaper since you only itterate over exactly what you need within your tile array.

Things you should know:

  • Camera location
  • Viewport width/height
  • Tile width/height

Now we can calculate how many tiles should be drawn.

  • Total horizontal tiles on screen = viewport.width / tileWidth
  • Total vertical tiles on screen = viewport.height / tileHeight

The math depends on how everything is set up but is very simple. For example it makes a difference if the center of the screen is the camera location, the top left or bottom left.

You should end up with something like this:

int startX = cameraWorldPosX / tileWidth;
int startY = cameraWorldPosY / tileHeight;

//When you have the position of the camera in the center of the screen you do something like this:

int startX = (cameraWorldPosX - viewport.width / 2) / tileWidth;
int startY = (cameraWorldPosY - viewport.height / 2) / tileHeight;

for (int y = startY; y < startY + viewportWidth / tileWidth; y++)
{
    for (int x = startX; x < startX + viewportHeight / tileHeight; x++)
    {
        //Draw logic
    }
}

The benefit of this over checking if a point is within your frustum is that with the latter you need to iterate over each point instead of using some simple array where you always itterate over a set amount of tiles that is equal to the amount of horizontal tiles * vertical tiles that actually need to draw. This way you can have huge maps and still have a good frame rate. Unfortunately this gets harder and trickier when using 3D but gets exponentially harder with the freedom the user gets with the camera. You can imagine a fixed perspective camera that moves with the character just needs a couple of hardcoded variables to do the same tricks on an array of meshes that represent your map.

\$\endgroup\$
0
\$\begingroup\$

Just use bounding sphere check.(you can calculate radius using pythagoras ) It fast as hell and also work with rotation. It's not perfect but never cause false culling.

For ad hoc optimized version Intersector have some rectangle contain rectanle methods these can work too. But you need to calculate rectangle for camera frustum your self.

\$\endgroup\$
0
\$\begingroup\$

This function checks if an actor is visible (works only for 2D). Works in all situations, for example when the actor is inside a group.

    /**
     * Returns if the actor is visible or not. Useful to implement 2D culling.
     **/
    public static boolean actorIsVisible(Actor actor) {
        Vector2 actorStagePos = actor.localToStageCoordinates(new Vector2(0,0));
        Vector2 actorStagePosTl = actor.localToStageCoordinates(new Vector2(
            actor.getWidth(), 
            actor.getHeight()));

        Vector3 actorPixelPos = new Vector3(actorStagePos.x, actorStagePos.y, 0);
        Vector3 actorPixelPosTl = new Vector3(actorStagePosTl.x, actorStagePosTl.y, 0);

        actorPixelPos = actor.getStage().getCamera().project(actorPixelPos);
        actorPixelPosTl = actor.getStage().getCamera().project(actorPixelPosTl);

        return !(actorPixelPosTl.x < 0 ||
                 actorPixelPos.x > Gdx.graphics.getWidth() ||
                 actorPixelPosTl.y < 0 ||
                 actorPixelPos.y > Gdx.graphics.getHeight()
                );
    }
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .