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.