Pergunta

Eu tenho tentado animar suavemente algum local do formulário do Windows, mas estou tendo alguns problemas se quiser que a velocidade seja variável. Em outras palavras, se eu quiser permitir que o usuário selecione a velocidade preferida para animação.

Encontrei o seguinte artigo que me ajudou bastante a realizar a animação que estava procurando, para o meu formulário. Parece melhor em todos os aspectos do que uma abordagem de trabalho de fundo ou tópicos que tentei no passado:http://www.vcskicks.com/animated-windows-form.html

Meu único problema agora é manter uma animação suave se eu quiser ter velocidades diferentes para a animação. Existem dois valores que são importantes no meu código, FPS e Px. O FPS representa os quadros por segundo (o que mais) e o PX representa o número de pixels para mover o formulário.

Problema 1) Para ter a animação mais suave possível, eu preferiria que o formulário mova 1px por vez, mas não acho que possa mover a forma o mais rápido que quero assim. Aumentar o valor do FPS para um valor muito alto não parece ter efeito, é como se exista um limite e acima desse limite, não haverá diferenças visíveis. Tenho certeza de que há uma boa explicação para isso.

Minha pergunta aqui é: você tem uma boa solução para esse problema ou a única solução é alterar o valor PX e mover o formulário em mais de 1px se eu quiser um movimento mais rápido?

Problema 2) Se a solução para a pergunta acima é alterar o valor do PX de acordo, descobri (testando valores diferentes) que um valor de FPS igual a 300 basta que minhas necessidades de mover o formulário tão lento e rápido quanto eu quiser. Então, se eu quisesse 10 velocidades, movendo o formulário por 1, 2, 3, 4, 5, 6, 7, 8, 9 e 10 pixels fornece animações lentas e rápidas, assim como eu quero. Se eu quisesse 5 velocidades, poderia usar 2, 4, 6, 8, 10, por exemplo.

Minha pergunta aqui é: há algum problema para usar um valor como 300 para FPS? Existem consequências ruins para esse valor?

E aqui está o meu código atual:

public partial class Form1 : Form {

    bool dir = true;

    public Form1() {
        InitializeComponent();

        Location = new Point(1280/2 - Width, 800/2 - Height/2);
    }

    private void button1_Click(object sender, EventArgs e) {
        double FPS = 300;
        int PX = 1;
        long lastTicks = 0;
        long currentTicks = 0;
        double interval = (double)Stopwatch.Frequency / FPS;

        while(dir ? Left <= 1280/2 : Left >= 1280/2 - Width) {
            Application.DoEvents();

            currentTicks = Stopwatch.GetTimestamp();

            if(currentTicks >= lastTicks + interval) {
                lastTicks = Stopwatch.GetTimestamp();

                this.Location = new Point(dir ? Left + PX : Left - PX, Top);

                this.Invalidate(); //refreshes the form
            }

            Thread.Sleep(1); //frees up the cpu
        }

        dir = !dir;
    }

}

Observação: Este é apenas um código de amostra, para fins de teste, não um código real, mas seja meu convidado, se você quiser apontar algumas coisas muito importantes que devo considerar ao portá -lo para o aplicativo real.

Foi útil?

Solução

Experimente esta implementação da minha sugestão anterior (sem contabilizar o FPS):

public partial class Form1 : Form
{
    private bool go;
    private int dx = 1;
    public Form1()
    {
        InitializeComponent();
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (go)
        {
            this.Location = new Point(this.Location.X + dx, this.Location.Y);
            if (Location.X < 10 || Location.X > 1200)
            {
                go = false;
                dx = -dx;
            }
            else
            {
                this.Invalidate();
            }
        }
    }
    private void button1_Click(object sender, EventArgs e)
    {
        go = true;
        this.Invalidate();
    }
}

Eu acho que você provavelmente terá que sair do WinForms para obter FPS mais altos.

Outras dicas

Eu acho que o Windows limita a taxa de repintura, por isso não importaria se você aumentasse o FPS até valores insanos; Se você quiser ver taxas de quadros mais altas, provavelmente terá que resultar em algo como a animação XNA/DirectX.

Você pode usar um cronômetro e escrever um manipulador de eventos decorrido que moveria e invalidaria seu formulário. Para esse fim, você não precisaria fazer o tópico. Além disso, em vez do código condicional em torno do booleano 'Dir', você pode negar o valor PX quando quiser alterar as direções (e fazer adições somente em vez do operador ternário no dir); Isso é possível, pois a subtração é a mesma que adicionar um negativo.

Isso deve tornar sua animação mais fácil de se estender para fazer outras coisas. Por diversão, você também pode criar um PY para se mover verticalmente também. Seja qual for o caso, espero que você se divirta com isso. :)

Se você obteve os resultados desejados com um valor FPS de 300, eu iria com isso. O conceito de quadros por segundo para Winforms não é o mesmo que videogames com uso intensivo de gráficos, portanto, um valor alto não será um problema. O valor do FPS aqui simplesmente ajusta a frequência com que o código é executado.

Solução super-matante

Resumo: Faça uma animação da sua janela se movendo e reproduza-a de volta (talvez a tela cheia)

Detalhes:
Suponha que sua janela seja 100x100 e seja @0,0
Tome uma tela da tela, bem, (0,0)-(200.200).
Use a tela para criar um clipe, que descreve mover sua janela de 0,0 para 100.100
Em seguida, crie uma janela sem fronteiras (0,0)-(200.200) e coloque um vídeo-player nela e reproduza a animação da sua janela se movendo para dentro.

Escusado será dizer que sua janela será estática. Mas você pode obter a melhor animação que existe. Você pode até adicionar alguns efeitos à sua janela em movimento, como balas na matriz ou navios Necromunga.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top