Suggestion to create 'AI Movement'? (2D game)

So, I managed to make my player on my map animate and move smoothly using the arrow keys (I even took a suggestion from a thread here to use booleans to fix ‘sticky movement’) I decided to see if I could implement some AI movement. I was able to generate a path for the player to follow (Using A* or BFS)

So far, I’m able to make the player follow the generated path, however, getting the animation to work is a little bit tricky.
Here are the the approaches I already took:

-Using the Robot class to press the keys (I was really hoping this would work, but it didn’t work as I hoped it would)
-Tried calling the setDely() and setDelX() methods (This approach also didn’t work due to the boolean method I took to fix the sticky movement)
-So, my current approach involved changing the booleans and calling the setDelX()/setDelY() methods, this is working for left to right animation, but it’s not doing so well for right to left animation. (Still trying to figure out why it’s behaving this way.)
Here’s the code for my current approach (I apologize for the comments lol) :

	public void moveAlongPath(TileMap map, Path path) {
		for(int count = 0; count < path.getLength(); count++)
		{	
			Node step = path.getStep(count);
			//System.out.println("Row: " + map.getRow(this.getY()) + " Col: " + map.getCol(this.getX()));
			
			//TODO Smoother diagonal movement.
			if(step.getRow() > map.getRow(this.getY()))
			{
				//Ensures all other movement is false.
				isUp = false;
				isLeft = false;
				isRight = false;
				setDelX(0);
				
				isDown = true;
				setDelY(2);
				return; //Fixes path following bug. 
			}
			/*
			 * PATH FOLLOWING BUG: 
			 * Changing this 'if' to 'else if' fixes 
			 * the path following for BFS, but 
			 * A* Search path following is wrong
			 * Changing it to just 'if' fixes A* path
			 * following, but BFS path following is wrong.
          *
          * FIX: Adding 'return' fixed this error. 
			 */
			if(step.getCol() > map.getCol(this.getX()))
			{
				//Ensures all other movement is false.
				isUp = false;
				isLeft = false;
				isDown = false; 
				setDelY(0);
				
				isRight = true;
				setDelX(2);
				return; //Fixes path following bug. 
			}
//			if(step.getCol() < map.getCol(this.getX()))
//			{
//				isUp = false;
//				isRight = false;
//				isDown = false;
//				setDelY(0);
//				
//				isLeft = true;
//				setDelX(-2);
//				return;
//			}
//			if(step.getRow() < map.getRow(this.getY()));
//			{
//				isRight = false;
//				isLeft = false;
//				isDown = false;
//				setDelX(0);
//				
//				isUp = true;
//				setDelY(-2);
//				return;
//			}
		}
	}

I’m just wondering what suggestions you guys would have or what approaches you would take to solve this problem. If you guys want to see some more code, let me know, thanks!

Wait, what exactly are you trying to do?

If you generated a path then all you need to do is move from the current (first) node to the next node (speed * delta_time) each update cycle until you reach the last node.

If you are trying to determine how to get the AI to choose a path, you just need to give it a way to choose goals. This can be done randomly or you can set paths by making goals in a level editor/hard code it and then have the AI go back and forth between the two.

What do you mean by animation? The animation should not be tied to the path, but to the direction of movement (meaning which direction the character faces). In which case (assuming top down) you can take a default direction (say 0, 1) and then find the direction between the current node and the next node, find the angle between those directions and apply that as the rotation (over a set number of updates). If it’s side on you just determine if you’re moving left or right and invert the sprite (I think).

I have a path, and my player can make it to the goal node.

There’s also no problems with the animation when I’m controlling the character with the arrow keys.

The problem I’m having is to make the player animate and move towards the goal by following the path generated. So, I don’t want to touch the keys, but I want the code from touching the keys to execute according to the path generated.

So if the path says the next Node position is 1 row below the current player node position, I want the same effect of pressing the down key: which includes setting the delX value and running the animation.

The code I have shared achieves the desired effect, (right to left animation + movement) the player moves towards the goal node with no problems, the commented out code is for left to right animation and movement, this for some reason doesn’t animate very well. Movement seems to work fine, but animation is a bit wonky.

Really what I wanted to know was other approaches people have taken to translate the animation gained from the arrow keys to AI movement

Thanks for the reply! I apologize for being unclear and I hope this cleared things up a bit!

Oh OK, well it looks like this is just dealing with movement, so if it’s a problem in the animation the error is probably not in this section of code. Although, if you comment out the right to left section and uncomment the left to right one does this fix the issue?

What does setDelX() and setDelY() do? I assume it just sets the deltaX value and deltaY value for movement?

I tried your suggestion and the player moves up (-deltaY) just fine, however, it’s not going left in movement or animation (-deltaX)
Oh, yeah, I guess the animation doesn’t really show in this section of code, but the booleans are what’s activating the code for animation, I’ll include it for reference :

	public void update() {
		checkCollisions();
		setX(getX() + getDelX());
		setY(getY() + getDelY());
		
		//Implemented sticky key bug fix. 
		if(isUp)
		{
			setDelY(-3);
			upAnim.runAnimation(); //Start the animation updates. 
			initialImage = walkUp[0]; //Facing a new direction, set the initialImage.
		}
		else if(isDown)
		{
			setDelY(3);
			downAnim.runAnimation();
			initialImage = walkDown[0];
		}
		else if(isRight)
		{
			setDelX(3);
			rightAnim.runAnimation();
			initialImage = walkRight[0];
		}
		else if(isLeft)
		{
			setDelX(-3);
			leftAnim.runAnimation();
			initialImage = walkLeft[0];
		}
		else
		{
			setDelY(0);
			setDelX(0);
		}
	}

