Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

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.
This ObstacleMoving gives us opportunities to create some cool design :