開発環境 Microsoft Visual C# 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Windows Game (4.0)
プロジェクト名 XnaGeoMap

GeoMap.png


Game1.cs
/*
 * プロジェクトのプロパティ
 * [XNA Game Studio]タブ
 * Use HiDef to access the complete API
 */
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace XnaGeoMap
{
    class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch sprite;
        SpriteFont font;
        BasicEffect effect;
        Texture2D map;
        VertexBuffer vertexBuffer;
        IndexBuffer indexBuffer;
        List<VertexPositionColor> vertices = new List<VertexPositionColor>();
        List<int> indices = new List<int>();
 
        readonly int[] box =
            {
                0,1,2,3,2,1,
                4,5,6,7,6,5,
                0,2,7,6,7,2,
                4,3,5,1,5,3,
                0,7,1,5,1,7,
                4,6,3,2,3,6,
            };
 
        // fps
        int fpsSec = -1;
        int fpsDraw = 0;
        int fpsCount = 0;
 
        // カメラ
        Vector3 camPos = new Vector3(-40, -40, 50);
        int camLat = -15;
        int camLon = 45;
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = 1280;
            graphics.PreferredBackBufferHeight = 720;
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }
 
        protected override void LoadContent()
        {
            sprite = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("SpriteFont1");
 
            effect = new BasicEffect(GraphicsDevice);
            effect.VertexColorEnabled = true;
            effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45),
                GraphicsDevice.Viewport.AspectRatio, 1, 1000);
 
            // 地形図
            map = Content.Load<Texture2D>("GeoMap");
            int elementCount = map.Width * map.Height;
            Color[] data = new Color[elementCount];
            map.GetData<Color>(0, null, data, 0, elementCount);
 
            int i = 0;
            for (int y = 0; y < map.Height; y++)
            {
                for (int x = 0; x < map.Width; x++)
                {
                    Color color = data[i];
                    color.G = 127;
                    int z;
                    if (0 < color.B)
                    {
                        z = -color.B;
                        //GenerateBar(x, y, 0, z, new Color(0, 0, 127, 1));
                    }
                    else
                    {
                        z = color.R;
                    }
                    GenerateBar(x, y, z, -256, color);
                    i++;
                }
            }
 
            vertexBuffer = new VertexBuffer(GraphicsDevice,
                typeof(VertexPositionColor), vertices.Count, BufferUsage.WriteOnly);
            vertexBuffer.SetData(vertices.ToArray());
 
            indexBuffer = new IndexBuffer(GraphicsDevice,
                typeof(int), indices.Count, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices.ToArray());
 
            base.LoadContent();
        }
 
        void GenerateBar(int x, int y, float top, float bottom, Color c)
        {
            int v = vertices.Count;
            top *= 0.25f;
            bottom *= 0.25f;
 
            vertices.Add(new VertexPositionColor(new Vector3(x + 0, y + 1, top), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 1, y + 1, top), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 0, y + 0, top), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 1, y + 0, top), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 1, y + 0, bottom), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 1, y + 1, bottom), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 0, y + 0, bottom), c));
            vertices.Add(new VertexPositionColor(new Vector3(x + 0, y + 1, bottom), c));
 
            for (int i = 0; i < 36; i++)
            {
                indices.Add(v + box[i]);
            }
        }
 
        protected override void Update(GameTime gameTime)
        {
            KeyboardState kState = Keyboard.GetState();
            if (kState.IsKeyDown(Keys.Escape)) Exit();
            if (kState.IsKeyDown(Keys.W)) Move(0, 0);
            if (kState.IsKeyDown(Keys.S)) Move(180, 0);
            if (kState.IsKeyDown(Keys.A)) Move(0, -90);
            if (kState.IsKeyDown(Keys.D)) Move(0, 90);
            if (kState.IsKeyDown(Keys.Up)) camLat = Math.Min(camLat + 1, 89);
            if (kState.IsKeyDown(Keys.Down)) camLat = Math.Max(camLat - 1, -89);
            if (kState.IsKeyDown(Keys.Left)) camLon = (camLon + 359) % 360;
            if (kState.IsKeyDown(Keys.Right)) camLon = (camLon + 1) % 360;
            if (kState.IsKeyDown(Keys.PageUp)) Move(90, 0);
            if (kState.IsKeyDown(Keys.PageDown)) Move(-90, 0);
 
            base.Update(gameTime);
        }
 
        private void Move(int lat, int lon)
        {
            float rad = MathHelper.ToRadians(camLat + lat);
            float z = (float)Math.Sin(rad) * 0.5f;
            float r = (float)Math.Cos(rad) * 0.5f;
            if (lon == 0) camPos.Z += z;
            rad = MathHelper.ToRadians(camLon + lon);
            float y = (float)Math.Cos(rad) * r;
            float x = (float)Math.Sin(rad) * r;
            camPos.Y += y;
            camPos.X += x;
        }
 
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
 
            // カメラ
            float rad = MathHelper.ToRadians(camLat);
            float z = (float)Math.Sin(rad);
            float r = (float)Math.Cos(rad);
            rad = MathHelper.ToRadians(camLon);
            float y = (float)Math.Cos(rad) * r;
            float x = (float)Math.Sin(rad) * r;
            effect.View = Matrix.CreateLookAt(camPos, camPos + new Vector3(x, y, z), Vector3.UnitZ);
 
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                GraphicsDevice.SetVertexBuffer(vertexBuffer);
                GraphicsDevice.Indices = indexBuffer;
                GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
                    0, 0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3);
            }
 
            // fps
            fpsDraw++;
            if (gameTime.TotalGameTime.Seconds != fpsSec)
            {
                fpsCount = fpsDraw;
                fpsDraw = 0;
                fpsSec = gameTime.TotalGameTime.Seconds;
            }
 
            sprite.Begin();
            string text = string.Format("fps={0} lat={1} lon={2}", fpsCount, camLat, camLon);
            sprite.DrawString(font, text, new Vector2(0, 0), Color.White);
            text = string.Format("x={0:f1} y={1:f1} z={2:f1}", camPos.X, camPos.Y, camPos.Z);
            sprite.DrawString(font, text, new Vector2(0, 20), Color.White);
            sprite.End();
 
            base.Draw(gameTime);
        }
    }
}
 
最終更新:2013年01月19日 11:47
添付ファイル