Good day!

There is a class Player , in it the corresponding methods are registered for a conclusion of the sprite of the player and for processing of its logic.

The logic is processed in the Update(...) method, it updates the position, checks for collisions, and the most important thing (for this question) is keyboard input processing.

Here is the listing of the method that handles input processing:

 protected override void KeyUpdate() { // ΠŸΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π½ΠΈΠ΅ событий с ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹ KeyboardState key = Keyboard.GetState(); // Π’Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ для выполнСния расчСтов Vector2 tempDirection = Direction; if (key.IsKeyDown(Keys.W)) { tempDirection.Y = -Speed; } if (key.IsKeyDown(Keys.S)) { tempDirection.Y = Speed; } if (key.IsKeyDown(Keys.A)) { tempDirection.X = -Speed; } if (key.IsKeyDown(Keys.D)) { tempDirection.X = Speed; } Direction = tempDirection; } 

Briefly explain how the current logic of movement of the character.

In the Player class, the following fields are required for our calculations: Position(X,Y) , Direction(X,Y) , Speed .

The current position is calculated in the PositionUpdate(...) method, which is part of the Update(...) method (still the same Player class):

 public void PositionUpdate(...) { Position.X += Direction.X; Position.Y += Direction.Y; Direction = new Vector2(0, 0); } 

This method is called after the KeyUpdate(...) method.

As you already could understand, the character can be moved only if the value of the Direction.X/Direction.Y property is present along the corresponding axes.

The Direction values ​​themselves are set in the KeyUpdate(...) method, allowing the character to move in different directions.

The values ​​are extracted from the Speed field, which has a strictly fixed value.

In the PositionUpdate(...) method, Direction is zeroed so that the character does not continue to move endlessly after the player has released the key.

It seems that I explained everything for the logic, at least I hope so.

What am I trying to do at the moment?

Eliminate the possibility of a diagonal movement of the character.

At the moment, the movement is carried out taking into account the position offset on both axes.

Good. Trying to fix this:

 protected override void KeyUpdate() { // ΠŸΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π½ΠΈΠ΅ событий с ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹ KeyboardState key = Keyboard.GetState(); // Π’Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ для выполнСния расчСтов Vector2 tempDirection = Direction; if (key.IsKeyDown(Keys.W)) { tempDirection.Y = -Speed; } else if (key.IsKeyDown(Keys.S)) { tempDirection.Y = Speed; } else if (key.IsKeyDown(Keys.A)) { tempDirection.X = -Speed; } else if (key.IsKeyDown(Keys.D)) { tempDirection.X = Speed; } Direction = tempDirection; } 

Fine. The character no longer moves diagonally. But ... it's not exactly that.

If you move left or right , then when you press the button up or down, the character at the same time turns in the appropriate direction.

It turns out that I turn in the other direction and I do not need to release the motion button first, and then press the desired one. And it is convenient. This is what I'm trying to achieve.

However, if you move up or down and at the same time try to turn left or right , nothing will happen and the character will continue to move up or down.

We are trying to do a little differently:

 protected override void KeyUpdate() { // ΠŸΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π½ΠΈΠ΅ событий с ΠΊΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹ KeyboardState key = Keyboard.GetState(); // Π’Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΉ ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ для выполнСния расчСтов Vector2 tempDirection = Direction; if (key.IsKeyDown(Keys.W)) { tempDirection.Y = -Speed; } if (key.IsKeyDown(Keys.S)) { tempDirection.Y = Speed; } if (key.IsKeyDown(Keys.A)) { tempDirection.X = -Speed; } if (key.IsKeyDown(Keys.D)) { tempDirection.X = Speed; } // Если имССтся ΠΊΠ°ΠΊΠΎΠ΅-Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ оси X if (tempDirection.X != 0) { // И ΠΏΡ€ΠΈ этом осущСствляСтся ΠΊΠ°ΠΊΠΎΠ΅-Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ оси Y if (tempDirection.Y != 0) { tempDirection.X = 0; // Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ двиТСния ΠΏΠΎ оси X } else { tempDirection.X = tempDirection.X > 0 ? Speed : -Speed; // Ссли Π½Π΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ ΠΏΠΎ оси Y, Ρ‚ΠΎ двигаСмся Π² Ρ‚Ρƒ ΠΈΠ»ΠΈ ΠΈΠ½ΡƒΡŽ сторону } } // Если имССтся ΠΊΠ°ΠΊΠΎΠ΅-Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ оси Y if (tempDirection.Y != 0) { // И ΠΏΡ€ΠΈ этом осущСствляСтся ΠΊΠ°ΠΊΠΎΠ΅-Π»ΠΈΠ±ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎ оси X if (tempDirection.X != 0) { tempDirection.Y= 0; // Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ двиТСния ΠΏΠΎ оси Y } else { tempDirection.Y= tempDirection.Y > 0 ? Speed : -Speed; // Ссли Π½Π΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ ΠΏΠΎ оси X, Ρ‚ΠΎ двигаСмся Π² Ρ‚Ρƒ ΠΈΠ»ΠΈ ΠΈΠ½ΡƒΡŽ сторону } } Direction = tempDirection; } 

And ... no. This method is not working. More precisely, the worker, but only half. The behavior mechanics is prevalent for the logic of the code above.

Those. in the listing above, the movement is left - right and there is a possibility of turning up - down , however, while moving up - down , the character can no longer turn left - right .

But it is necessary to change the code blocks in places - and the situation becomes completely reverse.

In the end I will summarize what I am trying to get.

  1. Block the possibility of diagonal movements

  2. Allow the character to instantly turn in any available direction without having to release the keys and press the ones you need.

Example: a player presses the W key and moves forward, but suddenly he presses the D key and at the same time does not release the W key , but the rotation towards D is still carried out . And so for all WASD keys, respectively.

  • You need to analyze not only tempDirection, but also Direction. - Pavel Mayorov

1 answer 1

Usually, the keyboard provides a subscription to key press and release events, and they would help you, because you could just handle the result of the last key pressed, not paying attention to which keys were still pressed.

I'm not an expert in XNA, but the search gave me a link to this article (eng.). To implement the necessary task, it is recommended to keep the old state of the keyboard and compare it with the new one. There is a sample code, pay attention to the UpdateInput method.

The method is not ideal, because there is a chance that the player will press the two buttons very quickly and then the same dilemma will arise again - to give preference to the vertical or horizontal. But access to the keyboard at a lower level in XNA does not seem to be granted.