This project is read-only.

Mixing xna and xen

Jun 26, 2010 at 9:10 AM

I want use xen,but within a xna program (inherited from microsoft.framework.game). How? What is the best way? I want to use both at the same time.

Jun 26, 2010 at 12:52 PM
Edited Jun 26, 2010 at 12:53 PM

This is the way XEN is ment to be used. Its just kind of a Grafik Engine that wraps around XNA and extend it.

Instead of deriving from Game.cs you let your programm derive from Application, which provides you the XEN basis structure.

But you can use parts from XNA within this too.

In fact some parts have been replaced  (Vertexdeclaratiosn and Effect system) but they are easy to understand in XEN (ok maybe not THAT easy, but they are very compfortable when you are used to them ;) )

This is a basic strukture for a XEN Game taken from tutorial 1:

 

using System;
using System.Collections.Generic;
using System.Text;



using Xen;
using Xen.Camera;
using Xen.Graphics;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


/*
 * Welcome to xen!
 * 
 * 
 * This tutorial shows how to implement the Application class.
 * (It's quite similar to the XNA Game class)
 * 
 * 
 * 
 * This sample demonstrates:
 * 
 * implementing the Application class
 * creating a draw target that draws to the screen
 * setting the clear colour of the draw target
 * 
 */
namespace Tutorials.Tutorial_01
{
	//Starting simple...
	//
	//This is a basic implementation of the Application class.
	//All it will do is draw to the screen, clearing it to blue.

	[DisplayName(Name = "Tutorial 01: Application Class")]
	public class Tutorial : Application
	{
		//A DrawTarget is a class that performs all the logic needed to complete a draw operation to
		//a surface (such as the screen or a texture).
		//
		//Drawing in xen is very explicit, the call to Draw() will perform the entire draw operation.
		//
		//A DrawTargetScreen is a draw target that draws items directly to the screen.
		//
		//In this tutorial all that will happen is the DrawTarget will clear itself to blue
		//(Most applications will only have one DrawTargetScreen)
		private DrawTargetScreen drawToScreen;

		//This method gets called just before the window is shown, and the device is created
		protected override void Initialise()
		{
			//draw targets usually need a camera.
			//create a 3D camera with default parameters
			Camera3D camera = new Camera3D();

			//create the draw target.
			drawToScreen = new DrawTargetScreen(this, camera);
		}

		//this is the default Update method.
		//Update() is called 60 times per second, which is the same rate that player input
		//is updated.
		//Note: Player input and Updating is explained in more detail in Tutorial 13
        protected override void Update(UpdateState state)
        {
            //quit when the back button is pressed (escape on the PC)
            if (state.PlayerInput[PlayerIndex.One].InputState.Buttons.Back.OnPressed)
                this.Shutdown();
        }

		//This is the main application draw method. All drawing code should go in here.
		//
		//Any drawing should be done through, or using the DrawState object.
		//Do not store a reference to a DrawState - if a method doesn't give access to it, you shouldn't be drawing in that method.
		//The most useful GraphicsDevice functionality is covered by the DrawState or other objects in Xen/Xen.Ex
		//The vast majority of applications shouldn't need to directly access the graphics device.
		protected override void Draw(DrawState state)
		{
                drawToScreen.Draw(state);
		}
	}
}




if you have any questiosn concerning XEN feel free to ask here
Greetings floAr
Jun 26, 2010 at 1:24 PM
Edited Jun 26, 2010 at 1:34 PM

Thank you. But i solved this problem like this (in this minute):

 

1.) I make a empty, extended xen-derived-class:

 

public class Game1 : Application
{
     public static DrawState drawState;
     public static UpdateState updateState;
     public static Application application;

     protected override void Initialise()
     {
          application = this;
          XnaComponents.Add(new Game2(this as Application));
     }


     /// --------------------------------------------------------
     protected override void Draw(DrawState state)
     {
	drawState = state;
     }


