Animated Obstacle : Moving Obstacle
Always with the view of having more level designing possibility and a richer gameplay, we'll create another kind of Obstacle : The ObstacleMoving.The ObstacleMoving is an obstacle that will follow a given path. You only have to draw the path in Tiled, and the code will generate an Obstacle that will follow this path, back and forth, or in a loop according to the properties you give it.
To draw the path, we'll use the polyline tool of Tiled :
And here is an animation showing how easy it is to create an ObstacleMoving... once you typed all the code, haha.
Modifying the Obstacle.java
First, obviously, this ObstacleMoving requires a PolylineMapObject instead of a RectangleMapObject, thus we can't use the Obstacle.java as is. We need to add a creator that takes into account the PolylineMapObject.
Here is the new creator in Obstacle.java :
public Obstacle(World world, OrthographicCamera camera, PolylineMapObject polylineObject){
}
Yes, this creator is empty. It's only here in order to be able to create a subclass, ObstacleMoving.java, that uses a PolylineMapObject.
And here is the code of the ObstacleMoving.java :
public class ObstacleMoving extends Obstacle{
private float speed;
private boolean backward, loop;
private Vector2 direction;
private Vector2[] path;
private int step;
public ObstacleMoving(World world, OrthographicCamera camera, PolylineMapObject polylineObject) {
super(world, camera, polylineObject);
//SPEED
if(polylineObject.getProperties().get("Speed") != null)
speed = Float.parseFloat((String) polylineObject.getProperties().get("Speed"));
else speed = 5;
//DOES THE PATH MAKE A LOOP ?
if(polylineObject.getProperties().get("Loop") != null)
loop = true;
else loop = false;
//WIDTH OF THE MOVING OBJECT
if(polylineObject.getProperties().get("Width") != null)
width = Integer.parseInt((String) polylineObject.getProperties().get("Width")) * GameConstants.PPT * GameConstants.MPP/2;
else
width = 2 * GameConstants.PPT * GameConstants.MPP/2;
//HEIGHT OF THE MOVING OBJECT
if(polylineObject.getProperties().get("Height") != null)
height = Integer.parseInt((String) polylineObject.getProperties().get("Height")) * GameConstants.PPT * GameConstants.MPP/2;
else
height = 2 * GameConstants.PPT * GameConstants.MPP/2;
path = new Vector2[polylineObject.getPolyline().getTransformedVertices().length/2];
for(int i = 0; i < path.length; i++){
path[i] = new Vector2(polylineObject.getPolyline().getTransformedVertices()[i*2]*GameConstants.MPP, polylineObject.getPolyline().getTransformedVertices()[i*2 + 1]*GameConstants.MPP);
}
polygonShape = new PolygonShape();
polygonShape.setAsBox(width, height);
bodyDef = new BodyDef();
bodyDef.type = getBodyType();
bodyDef.position.set(path[0]);
fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = 0f;
body = world.createBody(bodyDef);
body.createFixture(fixtureDef).setUserData("Objet");
body.setUserData("Objet");
polygonShape.dispose();
direction = new Vector2(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y);
body.setLinearVelocity(direction.clamp(speed, speed));
}
@Override
public BodyType getBodyType(){
return BodyType.KinematicBody;
}
@Override
public void active(){
if(!loop){
if(!backward){
if(!new Vector2(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y).hasSameDirection(direction)){
step++;
if(step == path.length){
backward = true;
step = path.length - 2;
}
direction.set(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y);
}
}
else{
if(!new Vector2(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y).hasSameDirection(direction)){
step--;
if(step < 0){
backward = false;
step = 1;
}
direction.set(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y);
}
}
}
else{
if(!new Vector2(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y).hasSameDirection(direction)){
step++;
if(step == path.length){
step = 0;
}
direction.set(path[step].x - body.getPosition().x, path[step].y - body.getPosition().y);
}
}
body.setLinearVelocity(direction.clamp(speed, speed));
}
}
About this code :
- First we check the properties of the PolylineMapObject to determine the speed, the dimension and the behavior of the ObstacleMoving.
- Then we put the coordinate of every points in an Array, which will form the path that the Obstacle will follow
- Then we create the body of the Obstacle.
- And we give a direction and an impulse to initiate the motion.
- Finally, it the active() method, we check if the Obstacle is between 2 points of the path Array, and we update the direction every time the Obstacle is not between 2 points.
