All pastes #783402 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-11-19 05:32 UTC
rendered paste body
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Ultima.XNA.IO;
using System.IO;
using Ultima.XNA.Input;
using Ultima.XNA.Collections;
using Microsoft.Xna.Framework.Input;

namespace Ultima.XNA
{
    public enum DrawType
    {
        Texture,
        Land,
        Static,
        Animation
    }

    public struct DrawSet
    {
        public int Id;
        public DrawType DrawType;
    }

    public class MapRendererComponent : DrawableClientComponent
    {
        private VertexPositionTexture[] vertices;
        private VertexBuffer vertexBuffer;
        private TileMatrix tileMatrix;
        private VertexDeclaration vertexDeclaration;
        private PrimitiveType primitiveType = PrimitiveType.TriangleStrip;
        private Vector3 PlayerLocation = new Vector3(1410, 1660, 0);
        private int displaySize = 34;
        private int count = 0;
        private DrawSet[] drawSets;

        public MapRendererComponent(Game game)
            : base(game)
        {
        }

        protected override void LoadGraphicsContent(bool loadAllContent)
        {
            base.LoadGraphicsContent(loadAllContent);

            vertices = new VertexPositionTexture[0x10000];
            //textureBuffer = new Texture2D[0x3FFF];
            drawSets = new DrawSet[0x3FFF];

            vertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionTexture.SizeInBytes * vertices.Length, ResourceUsage.None);
            tileMatrix = new TileMatrix(0, 0, 6144, 4096);
            vertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionTexture.VertexElements);
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            PlayerLocation.Z = tileMatrix.GetLandTile((int)PlayerLocation.X, (int)PlayerLocation.Y).Z;

            if (InputState.Keyboard.IsKeyDown(Keys.OemPlus) && displaySize < 96)
            {
                displaySize += 1;
                //vertices = new VertexPositionTexture[0x10000];
                //textureBuffer = new Texture2D[0x10000];
                //vertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionTexture.SizeInBytes * vertices.Length, ResourceUsage.None);
            }

            if (InputState.Keyboard.IsKeyDown(Keys.OemMinus) && displaySize > 1)
            {
                displaySize -= 1;
                //vertices = new VertexPositionTexture[0x10000];
                //textureBuffer = new Texture2D[0x10000];
                //vertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionTexture.SizeInBytes * vertices.Length, ResourceUsage.None);
            }

            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

            int dispSizeOver2 = displaySize / 2;

            int startX = (int)PlayerLocation.X - dispSizeOver2;
            int startY = (int)PlayerLocation.Y - dispSizeOver2;
            int maxX = (int)PlayerLocation.X + dispSizeOver2;
            int maxY = (int)PlayerLocation.Y + dispSizeOver2;
            
            int offset = 0;

            if (displaySize % 2 != 0)
            {
                maxX++;
                maxY++;
            }