     /// -----------------------------------------------------------
     protected override void Update(UpdateState state)
     {
          updateState = state;
     }


     /// ------------------------------------------------------------------------------------------------------------------
 protected
override void SetupGraphicsDeviceManager(GraphicsDeviceManager graphics, ref RenderTargetUsage presentation) { } /// --------------------------------------------------------------------------- protected override void LoadContent(DrawState state, ContentManager manager) { } }

2) I make a XNA Extended Component, with a (little bit!) manipulated tutorial 2 of XEN!

public class Game2 : DrawableGameComponent
{
     Game game;
     Application application;
     GraphicsDevice device;
     DrawTargetScreen drawToScreen;

     public Game2(Game game) : base(game)
     {
	this.game = game;
	this.application = Game1.application;
	this.device = game.GraphicsDevice;
	Initialize();
     }

		public override void Initialize()
		{
			Camera3D camera = new Camera3D();
			camera.LookAt(Vector3.Zero, new Vector3(0, 0, 4), Vector3.UnitY);
			drawToScreen = new DrawTargetScreen( application, camera);
			drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;
			SphereDrawer sphere = new SphereDrawer(Vector3.Zero);
			drawToScreen.Add(sphere);

			base.Initialize();
 		}

		protected override void LoadContent()
		{
		
		}

	
		protected override void UnloadContent()
		{
		}

		public override void Update(GameTime gameTime)
		{
			if (Game1.updateState.PlayerInput[PlayerIndex.One].InputState.Buttons.Back.OnPressed)
				application.Shutdown();

			base.Update(gameTime);
		}

		public override void Draw(GameTime gameTime)
		{
			// ------------
			drawToScreen.Draw(Game1.drawState);

			base.Draw(gameTime);
		}
	}

	class SphereDrawer : IDraw
	{
		private Xen.Ex.Geometry.Sphere sphereGeometry;
		private Matrix worldMatrix;
		private IShader shader;

		//constructor
		public SphereDrawer(Vector3 position)
		{
			Vector3 size = new Vector3(1, 1, 1);
			this.sphereGeometry = new Sphere(size, 32);
			this.worldMatrix = Matrix.CreateTranslation(position);
			MaterialShader material = new MaterialShader();

			Vector3 lightDirection = new Vector3(0.5f, 1, -0.5f); 
			material.Lights = new MaterialLightCollection();
			material.UsePerPixelSpecular = true;
			material.Lights.AmbientLightColour = Color.CornflowerBlue.ToVector3() * 0.5f; 
			material.Lights.AddDirectionalLight(true, lightDirection, Color.Gray);
 material.Lights.AddDirectionalLight(true, -lightDirection, Color.DarkSlateBlue); material.SpecularColour = Color.LightYellow.ToVector3();  this.shader = material; } public void Draw(DrawState state) { state.PushWorldMatrixMultiply(ref this.worldMatrix); if (sphereGeometry.CullTest(state)) { shader.Bind(state); sphereGeometry.Draw(state); } state.PopWorldMatrix(); } public bool CullTest(ICuller culler) { return true; } }
 
And it works perfekt! This is real XEN in XNA

 

Jun 26, 2010 at 1:33 PM
Edited Jun 26, 2010 at 1:37 PM

I'm surprised that code is working. It shouldn't be!

The Xen Application internally creates it's own XNA Game class. You can get it with a cast:

Game xnaGame = (Game)xenApplication;

The XNA components are accessible too, so if you have a DrawableGameComponent, you can add it. I'm improving support for using XNA classes alongside Xen classes in 2.0 (This is partly done in the Alpha).

The only point to be aware of, if that the render state is tracked by xen - and if the XNA component changes it, then the xen code may not notice - and you can get corrupt render state. There are ways around this, by calling DirtyInternalRenderState, although it's less likely in 2.0.

