2
\$\begingroup\$

I am trying to make a two sided platform game in Libgdx. Where I am scrolling through the TiledMap. I was easily implementing the horizontal scrolling using..

camera.position.x = player.getPositionX();

and it works fine. But when it comes to Vertical scroll .. I am observing very bad effects doing the same thing on y-axis. I tried it many ways. But No code could give could a real look and feel. Later I happen to find this video

http://blog.mimeoverse.com/post/581467761/the-ideal-platformer-camera-should-minimize

it says " The ideal platformer camera should:

minimize vertical motion lead in the direction the player is facing remain motionless during horizontal micro-adjustments The secret to achieving all three is (what I call) the trap. The trap is an invisible rectangle (made visible for this demo), roughly twice as wide and tall as the player sprite, with the same starting coordinates. Rather than follow the player sprite directly the camera follows the trap. When the player moves within the trap, the camera does not move. The trap only moves when the player pushes against one of its edges. " it demonstrates a good idea but Still there still seems something bad .. I am writing some wrong code

Rectangle trap_old,trap_new;

.....

trap_old = new Rectangle(player.getPositionX()-2*player.getWidth(),
                        player.getPositionY()+5*player.getHeight(),
                        5*player.getWidth(),
                        6*player.getHeight());

//.. inside render

trap_new = getNewTrapArea(player.getPositionX(),
                        player.getPositionY(),
                        player.getWidth(),
                        player.getHeight());

camera.position.x = trap_new.x;
camera.position.y = trap_new.y;
camera.update();

private Rectangle getNewTrapArea(float positionX, float positionY, float width, float height) {
    Rectangle temp = new Rectangle(positionX, positionY, width, height);
    if(temp.overlaps(trap_old))
        trap_new = trap_old;
    else
        trap_old = trap_new = new Rectangle(positionX-2*width, positionY+5*height, 5*width, 6*height);
    return trap_new;
}
\$\endgroup\$
1
  • \$\begingroup\$ I haven't looked through all of your code yet, I just wanted to make sure that when you initialize trap_old you meant to add 5*player.getHeight() instead of subtracting it. I can't tell what coordinate system you're using. \$\endgroup\$
    – Vincenzo
    Commented Jun 13, 2013 at 4:26

1 Answer 1

2
\$\begingroup\$

You need to rewrite the getNewTrapArea function. Instead of checking whether the two rectangles overlap, you should check whether the player is contained in the trap. Also, it's unnecessary to have two trap rectangles as fields of the class. The code below assumes you only have one, called trap.

Note: it wastes memory to recreate the rectangles every step. You should create the player and trap rectangles at the start of the game, and then just change the x and y values when the rectangles need to be moved.

Here is the code:

//in class
Rectangle trap, playerBounds;
//at start
playerBounds = new Rectangle(player.getPositionX(), player.getPositionY(), player.getWidth(), player.getHeight());
trap = new Rectangle(player.getPositionX()-2*player.getWidth(),
                    player.getPositionY()+5*player.getHeight(),
                    5*player.getWidth(),
                    6*player.getHeight());
//.. inside render
playerBounds.x = player.getPositionX();
playerBounds.y = player.getPositionY();
setNewTrapArea();
camera.position.x = trap.x;
camera.position.y = trap.y;
camera.update();

and the setNewTrapArea function:

private void setNewTrapArea() {
    if(trap.contains(playerBounds))
        return;
    if (playerBounds.x < trap.x)
        trap.x = playerBounds.x;
    else if (playerBounds.x + playerBounds.width > trap.x + trap.width)
        trap.x = playerBounds.x + playerBounds.width - trap.width;
    if (playerBounds.y < trap.y)
        trap.y = playerBounds.y;
    else if (playerBounds.y + playerBounds.height > trap.y + trap.height)
        trap.y = playerBounds.y + playerBounds.height - trap.height;
}

It might make more sense to have bounds be a field of the player class, but I'll leave that up to you.

\$\endgroup\$
2
  • \$\begingroup\$ Great Help. Thanks a lot lan. Things are working fine now. But there seems a problem when I want not to let the camera show places, where there is no map... this is a obvious solution I got from a tutorial if(camera.position.x<400){ camera.position.x=400; }else if(camera.position.x>map.widthmap.tileWidth-400){ camera.position.x=map.widthmap.tileWidth-400; } //...and same for y also but don't know how to get width n height in the new version of libgdx \$\endgroup\$ Commented Jun 13, 2013 at 7:22
  • \$\begingroup\$ Shouldn't you know how big your levels are? \$\endgroup\$ Commented Jun 13, 2013 at 8:17

You must log in to answer this question.

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