2016-08-08 60 views
0

Für die Entwicklung eines Side-Scrolling-Plattform 2D-Spiel möchte ich eine Moving-Kamera-Klasse implementieren, der Grund für die Verwendung der Klasse, anstatt die gesamte Karte zu bewegen ist, dass ich auch verwenden muss viele Objekte auf einmal werden eine Verzögerung verursachen. Ich kann das nicht zulassen.XNA 4.0 Kamera und Objekthandhabung auf dem Bildschirm

Es gibt einen schönen Algorithmus für die Handhabung der Kamera, wenn der Spieler sich weiter als die Breite des Bildschirms bewegt, dann bewegt sich die Kamera auf Spieler Richtung, bis er wieder in der Mitte des Bildschirms ist, ich habe mehrere Tage gearbeitet diesen Algorithmus funktioniert, aber es gab keinen Erfolg.

// Main 
public class Camera 
{ 
    protected float _zoom; 
    protected Matrix _transform; 
    protected Matrix _inverseTransform; 

    //The zoom scalar (1.0f = 100% zoom level) 
    public float Zoom 
    { 
     get { return _zoom; } 
     set { _zoom = value; } 
    } 

    // Camera View Matrix Property 
    public Matrix Transform 
    { 
     get { return _transform; } 
     set { _transform = value; } 
    } 

    // Inverse of the view matrix, 
    // can be used to get 
    // objects screen coordinates 
    // from its object coordinates 
    public Matrix InverseTransform 
    { 
     get { return _inverseTransform; } 
    } 

    public Vector2 Pos; 

    // Constructor 
    public Camera() 
    { 
     _zoom = 2.4f; 
     Pos = new Vector2(0, 0); 
    } 
    // Update 
    public void Update(GameTime gameTime) 
    { 

     //Clamp zoom value 
     _zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f); 
     //Create view matrix 
     _transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) * 
         Matrix.CreateTranslation(Pos.X, Pos.Y, 0); 
     //Update inverse matrix 
     _inverseTransform = Matrix.Invert(_transform); 

    } 
} 

Dies ist die Kameraklasse I für den Umgang mit dem Bildschirm gemacht, es ist Hauptzweck ist es, den Bildschirm, um die Größe, genauer zu vergrößern und, wann immer ich will meinen Bildschirm ändern, (Titel-Bildschirm, Bildschirm Spielen, Spiel vorbei und so.) Das Bewegen der Kamera ist ziemlich einfach mit Schlüsseln, so.

    if (keyState.IsKeyDown(Keys.D)) 
         Cam.Pos.X -= 20; 
        if (keyState.IsKeyDown(Keys.A)) 
         Cam.Pos.X += 20; 
        if (keyState.IsKeyDown(Keys.S)) 
         Cam.Pos.Y -= 20; 
        if (keyState.IsKeyDown(Keys.W)) 
         Cam.Pos.Y += 20; 

Und ofc. die Zeichnungsmethode, die die Kamera anwendet.

     spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, null, null, null, null, Cam.Transform); 

Hier kommt der Teil, wenn ich aufhöre, also was ich machen möchte, ist etwas wie 2 2D-Räume zu machen. Unter Raum verstehe ich den Ort, an dem ich normalerweise Objekte platziere. so "Vector2 (74, 63)" Also möchte ich einen Ort schaffen, wo ich Gegenstände zeichnen kann, die auf dem Bildschirm bleiben und sich nicht bewegen, und die Bildschirmgrenzen machen, die meinen Algorithmus zum Funktionieren bringen würden, was auch sein wird immer auf dem Bildschirm und als Zusatz wird geprüft, ob einer der Ränder des Bildschirms "room" die bestimmten Koordinaten der Karte "room" erreicht. Ich denke, dass der Grund dafür offensichtlich ist, weil ich nicht möchte, dass der Spieler die Kamera außerhalb der Karte bewegt, wenn er die Wand erreicht, sonst würde der Spieler bereits einen Teil der nächsten Karte sehen, wo er transformiert wird. Der Grund, beide Karten nebeneinander zu zeichnen, ist wiederum, die Ladezeit zu reduzieren, damit der Spieler nicht auf das Abspielen der nächsten Karte warten muss.

In Ordnung, also habe ich in mehr Probleme laufen, als ich erwartet hatte, so werde ich zusätzliche Informationen hinzufügen und mit dem Spieler-Klasse beginnt:

// Main 
public class Player 
{ 
    public Texture2D AureliusTexture; 
    public Vector2 position; 
    public Vector2 velocity; 
    public Vector2 PosForTheCam; // Variable that holds value for moving the camera 
    protected Vector2 dimensions; 
    protected CollisionPath attachedPath; 
    const float GRAVITY = 18.0f; 
    const float WALK_VELOCITY = 120f; 
    const float JUMP_VELOCITY = -425.0f; 

    // Constructor 
    public Player() 
    { 
     dimensions = new Vector2(23, 46); 
     position = new Vector2(50, 770); 
    } 

