我想做的是制作像Terraria这样的标题只是摇摆来回的一面而不是图形面我知道它只是一个.png来回摇摆但是任何人都可以帮助我和其他阅读此内容的人什么知道该怎么做?
所以我想要学习如何制作像Terraria中显示的标题一样的来回摇摆图像?
对于那些不知道Terraria是什么的人来说是这样的。
答案 0 :(得分:4)
徽标似乎在不相等的时间间隔内旋转并改变其大小。
首先,您需要熟悉this method:
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 :(得分:3)
你的意思是当你在菜单中选择东西时,我们可以在大约1:16(也可能在其他时间)看到效果?
据我所见,您可以通过简单的旋转和缩放来完成此操作。所以,如果你不想制作动画gif(你认为它是),你可以在你的XNA代码中做。使用带有alpha通道的png或gif(以便非文本透明)。
然后,当您使用spriteBatch.draw()
在屏幕上绘制时,您可以选择其中一个support scaling and rotation的重载。
然后你必须设置:
当我记得XNA时,时钟被发送到update()
方法,我们将不得不更新图像的旋转和比例。我们需要时钟,因为我们不能只设置rotaton = 10°
,XNA将为我们处理一切。我们必须自己计算每个时间步中的当前轮换。例如。如果一个完整的旋转应该持续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();
}
它没有经过测试,所以甚至可能存在语法错误,但我至少基本的想法应该是正确的,我认为重要的是你理解如何它可以在概念上完成。< / p>
将 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);
}