What I want to do is create a 3D world that exists on a plane, and I want to have a top-down camera view like so:
_____________ +x
|
|
|
|
|
|
+y
This will let me use all my existing code for ship movement and projectiles, etc. All I want to do is create a 3D world that mirrors my current 2D world, and I want to draw a model at the correct position and depth on the screen.
Here is my current draw function.
public void Draw(GameTime gameTime) { starfield.Draw(cam.Pos, cam.Zoom); spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.NonPremultiplied, null, null, null, null, cam.get_transformation(device)); int camx = (int)cam.Pos.X; int camy = (int)cam.Pos.Y; //Rectangle blackRect = new Rectangle(-10000, -10000, 100000 + (int)WorldSize.X, 100000 + (int)WorldSize.Y); //spriteBatch.Draw(MinimapTex, blackRect, Color.Black); // this view rectangle shifts around with the camera to provide a bit of a parallax feel to the background image Rectangle viewRectangle = new Rectangle(camx - (screenWidth / 2) - camx / 10, camy - (screenHeight / 2) - camy / 10, screenWidth + 200, screenWidth + 200); spriteBatch.Draw(backgroundTexture, viewRectangle, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.01f); viewRectangle = new Rectangle(camx - (screenWidth / 2) - camx / 8, camy - (screenHeight / 2) - camy / 8, screenWidth + 200, screenWidth + 200); spriteBatch.Draw(debrisfield2Texture, viewRectangle, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.1f); viewRectangle = new Rectangle(camx - (screenWidth / 2) - camx / 5, camy - (screenHeight / 2) - camy / 5, screenWidth + 200, screenWidth + 200); spriteBatch.Draw(debrisfieldTexture, viewRectangle, null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0.1f); foreach (Ship ship in ShipList) { DrawShipInfo(spriteBatch, ship); ship.Draw(gameTime, spriteBatch); } // draw the alpha-blended particles particleEffectManager.Draw(spriteBatch, "AlphaBlend", cam); spriteBatch.End(); // draw the additive particles spriteBatch.Begin(SpriteSortMode.Texture, BlendState.Additive, null, null, null, null, cam.get_transformation(device)); particleEffectManager.Draw(spriteBatch, "Additive", cam); spriteBatch.End(); debrisField.Draw(cam.Pos, cam.Zoom); }
So I know that this is a broad question, but what do I need to do to set up a 3D world with a camera that is slaved to my 2D camera? I'm speaking in very general terms.
Here is what I have been trying: I have replaced my regular ship's draw function with this DrawModel:
private void DrawModel() { Vector3 world_Position = new Vector3(device.Viewport.Width / 2, -device.Viewport.Height / 2, 0); Vector3 cameraPosition = new Vector3(world.GetCam().Pos, 1000); // Copy any parent transforms. Matrix[] transforms = new Matrix[xwingModel.Bones.Count]; xwingModel.CopyAbsoluteBoneTransformsTo(transforms); // Draw the model. A model can have multiple meshes, so loop. foreach (ModelMesh mesh in xwingModel.Meshes) { // This is where the mesh orientation is set, as well // as our camera and projection. foreach (BasicEffect effect in mesh.Effects) { effect.EnableDefaultLighting(); effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateRotationZ(-this.rotation) * Matrix.CreateScale(.50f) * Matrix.CreateTranslation(new Vector3(-Position.X, Position.Y, 400)); effect.View = Matrix.CreateLookAt(cameraPosition, Vector3.Zero, new Vector3(0, -1, 0)); effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 10000.0f); //effect.Projection = Matrix.CreateOrthographic(1280, 720, 1, 1000); } // Draw the mesh, using the effects set above. mesh.Draw(); } }
This function draws a model but it's just not right. I know that I'm not creating my 3D world properly.
So again, the real question here is:
1) How do I initialize a 3D world and set a camera up with a top-down perspective?
2) How do I ensure that my models are drawn onto the same Z-plane as my current 2D ships? If my 2D ship moves 50 pixels, I want to move my 3D ship 50 pixels.
Code examples appreciated.