XNA C# creating an Isometric view with 3D models - c#

I'm trying to make a simple isometric game engine but have some problems with the camera. When i have it like this i can see my model from the front. But i want to see it from an isometric perspective. I tried using a lot of methods but none seem to work. Perhaps I got stuck in the code itself? Can you guys help me with the code perhaps?
public class Camera : PositionedObject
{
#region Fields
private Matrix cameraRotation;
#endregion
#region Properties
public Matrix View
{
get;
set;
}
public Matrix Projection
{
get;
protected set;
}
public Vector3 Target
{
get;
set;
}
#endregion
#region Constructor
public Camera(Game game, Vector3 position, Vector3 target, Vector3 rotation, bool Orthographic, float near, float far)
: base(game)
{
Position = position;
RotationInRadians = rotation;
Target = target;
if (Orthographic)
{
Projection = Matrix.CreateOrthographic(Game.Window.ClientBounds.Width, Game.Window.ClientBounds.Height,
near, far);
}
else
{
Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
(float)Game.Window.ClientBounds.Width / (float)Game.Window.ClientBounds.Height, near, far);
}
}
#endregion
#region Public Methods
public override void Initialize()
{
base.Initialize();
cameraRotation = Matrix.Identity;
}
public override void Update(GameTime gameTime)
{
base.Update(gameTime);
cameraRotation = Matrix.CreateFromAxisAngle(cameraRotation.Forward, RotationInRadians.Z)
* Matrix.CreateFromAxisAngle(cameraRotation.Right, RotationInRadians.X)
* Matrix.CreateFromAxisAngle(cameraRotation.Up, RotationInRadians.Y);
Target = Position + cameraRotation.Forward;
View = Matrix.CreateLookAt(Position, Target, cameraRotation.Up);
}
public void Draw(BasicEffect effect)
{
effect.View = View;
effect.Projection = Projection;
}
#endregion
}

The easiest way is to calculate the camera position based on the focus point (a point on your ground, or whatever).
//Lets start with looking at origo for now.
Vector3 FocusPoint = Vector3.Zero;
//This tells us where the camera should be, RELATIVE to the point we are watching.
//I set this a little up and a little back
Vector3 CameraOffset = new Vector3(0f, 20f, 20f);
Matrix ViewMatrix
{
get
{
//The Offset is just up and back, we need to rotate it 45*
var rotatedOffset = Vector3.Transform(CameraOffset, Matrix.CreateRotationY(MathHelper.PiOver2 * 0.5f));
//Now we can create out viewmatrix. No need to use a transformed "up" unless it's not going to be upside down or something.
return Matrix.CreateLookAt(rotatedOffset, FocusPoint, Vector3.Up);
}
}

Related

Split a bullet in 3 different directions

