Roy Triesscheijn’s Weblog

My programming world

Archive for January, 2010

Tutorial: Using the XNA Content Pipeline for localization: Part 1, Strings

Posted by Roy Triesscheijn on 30th January 2010

Lately I’ve been working on making localization easier. I came up with an idea to use the content pipeline and content manager to automatically localize your strings*, textures and sounds (and any other content type you might want to localize).

In part one we create a new content pipeline extension and a new content manager without much effort. And we start to replace our strings with calls to our new content manager (that replaces the default one). In the end you will be able to load a string using Content.Load<String>(“Package.Key”); The correct string will be loaded from our xnb files (imported using a custom xml importer) in the language set in the content manager.

In part two we are going to extend this example to load other content as normal (Content.Load<Texture2D>(@”Folder\Name”);). And if you’ve created a localized version this will be loaded instead of the original file.

Part 1 is now up at SgtConker.Com: http://www.sgtconker.com/2010/01/article-using-xna-content-pipeline-extensions-for-localization/

Feel free to post any comments and questions either here or at sgtconker.com.

Part 2 will probably be up end of next week.

kick it on GameDevKicks.com

Tags: , , , , , ,
Posted in Blog, General Gamedesign, XNA | No Comments »

Mouse position in 3D, snippet

Posted by Roy Triesscheijn on 13th January 2010

And another snippet for today. I wanted to test some more path finding code so I wanted to move a collidable object with the mouse. To do so you have to ‘unproject’ your mouse coordinates (x and y) to a position in 3D space (x,y,z). I first tried to use the unproject method directly. But after reading the msdn article I figured out that the z-values can be either 0 (near clip plane) or something else (far clip plane). So this didn’t give me good results if I just plugged in the z level I wanted.

After reading on about rays and intersect methods, user ConkerJo on #XNA pointed out that intersect returns a point of intersection instead of true or false. So with that knowledge, and a little help from him and msdn, I quickly produced the following code.

This code will convert your mouse position to a point laying on the ground plane.

Remember that the definition of your ground plane is a normal. So if you want the x-z space to be the floor (eg. y is up), assign it like this:

private Plane GroundPlane = new Plane(0, 1, 0, 0);  //creates a plane on the x-z axises.

And if you use another common approach, where z is up and the ground is on x-y use this:

private Plane GroundPlane = new Plane(0, 0, 1, 0); //creates a plane on the x-y axises.

And now here’s the actual snippet:

/// <summary>
        /// Calculates where the mouse would be if it would float around at the level of the ground plane.
        /// Based on http://msdn.microsoft.com/en-us/library/bb203905.aspx and user conkerjo who
        /// pointed out that Ray.Intereset returns a vector3 and not a boolean (true/false) *DOH*.
        /// </summary>
        /// <returns></returns>
        private Vector3 CalculateMouse3DPosition()
        {
            int mouseX = Mouse.GetState().X;
            int mouseY = Mouse.GetState().Y;

            Vector3 nearsource = new Vector3((float)mouseX, (float)mouseY, 0f);
            Vector3 farsource = new Vector3((float)mouseX, (float)mouseY, 1f);

            Matrix world = Matrix.CreateTranslation(0, 0, 0);

            Vector3 nearPoint = device.Viewport.Unproject(nearsource,
                camera.ProjectionMatrix, camera.ViewMatrix , Matrix.Identity);

            Vector3 farPoint = device.Viewport.Unproject(farsource,
                camera.ProjectionMatrix, camera.ViewMatrix, Matrix.Identity);

            Vector3 direction = farPoint - nearPoint;
            direction.Normalize();
            Ray pickRay = new Ray(nearPoint, direction);
            float? position = pickRay.Intersects(GroundPlane);

            if (position.HasValue)
            {
                return pickRay.Position + pickRay.Direction * position.Value;
            }
            else
            {
                return target.Position;
            }
        }

Tags: , , , , , , , ,
Posted in Blog, General Gamedesign, XNA | 1 Comment »

Collision avoidance, path finding and smooth following, 3D snippet (C#/XNA)

Posted by Roy Triesscheijn on 13th January 2010

Today I converted my “Swarm Like collision avoidance, path finding and smooth following”- project (what a mouth full) to work with 3D coordinates, if you understood the code, you would know this wasn’t much of a problem. Anyway I did it for you today :) . (original article here).

public static void Attract(GameTime gameTime, Object3D ship, Object3D[] obstacles, Object3D target)
        {
            float pullDistance = Vector3.Distance(target.Position, ship.Position);

            //Only do something if we are not already there
            if (pullDistance > ((ship.Radius + target.Radius) * 1.5f))
            {
                Vector3 pull = (target.Position - ship.Position) * (1 / pullDistance); //the target tries to 'pull us in'
                Vector3 totalPush = Vector3.Zero;

                int contenders = 0;
                for (int i = 0; i < obstacles.Length; ++i)
                {

                    //draw a vector from the obstacle to the ship, that 'pushes the ship away'
                    Vector3 push = ship.Position - obstacles[i].Position;

                    //calculate how much we are pushed away from this obstacle, the closer, the more push
                    float distance = (Vector3.Distance(ship.Position, obstacles[i].Position) - obstacles[i].Radius) - ship.Radius;
                    //only use push force if this object is close enough such that an effect is needed
                    if (distance < ship.Radius * 3)
                    {
                        ++contenders; //count that this object is actively pushing

                        if (distance < 0.0001f) //prevent division by zero errors and extreme pushes
                        {
                            distance = 0.0001f;
                        }
                        float weight = 1 / distance;
                        totalPush += push * weight;
                    }
                }

                pull *= Math.Max(1, 4 * contenders); //4 * contenders gives the pull enough force to pull stuff trough (tweak this setting for your game!)
                pull += totalPush;

                //Normalize the vector so that we get a vector that points in a certain direction, which we van multiply by our desired speed
                pull.Normalize();
                //Set the ships new position;
                ship.Position += (pull * ship.Speed) * (float)gameTime.ElapsedGameTime.TotalSeconds;
            }
        }

Tags: , , , , , , , , ,
Posted in Blog, General Gamedesign, XNA | 6 Comments »