Arc-Ball kamera tipi, sabit bir hedefe bakan ve bu hedef etrafında serbestçe dönen kamera tipidir. Bu kamera türü ile genellikle araba yarışı oyunlarında arabamızı modifiye ederken yaptığımız değişiklikleri inceleyebildiğimiz sahnelerde karşılaşırız. Bu kamera sınıfında hedef etrafında rahatça dönmeye izin verilirken, hedefi çevirmeye veya görüntüden çıkmasına izin verilmez.
Birçok oyunda bu kamera kullanılırken dönme veya uzaklaşma için bir limit belirlenir. Bu durumları da göze alarak, oluşturacağımız kamera sınıfı için gerekli kod aşağıdaki gibidir.
public class ArcBallCamera : Camera { // İki eksen etrafındaki dönme miktarları public float RotationX { get; set; } public float RotationY { get; set; } // Y ekseni dönme limitleri (radian) public float MinRotationY { get; set; } public float MaxRotationY { get; set; } // Hedef ile kamera arası mesafe public float Distance { get; set; } // Mesafe limitleri public float MinDistance { get; set; } public float MaxDistance { get; set; } // Hesaplanan konum ve hedef public Vector3 Position { get; private set; } public Vector3 Target { get; set; } public ArcBallCamera(Vector3 Target, float RotationX, float RotationY, float MinRotationY, float MaxRotationY, float Distance, float MinDistance, float MaxDistance, GraphicsDevice graphicsDevice) : base(graphicsDevice) { this.Target = Target; this.MinRotationY = MinRotationY; this.MaxRotationY = MaxRotationY; // Y ekseni etrafındaki dönme miktarlarının limitler ile kilitlenmesi this.RotationY = MathHelper.Clamp(RotationY, MinRotationY, MaxRotationY); this.RotationX = RotationX; this.MinDistance = MinDistance; this.MaxDistance = MaxDistance; // Uzaklığın limitlere göre kilitlenmesi this.Distance = MathHelper.Clamp(Distance, MinDistance, MaxDistance); } public void Move(float DistanceChange) { this.Distance += DistanceChange; this.Distance = MathHelper.Clamp(Distance, MinDistance, MaxDistance); } public void Rotate(float RotationXChange, float RotationYChange) { this.RotationX += RotationXChange; this.RotationY += -RotationYChange; this.RotationY = MathHelper.Clamp(RotationY, MinRotationY, MaxRotationY); } public void Translate(Vector3 PositionChange) { this.Position += PositionChange; } public override void Update() { // Dönme değerlerine göre dönme matrisini hesapla Matrix rotation = Matrix.CreateFromYawPitchRoll(RotationX, - RotationY, 0); // Kamera ile hedef arasındaki uzaklığa göre Z eksenini hesapla, daha sonra kamera etrafında dönerek son görünümü bul Vector3 translation = new Vector3(0, 0, Distance); translation = Vector3.Transform(translation, rotation); Position = Target + translation; // Dönme matrisine göre kameranın üst kısmının matrisini hesapla Vector3 up = Vector3.Transform(Vector3.Up, rotation); View = Matrix.CreateLookAt(Position, Target, up); } }
Bu kamerayı oyunumuzda kullanmak için ise, ilk önce LoadContent() bölümünde tanımlamamız gerekir.
camera = new ArcBallCamera(Vector3.Zero, MathHelper.ToRadians(160), MathHelper.ToRadians(20), 0, MathHelper.PiOver2, 500, 400, 1500, GraphicsDevice);
Ayrıca kameranın güncellenmesinden sorumlu updateCamera() methodunu da yeni kamera türüne göre değiştirmemiz gerekir.
void updateCamera(GameTime gameTime) { // Klavye ve fare durumlarını al MouseState mouseState = Mouse.GetState(); KeyboardState keyState = Keyboard.GetState(); // Kameranın ne kadar döneceğini hesapla float deltaX = (float)lastMouseState.X - (float)mouseState.X; float deltaY = (float)lastMouseState.Y - (float)mouseState.Y; // Kamerayı döndür ((ArcBallCamera)camera).Rotate(deltaX * .01f, deltaY * .01f); // Fare tekerinin dönme miktarını hesapla float scrollDelta = (float)lastMouseState.ScrollWheelValue - (float)mouseState.ScrollWheelValue; // Kamerayı hareket ettir ((ArcBallCamera)camera).Move(scrollDelta); // Kamerayı güncelle camera.Update(); // Farenin konumunu güncelle lastMouseState = mouseState; }