Skip to content

Instantly share code, notes, and snippets.

@karno
Created March 16, 2010 12:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save karno/333906 to your computer and use it in GitHub Desktop.
Save karno/333906 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
namespace Pastiche.Common
{
public static class MathEx
{
/// <summary>
/// 指定した速度で移動します。
/// </summary>
/// <param name="origin">始点</param>
/// <param name="dest">終点</param>
/// <param name="speed">スピード</param>
/// <returns>位置の列挙</returns>
public static IEnumerable<Vector2> GetMovePosition(this Vector2 origin, Vector2 dest, float speed)
{
Vector2 unit = origin - dest;
float unitlen = unit.Length();
unit.X /= unitlen * speed;
unit.Y /= unitlen * speed;
int reqframes = (int)Math.Ceiling((origin.X - unit.X) / unit.X);
for (int i = 0; i < reqframes; i++)
{
origin += unit;
yield return origin;
}
yield return dest;
}
/// <summary>
/// 指定したフレーム数を使用して移動します。
/// </summary>
/// <param name="origin">始点</param>
/// <param name="dest">終点</param>
/// <param name="frames">使用フレーム数</param>
/// <returns>位置の列挙</returns>
public static IEnumerable<Vector2> GetMovePositionWithFrames(this Vector2 origin, Vector2 dest, int frames)
{
Vector2 unit = dest - origin;
unit.X /= frames;
unit.Y /= frames;
for (int i = 0; i < frames; i++)
{
origin += unit;
yield return origin;
}
yield return dest;
}
/// <summary>
/// 減速しながら移動します。
/// </summary>
/// <param name="origin">始点</param>
/// <param name="dest">終点</param>
/// <param name="maxspeed">最高速度</param>
/// <param name="brake">減速度(1.0以上を指定してください)</param>
/// <returns>位置の列挙</returns>
public static IEnumerable<Vector2> GetMovePositionWithSlowing(this Vector2 origin, Vector2 dest, float maxspeed, float brake)
{
//距離差
Vector2 dist = dest - origin;
float length = dist.Length();
//単位加速度(L/frames)
Vector2 unit = new Vector2(dist.X / length, dist.Y / length);
//単位あたりの最大加速度
Vector2 maxvector = new Vector2((float)(dist.X / length * maxspeed), (float)(dist.Y / length * maxspeed));
float mvnorm = maxvector.Length();
while ((dest.X - origin.X) * dist.X > 0 && (dest.Y - origin.Y) * dist.Y > 0)
{
Vector2 cv = unit * brake * (dest - origin).Length();
if (cv.X == 0 || cv.Y == 0)
break;
if (cv.Length() > mvnorm)
origin += maxvector;
else
origin += cv;
yield return origin;
}
yield return dest;
}
/// <summary>
/// エルミート曲線を用いて移動します。
/// </summary>
/// <param name="init">始点</param>
/// <param name="dest">終点</param>
/// <param name="initvector">始点接線ベクトル</param>
/// <param name="destvector">終点接線ベクトル</param>
/// <param name="frames">移動フレーム</param>
/// <returns>位置の列挙</returns>
public static IEnumerable<Vector2> GetMovePositionByHermite(Vector2 origin, Vector2 dest,
Vector2 origvector, Vector2 destvector, int frames)
{
for (int i = 0; i < frames; i++)
{
float u1 = i * 1.0f / (frames - 1);
float u2 = u1 * u1;
float u3 = u2 * u1;
float mP0 = 2 * u3 - 3 * u2 + 1;
float mV0 = u3 - 2 * u2 + u1;
float mP1 = -2 * u3 + 3 * u2;
float mV1 = u3 - u2;
yield return new Vector2(
origin.X * mP0 + origvector.X * mV0 + dest.X * mP1 + destvector.X * mV1,
origin.Y * mP0 + origvector.Y * mV0 + dest.Y * mP1 + destvector.Y * mV1);
}
}
/// <summary>
/// 指定した範囲内でランダムに場所を決定し、ベクトルとして返します。[非推奨]
/// </summary>
/// <param name="region">限定する移動先リージョン</param>
/// <returns>移動先ベクトル</returns>
public static Vector2 GetRundomPosition(this Rectangle region)
{
return new Vector2(MTwister.Next(region.Left, region.Right), MTwister.Next(region.Left, region.Right));
}
/// <summary>
/// 指定したラジアンとノルムから二次元ベクトルを生成します。
/// </summary>
/// <param name="rad">ラジアン</param>
/// <param name="norm">ノルム</param>
/// <returns>二次元ベクトル</returns>
public static Vector2 CreateVector(double rad, float norm)
{
return new Vector2((float)Math.Cos(rad) * norm, (float)Math.Sin(rad) * norm);
}
/// <summary>
/// 弧度法における度数をラジアンに変換します。
/// </summary>
/// <param name="deg">度数</param>
/// <returns>ラジアン</returns>
public static double ToRadian(this double deg)
{
return deg * Math.PI / 180.0;
}
/// <summary>
/// ラジアンを弧度法における度数に変換します。
/// </summary>
/// <param name="rad">ラジアン</param>
/// <returns>度数</returns>
public static double ToDegree(this double rad)
{
return rad * 180.0 / Math.PI;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment