私がやりたいのは、Terrariaのようなタイトルを、グラフィックス側ではなく、前後に揺れるだけにすることです。これは、.pngが前後に揺れるだけですが、これを読んだ他の人を助けてくれる人はいますか。それを行う方法を知っていますか?
では、Terrariaに表示されるタイトルのように前後に揺れる画像を作成する方法を学びたいのですが。
Terrariaが何であるかを知らない人々のためのこのような何か。
私がやりたいのは、Terrariaのようなタイトルを、グラフィックス側ではなく、前後に揺れるだけにすることです。これは、.pngが前後に揺れるだけですが、これを読んだ他の人を助けてくれる人はいますか。それを行う方法を知っていますか?
では、Terrariaに表示されるタイトルのように前後に揺れる画像を作成する方法を学びたいのですが。
Terrariaが何であるかを知らない人々のためのこのような何か。
ロゴが回転し、不均等な時間間隔でサイズが変化しているように見えます。
まず、この方法に慣れる必要があります。
SpriteBatch.Draw メソッド (Texture2D、Vector2、Nullable、Color、Single、Vector2、Single、SpriteEffects、Single)
パラメータは次のとおりです。
Texture2D texture, // texture of your logo
Vector2 position, // where to draw
Nullable<Rectangle> sourceRectangle, // null
Color color, // Color.White
float rotation, // you will be changing this
Vector2 origin, // and this
float scale, // also this
SpriteEffects effects, // SpriteEffects.None
float layerDepth // 0
次の変数を使用します。
float rotation = 0,
rotationSpeed = 0.002f, // this is how much rotation will change each frame
maximumAngle = 0.1f,
minimumAngle = -0.1f,
rotationDirection = 1,
scale = 1f, // 1 means 100%, 0.95f = 95%
scaleChange = 0.005f, // this may seem not much, but it's enough
maxScale = 1.1f,
minScale = 0.9f,
scaleDirection = 1;
DrawLogo();
メインDraw()
メソッドを入れるだけです。
void DrawLogo()
{
// these two very similar pieces of code will control scale and rotation
if (rotationDirection > 0)
{
if (rotation < maximumAngle)
rotation += rotationSpeed;
else
rotationDirection = -rotationDirection;
}
else
if (rotation > minimumAngle)
rotation -= rotationSpeed;
else
rotationDirection = -rotationDirection;
if (scaleDirection > 0)
{
if (scale < maxScale)
scale += scaleChange;
else
scaleDirection = -scaleDirection;
}
else
if (scale > minScale)
scale -= scaleChange;
else
scaleDirection = -scaleDirection;
Texture2d t2d = logoTexture;
spriteBatch.Draw(t2d,
centerScreen, // change this to `new Vector2(123, 456)`
null, // null means draw entire texture
Color.White, // no tinting
rotation, // the rotation we calculate above
new Vector2(t2d.Width / 2, t2d.Height / 2),
// this sets rotation point to the center of the texture
scale, // the scale we calculate above
SpriteEffects.None, // you can mirror your texture with this
0); // I usually leave it zero :p
}
これはテスト済みで、問題なく動作します:)
1:16 あたり (おそらく他の時間も) で、メニューで何かを選択したときに見られる効果のことですか?
私が見る限り、単純な回転とスケーリングでこれを行うことができます。したがって、アニメーション GIF を作成したくない場合 (そうであると思われます) は、XNA コード内で行うことができます。アルファチャンネルを使用してpngまたはgifを取得します(非テキストが透明になるように)。
次に、画面に描画するときに、スケーリングと回転をサポートspriteBatch.draw()
するオーバーロードの 1 つを選択できます。
次に、設定する必要があります。
update()
私がXNAを覚えている限り、クロックはメソッドに送信されるため、そこで画像の回転とスケールを更新する必要があります。rotaton = 10°
設定するだけではなく、XNA がすべてを処理してくれるため、クロックが必要です。各時間ステップで現在の回転を自分で計算する必要があります。たとえば、1 回転が 10 秒間持続し、5 秒が経過した場合、半回転したことがわかります。したがって、XNA: と伝えSet our rotation to 180° now
、次のタイム ステップでは、: と伝えますSet our rotation to 190° now
。
基本的なコンセプトは次のとおりです。
ここで行う最善の方法は、スケーリングと回転に sin() または cos() 関数を使用することです。それらの良い点:
ここで私の数学が正しいことを願っています。私はすべてを説明しますので、何かが間違っている場合は他の人が私を修正できます。または、何かが間違っているかどうかを調べることもできます。ここでは sin() を使用します。これは 0 から始まるため、この場合は何も起こらないことを意味します。それが私たちが望んでいることです。何も起こらない状況から始めたいのです。
現在、sin() のサイクル時間は 2*PI です。もちろん、スケーリングが 2*PI 続くようにするのではなく、1000 ミリ秒程度にする必要があります。C# での定義を変更することはできませんが、Math.Sin()
内部でスローする値を変更することはできます。したがって、1000 ミリ秒を意味するMath.Sin()
場合は 2PI を指定し、500 ミリ秒を意味する場合は PI を指定します。
これらのメンバー変数を定義します。
// define some variables for rotation and scale speed, in milliseconds
int fullRotationTime = 1000; // max rotation will be reached after 1 second
float maxRotationAngle = MathHelper.ToRadians(10); // we will rotate by 10 degree up and down
int rotationTimePassed = 0;
float currentRotationAngle = 0;
int fullScaleTime = 1000; // max scale will be reached after 1 second
float maxScaleSize = 1.2f; // we will scale to 20% larger max
int scaleTimePassed = 0;
float currentScaleFactor = 1.0;
メソッドでは、Update()
すでに行ったローテーションの量を計算します。
protected virtual void Update(GameTime gameTime)
{
int milliseconds = gameTime.ElapsedGameTime.TotalMilliseconds;
// these are the milliseconds in the current rotation
rotationTimePassed += milliseconds;
scaleTimePassed += milliseconds;
if (rotationTimePassed >= fullRotationTime)
rotationTimePassed %= fullRotationTime;
if (scaleTimePassed >= fullScaleTime)
scaleTimePassed %= fullScaleTime;
float rotationTimeAdjustedToTwoPi = ((float)rotationTimePassed)/fullRotationTime * 2* Math.PI);
currentRotationAngle = maxRotationAngle * Math.Sin(rotationTimeAdjustedToTwoPi);
// we do not want the scaling to be negative, thus we add 1 to the whole and
// divide by 2. Then the maximum will be 1 and the minimum 0
float scaleTimeAdjustedToTwoPi = ((float)scaleTimePassed)/fullScaleTime * 2* Math.PI);
currentScaleFactor = maxScaleSize * (Math.Sin(scaleTimeAdjustedToTwoPi) + 1)/2;
}
次に、Draw()
メソッドで、前に計算された値を取得し、回転およびスケーリングされた画像を表示できます。
protected virtual void Draw()
{
spriteBatch.Begin();
spriteBatch.Draw(texture,
new Vector2(50, 50),
null,
Color.White,
currentRotationAngle,
new Vector2(texture.width/2, texture.height/2),
currentScaleFactor,
SpriteEffects.None,
0
);
spriteBatch.End();
}
テストされていないため、構文エラーが発生する可能性もありますが、少なくとも基本的な考え方は正しいはずです。重要なことは、概念的にどのように実行できるかを理解することだと思います.
user1306322が言及した可変時間ステップを上記のコードに統合するのは簡単です。次のように、現在のタイム スライスが終了したかどうかを確認する if 条件がありましたif (rotationTimePassed >= fullRotationTime)
。
ここで、タイム スライスを可変長にしたいので、乱数に基づいて新しいタイム スライスを調整します。このような:
var rand = new Random();
if (rotationTimePassed >= fullRotationTime)
{
rotationTimePassed %= fullRotationTime;
// next rotation might take between 0.5 and 2.5 seconds
fullRotationTime = rand.next(500, 2500);
}