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.