2016-08-08 12 views
0

サイドスクロールプラットフォームの2Dゲームを開発するには、移動するカメラクラスを実装する必要があります。マップ全体を移動する代わりにクラスを使用する理由は、一度に多くのオブジェクトが遅れを引き起こします。私はそれを起こさせることはできません。XNA 4.0画面上のカメラとオブジェクトの処理

カメラを操作するための素晴らしいアルゴリズムがあります。プレーヤーが画面の幅よりも大きく動き、カメラがプレーヤーの方向に移動して画面の中央に戻ってくると、数日間働いていますしかし、このアルゴリズムを動作させることは成功していません。

// 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); 

    } 
} 

これは、それが主な目的私は、画面を処理するために作られたカメラクラスださは、画面を再生する、(、私は私の画面を変更するたびにズームアウトして、より正確には、タイトル画面を画面のサイズを変更することですゲームオーバーなど) このように、カメラを移動することは非常に簡単です。

    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; 

およびofc。描画方法はカメラを適用します。

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

ここでは私が止めるときに来るので、私がやりたいことは2次元の2部屋のようにしています。部屋で私は通常、物を置く場所を意味する。この "Vector2(74、63)"のように、スクリーンに固執して動かないアイテムを描画し、アルゴリズムを動作させる画面の境界を作る場所を作りたい、魔女になる常に画面上に表示され、追加として、画面「部屋」の境界線の1つが地図「部屋」の特定の座標に達しているかどうかをチェックします。 その理由は、プレイヤーが壁に到達したときにカメラを地図の外に移動させたくないからだと思います。さもなければ、プレイヤーは次の地図の一部をすでに見ているでしょう。 両方のマップを隣り合わせて描画する理由は、やはりローディング時間を短縮して、プレーヤが次のマップの再生を待つ必要がないためです。

さてさて、私は、私はので、私は、余分な情報を追加しますとプレイヤークラスで始まりますが予想よりも多くのトラブルに遭遇しました:

// 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 

    } 
} 

だから私はそれを明確に私は私の友人に尋ねたと述べています重力と坂道を扱いたいので私はそれをUnityのように同じように動作させるために、ほとんどの作業を行います。そして、彼はそれをどうやって行うのか知っていました。 メインクラスのカメラを扱うUpdateメソッドを追加します。

     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; 
        } 

私はあなたの方法を使用し、結果は多くの場合、それ自体で、そのカメラが移動してしまったか、それは全く動かないように私は、カメラを処理する方法がわからないと思います。

答えて

0

HUDのようにカメラでオブジェクトを動かしたくない場合は、実際のシーンの後に描画するカメラマトリックスを使わずに2番目のspriteBatch.Begin()が必要です。

カメラをマップから移動させないようにするには、何らかの衝突検出を使用できます。ちょうどあなたのカメラの右の境界線を計算してください。それはあなたのカメラの起源がどこにあるかに依存します。

カメラのマトリックスはこのように機能していますか?位置が負であるか、間違った方向に移動するためです。

これは私の見た目です。

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)); 

ビューポートの幅/高さ* 0.5 center you camera。 また、はい、位置は主に負の値を扱うプレイヤー

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

を次のカメラにあなたのPos.X/Y

の後ろにこれを適用する最初の問題としてではなく、それに慣れていることを見たことができます。 (私はカメラのチュートリアルを使用しました)しかし、質問の一部は未回答のままです。どのようにしてこのカメラを主人公に従わせ、キャラクターが部屋の終わりに達すると動かさないようにすることができます。 1つの画面の高さの部屋の文字で。 –

+0

追加するのを忘れました。はい、カメラの位置はデフォルトで左上隅にあります。 –

+0

プレーヤークラスはありますか? "camera.position"の代わりに、プレイヤーをマトリックスに配置します。私は私の答えを編集しました。他の部分については、衝突検出を読む。 – SKSK

関連する問題