I'm trying to assign a skill to a projectile that, when used, divides the project into 3 (the original projectile and 2 more new ones).
However, when I instantiate these two clones, I cannot attribute any movement to them. The idea would be for them to take this route:
The green dotted curve indicating the motion of the original bullet, the blue vector indicating the instantaneous velocity of the original bullet at time of special activation, the red vectors indicating the two velocity vectors belonging to each of the newly spawned bullets, and the green angle indicating the direction of the new bullet relative to the original velocity direction
But at the moment, they are just standing at the point of the parabola where they were instantiated. No matter what I do, I can't seem to attach any value to their rigidbody2D. Does anyone know how to fix this?
This is my code so far
Ability Script:
public class AirSpecialSplit : MonoBehaviour, IAirSpecial
{
public float SplitAngleInDegrees = 10;
GameObject bird_down;
GameObject bird_up;
public void ExecuteAirSpecial()
{
{
//hold the velocity of the original bird
Vector2 original_velocity = this.gameObject.GetComponent<Rigidbody2D>().velocity;
//clone two new birds
bird_down = Birb.MakeBirbCopy(this.gameObject);
bird_up = Birb.MakeBirbCopy(this.gameObject);
//get the rigidboy from the clones
Rigidbody2D rb_bird_down = bird_down.GetComponent<Rigidbody2D>();
Rigidbody2D rb_bird_up = bird_up.GetComponent<Rigidbody2D>();
rb_bird_down.velocity = new Vector2(original_velocity.x, original_velocity.y) * Time.deltaTime;
rb_bird_up.AddForce(new Vector2(3, 5) * 500);
}
}
}
Main Bird:
public class Birb : MonoBehaviour
{
#region Provided Code, Do Not Edit
private Rigidbody2D m_rigidbody;
private bool m_canExecuteAirSpecial = true;
public bool CanExecuteAirSpecial
{
get
{
return m_rigidbody.simulated && m_canExecuteAirSpecial;
}
}
private void Awake()
{
m_rigidbody = GetComponent<Rigidbody2D>();
StopBirbSimulation();
}
public void StopBirbSimulation()
{
m_rigidbody.simulated = false;
}
public void StartBirbSimulation()
{
m_rigidbody.simulated = true;
}
public void SetPosition( Vector3 position )
{
if ( m_rigidbody.simulated )
{
m_rigidbody.MovePosition( position );
}
else
{
transform.position = position;
}
}
public void ExecuteAirSpecial()
{
GetComponent<IAirSpecial>().ExecuteAirSpecial();
m_canExecuteAirSpecial = false;
}
private void OnCollisionEnter2D( Collision2D collision )
{
m_canExecuteAirSpecial = false;
}
public static GameObject MakeBirbCopy( GameObject original )
{
Birb newBirb = Instantiate(original).GetComponent<Birb>();
newBirb.m_canExecuteAirSpecial = false;
return newBirb.gameObject;
}
#endregion
[Range( 0, 25 )]
public float LaunchForce = 12;
public void Launch(Vector3 offset, float maximumStretch, Rigidbody2D rigidbody)
{
rigidbody.velocity = new Vector2(offset.x * -LaunchForce, offset.y * -LaunchForce) * (maximumStretch/2);
}
}
Ok, apparently, I just need to set the "simulated" to true after instantiate.
rb_bird_down.simulated = true;
rb_bird_up.simulated = true;
The documentation could be clearer about this since they say that all attributes are copied, which is not the case...

XNA 4.0 2D Camera With Cursor Active

I am pretty new to XNA framework For now I can do drawing, animations and so, But I have encountered a problem with Camera displaying cursor.
I want to achieve a 2D game where you use cursor as main controller (selecting, moving on map and so). I want the camera to be controlled by cursor Right-click and drag.
I have created very simple logic for moving it, but it's not working.
Anytime I press RButton and drag it, camera is working well.
The problem pop up when do it again. Whole View resets to initial position. I guess the problem is with mouse position relative to world.
I am adding my camera Class
class TCCamera : IDrawable
{
public Matrix transformation;
Viewport viewport;
Vector2 centre;
public TCCamera(Viewport vport)
{
viewport = vport;
this.centre = new Vector2();
}
public void LoadContent(Microsoft.Xna.Framework.Content.ContentManager Content)
{
}
public void Draw(SpriteBatch spriteBatch)
{
throw new NotImplementedException();
}
public Matrix Translate
{
get
{
return this.transformation;
}
}
public void Update(GameTime gameTime)
{
MouseState mstat = Mouse.GetState();
if (mstat.RightButton == ButtonState.Pressed)
{
this.centre.X = mstat.X;
this.centre.Y = mstat.Y;
transformation = Matrix.CreateTranslation(new Vector3(-centre.X, -centre.Y, 0));
}
}
}
}
And also the Cursor Class
class TCCursor : IDrawable
{
Texture2D tex;
public Vector2 pos;
Rectangle bBox;
public TCCursor()
{
this.pos = new Vector2();
this.bBox = new Rectangle(0, 0, 50, 50);
}
public void LoadContent(ContentManager Content)
{
tex = Content.Load<Texture2D>("cursor");
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(tex, bBox, Color.White);
}
public void Update(GameTime gameTime)
{
MouseState value = Mouse.GetState();
this.pos.X = value.X;
this.pos.Y = value.Y;
this.bBox.X = value.X;
this.bBox.Y = value.Y;
}
}
And also I am drawing as
spriteBatch.Begin(SpriteSortMode.Immediate,
BlendState.AlphaBlend,
null, null, null, null, camera.Translate);
I still cannot completely understand the concept of World and View Matrices and their Math.
After a while I have found the solution using inverse matrices.
I have found this extremly useful: Tutorial XNA Camera

