C# 动画标题(如Terraria和游戏标题)

C# 动画标题(如Terraria和游戏标题),c#,.net,xna,title,C#,.net,Xna,Title,我想做的是制作一个像Terraria这样的标题,只是前后摇摆的一面,而不是图形的一面,我知道它只是一个.png前后摇摆的画面,但是有谁能帮助我和其他读过这篇文章的人,知道怎么做吗 所以我想学习如何制作一个前后摇摆的图像,就像Terraria中显示的标题一样 对于那些不知道Terraria是什么的人来说是这样的 你是说当你在菜单中选择东西时,我们在1:16左右(可能在其他时间也会看到)看到的效果 概念 就我所见,你可以通过简单的旋转和缩放来做到这一点。因此,如果您不想制作动画gif(您认为是这样)

我想做的是制作一个像Terraria这样的标题,只是前后摇摆的一面,而不是图形的一面,我知道它只是一个.png前后摇摆的画面,但是有谁能帮助我和其他读过这篇文章的人,知道怎么做吗

所以我想学习如何制作一个前后摇摆的图像,就像Terraria中显示的标题一样

对于那些不知道Terraria是什么的人来说是这样的


你是说当你在菜单中选择东西时,我们在1:16左右(可能在其他时间也会看到)看到的效果

概念 就我所见,你可以通过简单的旋转和缩放来做到这一点。因此,如果您不想制作动画gif(您认为是这样),您可以在XNA代码中制作。以带有alpha通道的png或gif为例(这样非文本是透明的)

然后,当您使用
spriteBatch.draw()
在屏幕上绘制它时,您可以选择其中一个重载

然后您必须设置:

  • 要进行的旋转(将随时间进行旋转)
  • 原点(到图像的中心)
  • 比例(将随时间缩放)
就我记忆中的XNA而言,时钟被发送到
update()
方法,因此我们必须更新那里图像的旋转和缩放。我们需要时钟,因为我们不能只设置旋转=10°,XNA将为我们处理一切。我们必须自己计算每个时间步中的当前旋转。例如,如果一个完整的旋转持续10秒,并且已经过去了5秒,那么你知道你有一个半旋转。所以我们会告诉XNA:
现在将旋转设置为180°
,在下一个时间步骤中,我们可能会告诉:
现在将旋转设置为190°

基本概念是:

  • 计算我们在当前时间步长内完成了多少部分旋转/缩放
  • 告诉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;
    
    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;
    
    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);
    }
    

    徽标似乎在不相等的时间间隔内旋转并改变其大小

    首先,您需要熟悉:

    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
    
    只需放置
    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
    }
    
    void DrawLogo()
    {
    //这两段非常相似的代码将控制缩放和旋转
    如果(旋转方向>0)
    {
    if(旋转<最大角度)
    旋转+=旋转速度;
    其他的
    旋转方向=-旋转方向;
    }
    其他的
    如果(旋转>最小角度)
    旋转-=旋转速度;
    其他的
    旋转方向=-旋转方向;
    如果(缩放方向>0)
    {
    if(比例<最大比例)
    比例+=比例变化;
    其他的
    scaleDirection=-scaleDirection;
    }
    其他的
    如果(比例>最小比例)
    比例-=比例变化;
    其他的
    scaleDirection=-scaleDirection;
    纹理2d t2d=纹理;
    spriteBatch.Draw(t2d,
    centerScreen,//将其更改为“新矢量2(123456)”`
    null,//null表示绘制整个纹理
    颜色。白色,//无着色
    旋转,//我们上面计算的旋转
    新矢量2(t2d.宽度/2,t2d.高度/2),
    //这会将旋转点设置为纹理的中心
    scale,//我们上面计算的比例
    SpriteEffects.None,//你可以用这个镜像你的纹理
    0);//我通常将其保留为0:p
    }
    

    这是经过测试的,效果很好:)

    谢谢,我现在就试用一下,只有一个问题:如何集成XNA