if you put the row test above the column test does it fix the left error?

         if(step.getRow() < map.getRow(this.getY()));
         {
            isRight = false;
            isLeft = false;
            isDown = false;
            setDelX(0);
            
            isUp = true;
            setDelY(-2);
            return;
         }
         if(step.getCol() < map.getCol(this.getX()))
         {
            isUp = false;
            isRight = false;
            isDown = false;
            setDelY(0);
            
            isLeft = true;
            setDelX(-2);
            return;
         }

Huh, I think we’re getting somewhere, Eclipse is giving me an unreachable code when I switched the tests around


         if(step.getRow() < map.getRow(getY()));
			{
				isRight = false;
				isLeft = false;
				isDown = false;
				setDelX(0);
				
				isUp = true;
				setDelY(-2);
				return;
			}
         //Unreachable code error?
			if(step.getCol() < map.getCol(getX()))
			{
				isUp = false;
				isRight = false;
				isDown = false;
				setDelY(0);
				
				isLeft = true;
				setDelX(-2);
				return;
			}

That unreachable code error is because your first if has a ; before the curly braces, so it returns no matter what (because the first if statement code is always run).

Darn, should’ve caught that.

Well, I think I deserve the medal for Java noob of the year for that mistake, that fixed the left animation, I tried to run it with all 4 if statements, and the animation is still wonky, hmm, maybe it’s the order of the if statements?

What do you mean by wonky? Does it play out of order, backwards, inverted, rotated? Does it play one animation and then another unexpected one?

The movement is stuck in one place with all the directions playing their animation

So I’m able to see the animation play, but I can also see the right/left of the player at the same time, I can faintly see the back/front of the player, and their is no movement, just animating in the same position.

Set the initialImage before calling runAnimation()?

Which directions for movement work properly and which for animations? You can always try rearranging the order of the direction checks to see if there’s a pattern.

I tried it with, it didn’t change anything, I should have mentioned that initialImage is for when I let go of the arrow key, the image will be the still image of the direction I was pressing.
I think I have an idea, maybe I need to rewrite my if statements because I think some are getting skipped with the way I have it set, or they are not getting called correctly, I’m thinking of trying some nesting
I’ll update tomorrow, if you have any other suggestions, let me know, and thanks!

After much frustration, I decided to try a different way of doing things,
I think this approach is a bit more cleaner, but the new problem that came up
is the pressing two keys simultaneously. Anyone have any ideas?



	public void moveAlongPath(TileMap map, Path path) {
		for(int count = 0; count < path.getLength(); count++)
		{	
			Node step = path.getStep(count);

			//Checking the rows
			if(map.getRow(getY()) != step.getRow())
			{

				//Current position at the top. 
				if(map.getRow(getY()) < step.getRow())
				{
					this.keyPressed(KeyEvent.VK_RIGHT); //This is getting ignored?
					this.keyPressed(KeyEvent.VK_DOWN);
				}
			}
			if(map.getRow(getY()) == step.getRow())
				this.keyReleased(KeyEvent.VK_DOWN);
			if(map.getCol(getX()) == step.getCol())
				this.keyReleased(KeyEvent.VK_RIGHT);
		}
	}


Can we see your this.keyPressed() method?

Have you placed any debugging output (println’s) in the keyPressed method to check that it’s working correctly and doing what it should be doing?

keyPressed method.


	public void keyPressed(int key) {
		
		if(key == KeyEvent.VK_UP || key == KeyEvent.VK_W)
			isUp = true;
		if(key == KeyEvent.VK_DOWN || key == KeyEvent.VK_S)
		{	
			System.out.println("DOWN");
			isDown = true;
		}
		if(key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_D)
		{	
			System.out.println("RIGHT");
			isRight = true;
		}
		if(key == KeyEvent.VK_LEFT || key == KeyEvent.VK_A)
			isLeft = true;
	}

code being manipulated in update



		//Implemented sticky key bug fix. 
		if(isUp)
		{
			setDelY(-3);
			upAnim.runAnimation(); //Start the animation updates. 
			initialImage = walkUp[0]; //Facing a new direction, set the initialImage.
		}
		else if(isDown)
		{
			setDelY(3);
			downAnim.runAnimation();
			initialImage = walkDown[0];
		}
		else if(isRight)
		{
			setDelX(3);
			rightAnim.runAnimation();
			initialImage = walkRight[0];
		}
		else if(isLeft)
		{
			setDelX(-3);
			leftAnim.runAnimation();
			initialImage = walkLeft[0];
		}
		else
		{
			setDelY(0);
			setDelX(0);
		}


I placed some print out’s and both messages are printing out, but my player is only going down until the path dictates to no longer go down, then the player goes to the right diagonally (right + down)

I think I may have figured it out after I looked at my post with the code from update:


		//Implemented sticky key bug fix. 
		if(isUp)
		{
			setDelY(-3);
			upAnim.runAnimation(); //Start the animation updates. 
			initialImage = walkUp[0]; //Facing a new direction, set the initialImage.
		}
		else if(isDown)
		{
			setDelY(3);
			downAnim.runAnimation();
			initialImage = walkDown[0];
		}
		if(isRight)   //WRONG: else if(isRight)
		{
			setDelX(3);
			rightAnim.runAnimation();
			initialImage = walkRight[0];
		}
		else if(isLeft)
		{
			setDelX(-3);
			leftAnim.runAnimation();
			initialImage = walkLeft[0];
		}
		else
		{
			setDelY(0);
			setDelX(0);
		}

TESTED (and it works!): using ‘else if’ caused the isRight code not to execute since isDown was true, isRight never got reached

Well, thanks so much for the help guys! I can’t believe it was due to small mistakes as this >.< (Java noob of the year award REALLY does go to me…)
Well, I really appreciate you guys talking me through this, thanks again!