C# Creating Authentic Camera /w head

I've been dabbling with this problem for a few days now, which is really embarrassing, cause you'd think it would be really easy to fix.
I'm working on making the Camera function for a game I'm making in XNA (yes, I know XNA is no longer supported, please stop telling me). It is being developed for the Oculus Rift, and I got it partially working, with joints from Shoulders to Neck, and Neck to Head.
The eyes are what is currently troubling me. Currently, when looking straight forward, it works fine. But as soon as I rotate (Pitch), the eyes do not follow. They basically get stuck on the same offset (like, x+2 and x-2 from camera position), which means that when I turn 180 degrees around, the eyes are now swapped. So my left vision is my right camera, and vice versa.
Here's my code:
[CameraController.cs]
public override void Update(GameTime gameTime)
{
Vector3 leftEyePosition = GetEyePosition(Eyes.Left);
Vector3 rightEyePosition = GetEyePosition(Eyes.Right);
_leftEyeCamera.Update(gameTime, leftEyePosition, NeckHead.Yaw, NeckHead.Pitch, NeckHead.Roll, 2);
_rightEyeCamera.Update(gameTime, rightEyePosition, NeckHead.Yaw, NeckHead.Pitch, NeckHead.Roll, -2);
}
private Vector3 GetEyePosition(Eyes eyes)
{
Matrix neckHead = GetHeadPositions();
Vector3 eye = (eyes == Eyes.Left ? neckHead.Left : neckHead.Right);
Vector3 eyePosition = NeckHead.Position;
return (eye + eyePosition);
}
private Matrix GetHeadPositions()
{
Matrix shoulderNeck = ShoulderNeck.GetMatrix();
Matrix neckHead = NeckHead.GetMatrix()*shoulderNeck;
return neckHead;
}
[Joint.cs]
public class Joint
{
private float _pitch;
private Vector3 _position;
private float _roll;
private float _yaw;
public Joint(Joint childJoint, Vector3 position)
{
ChildJoint = childJoint;
Position = position;
}
public Vector3 Position { get; set; }
public float Yaw { get; set; }
public float Pitch { get; set; }
public float Roll { get; set; }
public Joint ChildJoint { get; private set; }
public Matrix GetMatrix()
{
return Matrix.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
}
}
[FpsCamera.cs Update method]
public void Update(GameTime gameTime, Vector3 position, float yaw, float pitch, float roll)
{
Matrix rotationMatrix = Matrix.CreateFromYawPitchRoll(pitch, yaw, roll);
Vector3 transformedReference = Vector3.Transform(Vector3.Forward, rotationMatrix);
Vector3 target = transformedReference + position;
view = Matrix.CreateLookAt(position, target, rotationMatrix.Up);
}
As far as I can tell, this should be working, right? I think it might be a problem with one of the matrices, but if I knew, I wouldn't be asking, so... Anyone got a hunch?
Complete classes:
http://pastebin.com/zUVwAPFt
http://pastebin.com/jTbnNsJm
Thanks
Bjarke
Ps. Shorted it down for all you guys asking.
Right. Silly me. After about a week of researching, I finally went to see if what I thought I was completely sure of, wasn't true. I'd mixed up what directions Yaw and Pitch works, which obviously resulted in VERY odd-working code.
So in the end, if anyone has a problem similar to this, if it is not the Yaw, Pitch or Roll axis that's a problem, you wont find the answer here.

How do I fix a StackOverflowException?

