Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am a newbie in 3D game development and I am trying to make a real-time strategy game. I am struggling with the camera currently as I am unable to make it look like they do in RTS games.

Here is my Camera.cs class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace BB
{
    public class Camera : Microsoft.Xna.Framework.GameComponent
    {
        public Matrix view;
        public Matrix projection;
        protected Game game;
        KeyboardState currentKeyboardState;
        Vector3 cameraPosition = new Vector3(600.0f, 0.0f, 600.0f);
        Vector3 cameraForward = new Vector3(0, -0.4472136f, -0.8944272f);
        BoundingFrustum cameraFrustum = new BoundingFrustum(Matrix.Identity);

        // Light direction
        Vector3 lightDir = new Vector3(-0.3333333f, 0.6666667f, 0.6666667f);

        public Camera(Game game) : base(game)
        {
            this.game = game;
        }

        public override void Initialize()
        {
            this.view = Matrix.CreateLookAt(this.cameraPosition, this.cameraPosition + this.cameraForward, Vector3.Up);
            this.projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, this.game.renderer.aspectRatio, 1, 10000);

            base.Initialize();
        }

        /* Handles the user input
         * @ param   GameTime gameTime
         */
        private void HandleInput(GameTime gameTime)
        {
            float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;

            currentKeyboardState = Keyboard.GetState();
        }

        void UpdateCamera(GameTime gameTime)
        {
            float time = (float)gameTime.ElapsedGameTime.TotalMilliseconds;

            // Check for input to rotate the camera.
            float pitch = 0.0f;
            float turn = 0.0f;

            if (currentKeyboardState.IsKeyDown(Keys.Up))
                pitch += time * 0.001f;

            if (currentKeyboardState.IsKeyDown(Keys.Down))
                pitch -= time * 0.001f;

            if (currentKeyboardState.IsKeyDown(Keys.Left))
                turn += time * 0.001f;

            if (currentKeyboardState.IsKeyDown(Keys.Right))
                turn -= time * 0.001f;

            Vector3 cameraRight = Vector3.Cross(Vector3.Up, cameraForward);
            Vector3 flatFront = Vector3.Cross(cameraRight, Vector3.Up);

            Matrix pitchMatrix = Matrix.CreateFromAxisAngle(cameraRight, pitch);
            Matrix turnMatrix = Matrix.CreateFromAxisAngle(Vector3.Up, turn);

            Vector3 tiltedFront = Vector3.TransformNormal(cameraForward, pitchMatrix * turnMatrix);

            // Check angle so we cant flip over
            if (Vector3.Dot(tiltedFront, flatFront) > 0.001f)
            {
                cameraForward = Vector3.Normalize(tiltedFront);
            }

            // Check for input to move the camera around.
            if (currentKeyboardState.IsKeyDown(Keys.W))
                cameraPosition += cameraForward * time * 0.4f;

            if (currentKeyboardState.IsKeyDown(Keys.S))
                cameraPosition -= cameraForward * time * 0.4f;

            if (currentKeyboardState.IsKeyDown(Keys.A))
                cameraPosition += cameraRight * time * 0.4f;

            if (currentKeyboardState.IsKeyDown(Keys.D))
                cameraPosition -= cameraRight * time * 0.4f;

            if (currentKeyboardState.IsKeyDown(Keys.R))
            {
                cameraPosition = new Vector3(0, 50, 50);
                cameraForward = new Vector3(0, 0, -1);
            }

            cameraForward.Normalize();

            // Create the new view matrix
            view = Matrix.CreateLookAt(cameraPosition, cameraPosition + cameraForward, Vector3.Up);

            // Set the new frustum value
            cameraFrustum.Matrix = view * projection;
        }

        public override void Update(Microsoft.Xna.Framework.GameTime gameTime)
        {
            HandleInput(gameTime);
            UpdateCamera(gameTime);
        }
    }
}

The problem is that the initial view is looking in a horizontal direction. I would like to have an RTS like top down view (but with a slight pitch). Can you help me out?

share|improve this question
add comment

2 Answers

up vote 2 down vote accepted

I think that problem is in your view matrix. The third parameter is so called "up vector". You should maybe se it to Vector3.Forward. Or you can calculate it as this.cameraForward.cross(Vector3.right) - I don't know, if XNA syntax is like this, but there should be cross product of vector cameraForward and vector pointing to the right (or left).

share|improve this answer
    
the Matrix.CreateLookAt method does this internally. He is correct supplying Vector3.Up as the 3rd arg. Internally, it uses the Vector3.Up as a helper to determine the ortho up vector. –  Steve H Mar 18 '11 at 20:39
add comment
view = Matrix.CreateLookAt(cameraPosition, cameraPosition + cameraForward, Vector3.Up);

that second argument for the createlookat() is a camera target.

im currently working on my first 3d rts also and the way i have it set up is my camera controls move a vector3 "target" which is set as my cameras target and the in my update() after controls:

"cameraposition = new vectors3(target.x,target.y + zoom, target.z-zoom)"

where zoom is a variable that changes with the scroll wheel

and if you want to add in camera rotation you just apply some trig to the x/z

if (keyboardstatecurrent.IsKeyDown(Keys.Up))
    target = new Vector3(target.X + (float)(camSpeed * Math.Cos(CamRotation)), target.Y, target.Z + (float)(camSpeed * Math.Sin(CamRotation)));

if (keyboardstatecurrent.IsKeyDown(Keys.Down))
    target = new Vector3(target.X - (float)(camSpeed * Math.Cos(CamRotation)), target.Y, target.Z - (float)(camSpeed * Math.Sin(CamRotation)));

if (keyboardstatecurrent.IsKeyDown(Keys.Left))
    CamRotation = CamRotation + 0.1;

if (keyboardstatecurrent.IsKeyDown(Keys.Right))
    CamRotation = CamRotation - 0.1;

Camrotation is initialized as 0 and is in radians.

        cameraposition = new Vector3(target.X - (float)(Zoom * Math.Cos(CamRotation)), target.Y + Zoom, target.Z - (float)(Zoom * Math.Sin(CamRotation)));
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.