Простая анимация на c

#visual-c #animation

#visual-c #Анимация

Вопрос:

Итак, я попробовал некоторые очень простые анимационные материалы (если это вообще можно назвать анимацией) в Windows. Я перепутал параметры вывода текста (координаты для текста) без анимации. По сути, он печатал «привет» в нескольких разных местах один раз, и после этого казалось, что ничего не происходит. Проблема в том, что текст выводится на экран без удаления текста из предыдущего вызова InvalidateRect с экрана. Кроме того, когда вы добавляете некоторые простые значения увеличивающихся рядов (например, 1,2,3,4,5 и т.д.) в качестве параметров для вывода текста, такой проблемы нет.

 #include <Windows.h>

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
struct point
{
    double x;
    double y;
    double t;
};


point obj={30,30,1};

int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR cmdLine,int cmdShow)
{
    WNDCLASSEX windowsClass={0};



    windowsClass.hCursor=LoadCursor(NULL,IDC_ARROW);
    windowsClass.cbSize=sizeof(WNDCLASSEX);
    windowsClass.hInstance=hInstance;
    windowsClass.lpfnWndProc=WndProc;
    windowsClass.cbClsExtra=NULL;
    windowsClass.style=CS_HREDRAW | CS_VREDRAW;
    windowsClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
    windowsClass.hbrBackground=(HBRUSH)GetStockObject(NULL_BRUSH);
    windowsClass.lpszClassName="Devjeet's Window";

    if(!RegisterClassExA(amp;windowsClass))
        return -1;
    HWND hWnd = CreateWindowExA(NULL,"Devjeet's Window","Animation V1 By Devjeet",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,400,400,NULL,NULL,hInstance,NULL);

    if(!hWnd)
        return -1;
    ShowWindow(hWnd,cmdShow);


    MSG msg={0};

    while(msg.message!=WM_QUIT)
    {
        if(PeekMessage(amp;msg,0,0,0,PM_REMOVE))
        {
            TranslateMessage(amp;msg);
            DispatchMessage(amp;msg);
        }
    }
    return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    HDC hDC;
    PAINTSTRUCT paintStruct;

    switch(message)
    {

    case WM_PAINT:
        hDC=BeginPaint(hWnd,amp;paintStruct);

        TextOut(hDC,(int)(obj.x),(int)(obj.y),"Hello",sizeof("Hello"));
        obj.y=(double)(30*obj.t (obj.t*obj.t*9.8/2));
        obj.x=(double)(30*obj.t (obj.t*obj.t*9.8/2));
        obj.t =.8;


        EndPaint(hWnd,amp;paintStruct);
        if(obj.y>100.0)
        {
            obj.x=30.0;
            obj.y=30.0;
            obj.t=1.0;
        }

        Sleep(800);
        InvalidateRect(hWnd,NULL,TRUE);
        break;
    case WM_DESTROY:
        PostQuitMessage(NULL);
        break;
    default:
        return DefWindowProc(hWnd,message,wParam,lParam);
        break;
    }
    return 0;
}
  

Комментарии:

1. мой вопрос в том, почему это происходит? что-то не так с уравнением или есть что-то о Windows, чего я не знаю?

2. @devjeetroy: какое отношение название вашего вопроса имеет к вашему вопросу?

3. @Mat Извините, ребята, это была ошибка. Это был заголовок вопроса, который я думал опубликовать ранее

Ответ №1:

Первое: никогда, никогда не вызывайте Sleep из своего WM_PAINT hander. Вы заблокируете свой пользовательский интерфейс.

Рекомендуемый способ создания простой анимации в Windows — использовать SetTimer и обрабатывать WM_TIMER сообщение. Ваш WM_TIMER обработчик определяет, где должен быть ваш спрайт, и вызывает InvalidateRect . Вы можете либо сделать недействительным все окно, либо только старую и новую позиции перемещенного спрайта.

В ответ на InvalidateRect Windows отправит вам WM_PAINT сообщение, позволяющее перерисовать ваше окно.

Что касается того, почему он не стирает старую: вы указали NULL_BRUSH в качестве фона окна, что означает, что обработчик по умолчанию WM_ERASEBKGND (где Windows удалит содержимое вашего окна) ничего не делает. Вам либо нужно обработать WM_ERASEBKGND самостоятельно (чтобы стереть окно, используя, например, — FillRect ), либо вам также нужно обработать эту часть в вашем WM_PAINT обработчике.

О, и причина, по которой простое увеличение позиции работает, вероятно, заключается в том, что (если я правильно помню), TextOut удалит фон ограничивающей рамки для данного текста. Поскольку это, вероятно, на пару пикселей больше текста, предыдущий текст будет удален, если он находится всего в одном пикселе.