Random movement of wandering monsters in x & y axis in LibGDX
- by Vishal Kumar
I am making a simple top down RPG game in LibGDX. What I want is ... the enemies should wander here and there in x and y directions in certain interval so that it looks natural that they are guarding something. I spend several hours doing this but could not achieve what I want. After  a long time of coding, I came with this code. But what I observed is when enemies come to an end of x or start of x or start of y or end of y of the map. It starts flickering for random intervals. Sometimes they remain nice, sometimes, they start flickering for long time.
public class Enemy extends Sprite {
    public float MAX_VELOCITY = 0.05f;
    public static final int MOVING_LEFT = 0;
    public static final int MOVING_RIGHT = 1;
    public static final int MOVING_UP = 2;
    public static final int MOVING_DOWN = 3;
    public static final int HORIZONTAL_GUARD = 0;
    public static final int VERTICAL_GUARD = 1;
    public static final int RANDOM_GUARD = 2;
    private float startTime = System.nanoTime();
    private static float SECONDS_TIME = 0;
    private boolean randomDecider;
    public int enemyType;
    public static final float width = 30 * World.WORLD_UNIT;
    public static final float height = 32 * World.WORLD_UNIT;
    public int state;
    public float stateTime;
    public boolean visible;
    public boolean dead;
    public Enemy(float x, float y, int enemyType) {
        super(x, y);
        state = MOVING_LEFT;
        this.enemyType = enemyType;
        stateTime = 0;
        visible = true;
        dead = false;
        boolean random = Math.random()>=0.5f ? true :false;
        if(enemyType == HORIZONTAL_GUARD){
            if(random)
            velocity.x = -MAX_VELOCITY;
            else
            velocity.x = MAX_VELOCITY;
        }
        if(enemyType == VERTICAL_GUARD){
            if(random)
            velocity.y = -MAX_VELOCITY;
            else
            velocity.y = MAX_VELOCITY;
        }
        if(enemyType == RANDOM_GUARD){
            //if(random)
            //velocity.x = -MAX_VELOCITY;
            //else
            //velocity.y = MAX_VELOCITY;
        }
    }
    public void update(Enemy e, float deltaTime) { 
        super.update(deltaTime);
        e.stateTime+= deltaTime;
        e.position.add(velocity);
        // This is for updating the Animation for Enemy Movement Direction. VERY IMPORTANT FOR REAL EFFECTS
        updateDirections();
        //Here the various movement methods are called depending upon the type of the Enemy
        if(e.enemyType == HORIZONTAL_GUARD)
            guardHorizontally();
        if(e.enemyType == VERTICAL_GUARD)
            guardVertically();
        if(e.enemyType == RANDOM_GUARD)
            guardRandomly();
            //quadrantMovement(e, deltaTime);
    }
    private void guardHorizontally(){
        if(position.x <= 0){
            velocity.x= MAX_VELOCITY;
            velocity.y= 0;
        }
        else if(position.x>= World.mapWidth-width){
            velocity.x= -MAX_VELOCITY;
            velocity.y= 0;
        }
    }
    private void guardVertically(){
        if(position.y<= 0){
            velocity.y= MAX_VELOCITY;
            velocity.x= 0;
            }
            else if(position.y>= World.mapHeight- height){
            velocity.y=  -MAX_VELOCITY;
            velocity.x= 0;
            }   
    }
    private void guardRandomly(){
        if (System.nanoTime() - startTime >= 1000000000) {
            SECONDS_TIME++;
            if(SECONDS_TIME % 5==0)
            randomDecider = Math.random()>=0.5f ? true :false;
            if(SECONDS_TIME>=30)
            SECONDS_TIME =0;
            startTime = System.nanoTime();
        }
        if(SECONDS_TIME <=30){
            if(randomDecider && position.x >= 0)
            velocity.x= -MAX_VELOCITY;
            else{
            if(position.x < World.mapWidth-width)
            velocity.x= MAX_VELOCITY;
            else
            velocity.x= -MAX_VELOCITY;  
            }
            velocity.y =0;
        }
        else{
            if(randomDecider && position.y >0)
            velocity.y= -MAX_VELOCITY;
            else
            velocity.y= MAX_VELOCITY;
            velocity.x =0;
         }   
        /*
        //This is essential so as to keep the enemies inside the boundary of the Map
        if(position.x <= 0){
        velocity.x= MAX_VELOCITY;
        //velocity.y= 0;
        }
        else if(position.x>= World.mapWidth-width){
        velocity.x= -MAX_VELOCITY;
        //velocity.y= 0;
        }
        else
        if(position.y<= 0){
        velocity.y= MAX_VELOCITY;
        //velocity.x= 0;
        }
        else if(position.y>= World.mapHeight- height){
        velocity.y=  -MAX_VELOCITY;
        //velocity.x= 0;
        }   
        */    
    }
    private void updateDirections() {
        if(velocity.x > 0)
            state = MOVING_RIGHT;
        else
            if(velocity.x<0)
            state = MOVING_LEFT;
        else
            if(velocity.y>0)
            state = MOVING_UP;
        else
            if(velocity.y<0)
            state = MOVING_DOWN;        
    }
    public Rectangle getBounds() {
        return new Rectangle(position.x, position.y, width, height);
    }
    private void quadrantMovement(Enemy e, float deltaTime) {
            int temp = e.getEnemyQuadrant(e.position.x, e.position.y);
            boolean random = Math.random()>=0.5f ? true :false;
            switch(temp){
            case 1:
                    velocity.x = MAX_VELOCITY;
                break;
            case 2:
                    velocity.x = MAX_VELOCITY;
                break;
            case 3:
                    velocity.x = -MAX_VELOCITY;
                break;
            case 4:
                    velocity.x = -MAX_VELOCITY;
                break;
            default:
             if(random)
                    velocity.x = MAX_VELOCITY;
             else
                 velocity.y =-MAX_VELOCITY;
            }
            }
    public float getDistanceFromPoint(float p1,float p2){
        Vector2 v1 = new Vector2(p1,p2);
        return position.dst(v1);
    }
    private  int getEnemyQuadrant(float x, float y){
        Rectangle enemyQuad = new Rectangle(x, y, 30, 32);
        if(ScreenQuadrants.getQuad1().contains(enemyQuad))
            return 1;
        if(ScreenQuadrants.getQuad2().contains(enemyQuad))
            return 2;
        if(ScreenQuadrants.getQuad3().contains(enemyQuad))
            return 3;
        if(ScreenQuadrants.getQuad4().contains(enemyQuad))
            return 4;
        return 0;
    }
}
Is there a better way of doing this. I am new to game development. I shall be very grateful to any help or reference.