    public void Update(float deltaSeconds, List<CollisionPath> collisionPaths) 
    { 

     #region Input handling 
     KeyboardState keyState = Keyboard.GetState(); 

     if (keyState.IsKeyDown(Keys.Left)) 
     { 
      velocity.X = -WALK_VELOCITY; 
     } 
     else if (keyState.IsKeyDown(Keys.Right)) 
     { 
      velocity.X = WALK_VELOCITY; 
     } 
     else 
     { 
      velocity.X = 0; 
     } 



     if (attachedPath != null && keyState.IsKeyDown(Keys.Space)) 
     { 
      velocity.Y = JUMP_VELOCITY; 
      attachedPath = null; 
     } 

     velocity.Y += GRAVITY; 

     #endregion 

     #region Region of handling the camera based on Player 
     PosForTheCam.X = velocity.X; 



     #endregion 

     #region Collision checking 
     if (velocity.Y >= 0) 
     { 
      if (attachedPath != null) 
      { 
       position.X += velocity.X * deltaSeconds; 
       position.Y = attachedPath.InterpolateY(position.X) - dimensions.Y/2; 
       velocity.Y = 0; 

       if (position.X < attachedPath.MinimumX || position.X > attachedPath.MaximumX) 
       { 
        attachedPath = null; 
       } 
      } 
      else 
      { 
       Vector2 footPosition = position + new Vector2(0, dimensions.Y/2); 
       Vector2 expectedFootPosition = footPosition + velocity * deltaSeconds; 

       CollisionPath landablePath = null; 
       float landablePosition = float.MaxValue; 


       foreach (CollisionPath path in collisionPaths) 
       { 
        if (expectedFootPosition.X >= path.MinimumX && expectedFootPosition.X <= path.MaximumX) 
        { 
         float pathOldY = path.InterpolateY(footPosition.X); 
         float pathNewY = path.InterpolateY(expectedFootPosition.X); 

         if (footPosition.Y <= pathOldY && expectedFootPosition.Y >= pathNewY && pathNewY < landablePosition) 
         { 
          landablePath = path; 
          landablePosition = pathNewY; 
         } 
        } 
       } 

       if (landablePath != null) 
       { 
        velocity.Y = 0; 
        footPosition.Y = landablePosition; 
        attachedPath = landablePath; 

        position.X += velocity.X * deltaSeconds; 
        position.Y = footPosition.Y - dimensions.Y/2; 
       } 
       else 
       { 
        position = position + velocity * deltaSeconds; 
       } 
      } 
     } 
     else 
     { 
      position += velocity * deltaSeconds; 
      attachedPath = null; 
     } 
     #endregion 

    } 
} 

So stelle ich klar, dass ich meinen Freund gebeten, mache das meiste davon, weil ich mit der Schwerkraft und den Steigungen umgehen wollte, also haben wir es ähnlich wie in Unity gemacht. Und er wusste genau, wie das geht. Und so werde ich die Update-Methode hinzufügen, die die Kamera aus der Hauptklasse behandelt.

     MM.Update(gameTime); // Map Managher update function for map handling 

        Cam.Update(gameTime); // Camera update 
        Cam.Zoom = 2.4f; // Sets the zoom level for the title screen 
        // Takes the start position for camera in map and then turns off the update 
        // so the camera position can be changed. Else it would just keep an infinite 
        // loop and we couldn't change the camera. 
        if (StartInNewRoom) 
        { 
         Cam.Pos = MM.CameraPosition; // Applys the camera position value from the map manager class 
         StartInNewRoom = false; 
        } 

Ich bin nicht sicher, wie die Kamera zu handhaben, wie ich Ihre Methode verwendet und das Ergebnis oft, dass die Kamera bewegt sich von selbst beendet oder es gar nicht bewegen.

Antwort

0

Wenn Sie nicht möchten, dass sich Objekte mit der Kamera wie ein HUD bewegen, benötigen Sie ein zweites SpriteBatch.Begin() ohne Ihre Kameramatrix, die Sie nach Ihrer tatsächlichen Szene zeichnen.

Damit die Kamera nicht aus der Karte herausfährt, können Sie eine Kollisionserkennung verwenden. Berechne einfach den rechten Rand deiner Kamera. Es hängt davon ab, wo der Ursprung Ihrer Kamera ist.

Funktioniert Ihre Kameramatrix so? Weil die Position negativ sein sollte oder sich in die falsche Richtung bewegt.

So sieht meine aus.

return Matrix.CreateTranslation(new Vector3(-camera.position.X, -camera.position.Y, 0)) * 
    Matrix.CreateRotationZ(Rotation) * Matrix.CreateScale(Zoom) * 
    Matrix.CreateTranslation(new Vector3(Viewport.Width * 0.5f, Viewport.Height * 0.5f, 0)); 

Ansichtsfenster.Breite/Höhe * 0,5 zentriert die Kamera. Sie können auch dies gilt hinter Pos.X/Y

Zur Kamera folgt Spieler

public void Update(Player player) 
    { 

     //Clamp zoom value 
     _zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f); 
     //Create view matrix 
     _transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) * 
         Matrix.CreateTranslation(player.Pos.X, player.Pos.Y, 0); 
     //Update inverse matrix 
     _inverseTransform = Matrix.Invert(_transform); 

    } 
+0

ja, die Position arbeitet hauptsächlich mit negativen Werten, zuerst, als ein Problem gesehen, aber daran gewöhnt. (Ich habe ein Tutorial für die Kamera verwendet) Aber ein Teil der Frage bleibt unbeantwortet, wie kann ich diese Kamera dem Hauptcharakter folgen lassen und ihn nicht bewegen, wenn der Charakter das Ende des Raumes erreicht, und ich möchte nicht, dass die Kamera mitgeht mit dem Charakter in der einen Bildschirmhöhe Räume. –

+0

Forgot to add, yes also meine Kameraposition befindet sich standardmäßig in der oberen linken Ecke. –

+0

Hast du eine Spielerklasse? anstelle der "camera.position" setze deine Spielerposition in die Matrix. Ich habe meine Antwort bearbeitet. Zum anderen Teil in Kollisionserkennung einlesen. – SKSK