Faire défiler l’arrière-plan ou la caméra en fonction de la position du personnage

Je travaille sur un jeu de rôle avec une vue de haut en bas. Je veux charger une image dans l’arrière-plan sur laquelle le personnage marche, mais je n’ai pas encore trouvé comment redessiner l’arrière-plan de manière à ce qu’il défile. La plupart des exemples que je trouve sont le défilement automatique.

Je veux que la caméra rest centrée sur le personnage jusqu’à ce que l’image d’arrière-plan atteigne ses limites, puis le personnage se déplacera sans que l’image ne soit redessinée dans une autre position.

Votre question est un peu floue, mais je pense en comprendre le sens. Regardons vos besoins.

  1. Vous avez une caméra suspendue qui regarde directement vers le bas dans un plan en deux dimensions. Nous pouvons représenter cela comme une simple paire de coordonnées {x, y}, correspondant au point du plan regardé par la caméra.
  2. La caméra peut suivre le mouvement d’un object, probablement du joueur, mais plus généralement de tout ce qui se trouve dans le monde du jeu.
  3. La caméra doit restr dans les limites du monde du jeu.

Ce qui est assez simple à mettre en œuvre. En termes généraux, quelque part dans votre méthode Update() , vous devez suivre les étapes permettant de remplir chacune de ces exigences:

 if (cameraTarget != null) { camera.Position = cameraTarget.Position; ClampCameraToWorldBounds(); } 

En d’autres termes: si nous avons un object cible, verrouillez notre position sur sa position; mais assurez-vous que nous ne sortons pas des limites.

ClampCameraToBounds() est également simple à implémenter. En supposant que vous ayez un object, world , qui contient une propriété Bounds qui représente l’étendue du monde en pixels:

 private void ClampCameraToWorldBounds() { var screenWidth = graphicsDevice.PresentationParameters.BackBufferWidth; var screenHeight = graphicsDevice.PresentationParameters.BackBufferHeight; var minimumX = (screenWidth / 2); var minimumY = (screnHeight / 2); var maximumX = world.Bounds.Width - (screenWidth / 2); var maximumY = world.Bounds.Height - (screenHeight / 2); var maximumPos = new Vector2(maximumX, maximumY); camera.Position = Vector2.Clamp(camera.Position, minimumPos, maximumPos); } 

Cela garantit que la caméra n’est jamais plus près que la moitié d’un écran au bord du monde. Pourquoi un demi-écran? Parce que nous avons défini le {x, y} de la caméra comme étant le point qu’elle regarde , ce qui signifie qu’il devrait toujours être centré sur l’écran.

Cela devrait vous donner une caméra avec le comportement que vous avez spécifié dans votre question. À partir de là, il vous suffit d’implémenter votre rendu de terrain pour que votre arrière-plan soit dessiné par rapport à la coordonnée {x, y} spécifiée par l’object caméra.

Étant donné la position d’un object dans les coordonnées du monde du jeu, nous pouvons traduire cette position dans l’espace de la caméra:

 var worldPosition = new Vector2(x, y); var cameraSpace = camera.Position - world.Postion; 

Et puis de l’espace caméra vers l’espace écran:

 var screenSpaceX = (screenWidth / 2) - cameraSpace.X; var screenSpaceY = (screenHeight / 2) - cameraSpace.Y; 

Vous pouvez ensuite utiliser les coordonnées d’espace d’écran d’un object pour le rendre.

Vous pouvez représenter la position dans un simple vecteur2 et le déplacer vers une entité quelconque. public Vector2 cameraPosition;

Lorsque vous chargez votre niveau, vous devrez définir la position de la caméra sur votre lecteur (ou sur l’object sur lequel il devrait être)

Vous aurez besoin d’une masortingce et d’autres éléments, comme indiqué dans le code ci-dessous. C’est expliqué dans les commentaires. En procédant ainsi, vous éviterez d’append cameraPosition à tout ce que vous dessinez.

  //This will move our camera ScrollCamera(spriteBatch.GraphicsDevice.Viewport); //We now must get the center of the screen Vector2 Origin = new Vector2(spriteBatch.GraphicsDevice.Viewport.Width / 2.0f, spriteBatch.GraphicsDevice.Viewport.Height / 2.0f); //Now the masortingx, It will hold the position, and Rotation/Zoom for advanced features Masortingx cameraTransform = Masortingx.CreateTranslation(new Vector3(-cameraPosition, 0.0f)) * Masortingx.CreateTranslation(new Vector3(-Origin, 0.0f)) * Masortingx.CreateRotationZ(rot) * //Add Rotation Masortingx.CreateScale(zoom, zoom, 1) * //Add Zoom Masortingx.CreateTranslation(new Vector3(Origin, 0.0f)); //Add Origin //Now we can start to draw with our camera, using the Masortingx overload spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise, null, cameraTransform); DrawTiles(spriteBatch); //Or whatever method you have for drawing tiles spriteBatch.End(); //End the camera spritebatch // After this you can make another spritebatch without a camera to draw UI and things that will not move 

J’ai ajouté le zoom et la rotation si vous voulez append quelque chose d’extraordinaire, il suffit de remplacer les variables.

Cela devrait vous aider à démarrer.

Cependant, vous voudrez vous assurer que la caméra est dans les limites et la faire suivre.

Je vais vous montrer comment append un défilement régulier. Toutefois, si vous souhaitez un défilement simple, consultez cet exemple .

  private void ScrollCamera(Viewport viewport) { //Add to the camera positon, So we can see the origin cameraPosition.X = cameraPosition.X + (viewport.Width / 2); cameraPosition.Y = cameraPosition.Y + (viewport.Height / 2); //Smoothly move the camera towards the player cameraPosition.X = MathHelper.Lerp(cameraPosition.X , Player.Position.X, 0.1f); cameraPosition.Y = MathHelper.Lerp(cameraPosition.Y, Player.Position.Y, 0.1f); //Undo the origin because it will be calculated with the Masortingx (I know this isnt the best way but its what I had real quick) cameraPosition.X = cameraPosition.X -( viewport.Width / 2); cameraPosition.Y = cameraPosition.Y - (viewport.Height / 2); //Shake the camera, Use the mouse to scroll or anything like that, add it here (Ex, Earthquakes) //Round it, So it dosent try to draw in between 2 pixels cameraPosition.Y= (float)Math.Round(cameraPosition.Y); cameraPosition.X = (float)Math.Round(cameraPosition.X); //Clamp it off, So it stops scrolling near the edges cameraPosition.X = MathHelper.Clamp(cameraPosition.X, 1f, Width * Tile.Width); cameraPosition.Y = MathHelper.Clamp(cameraPosition.Y, 1f, Height * Tile.Height); } 

J’espère que cela t’aides!