user959631
user959631

Reputation: 992

Bouncing sprite off walls when sprite is rotating with accelerometer

I have a sprite that rotates based on the pitch and roll of the device. The code that I use to rotate the sprite is:

double myRadians = Math.atan2(-Gdx.input.getRoll(), Gdx.input.getPitch());
float myDegress = Math.round(((myRadians*180)/Math.PI));

I also set the position of the sprite like so:

float yChange = Math.round(Gdx.input.getRoll());
float xChange = Math.round(-Gdx.input.getPitch());
float yMove = Math.round(yChange/1.5);
float xMove = Math.round(xChange/1.5);

Now, when ever this sprite object collides with a "wall" I want it to bounce back. But mirrored first. I have done that like so:

// mirror sprite
// pitchAndRoll is a Vector2 and set to the pitch and roll 
// at the time of collision
float flippedRotation = sprite.getRotation() * -1;

float yChange = Math.round(pitchAndRoll.y);
float xChange = Math.round(-pitchAndRoll.x);

if (whichWall.equals(Walls.WALL_LEFT)){
    // left wall        

    flippedRotation = sprite.getRotation() * -1;

    xChange = Math.round(pitchAndRoll.x);
}else if (whichWall.equals(Walls.WALL_RIGHT)){
    // right wall   

    flippedRotation = sprite.getRotation() * -1;

    xChange = Math.round(pitchAndRoll.x);
}else if (whichWall.equals(Walls.WALL_BOTTOM)){
    // bottom wall

    flippedRotation += 180;                 

    yChange = Math.round(-pitchAndRoll.y);
}else if (whichWall.equals(Walls.WALL_TOP_LEFT)){
    // top left wall        

    flippedRotation += 180;     

    yChange = Math.round(-pitchAndRoll.y);
}else if (whichWall.equals(Walls.WALL_TOP_RIGHT)){
    // top right wall   

    flippedRotation += 180;     

    yChange = Math.round(-pitchAndRoll.y);
}

The walls are all perfectly horizontal and vertical, respectively.

The first collision is fine, any other collisions that occur, the sprite just goes right through the walls.

But my main issue is that as the sprite is controlled using the device's accelerometer, if the user has the device pointing downwards, the sprite will move down fine, hit the wall, bounce back, then move back down and the loop continues. I want to prevent this from happening but can't think how.

It's hard to explain so I here are some images that hopefully make more sense =]]

Image 1 Image 2 Image 3 Image 4 Image 5

I hope these pictures give you a better understanding of what I am trying to do and if you could in anyway, help me, or point me into the right direction, or any alternatives would be amazing!! Thanks in advance.

Upvotes: 1

Views: 795

Answers (2)

user959631
user959631

Reputation: 992

The way I have "fixed" it, is by checking if the device's tilt has changed from the point of collision, if not the sprite continues to move in the direction it was bounced off from the wall, until the device's tilt changes.

Thanks for the help.

Upvotes: 0

user3312130
user3312130

Reputation: 178

So, the main problem that you're having is that the sprite keeps facing the same direction when you want it to bounce off and travel in a new direction away from the wall?

I think that this is happening because you are directly setting the angle and the position of the sprite from the pitch and roll given by the accelerometer, so as long as your device is tilted the sprite will move toward the same angle at the same speed. At the time of the collision, your sprite is only updated away from the wall one time, so it turns back toward the direction given by the accelerometer after the collision has ended.

The way that you solve this problem depends on how you intend for the game to work. Personally, I think that the way it works is fine because you are always in control of the object, and if you want it to move in another direction, you can tilt the device.

One way in which you could achieve moving in the opposite direction would be to throttle control of the object for a temporary period, by only updating the object's movement and not changing its accelerometer-given facing for a certain duration. To do this you would need to use the rotation of your sprite in its movement, with something like

xChange = Math.cos(spriteRotationInRadians)*speed;
yChange = Math.sin(spriteRotationInRadians)*speed;

You could also set the facing continuously, for example, by using the "left" condition after colliding with the left wall until the object collides with another wall, but I'm not sure if your methods for updating the rotation/movement of the object would let this solution work.

Another possibility is to set the object's speed to a large number at collision, and then update this speed over time through player controls so that the player has the ability to recover from the collision.


The most flexible solution is to implement Box2D physics in your game. It may seem tough at first, but there are many tutorials on how to use it in LibGDX.

In Box2D, you could set gravity to 0, set an object's linear damping to be greater than 0, place some lines to collide with at the edges of the screen, and update the object's velocity based on this:

x_Vel = Math.cos(objectRotationInRadians)*speed;
y_Vel = Math.sin(objectRotationInRadians)*speed;

where the rotation is taken from the accelerometer. You could then draw a sprite rotated with the Box2D object. Box2D alone will not take care of the bouncing problem, as your object will continue to travel in the same direction as the accelerometer, but should definitely solve your traveling through walls problem and will give you a less glitchy game if you want to expand collisions to include other objects.

With Box2D, for example, you could make the impact of walls upon an object cause it to reflect at a great speed (through restitution), allowing the object to bounce off of walls but still be controlled by the player.

Here are some helpful links on Box2D should you go that route:

Simple bouncing ball code

Information about setting up Box2D

C++ Box2D series of tutorials

Upvotes: 1

Related Questions