/*
* プロジェクトのプロパティ
* [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);
}
}
}