            for (int y = startY; y < maxY; y++)
            {
                for (int x = startX; x < maxX; x++)
                {
                    Vector3 drawOffset = new Vector3();

                    int xIndex = x - startX;
                    int yIndex = y - startY;

                    drawOffset.X = xIndex * 44;
                    drawOffset.Y = yIndex * 44;

                    int heightOffset = 0;

                    object[] objs = SortObjects(tileMatrix.GetObjects(x, y));

                    for (int i = 0; i < objs.Length; i++, offset++, count++)
                    {
                        int vertexIndex = ((offset) * 6);
                        int textureIndex = offset;
                            
                        object obj = objs[i];
                    
                        if (obj is Tile)
                        {
                            Tile tile = (Tile)obj;
                            int z = (tile.Z << 2);

                            drawSets[textureIndex].Id = tile.ID;
                            drawSets[textureIndex].DrawType = DrawType.Texture;

                            Artwork.EnsureTextmap(GraphicsDevice, tile.ID);
                            
                            Tile eastTile = tileMatrix.GetLandTile(x + 1, y);//right
                            Tile southTile = tileMatrix.GetLandTile(x, y + 1);//bottom
                            Tile downTile = tileMatrix.GetLandTile(x + 1, y + 1);//bottom right

                            int east = (eastTile.Z - tile.Z) << 2;
                            int south = (southTile.Z - tile.Z) << 2;
                            int down = (downTile.Z - tile.Z) << 2;

                            vertices[vertexIndex].Position = drawOffset + new Vector3(0 - z, 0 - z, 0);
                            vertices[vertexIndex].TextureCoordinate = new Vector2(0, 0);
                            vertices[vertexIndex + 1].Position = drawOffset + new Vector3(44 - z - east, 0 - z - east, 0);
                            vertices[vertexIndex + 1].TextureCoordinate = new Vector2(1, 0);
                            vertices[vertexIndex + 2].Position = drawOffset + new Vector3(44 - z - down, 44 - z - down, 0);
                            vertices[vertexIndex + 2].TextureCoordinate = new Vector2(1, 1);
                            vertices[vertexIndex + 3].Position = drawOffset + new Vector3(0 - z - south, 44 - z - south, 0);
                            vertices[vertexIndex + 3].TextureCoordinate = new Vector2(0, 1);
                            vertices[vertexIndex + 4] = vertices[vertexIndex];
                            vertices[vertexIndex + 5] = vertices[vertexIndex + 2];
                        }
                        else if (obj is HuedTile)
                        {
                            HuedTile stc = (HuedTile)obj;

                            for (int a = 0; a < i; a++)
                            {
                                if (obj is HuedTile)
                                {
                                    heightOffset = TileData.ItemTable[((HuedTile)obj).ID & 0x3FFF].CalcHeight;
                                }
                            }

                            drawSets[textureIndex].Id = stc.ID;
                            drawSets[textureIndex].DrawType = DrawType.Static;    

                            Artwork.EnsureStatic(GraphicsDevice, stc.ID);
                            Texture2D texture = Artwork.GetTexture(stc.ID, DrawType.Static);

                            int z = (stc.Z) << 2;

                            Vector3[] srcVectors = new Vector3[4];

                            float width = texture.Width * 1.40f;
                            float height = texture.Height * 1.40f;

                            Vector3 rotationPoint = new Vector3(-width / 2, -height / 2, 0);
                            Matrix rotationMatrix = Matrix.CreateTranslation(rotationPoint) *
                                Matrix.CreateRotationZ(MathHelper.ToRadians(-45));

                            srcVectors[0] = Vector3.Transform(new Vector3(0, 0 - z, 0), rotationMatrix);
                            srcVectors[1] = Vector3.Transform(new Vector3(width, 0 - z, 0), rotationMatrix);
                            srcVectors[2] = Vector3.Transform(new Vector3(width, height - z, 0), rotationMatrix);
                            srcVectors[3] = Vector3.Transform(new Vector3(0, height - z, 0), rotationMatrix);

                            vertices[vertexIndex + 0].Position = drawOffset + srcVectors[0];
                            vertices[vertexIndex + 1].Position = drawOffset + srcVectors[1];
                            vertices[vertexIndex + 2].Position = drawOffset + srcVectors[2];
                            vertices[vertexIndex + 3].Position = drawOffset + srcVectors[3];

                            vertices[vertexIndex + 0].TextureCoordinate = new Vector2(0, 0);
                            vertices[vertexIndex + 1].TextureCoordinate = new Vector2(1, 0);
                            vertices[vertexIndex + 2].TextureCoordinate = new Vector2(1, 1);
                            vertices[vertexIndex + 3].TextureCoordinate = new Vector2(0, 1);

                            vertices[vertexIndex + 4] = vertices[vertexIndex + 0];
                            vertices[vertexIndex + 5] = vertices[vertexIndex + 2];
                        }                              
                    }
                }
            }

            vertexBuffer.SetData<VertexPositionTexture>(vertices);

