using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace XnaWheel
{
class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch sprite;
SpriteFont font;
BasicEffect effect;
VertexBuffer vbSide;
IndexBuffer ibSide;
VertexBuffer vbTread;
IndexBuffer ibTread;
Texture2D texture;
// fps
int fpsSec = -1;
int fpsDraw = 0;
int fpsCount = 0;
// カメラ
int camLat = 0;
int camLon = 90;
float camDist = 3;
float speed = 0;
float angle = 0;
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");
texture = Content.Load<Texture2D>("Wheel");
effect = new BasicEffect(GraphicsDevice);
effect.Texture = texture;
effect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 10);
GenerateSide();
GenerateTread(32);
base.LoadContent();
}
private void GenerateSide()
{
// 頂点
VertexPositionTexture[] vertices = new VertexPositionTexture[8];
vertices[0] = new VertexPositionTexture(new Vector3(-0.5f, 0.5f, 0.25f), new Vector2(0, 0));
vertices[1] = new VertexPositionTexture(new Vector3(0.5f, 0.5f, 0.25f), new Vector2(1, 0));
vertices[2] = new VertexPositionTexture(new Vector3(-0.5f, -0.5f, 0.25f), new Vector2(0, 1));
vertices[3] = new VertexPositionTexture(new Vector3(0.5f, -0.5f, 0.25f), new Vector2(1, 1));
vertices[4] = new VertexPositionTexture(new Vector3(0.5f, 0.5f, -0.25f), new Vector2(0, 0));
vertices[5] = new VertexPositionTexture(new Vector3(-0.5f, 0.5f, -0.25f), new Vector2(1, 0));
vertices[6] = new VertexPositionTexture(new Vector3(0.5f, -0.5f, -0.25f), new Vector2(0, 1));
vertices[7] = new VertexPositionTexture(new Vector3(-0.5f, -0.5f, -0.25f), new Vector2(1, 1));
vbSide = new VertexBuffer(GraphicsDevice,
typeof(VertexPositionTexture), vertices.Length, BufferUsage.WriteOnly);
vbSide.SetData(vertices);
// 索引
short[] indices = new short[12];
indices[0] = 0; indices[1] = 1; indices[2] = 2;
indices[3] = 3; indices[4] = 2; indices[5] = 1;
indices[6] = 4; indices[7] = 5; indices[8] = 6;
indices[9] = 7; indices[10] = 6; indices[11] = 5;
ibSide = new IndexBuffer(GraphicsDevice,
typeof(short), indices.Length, BufferUsage.WriteOnly);
ibSide.SetData(indices);
}
private void GenerateTread(int slices)
{
// 頂点
VertexPositionColor[] vertices = new VertexPositionColor[slices * 2];
int i = 0;
for (int n = 0; n < slices; n++)
{
float rad = (float)n / slices * MathHelper.TwoPi;
float y = (float)(Math.Cos(rad) * 0.5);
float x = (float)(Math.Sin(rad) * 0.5);
vertices[i++] = new VertexPositionColor(new Vector3(x, y, 0.25f), Color.Black);
vertices[i++] = new VertexPositionColor(new Vector3(x, y, -0.25f), Color.Black);
}
vbTread = new VertexBuffer(GraphicsDevice,
typeof(VertexPositionColor), vertices.Length, BufferUsage.WriteOnly);
vbTread.SetData(vertices);
// 索引
short[] indices = new short[slices * 6];
i = 0;
for (int n = 0; n < slices; n++)
{
for (int m = 0; m < 6; m++)
{
indices[i++] = (short)((n * 2 + ((m < 3) ? m : 6 - m)) % (slices * 2));
}
}
ibTread = new IndexBuffer(GraphicsDevice,
typeof(short), indices.Length, BufferUsage.WriteOnly);
ibTread.SetData(indices);
}
protected override void Update(GameTime gameTime)
{
KeyboardState kState = Keyboard.GetState();
if (kState.IsKeyDown(Keys.Escape)) Exit();
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 + 1) % 360;
if (kState.IsKeyDown(Keys.Right)) camLon = (camLon + 359) % 360;
if (kState.IsKeyDown(Keys.PageUp)) camDist = Math.Max(camDist - 0.1f, 0.1f);
if (kState.IsKeyDown(Keys.PageDown)) camDist = Math.Min(camDist + 0.1f, 5);
if (kState.IsKeyDown(Keys.X)) speed += 0.25f;
if (kState.IsKeyDown(Keys.Z)) speed = Math.Max(speed - 0.5f, 0);
angle += speed;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// カメラ位置
float rad = MathHelper.ToRadians(camLat);
float y = (float)Math.Sin(rad) * camDist;
float r = (float)Math.Cos(rad) * camDist;
rad = MathHelper.ToRadians(camLon);
float x = (float)Math.Cos(rad) * r;
float z = (float)Math.Sin(rad) * r;
effect.View = Matrix.CreateLookAt(new Vector3(x, y, z), Vector3.Zero, Vector3.Up);
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
// 側面
effect.World = Matrix.CreateRotationZ(MathHelper.ToRadians(angle));
effect.TextureEnabled = true;
effect.VertexColorEnabled = false;
pass.Apply();
GraphicsDevice.SetVertexBuffer(vbSide);
GraphicsDevice.Indices = ibSide;
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
0, 0, vbSide.VertexCount, 0, ibSide.IndexCount / 3);
// 接地面
effect.World = Matrix.Identity;
effect.TextureEnabled = false;
effect.VertexColorEnabled = true;
pass.Apply();
GraphicsDevice.SetVertexBuffer(vbTread);
GraphicsDevice.Indices = ibTread;
GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
0, 0, vbTread.VertexCount, 0, ibTread.IndexCount / 3);
}
// fps
fpsDraw++;
if (gameTime.TotalGameTime.Seconds != fpsSec)
{
fpsCount = fpsDraw;
fpsDraw = 0;
fpsSec = gameTime.TotalGameTime.Seconds;
}
// 2D描画
sprite.Begin();
string text = string.Format("fps={0} lat={1} lon={2} dist={3:f1}",
fpsCount, camLat, camLon, camDist);
sprite.DrawString(font, text, new Vector2(0, 0), Color.White);
text = string.Format("speed={0:f1}", speed);
sprite.DrawString(font, text, new Vector2(0, 20), Color.White);
sprite.End();
base.Draw(gameTime);
}
}
}