3 votes

Coincé dans la réalisation d'un moteur de mouvement pour jeu 2D

Je suis en train de créer un moteur de mouvement pour mon jeu de haut en bas en 2D, mais je suis resté bloqué en essayant de résoudre le problème suivant :

  • Le joueur peut se déplacer en utilisant les touches fléchées, qui vous accélèrent dans les directions respectives. Il y a une friction, donc vous arrêtez de bouger après avoir relâché les touches, mais pas instantanément.
  • Lorsque vous tenez deux touches perpendiculaires, vous accélérez dans cette direction de 45° à la même vitesse que sur un axe.
  • Il existe une vitesse maximale à partir de laquelle vous ne pouvez pas accélérer. en marchant Cela limite également votre vitesse de marche maximale, évidemment. Vous pouvez vous faire assommer, et donc dépasser cette vitesse cependant.
  • Si vous vous déplacez plus vite que la vitesse de marche maximale, vous pouvez ralentir plus rapidement si vous maintenez les touches dans la ou les directions opposées.

Pseudocode pour le premier point, sans friction :

gameTick(){

  tempX += LeftKeyHeld ? -1 : 0;
  tempX += RightKeyHeld ? 1 : 0;
  tempY += UpKeyHeld ? -1 : 0;
  tempY += DownKeyHeld ? 1 : 0;
  ratio = 0.71;

  if( |tempX| == |tempY| ) {
    tempX =tempX* ratio;
    tempY =tempY* ratio;
  }
  player.x += tempX;
  player.y += tempY;
}

Je peux résoudre le problème de la friction (en obtenant la longueur du vecteur de mouvement, en la réduisant de la friction, en la projetant à nouveau avec le même rapport x:y), mais je ne parviens pas à obtenir la vitesse maximale.

J'ai essayé une solution consistant à ne pas permettre au joueur de marcher du tout lorsqu'il dépasse la vitesse maximale, mais cela viole le point 4. De plus, cela a eu le désagréable effet secondaire que lorsque vous vous déplacez à la vitesse maximale vers la gauche, et que vous commencez à appuyer vers le bas, la direction du mouvement ne change pas, ou à peine.

J'ai ensuite commencé à réfléchir à de nombreux produits, différences et autres choses avec les vecteurs, mais la plupart du temps, je n'arrivais plus à suivre ou je rencontrais les premiers problèmes.

Donc, en conclusion, quelqu'un pourrait-il expliquer un système qui remplit tous les points ci-dessus, ou indiquer un article qui explique comment un tel système pourrait être mis en œuvre ? Ne vous inquiétez pas si vous proposez quelque chose de complexe, je peux comprendre même des concepts difficiles avec un peu de temps.

Merci pour votre aide !

1voto

Szoltomi Points 173

Désolé de ne pas vous laisser y réfléchir plus d'un jour, mais j'ai réussi à résoudre le problème, et ce n'est pas deux lignes de code. (Mais quand même merci à tous pour les idées)

Parce que je suis paresseux et fatigué, je ne le changerai pas en pseudocode, sauf pour les deux méthodes suivantes :

updateGame(){
  player.walk();
  player.move();
}
player.move(){
  player.x += player.speedX
  player.y += player.speedY
}  

Et le code (java) :

public void walk() {
    float tempX = 0;
    float tempY = 0;
    float accelX;
    float accelY;
    float nextSpeedX;
    float nextSpeedY;
    float nextSpeed;
    float speed;
    tempX += walkLeft ? -1 : 0;
    tempX += walkRight ? 1 : 0;
    tempY += walkUp ? -1 : 0;
    tempY += walkDown ? 1 : 0;

    if (Math.abs(tempX) == Math.abs(tempY)) {
        tempX = (float) tempX * rat;
        tempY = (float) tempY * rat;
    }

    accelX = tempX * (float) runSpeed;
    accelY = tempY * (float) runSpeed;
    speed = (float) Math.sqrt(speedX * speedX + speedY * speedY);
    nextSpeedX = speedX + accelX;
    nextSpeedY = speedY + accelY;
    nextSpeed = (float) Math.sqrt(nextSpeedX * nextSpeedX + nextSpeedY * nextSpeedY);

    if (nextSpeed > maxSpeed) { //can't accelerate by running
        if (nextSpeed > speed) {  //wants to accelerate
            if (speed > maxSpeed) {  //the current speed is larger than maximum.
                float diff = (float)(speed / nextSpeed);
                float greenX = nextSpeedX*diff;
                float greenY = nextSpeedY*diff;
                accelX = greenX-speedX;
                accelY = greenY-speedY;
            } else { //speed <= maxspeed
                float diff = (float)(maxSpeed / nextSpeed);
                float greenX = nextSpeedX*diff;
                float greenY = nextSpeedY*diff;
                accelX = greenX-speedX;
                accelY = greenY-speedY;
            }
        } else { //wants to slow! allow it!
            //acceleration doesn't need to be changed
        }
    } else { //no problem, allow it!
        //acceleration doesn't need to be changed
    }
    speedX += accelX;
    speedY += accelY;
}

Il pourrait être plus court, un peu plus optimisé, mais il fonctionne. J'espère que cela aidera toute personne qui se heurtera à ce problème à l'avenir.

0voto

Liran Orevi Points 2126

Ajouter au fond :

 If (|tempX|>maxSpeed)
   tempX=maxSpeed*sign(tempX);

 If (|tempY|>maxSpeed)
   tempY=maxSpeed*sign(tempX);

W [ ] { [ ] retourne -1 ; }

0voto

JAB Points 11053

Je suggérerais d'associer une vitesse spécifique au joueur en plus de la position, et de ne vérifier cette vitesse par rapport à la vitesse maximale que lorsque les touches fléchées sont pressées.

Si la vitesse dépasse la vitesse maximale, mais que les touches fléchées du côté opposé sont pressées, alors vous gardez la vitesse actuelle au-dessus de la vitesse maximale et appliquez simplement l'accélération négative.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X