Finally, there is also Xen.GameComponentHost, which is a DrawabeGameComponent that can host a Xen application within it - but it's quite buggy and doesn't work with all the tutorials correctly.

Jun 27, 2010 at 7:39 PM

The first try is not very good. Here is the second contribution. It is a very, very nasty way, because i changed the source a little bit. Now i need only one class for a xenGame. This class
can use xna an xen code without changes.

Modifications in Application.cs
- Line 355 in XNAGameAppWrapper (under XNALogic logic)-> public static GameTime publicGameTime;
- Line 449 (first line in Draw(...)) -> publicGameTime = gameTime;
- Line 454 (first line in Update(...)) -> publicGameTime = gameTime;
- Line 1067, i changed Draw(state) to Draw(XNAGameAppWrapper.publicGameTime, state);
- Line 1089, i changed protected internal abstract void Initialise(); to protected internal abstract void Initialize();
- Line 1108, i changed protected internal abstract void Draw(DrawState state); in protected internal abstract void Draw(GameTime gameTime, DrawState state); //daliman
- Line 1283, i changed this.Update(state); to this.Update(XNAGameAppWrapper.publicGameTime, state);

My XenGame-Temlate looks like this:

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;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using Xen;
using Xen.Camera;
using Xen.Graphics;
using Xen.Ex.Geometry;
using Xen.Ex.Material;

namespace Xen 
{
	public class xenGame : Application
	{
		#if DEBUG // 1 von 4
			private Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay stats;
		#endif

		private DrawTargetScreen drawToScreen;


		/// 1-----------------------------------------------------------------------------------------------------------------
		protected override void SetupGraphicsDeviceManager(GraphicsDeviceManager graphics, ref RenderTargetUsage presentation)
		{
		}


		/// 2-------------------------------
		protected override void Initialize()
		{
			#if DEBUG // 2 von 4
			Resource.EnableResourceTracking();
			#endif

			Camera3D camera = new Camera3D();
			camera.LookAt(Vector3.Zero, new Vector3(0, 0, 4), Vector3.UnitY);
			drawToScreen = new DrawTargetScreen(this, camera);
			drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;
			SphereDrawer sphere = new SphereDrawer(Vector3.Zero);
			drawToScreen.Add(sphere);
			
			#if DEBUG // 3 von 4
				stats = new Xen.Ex.Graphics2D.Statistics.DrawStatisticsDisplay(application.UpdateManager);
				this.drawToScreen.Add(stats);
			#endif
		}


		/// 3--------------------------------------------------------------------------------------------------------------------------------------
		protected override void LoadContent(DrawState state, ContentManager manager)
		{
			#if DEBUG // 4 von 4
				stats.Font = contentManager.Load<SpriteFont>("Arial");
			#endif
		}


		/// 4--------------------------------------------------------------------------------------------------------------------------------------
		//protected override void Update(GameTime gameTime)
		protected override void Update(GameTime gameTime, UpdateState state)
		{	
			if (state.PlayerInput[PlayerIndex.One].InputState.Buttons.Back.OnPressed)
				this.Shutdown();
		}


		/// 5--------------------------------------------------------------------------------------------------------------------------------------
		protected override void Draw(GameTime gameTime,  DrawState state)
		{
			drawToScreen.Draw(state);
		}

	}

	class SphereDrawer : IDraw
	{
           // Code from Tutorial 2
} }

 

Jun 28, 2010 at 10:15 AM

The methodes initialize and update within the xna componente do not run. Therefore, i also add the following changes:

in Application.cs:
Line 417: Change order:  base.Initialize(); after logic.Initialise();
Line 443: add Code 'base.Update(gameTime);' after 'logic.Update(gameTime.TotalRealTime.Ticks, gameTime.TotalGameTime.Ticks);'

and in my xenGameTemplate (at the end of Initialize()):
Game xnaGame = (Game)this;
XnaComponents.Add(new GameComponent1(xnaGame));

This is not tested, but it works for me!