            if (InputState.Keyboard.IsKeyDown(Keys.A))
            {
                PlayerLocation.X -= 1;
            }
            if (InputState.Keyboard.IsKeyDown(Keys.D))
            {
                PlayerLocation.X += 1;
            }
            if (InputState.Keyboard.IsKeyDown(Keys.W))
            {
                PlayerLocation.Y -= 1;
            }
            if (InputState.Keyboard.IsKeyDown(Keys.S))
            {
                PlayerLocation.Y += 1;
            }
            if (InputState.KeyboardSpaceJustPressed)
            {
                if (primitiveType == PrimitiveType.TriangleStrip)
                {
                    primitiveType = PrimitiveType.LineStrip;
                }
                else
                {
                    primitiveType = PrimitiveType.TriangleStrip;
                }
            }
        }

        private object[] SortObjects(object[] objs)
        {
            List<object> objList = new List<object>(objs);
            objList.Sort( new Comparison<object>(Compare));

            return objList.ToArray();
        }

        private int Compare(object a, object b)
        {
            int az;
            int bz;

            int athreshhold;
            int bthreshhold;

            int atype;
            int btype;

            int atiebreaker;
            int btiebreaker;

            GetStats(a, out az, out athreshhold, out atype, out atiebreaker);
            GetStats(b, out bz, out bthreshhold, out btype, out btiebreaker);
            
            az += athreshhold;
            bz += bthreshhold;

            int compare = az - bz;

            if (compare == 0)
            {
                compare = atype - btype;
            }
            if (compare == 0)
            {
                compare = athreshhold - bthreshhold;
            }
            if (compare == 0)
            {
                compare = atiebreaker - btiebreaker;
            }

            return compare;

        }

        public void GetStats(object obj, out int z, out int treshold, out int type, out int tiebreaker)
        {
            /*if (obj is MobileCell)
            {
                MobileCell cell = (MobileCell)obj;
                z = cell.Z;
                treshold = 2;
                type = 3;
                if (cell.m_Mobile.Player)
                {
                    tiebreaker = 0x40000000;
                }
                else
                {
                    tiebreaker = cell.Serial;
                }
            }
            else*/ 
            if (obj is Tile)
            {
                Tile tile = (Tile)obj;
                z = tile.Z;
                treshold = 0;
                type = 0;
                tiebreaker = 0;
            }
            /*else if (obj is DynamicItem)
            {
                int num;
                DynamicItem item = (DynamicItem)obj;
                z = item.Z;
                if (Map.m_ItemFlags[item.ID & 0x3fff][TileFlag.Background])
                {
                    num = 0;
                }
                else
                {
                    num = 1;
                }
                treshold = (item.Height == 0) ? num : (num + 1);
                type = ((item.ID & 0x3fff) == 0x2006) ? 4 : 2;
                tiebreaker = item.Serial;
            }*/
            else if (obj is HuedTile)
            {
                int tresh;
                HuedTile item2 = (HuedTile)obj;
                z = item2.Z;

                if ((TileData.ItemTable[item2.ID & 0x3FFF].Flags & TileFlag.Background) != TileFlag.None)
                {
                    tresh = 0;
                }
                else
                {
                    tresh = 1;
                }
                treshold = (TileData.ItemTable[item2.ID & 0x3FFF].Height == 0) ? tresh : (tresh + 1);
                type = 1;
                tiebreaker = 1;
            }
            else
            {
                z = 0;
                treshold = 0;
                type = 0;
                tiebreaker = 0;
            }
        }


        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            Viewport viewport = GraphicsDevice.Viewport;

            int vertPos = 0;

            GraphicsDevice.VertexDeclaration = vertexDeclaration;
            GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionTexture.SizeInBytes);
            GraphicsDevice.Viewport = Engine.GameViewport;
            GraphicsDevice.RenderState.AlphaBlendEnable = true;
            GraphicsDevice.RenderState.AlphaBlendOperation = BlendFunction.Add;
            GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
            GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
            GraphicsDevice.RenderState.SeparateAlphaBlendEnabled = false;
            GraphicsDevice.RenderState.AlphaTestEnable = true;
            GraphicsDevice.RenderState.AlphaFunction = CompareFunction.Greater;
            GraphicsDevice.RenderState.ReferenceAlpha = 0;
            GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.None;
            GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.None;

            BasicEffect.Projection =
                Matrix.CreateRotationZ(MathHelper.ToRadians(45)) *
                Matrix.CreateTranslation(new Vector3(512, 352 - ((displaySize / 2) * (62.25f)), 0)) *
                Matrix.CreateOrthographicOffCenter(0, Engine.Width, Engine.Height, 0, 0, 1);

            BasicEffect.TextureEnabled = true;

            BasicEffect.Begin();
            BasicEffect.CurrentTechnique.Passes[0].Begin();

            for (int i = 0; i < count; i++, vertPos += 6)
            {
                BasicEffect.Texture = Artwork.GetTexture(drawSets[i].Id, drawSets[i].DrawType);
                BasicEffect.CommitChanges();

                GraphicsDevice.DrawPrimitives(primitiveType, vertPos, 4);
            }

            BasicEffect.CurrentTechnique.Passes[0].End();
            BasicEffect.End();

            GraphicsDevice.Viewport = viewport;

            count = 0;
        }
    }
}