Im trying to make a game in Monogame and have followed a camera tutorial here https://www.youtube.com/watch?v=c_SPRT7DAeM&t=180s (which works great) The only problem is that when it zooms it zooms to the corner of the player sprite as you can see here:
Here is my code
camera.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace RpgGameCrossPlatform
{
class Camera
{
private Matrix transform;
public Matrix Transform
{
get { return transform; }
}
private Vector2 centre;
private Viewport viewport;
private float zoom = 3;
public float rotation = 0;
public float CentreX
{
get { return centre.X; }
set { centre.X = value; }
}
public float CentreY
{
get { return centre.Y; }
set { centre.Y = value; }
}
public float Zoom
{
get { return zoom; }
set { zoom = value; if (zoom < 0.1f) zoom = 0.1f; }
}
public Camera (Viewport newViewport)
{
viewport = newViewport;
}
public void CameraUpdate(Vector2 position)
{
centre = new Vector2(position.X, position.Y);
transform = Matrix.CreateTranslation(new Vector3(-centre.X, -centre.Y, 0)) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
Matrix.CreateTranslation(new Vector3(viewport.Width / 2, viewport.Height / 2, 0));
}
}
}
player.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace RpgGameCrossPlatform
{
class Camera
{
private Matrix transform;
public Matrix Transform
{
get { return transform; }
}
private Vector2 centre;
private Viewport viewport;
private float zoom = 3;
public float rotation = 0;
public float CentreX
{
get { return centre.X; }
set { centre.X = value; }
}
public float CentreY
{
get { return centre.Y; }
set { centre.Y = value; }
}
public float Zoom
{
get { return zoom; }
set { zoom = value; if (zoom < 0.1f) zoom = 0.1f; }
}
public Camera (Viewport newViewport)
{
viewport = newViewport;
}
public void CameraUpdate(Vector2 position)
{
centre = new Vector2(position.X, position.Y);
transform = Matrix.CreateTranslation(new Vector3(-centre.X, -centre.Y, 0)) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
Matrix.CreateTranslation(new Vector3(viewport.Width / 2, viewport.Height / 2, 0));
}
}
}
and game.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace RpgGameCrossPlatform
{
class Camera
{
private Matrix transform;
public Matrix Transform
{
get { return transform; }
}
private Vector2 centre;
private Viewport viewport;
private float zoom = 3;
public float rotation = 0;
public float CentreX
{
get { return centre.X; }
set { centre.X = value; }
}
public float CentreY
{
get { return centre.Y; }
set { centre.Y = value; }
}
public float Zoom
{
get { return zoom; }
set { zoom = value; if (zoom < 0.1f) zoom = 0.1f; }
}
public Camera (Viewport newViewport)
{
viewport = newViewport;
}
public void CameraUpdate(Vector2 position)
{
centre = new Vector2(position.X, position.Y);
transform = Matrix.CreateTranslation(new Vector3(-centre.X, -centre.Y, 0)) *
Matrix.CreateScale(new Vector3(Zoom, Zoom, 0)) *
Matrix.CreateTranslation(new Vector3(viewport.Width / 2, viewport.Height / 2, 0));
}
}
}
help would be appreciated as well as some general tips as I am new :)
This could mean that the camera is focussing on the player's default position, which is always on top-left.
You should set a center position (called the 'origin') for the player, this could be done by adding half of the player's width (for x) and height (for y) at the current default position it's focussing at.
Related
I am using the following code to draw a curved dotted line using a line renderer(Copied from the net). It's working but the curve is forming downward like a boat. I want to draw the curve in the opposite direction. I tried adjusting the values but no luck. can anyone can please say how to do this with this code? or can suggest me new set of code
NB- I only have very basic knowledge in programming.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawLineRenderer : MonoBehaviour
{
public Transform Point1;
public Transform Point2;
public Transform Point3;
public LineRenderer linerenderer;
public float vertexCount = 12;
public float Point2Ypositio = 2;
// Start is called before the first frame update
void Start()
{
linerenderer.SetWidth(10, 10);
}
public void buttonPress()
{
Point2.transform.position = new Vector3((Point1.transform.position.x + Point3.transform.position.x)/2, Point2Ypositio, (Point1.transform.position.z + Point3.transform.position.z) *2);
var pointList = new List<Vector3>();
for(float ratio = 0;ratio<=1;ratio+= 1/vertexCount)
{
var tangent1 = Vector3.Lerp(Point1.position, Point2.position, ratio);
var tangent2 = Vector3.Lerp(Point2.position, Point3.position, ratio);
var curve = Vector3.Lerp(tangent1, tangent2, ratio);
pointList.Add(curve);
}
linerenderer.positionCount = pointList.Count;
linerenderer.SetPositions(pointList.ToArray());
}
}
Set Point2Ypositio =600
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DrawLineRenderer : MonoBehaviour
{
public Transform Point1;
public Transform Point2;
public Transform Point3;
public LineRenderer linerenderer;
public float vertexCount = 12;
public float Point2Ypositio = 600;
// Start is called before the first frame update
void Start()
{
linerenderer.SetWidth(10, 10);
}
public void buttonPress()
{
Point2.transform.position = new Vector3((Point1.transform.position.x + Point3.transform.position.x)/2, Point2Ypositio, (Point1.transform.position.z + Point3.transform.position.z) *2);
var pointList = new List<Vector3>();
for(float ratio = 0;ratio<=1;ratio+= 1/vertexCount)
{
var tangent1 = Vector3.Lerp(Point1.position, Point2.position, ratio);
var tangent2 = Vector3.Lerp(Point2.position, Point3.position, ratio);
var curve = Vector3.Lerp(tangent1, tangent2, ratio);
pointList.Add(curve);
}
linerenderer.positionCount = pointList.Count;
linerenderer.SetPositions(pointList.ToArray());
}
}
I am currently coding an arkanoid type game for my school project and just started out on monogame. I encountered a collision problem on the big red rectangle and the ball. I just cant figure out what is wrong with my code I appreciate all of your help in advance.
Collision Video: https://youtu.be/HOuUS8bUKn4
Game1.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
namespace TSA3
{
public class Game1 : Game
{
private GraphicsDeviceManager graphics;
private SpriteBatch spriteBatch;
// Platform
Platform platform;
Texture2D platformTexture;
Rectangle platformRectangle;
Color platformColor;
// Ball
Ball ball;
Texture2D ballTexture;
Rectangle ballRectangle;
Color ballColor;
bool ballDirectionX = true, ballDirectionY = true;
// Enemy
Enemy enemy;
Texture2D enemyTexture;
Rectangle enemyRectangle;
Color enemyColor;
Random random = new Random();
public const int ScreenW = 1200, ScreenH = 720;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
graphics.PreferredBackBufferWidth = ScreenW;
graphics.PreferredBackBufferHeight = ScreenH;
graphics.ApplyChanges();
Window.AllowUserResizing = false;
Window.AllowAltF4 = true;
Window.Title = "Arkanoid";
// Platform
platformTexture = Content.Load<Texture2D>("platform");
platformRectangle = new Rectangle(0, Window.ClientBounds.Height - 50, 100, 30);
platformColor = Color.White;
// Ball
ballTexture = Content.Load<Texture2D>("ball");
ballRectangle = new Rectangle(0, 0, 20, 20);
ballColor = Color.DarkBlue;
// Enemy
enemyTexture = Content.Load<Texture2D>("enemyPiece");
enemyRectangle = new Rectangle(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2, 200, 200);
enemyColor = Color.White;
base.Initialize();
}
protected override void LoadContent()
{
// Player
platform = new Platform(platformTexture, platformRectangle, platformColor, Window.ClientBounds.Width - 100);
// Ball
ball = new Ball(ballTexture, ballRectangle, ballColor, Window.ClientBounds.Width - 20, Window.ClientBounds.Height - 20, ballDirectionX, ballDirectionY);
// Enemy
enemy = new Enemy(enemyTexture, enemyRectangle, enemyColor);
spriteBatch = new SpriteBatch(GraphicsDevice);
}
float spawn = 0;
protected override void Update(GameTime gameTime)
{
spawn += (float)gameTime.ElapsedGameTime.TotalSeconds;
ball.ballBounce(platform.PlatformRectangle);
Keys[] k = Keyboard.GetState().GetPressedKeys();
foreach (Keys key in k)
{
platform.platformMovement(key);
break;
}
if (Keyboard.GetState().IsKeyDown(Keys.Space) && !ball.StartGame)
ball.StartGame = true;
ball.ballCollision(platform.PlatformRectangle);
ball.enemyCollision(enemy.enemyRectangle);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
spriteBatch.Draw(ball.BallTexture, ball.BallRectangle, ball.BallColor);
spriteBatch.Draw(platform.PlatformTexture, platform.PlatformRectangle, platform.PlatformColor);
spriteBatch.Draw(enemy.enemyTexture, enemy.enemyRectangle, enemy.enemyColor);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Ball.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;
namespace TSA3
{
public class Ball
{
Texture2D ballTexture;
Rectangle ballRectangle;
Color ballColor;
int boundaryX, boundaryY;
bool ballDirectionX, ballDirectionY;
bool startGame;
public const int BALL_SPEED = 7;
public Ball(Texture2D ballTexture, Rectangle ballRectangle, Color ballColor, int boundaryX, int boundaryY, bool ballDirectionX, bool ballDirectionY)
{
this.ballTexture = ballTexture;
this.ballRectangle = ballRectangle;
this.ballColor = ballColor;
this.boundaryX = boundaryX;
this.boundaryY = boundaryY;
this.ballDirectionX = ballDirectionX;
this.ballDirectionY = ballDirectionY;
startGame = false;
}
public Texture2D BallTexture { get => ballTexture; }
public Rectangle BallRectangle { get => ballRectangle; }
public Color BallColor { get => ballColor; }
public bool StartGame { get => startGame; set => startGame = value; }
public void ballBounce(Rectangle platformRectangle)
{
if (startGame)
{
if (ballRectangle.X <= 0)
ballDirectionX = true;
else if (ballRectangle.X >= boundaryX)
ballDirectionX = false;
if (ballRectangle.Y <= 0)
{
ballDirectionY = true;
}
else if (ballRectangle.Y >= boundaryY)
{
startGame = false;
}
if (ballDirectionX)
ballRectangle.X += BALL_SPEED;
else
ballRectangle.X -= BALL_SPEED;
if (ballDirectionY)
ballRectangle.Y += BALL_SPEED;
else
ballRectangle.Y -= BALL_SPEED;
}
else
{
ballRectangle.Location = new Point(platformRectangle.X + (platformRectangle.Width / 2) - 10, platformRectangle.Y - (ballRectangle.Height - 5));
}
}
public void ballCollision(Rectangle platform)
{
if (ballRectangle.Intersects(platform))
ballDirectionY = false;
}
public void enemyCollision(Rectangle enemyRectangle)
{
if (ballRectangle.Intersects(enemyRectangle))
ballDirectionY = false;
}
}
}
Enemy.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Text;
namespace TSA3
{
public class Enemy
{
public Texture2D enemyTexture;
public Rectangle enemyRectangle;
public Color enemyColor;
public bool isVisible = true;
Random random = new Random();
public Enemy(Texture2D enemyTexture, Rectangle enemyRectangle, Color enemyColor)
{
this.enemyTexture = enemyTexture;
this.enemyRectangle = enemyRectangle;
this.enemyColor = enemyColor;
}
public Texture2D EnemyTexture { get => enemyTexture; }
public Rectangle EnemyRectangle { get => enemyRectangle; }
public Color EnemyColor { get => enemyColor; }
}
}
Platform.cs
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Text;
namespace TSA3
{
public class Platform
{
Texture2D platformTexture;
Rectangle platformRectangle;
Color platformColor;
int boundaryX;
public const int PLATFORM_SPEED = 10;
public Platform(Texture2D platformTexture, Rectangle platformRectangle, Color platformColor, int boundaryX)
{
this.platformTexture = platformTexture;
this.platformRectangle = platformRectangle;
this.platformColor = platformColor;
this.boundaryX = boundaryX;
}
public Texture2D PlatformTexture { get => platformTexture; }
public Rectangle PlatformRectangle { get => platformRectangle; }
public Color PlatformColor { get => platformColor; }
public void platformMovement(Keys controls)
{
if (controls == Keys.A && platformRectangle.X > 0)
platformRectangle.X -= PLATFORM_SPEED;
if (controls == Keys.D && platformRectangle.X < boundaryX)
platformRectangle.X += PLATFORM_SPEED;
}
}
}
Thank you in advance to anyone who will help!
This method is missing the necessary code to function properly to approach the block from any side:
public void enemyCollision(Rectangle enemyRectangle)
{
if (ballRectangle.Intersects(enemyRectangle))
ballDirectionY = false;
}
Currently it only works the same as your platform does: set the Y direction upwards on collision. This works fine for the platform, as it's thin and close to the edge of the screen, so it doesn't need other collision checks.
Try improving this method similair with what you've done with the ball collisions on the edges of the screen.
What would be important here, is knowing the positions of the corners of the red rectangle, so you can calculate at which position the ball is hitting the rectangle.
As far I know, you cannot have the exact borders, but you can measure the same with calculating the positions of the corners. you could for example take the EnemyRectangle and get their x/y position, that would be it's top-left, than you can add the rectangle's width, and you'll have the top-right (same also works with the height for the bottom corners). If you calculate the balls position along with the rectangle corners, you'll know at which side the ball is colliding with the screen.
An example of a collision on top:
public void enemyCollision(Rectangle enemyRectangle)
{
if (ballRectangle.Intersects(enemyRectangle))
{
if (ballRectangle.x > enemyRectangle.x &&
ballRectangle.x < enemyRectangle.x + enemyRectangle.Width &&
ballRectangle.y > enemyRectangle.y)
ballDirectionY = false;
}
}
I'm making a game using XNA 4.0 and c#.
I just made my camera class and it's almost working as expected, except for one thing.
I can move with my mouse to rotate the camera but the problem is that when I get to the border of the screen, the mouse stops and so does the camera movement.
Is there any way to allow the mouse pointer to be outside of the screens boundaries to be able to keep tracking the pointer? Or is there any simpler way around?
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
public class ArcBallCamera
{
private float speeder = 100;
public ArcBallCamera(float aspectRation, Vector3 lookAt)
: this(aspectRation, MathHelper.PiOver4, lookAt, Vector3.Up, 0.1f, float.MaxValue) { }
public ArcBallCamera(float aspectRatio, float fieldOfView, Vector3 lookAt, Vector3 up, float nearPlane, float farPlane)
{
this.aspectRatio = aspectRatio;
this.fieldOfView = fieldOfView;
this.lookAt = lookAt;
this.nearPlane = nearPlane;
this.farPlane = farPlane;
}
/// <summary>
/// Recreates our view matrix, then signals that the view matrix
/// is clean.
/// </summary>
public void ReCreateViewMatrix()
{
//Calculate the relative position of the camera
position = Vector3.Transform(Vector3.Backward, Matrix.CreateFromYawPitchRoll(yaw, pitch, 0));
//Convert the relative position to the absolute position
position *= zoom;
position += lookAt;
//Calculate a new viewmatrix
viewMatrix = Matrix.CreateLookAt(position, lookAt, Vector3.Up);
viewMatrixDirty = false;
}
/// <summary>
/// Recreates our projection matrix, then signals that the projection
/// matrix is clean.
/// </summary>
public void ReCreateProjectionMatrix()
{
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(fieldOfView, AspectRatio, nearPlane, farPlane);
projectionMatrixDirty = false;
}
#region HelperMethods
/// <summary>
/// Moves the camera and lookAt at to the right,
/// as seen from the camera, while keeping the same height
/// </summary>
public void MoveCameraRight(float amount)
{
Vector3 right = Vector3.Normalize(LookAt - Position); //calculate forward
right = Vector3.Cross(right, Vector3.Up); //calculate the real right
//right.Y = 0;
right.Normalize();
LookAt += right * amount;
}
/// <summary>
/// Moves the camera and lookAt forward,
/// as seen from the camera, while keeping the same height
/// </summary>
public void MoveCameraForward(float amount)
{
Vector3 forward = Vector3.Normalize(LookAt - Position);
// forward.Y = 0;
forward.Normalize();
LookAt += forward * amount;
}
/// <summary>
/// Moves the camera and lookAt up or down,
/// LOL
/// </summary>
public void MoveCameraUp(float amount)
{
Vector3 up = Vector3.Normalize(LookAt - position);
up = Vector3.Cross(up, Vector3.Left); //Calculate the REAL FUCKING UP/DOWN
up.X = 0;
up.Z = 0;
up.Normalize();
LookAt += up * amount;
}
#endregion
#region FieldsAndProperties
//We don't need an update method because the camera only needs updating
//when we change one of it's parameters.
//We keep track if one of our matrices is dirty
//and reacalculate that matrix when it is accesed.
private bool viewMatrixDirty = true;
private bool projectionMatrixDirty = true;
public float MinPitch = -MathHelper.PiOver2 + 0.3f;
public float MaxPitch = MathHelper.PiOver2 - 0.3f;
private float pitch;
public float Pitch
{
get { return pitch; }
set
{
viewMatrixDirty = true;
pitch = MathHelper.Clamp(value, MinPitch, MaxPitch);
}
}
private float yaw;
public float Yaw
{
get { return yaw; }
set
{
viewMatrixDirty = true;
yaw = value;
}
}
private float fieldOfView;
public float FieldOfView
{
get { return fieldOfView; }
set
{
projectionMatrixDirty = true;
fieldOfView = value;
}
}
private float aspectRatio;
public float AspectRatio
{
get { return aspectRatio; }
set
{
projectionMatrixDirty = true;
aspectRatio = value;
}
}
private float nearPlane;
public float NearPlane
{
get { return nearPlane; }
set
{
projectionMatrixDirty = true;
nearPlane = value;
}
}
private float farPlane;
public float FarPlane
{
get { return farPlane; }
set
{
projectionMatrixDirty = true;
farPlane = value;
}
}
public float MinZoom = 1;
public float MaxZoom = float.MaxValue;
private float zoom = 1;
public float Zoom
{
get { return zoom; }
set
{
viewMatrixDirty = true;
zoom = MathHelper.Clamp(value, MinZoom, MaxZoom);
}
}
private Vector3 position;
public Vector3 Position
{
get
{
if (viewMatrixDirty)
{
ReCreateViewMatrix();
}
return position;
}
}
private Vector3 lookAt;
public Vector3 LookAt
{
get { return lookAt; }
set
{
viewMatrixDirty = true;
lookAt = value;
}
}
#endregion
#region ICamera Members
public Matrix ViewProjectionMatrix
{
get { return ViewMatrix * ProjectionMatrix; }
}
private Matrix viewMatrix;
public Matrix ViewMatrix
{
get
{
if (viewMatrixDirty)
{
ReCreateViewMatrix();
}
return viewMatrix;
}
}
private Matrix projectionMatrix;
public Matrix ProjectionMatrix
{
get
{
if (projectionMatrixDirty)
{
ReCreateProjectionMatrix();
}
return projectionMatrix;
}
}
#endregion
}
You can reset the mouse position for every frame.
Example:
// Center of the window
var resetPosition = new Point(WindowWidth / 2, WindowHeight / 2);
// Get the movement since the last frame
var mouseState = Mouse.GetState();
var mousePosition = new Point(mouseState.X, mouseState.Y);
var delta = mousePosition - resetPosition;
// Reset the mouse position
Mouse.SetPosition(resetPosition.X, resetPosition.Y);
// Use the delta
RotateCamera(delta);
I have 3 classes: a game class, a camera class and a model class. The project builds and runs,
the model appears, when i press w and make it go forward the camera follows it, but when i restart the project and rotate the model to face any other ways it seems to do a nose dive, and not go stright, what im trying to achieve is a camera which follows the model,
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace test1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
//Visual components
Ship ship = new Ship();
Camera _camera;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// this.graphics.ToggleFullScreen();
this._camera = new Camera(graphics.GraphicsDevice.Viewport);
this._camera.LookAt = new Vector3(0.0f, 0.0f, 0.0f);
this._camera.Position = new Vector3(0.0f, -5000.0f, 1000.0f);
base.Initialize();
}
protected override void LoadContent()
{
ship.Model = Content.Load<Model>("Models/p1_wedge");
ship.Transforms = _camera.SetupEffectDefaults(ship.Model);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
// Get some input.
UpdateInput();
base.Update(gameTime);
}
protected void UpdateInput()
{
// Get the game pad state.
GamePadState currentState = GamePad.GetState(PlayerIndex.One);
KeyboardState currentKeyState = Keyboard.GetState();
ship.Update(currentState);
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
//camera
this._camera.Update();
_camera.LookAt = ship.Position;
Matrix shipTransformMatrix = ship.RotationMatrix
* Matrix.CreateTranslation(ship.Position);
DrawModel(ship.Model, shipTransformMatrix, ship.Transforms);
base.Draw(gameTime);
}
public void DrawModel(Model model, Matrix modelTransform,
Matrix[] absoluteBoneTransforms)
{
//Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in model.Meshes)
{
//This is where the mesh orientation is set
foreach (BasicEffect effect in mesh.Effects)
{
effect.World =
absoluteBoneTransforms[mesh.ParentBone.Index] *
modelTransform;
effect.Projection = _camera.ProjectionMatrix;
effect.View = _camera.ViewMatrix;
}
//Draw the mesh, will use the effects set above.
mesh.Draw();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace test1
{
public class Camera
{
private Vector3 _position;
private Vector3 _lookAt;
private Matrix _viewMatrix;
private Matrix _projectionMatrix;
private float _aspectRatio;
public Camera(Viewport viewport)
{
this._aspectRatio = ((float)viewport.Width) / ((float)viewport.Height);
this._projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(40.0f),
this._aspectRatio,
1.0f,
10000.0f);
}
public Matrix[] SetupEffectDefaults(Model myModel)
{
Matrix[] absoluteTransforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(absoluteTransforms);
foreach (ModelMesh mesh in myModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.Projection = ProjectionMatrix;
effect.View = ViewMatrix;
}
}
return absoluteTransforms;
}
public Vector3 Position
{
get { return this._position; }
set { this._position = value; }
}
public Vector3 LookAt //= Vector3.Zero;
{
get { return this._lookAt; }
set { this._lookAt = value; }
}
public Matrix ViewMatrix
{
get { return this._viewMatrix; }
}
public Matrix ProjectionMatrix
{
get { return this._projectionMatrix; }
}
public void Update()
{
this._viewMatrix =
Matrix.CreateLookAt(this._position, this._lookAt, Vector3.Up);
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace test1
{
class Ship
{
public Model Model;
public Matrix[] Transforms;
//Position of the model in world space
public Vector3 Position = Vector3.Zero;
//Velocity of the model, applied each frame to the model's position
public Vector3 Velocity = Vector3.Zero;
private const float VelocityScale = 5.0f;
public Matrix RotationMatrix =
Matrix.CreateRotationX(MathHelper.PiOver2);
private float rotation;
public float Rotation
{
get { return rotation; }
set
{
float newVal = value;
while (newVal >= MathHelper.TwoPi)
{
newVal -= MathHelper.TwoPi;
}
while (newVal < 0)
{
newVal += MathHelper.TwoPi;
}
if (rotation != value)
{
rotation = value;
RotationMatrix =
Matrix.CreateRotationX(MathHelper.PiOver2) *
Matrix.CreateRotationZ(rotation);
}
}
}
public void Update(GamePadState controllerState)
{
KeyboardState currentKeyState = Keyboard.GetState();
if (currentKeyState.IsKeyDown(Keys.A))
Rotation += 0.10f;
else
// Rotate the model using the left thumbstick, and scale it down.
Rotation -= controllerState.ThumbSticks.Left.X * 0.10f;
if (currentKeyState.IsKeyDown(Keys.D))
Rotation -= 0.10f;
if (currentKeyState.IsKeyDown(Keys.W))
Velocity += RotationMatrix.Forward * VelocityScale;
else
// Finally, add this vector to our velocity.
Velocity += RotationMatrix.Forward * VelocityScale *
controllerState.Triggers.Right;
// In case you get lost, press A to warp back to the center.
if (currentKeyState.IsKeyDown(Keys.Enter))
{
Position = Vector3.Zero;
Velocity = Vector3.Zero;
Rotation = 0.0f;
}
Position += Velocity;
Velocity *= 0.95f;
}
}
}
I'd do it this way:
I'm showing it in a plane to easy understanding, but it's not needed to do the calcs.
You only need a forward vector for the camera, a forward vector for the ship, a distance from the camera to the ship and an elevation vector for the camera.
this way when ship moves would do something similar to this:
Camera.Forward = Vector3.Lerp( Ship.Forward, Camera.Fordward, 0.05f);
Camera.Forward.Normalize();
Camera.Forward*=Camera.Distance;
Camera.Target = Ship.Target;
Camera.Source = Ship.Target - Camera.Forward;
Camera.Position = Camera.Source + Camera.Elevation;
I hope this will be useful.
What I have:
game class
model class for my ship
Camera class
when I Press F5 my game opens, it shows blue, but my model doesnt appear, anyone got any advice for why this is happening?
if anyone would be able to help i would really thankful.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace test1
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
//Visual components
Ship ship = new Ship();
Camera _camera;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
this.graphics.ToggleFullScreen();
this._camera = new Camera(graphics.GraphicsDevice.Viewport);
this._camera.LookAt = new Vector3(0.0f, 0.0f, -1.0f);
base.Initialize();
}
protected override void LoadContent()
{
ship.Model = Content.Load<Model>("Models/p1_wedge");
ship.Transforms = _camera.SetupEffectDefaults(ship.Model);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed ||
Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
// Get some input.
UpdateInput();
base.Update(gameTime);
}
protected void UpdateInput()
{
// Get the game pad state.
GamePadState currentState = GamePad.GetState(PlayerIndex.One);
KeyboardState currentKeyState = Keyboard.GetState();
ship.Update(currentState);
}
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
//camera
this._camera.Update();
_camera.LookAt = ship.Position;
Matrix shipTransformMatrix = ship.RotationMatrix
* Matrix.CreateTranslation(ship.Position);
DrawModel(ship.Model, shipTransformMatrix, ship.Transforms);
base.Draw(gameTime);
}
public static void DrawModel(Model model, Matrix modelTransform,
Matrix[] absoluteBoneTransforms)
{
//Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in model.Meshes)
{
//This is where the mesh orientation is set
foreach (BasicEffect effect in mesh.Effects)
{
effect.World =
absoluteBoneTransforms[mesh.ParentBone.Index] *
modelTransform;
}
mesh.Draw();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace test1
{
class Ship
{
public Model Model;
public Matrix[] Transforms;
//Position of the model in world space
public Vector3 Position = Vector3.Zero;
//Velocity of the model, applied each frame to the model's position
public Vector3 Velocity = Vector3.Zero;
private const float VelocityScale = 5.0f;
public Matrix RotationMatrix =
Matrix.CreateRotationX(MathHelper.PiOver2);
private float rotation;
public float Rotation
{
get { return rotation; }
set
{
float newVal = value;
while (newVal >= MathHelper.TwoPi)
{
newVal -= MathHelper.TwoPi;
}
while (newVal < 0)
{
newVal += MathHelper.TwoPi;
}
if (rotation != value)
{
rotation = value;
RotationMatrix =
Matrix.CreateRotationX(MathHelper.PiOver2) *
Matrix.CreateRotationZ(rotation);
}
}
}
public void Update(GamePadState controllerState)
{
KeyboardState currentKeyState = Keyboard.GetState();
if (currentKeyState.IsKeyDown(Keys.A))
Rotation += 0.10f;
else
// Rotate the model using the left thumbstick, and scale it down.
Rotation -= controllerState.ThumbSticks.Left.X * 0.10f;
if (currentKeyState.IsKeyDown(Keys.D))
Rotation -= 0.10f;
if (currentKeyState.IsKeyDown(Keys.W))
Velocity += RotationMatrix.Forward * VelocityScale;
else
// Finally, add this vector to our velocity.
Velocity += RotationMatrix.Forward * VelocityScale *
controllerState.Triggers.Right;
// In case you get lost, press A to warp back to the center.
if (currentKeyState.IsKeyDown(Keys.Enter))
{
Position = Vector3.Zero;
Velocity = Vector3.Zero;
Rotation = 0.0f;
}
Position += Velocity;
Velocity *= 0.95f;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Graphics;
namespace test1
{
public class Camera
{
private Vector3 _position;
private Vector3 _lookAt;
private Matrix _viewMatrix;
private Matrix _projectionMatrix;
private float _aspectRatio;
public Camera(Viewport viewport)
{
this._aspectRatio = ((float)viewport.Width) / ((float)viewport.Height);
this._projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(40.0f),
this._aspectRatio,
20000.0f,
30000.0f);
}
public Vector3 Position
{
get { return this._position; }
set { this._position = value; }
}
public Vector3 LookAt
{
get { return this._lookAt; }
set { this._lookAt = value; }
}
public Matrix ViewMatrix
{
get { return this._viewMatrix; }
}
public Matrix ProjectionMatrix
{
get { return this._projectionMatrix; }
}
public void Update()
{
this._viewMatrix =
Matrix.CreateLookAt(this._position, this._lookAt, Vector3.Up);
}
public Matrix[] SetupEffectDefaults(Model myModel)
{
Matrix[] absoluteTransforms = new Matrix[myModel.Bones.Count];
myModel.CopyAbsoluteBoneTransformsTo(absoluteTransforms);
foreach (ModelMesh mesh in myModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.Projection = ProjectionMatrix;
effect.View = ViewMatrix;
}
}
return absoluteTransforms;
}
}
}
EDIT
public static void DrawModel(Model model, Matrix modelTransform,
Matrix[] absoluteBoneTransforms)
{
//Draw the model, a model can have multiple meshes, so loop
foreach (ModelMesh mesh in model.Meshes)
{
//This is where the mesh orientation is set
foreach (BasicEffect effect in mesh.Effects)
{
effect.World =
absoluteBoneTransforms[mesh.ParentBone.Index] *
modelTransform;
effect.Projection = _camera.ProjectionMatrix;
effect.View = _camera.ViewMatrix;
}
//Draw the mesh, will use the effects set above.
mesh.Draw();
}
I think there are 2 issues with your code:
Look At You don't seem to update the Look At of your camera to point towards your spaceship, either make your camera "track" the spaceship by giving it a reference to it and in your Update update the look at position or manually update the lookat position from your Game1.
View / Projection Matrix Even though your camera has a view matrix and a projection matrix, you don't use them in your DrawModel. When you assign your world, consider adding the two following lines
effect.Projection = _camera.ProjectionMatrix;
effect.View = _camera.ViewMatrix;
There are possibly several issues in your code preventing it from working as expected. The two that pop out at me is that 1.) you never set the camera position so it defaults to 0,0,0 which colocates it with the ship model. So your camera is actually inside the model and any triangle that is in it's view would be culled as a backside triangle if 2.) it wasn't already frustrum culled since your nearplane is set to 20000.