I am getting a StackOverflowException in my C# program.
Cmodel.cs
public class CModel
{
public Vector3 Position { get; set; }
public Vector3 Rotation { get; set; }
public Vector3 Scale { get; set; }
public Model Model { get; private set; }
public BoundingSphere BoundingSphere
{
get
{
// no need for rotation, as this is a sphere
Matrix worldTransform = Matrix.CreateScale(Scale) *
Matrix.CreateTranslation(Position); // THIS IS WHERE THE EXCEPTION OCCURS
BoundingSphere transformed = BoundingSphere;
transformed = transformed.Transform(worldTransform);
return transformed;
}
}
private Matrix[] modelTransforms;
private GraphicsDevice graphicsDevice;
private BoundingSphere boundingsphere;
public CModel(Model Model, Vector3 Position, Vector3 Rotation,
Vector3 Scale, GraphicsDevice graphicsDevice)
{
this.Model = Model;
modelTransforms = new Matrix[Model.Bones.Count];
Model.CopyAbsoluteBoneTransformsTo(modelTransforms);
buildBoundingSphere();
}
public void Draw(Matrix View, Matrix Projection)
{
// Calculate the base transformation by combining
// translation, rotation, and scaling
Matrix baseWorld = Matrix.CreateScale(Scale)
* Matrix.CreateFromYawPitchRoll(
Rotation.Y, Rotation.X, Rotation.Z)
* Matrix.CreateTranslation(Position);
foreach (ModelMesh mesh in Model.Meshes)
{
Matrix localWorld = modelTransforms[mesh.ParentBone.Index]
* baseWorld;
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
BasicEffect effect = (BasicEffect)meshPart.Effect;
effect.World = localWorld;
effect.View = View;
effect.Projection = Projection;
effect.EnableDefaultLighting();
}
mesh.Draw();
}
}
private void buildBoundingSphere()
{
BoundingSphere sphere = new BoundingSphere(Vector3.Zero, 0);
// Merge all the model's built in bounding spheres
foreach (ModelMesh mesh in Model.Meshes)
{
BoundingSphere transformed = mesh.BoundingSphere.Transform(
modelTransforms[mesh.ParentBone.Index]);
sphere = BoundingSphere.CreateMerged(sphere, transformed);
}
this.boundingsphere = sphere;
}
}
}
You have a recursive call in your getter which will call itself and cause the StackOverflowException :
public BoundingSphere BoundingSphere
{
get
{
...
BoundingSphere transformed = BoundingSphere;
...
}
}
It's not completely clear what you meant to write - but if you want to preserve any state you will need a backing field for storing the bounding sphere instead.
Your get method calls itself: BoundingSphere calls BoundingSphere.
private BoundingSphere _boundingsphere = null;
public BoundingSphere BoundingSphere
{
get
{
// no need for rotation, as this is a sphere
**Matrix worldTransform = Matrix.CreateScale(Scale)
* Matrix.CreateTranslation(Position);**
BoundingSphere transformed = _boundingsphere;
transformed = transformed.Transform(worldTransform);
return transformed;
}
set
{
_boundingsphere = value;
}
}
When you use following form:
public BoundingSphere BoundingSphere { get; set }
you don't need to specify variable to store actual value, but when you implement get or set explicitly you should declare additional variable and use it in get, set implementations.
Look at the call stack or the exception's stack trace.
Identify the loop.
Figure out how to break the loop.
I think you're needing to change
get
{
...
BoundingSphere transformed = BoundingSphere; // public property
...
}
to this
get
{
...
BoundingSphere transformed = boundingsphere; // private variable
...
}

Move sprite in the direction of the value from the rotation?

I'm new to XNA and I'm building an Asteroids game. I have some problems to get my spaceship to move forward in the direction I want. When I press the arrow up key, I want the engine to start and move the space ship in the same directions as the rotation of the spaceship? Help is preciated! I add the subclass that is my spaceship. The Draw method and its variables are in the main class. I'm not sure what to have in the EngineOn method?
class Spaceship: GameObject
{
// Konstruktor
public Spaceship(Texture2D texture, Vector2 position): base(texture, position)
{
}
public override void Update()
{
direction = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
position += direction * speed; //position = position + direction
//base.Update();
}
// Metod som beräknar rymdskeppets färd i riktningen
public void EngineOn()
{
Update();
}
// Metod som beräknar rymdskeppets rotation motsols
public void RotateLeft()
{
rotation -= rotationSpeed;
}
// Metod som beräknar rymdskeppets rotation medsols
public void RotateRight()
{
rotation += rotationSpeed;
}
// Metod som beräknar bana för avlossade skott
public void Fire()
{
}
}
public void EngineOn()
{
speed = 20;
}
public void EngineOff()
{
speed = 0;
}
P.S. Your speed is CPU is dependent, multiply your speed on deltaTime
public override void Update(GameTime gameTime)
{
direction = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
position += direction * speed * gameTime.ElapsedGameTime.Milliseconds;
}

Categories