我想做的是像Terraria这样的标题,而不是图形的来回摇摆,我知道它只是一个.png来回摇摆,但任何人都可以帮助我和其他阅读此书的人,该怎么做?
所以我想学习如何像Terraria中显示的标题一样来回摇摆?
对于不知道Terraria是什么的人,类似的东西。
http://www.youtube.com/watch?v=3k8pmg42l3m
看来徽标在非平等时间间隔内旋转并更改其大小。
首先,您需要熟悉此方法:
spriteBatch.draw方法(texture2d,vector2,nullable,color,single,single,vector2,single,spriteEffs,单个)
)
参数为:
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代码中进行操作。用alpha-enannel取PNG或GIF(以便非文本是透明的)。
然后,当您使用spriteBatch.draw()
在屏幕上绘制它时,您可以选择一个支持缩放和 rotation 的过载之一。。
然后您必须设置:
- 您想要的旋转(随着时间的推移会旋转)
- 原点(到图像的中心)
- 比例尺(将随时间扩展)
,就我记得XNA而言,时钟被发送到update()
方法,我们将不得不更新那里的图像的旋转和尺度。我们需要时钟,因为我们不能仅设置rotaton = 10°
,而XNA将为我们处理所有内容。我们必须在每个时间步骤中计算当前旋转。例如。如果完全旋转将持续10秒和5秒,那么您知道您的旋转半旋转。因此,我们会告诉XNA:Set our rotation to 180° now
,在下一次步骤中,我们可能会说:Set our rotation to 190° now
。
基本概念是:
- 计算我们在当前时间步骤中所做的旋转/比例的多少
- 告诉XNA在此时间步骤中调整此旋转/比例
- 一次遍历这两个步骤
实施
我认为这里最好的事情是使用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);
}