Убрать мерцание и изменить/добавить характер анимации

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

#include <windows.h>
#include <windowsX.h>
#include <tchar.h>
#include <gdiplus.h>
#include <vector>
#include <gdiplusgraphics.h>    
#include <gdiplusheaders.h>
#include "Math.h"
#pragma comment(lib, "Gdiplus")
#define _USE_MATH_DEFINES
#pragma comment(lib,"Gdiplus.lib")
 
using namespace Gdiplus;
using namespace std;
 
Bitmap* imgTextureMetall;
HWND hWnd = NULL;
MSG  msg;
BOOL bRet;
ULONG_PTR           gdiToken;
GdiplusStartupInput gdiStartupInput;
HDC  hdc;
PAINTSTRUCT ps;
//Bitmap* imgTrain = NULL;
 
/* -- ANIMATION DATA --*/
// массив точек, характеризующие ключевые и промежуточные кадры
std::vector<Gdiplus::PointF> startKeyVector;
Gdiplus::PointF* A;
Gdiplus::PointF* B;
Gdiplus::PointF* P;
Bitmap* imgRoad;
Image* gifTrain;
UINT framesCount;
UINT indexCurrentFrame;
int stage = 0;              // переменная для интерполяции
float t = 0.f;              // параметр для интерполяции
float k_sizeX = 0.6;            // коэффициент масштабирования
float k_sizeY = 0.6;            // коэффициент масштабирования
PointF sizeWheel(70, 70);
 
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 
void OnDisplay(Gdiplus::Graphics& g);
void OnDestroy(HWND hwnd);
void OnDisplay(HDC hdc);
void CopyArrToVector(PointF _array[], std::vector<Gdiplus::PointF>& _vector, int _size);
void CopyPointFToVector(PointF _point, std::vector<Gdiplus::PointF>& _vector);
PointF Tween(const PointF& A, const PointF& B, float t);
void Tween(const PointF* A, const PointF* B, PointF* P, int count, float t);
void IncrementT(int framesCount);
void OnDisplay_Wheels(Graphics& drawingBoard, PointF centerPointWheel, PointF sizeWheel, int wheels, float gap, SolidBrush& Brush1, Pen& Pen1, SolidBrush& Brush2, Pen& Pen2, std::vector<Gdiplus::PointF>& Vector);
 
int g_step = 0;
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    ULONG_PTR gdiToken = 0;
    Gdiplus::GdiplusStartupInput gdiStartupInput;
    Gdiplus::GdiplusStartup(&gdiToken, &gdiStartupInput, NULL);
 
    WNDCLASSEX wc = { sizeof(wc) };
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = TEXT("MyWindowClass");
    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, TEXT("Cannot register class"), TEXT("Error"), MB_OK);
        return 0;
    }
    Status stRet = GdiplusStartup(&gdiToken, &gdiStartupInput, NULL);
    imgRoad = new Bitmap(L"Lune.jpg");
    HWND hWnd = CreateWindow(TEXT("MyWindowClass"), TEXT("MyWindowTitle"), WS_OVERLAPPEDWINDOW, 500, 500, 2000, 1500, 0, 0, hInstance, 0);
    if (!hWnd)
    {
        MessageBox(NULL, TEXT("Cannot create main window"), TEXT("Error"), MB_OK);
        return 0;
    }
    imgTextureMetall = new Bitmap(L"texture.jpeg");
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
 
    MSG msg;
    if (Ok == stRet) {
        while (GetMessage(&msg, NULL, 0, 0))
        {
            if (bRet == -1) {
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
 
    Gdiplus::GdiplusShutdown(gdiToken);
    return msg.wParam;
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_ERASEBKGND: // подавить мерцание
        return 1;
 
    case WM_CREATE:
        gifTrain = Image::FromFile(L"Lunohod.gif");
        indexCurrentFrame = 0;
        if (NULL != gifTrain) {
            framesCount = gifTrain->GetFrameCount(&FrameDimensionTime);
        }
        SetTimer(hWnd, 1, 100, 0);
        break;
 
    case WM_TIMER:
        indexCurrentFrame = (indexCurrentFrame + 1) % framesCount;
        IncrementT(framesCount);
        gifTrain->SelectActiveFrame(&FrameDimensionTime, indexCurrentFrame);
        g_step++;
        InvalidateRect(hWnd, 0, FALSE);
        break;
 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        OnDisplay(hdc);
        ValidateRect(hWnd, 0);
        break;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
 
    default:
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    return 0;
}
 
void IncrementT(int framesCount) {
    if (t < 0) {
        stage = 0;
        t = 0;
    }
    else {
        t += (float)1 / framesCount * 3;
        if (t > 1) {
            t = 0;
            stage += 1;
        }
    }
}
 
void OnDestroy(HWND hwnd) {
    PostQuitMessage(0);
}
void CopyArrToVector(PointF _array[], std::vector<Gdiplus::PointF>& _vector, int _size) {
    for (int i = 0; i < _size; i++) {
        _vector.push_back(_array[i]);
    }
}
void CopyPointFToVector(PointF _point, std::vector<Gdiplus::PointF>& _vector) {
    _vector.push_back(_point);
}
 
void OnDisplay_Wheels(Graphics& drawingBoard, PointF centerPointWheel, PointF sizeWheel, int wheels, float gap, SolidBrush& Brush1, Pen& Pen1, SolidBrush& Brush2, Pen& Pen2, std::vector<Gdiplus::PointF>& Vector)
{
}
 
 
// рисуем свою картинку в начале координат
void OnDisplay(Gdiplus::Graphics& g1)
{
    Rect rectInstance;
    g1.GetVisibleClipBounds(&rectInstance);
    Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g1);
    Graphics drawingBoard(&backBuffer);
    drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
 
    SolidBrush greenBrush(Color(0, 180, 0));
    SolidBrush yellowBrush(Color::Yellow);
    SolidBrush orangeBrush(Color::Orange);
    SolidBrush redBrush(Color(255, 50, 50));
    SolidBrush blackBrush(Color(20, 20, 20));
    HatchBrush hatchBrush(HatchStyleDarkVertical, Color::Silver, Color::Wheat);
    Gdiplus::Pen greenPen(Color(0, 150, 0));
    Gdiplus::Pen redPen(Color(255, 0, 0));
    Gdiplus::Pen blackPen(Color(0, 0, 0));
    Gdiplus::Pen orangePen(Color::Orange);
    Gdiplus::Pen yellowPen(Color::Yellow);
    Gdiplus::Pen WhitePen(Color(255, 255, 255));
    Color colorWhite(Color::White);
    SolidBrush WhiteBrush(Color::White);
    SolidBrush DarkGrayBrush(Color(108, 108, 108));
    SolidBrush BlueBrush(Color(56, 44, 144));
    SolidBrush SaddleBrownBrush(Color(128, 68, 4));
    SolidBrush BrunBrown(Color(68, 36, 4));
    SolidBrush DarkTurquoiseBrown(Color(0, 206, 209));
    SolidBrush DarkCyanBrown(Color(0, 139, 139));
    Gdiplus::Pen BrushPen(Color(68, 36, 4));
    Gdiplus::Pen BluePen(Color(56, 44, 144));
    Color windowsColors[4] = {
        Color::MediumTurquoise,
        Color::SkyBlue,
        Color::MediumTurquoise,
        Color::SteelBlue,
    };
    Color colors[3] = { Color(255, 0, 255, 255), Color(255, 0, 155, 155), Color(255, 0, 0, 0) };
    float pos[3] = { 0.0f, 0.3f, 1.0f };
    Color colors1[3] = { Color(255, 0, 255, 255), Color(255, 0, 155, 155), Color(255, 0, 0, 0) };
    float pos1[3] = { 0.0f, 0.3f, 1.0f };
    int n = 4;
 
    //составное перо
    Pen CompPen(Color::Black, 6.f);
    float comp[6] = { 0.0f, 0.2f, 0.3f, 0.7f, 0.8f, 1.0f };
    CompPen.SetCompoundArray(comp, 6);
 
 
    //голубой корпус
    PointF points[4] = { PointF(190, 410), PointF(150, 310), PointF(450, 310), PointF(400, 410) };
    // +4
    CopyArrToVector(points, startKeyVector, 4);
    g1.FillPolygon(&DarkTurquoiseBrown, points, 4);
    g1.DrawPolygon(&blackPen, points, 4);
 
    //оконтовочный бортик (голубой)
    PointF pointsa[4] = { PointF(120, 300), PointF(480, 300), PointF(480, 320), PointF(120, 320) };
    // +4
    CopyArrToVector(pointsa, startKeyVector, 4);
    g1.FillPolygon(&DarkCyanBrown, pointsa, 4);
    g1.DrawPolygon(&blackPen, pointsa, 4);
 
    //серая антенна
    PointF pointsb[4] = { PointF(350, 300), PointF(510, 140), PointF(513, 143), PointF(355, 300) };
    // +4
    CopyArrToVector(pointsb, startKeyVector, 4);
    g1.FillPolygon(&DarkGrayBrush, pointsb, 4);
    g1.DrawPolygon(&blackPen, pointsb, 4);
    g1.DrawCurve(&CompPen, pointsb, 4);
 
    //линейный градиент 1
    PointF windowsPoints[5] = { PointF(190, 410), PointF(150, 310), PointF(295, 410), PointF(450, 310), PointF(400, 410) };
    CopyArrToVector(windowsPoints, startKeyVector, 5);
    PointF centerPointWindow(295, 410);  // координаты центра для окна
    PathGradientBrush pthGrBrush(windowsPoints, 5); // кисть градиента контура
    pthGrBrush.SetCenterPoint(centerPointWindow);
    pthGrBrush.SetInterpolationColors(colors, pos, 5);
    pthGrBrush.SetSurroundColors(windowsColors, &n);
    g1.FillPolygon(&pthGrBrush, windowsPoints, 5);
    g1.DrawPolygon(&blackPen, windowsPoints, 5);
 
    // Надпись
    Font font(L"Courier", 25.f, FontStyleBold);
    g1.DrawString(L"СССР", -1, &font, PointF(250, 330), &SaddleBrownBrush);
 
    // Эллипсы
    g1.RotateTransform(-30);
    g1.TranslateTransform(0.0f, 0.0f);
    g1.DrawEllipse(&BrushPen, -110, 25, 150, 300);
    g1.FillEllipse(&BlueBrush, -110, 25, 150, 300);
    g1.RotateTransform(68);
    g1.DrawEllipse(&BrushPen, 435, -45, 70, 30);
    g1.FillEllipse(&DarkGrayBrush, 435, -45, 70, 30);
    g1.DrawEllipse(&BrushPen, 444, -75, 60, 26);
    g1.FillEllipse(&DarkGrayBrush, 444, -75, 60, 26);
    g1.DrawEllipse(&BrushPen, 453, -100, 50, 22);
    g1.FillEllipse(&DarkGrayBrush, 453, -100, 50, 22);
    g1.DrawEllipse(&BrushPen, 461, -120, 40, 18);
    g1.FillEllipse(&DarkGrayBrush, 461, -120, 40, 18);
    g1.DrawEllipse(&BrushPen, 468, -136, 30, 14);
    g1.FillEllipse(&DarkGrayBrush, 468, -136, 30, 14);
 
    g1.RotateTransform(0); //Колеса
    // Колесо1
    g1.RotateTransform(0);
    g1.DrawEllipse(&BrushPen, 375, 200, 70, 70);
    g1.FillEllipse(&SaddleBrownBrush, 375, 200, 70, 70);
    g1.DrawEllipse(&BrushPen, 390, 215, 40, 40);
    g1.FillEllipse(&WhiteBrush, 390, 215, 40, 40);
    g1.DrawEllipse(&BrushPen, 397.5, 222.5, 25, 25);
    g1.FillEllipse(&BrunBrown, 397.5, 222.5, 25, 25);
    // Колесо2
    g1.DrawEllipse(&BrushPen, 435, 155, 70, 70);
    g1.FillEllipse(&SaddleBrownBrush, 435, 155, 70, 70);
    g1.DrawEllipse(&BrushPen, 450, 170, 40, 40);
    g1.FillEllipse(&WhiteBrush, 450, 170, 40, 40);
    g1.DrawEllipse(&BrushPen, 457.5, 177.5, 25, 25);
    g1.FillEllipse(&BrunBrown, 457.5, 177.5, 25, 25);
    // Колесо3
    g1.DrawEllipse(&BrushPen, 495, 110, 70, 70);
    g1.FillEllipse(&SaddleBrownBrush, 495, 110, 70, 70);
    g1.DrawEllipse(&BrushPen, 510, 125, 40, 40);
    g1.FillEllipse(&WhiteBrush, 510, 125, 40, 40);
    g1.DrawEllipse(&BrushPen, 517.5, 132.5, 25, 25);
    g1.FillEllipse(&BrunBrown, 517.5, 132.5, 25, 25);
    // Колесо4
    g1.DrawEllipse(&BrushPen, 555, 65, 70, 70);
    g1.FillEllipse(&SaddleBrownBrush, 555, 65, 70, 70);
    g1.DrawEllipse(&BrushPen, 570, 80, 40, 40);
    g1.FillEllipse(&WhiteBrush, 570, 80, 40, 40);
    g1.DrawEllipse(&BrushPen, 577.5, 87.5, 25, 25);
    g1.FillEllipse(&BrunBrown, 577.5, 87.5, 25, 25);
    g1.TranslateTransform(0.0f, 0.0f);
}
 
void OnDisplay(HDC hdc)
{
    Graphics g1(hdc);
    Rect rectInstance;
    g1.GetVisibleClipBounds(&rectInstance);
    Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g1);
    Graphics drawingBoard(&backBuffer);
    drawingBoard.DrawImage(imgRoad, rectInstance);
 
    // дорога
    TextureBrush textureBrush(imgTextureMetall);
    Pen texturePen(&textureBrush, 30);
    drawingBoard.DrawLine(&texturePen, 0, 1100, 2000, 1100);
    RectF rectim(100.f, 1200.f, 400.f, 200.f);
    drawingBoard.DrawImage(gifTrain, rectim);
 
    //линейный градиент
    LinearGradientBrush pthGrBrush(Rect(200, 200, 300, 150), Color::White, Color::White, 45.f);
    g1.DrawImage(&backBuffer, rectInstance);
 
    // заставляем крутиться на 360 градусов вокруг точки 
    if (g_step < 50)
    {
        float angl = 360.f * g_step / 50;
        g1.ResetTransform();
        g1.TranslateTransform(600.f, 500.f);
        g1.RotateTransform(angl);
        OnDisplay(g1);
    }
 
    // заставляем двигаться горизонтально
    else if (g_step < 130)
    {
        float dist = 5.f * (g_step - 50);
        g1.ResetTransform();
        g1.TranslateTransform(600.f + dist, 500.f);
        OnDisplay(g1);
    }
 
    // поворачиваем на 30 градусов и заставляем двигаться наклонно
    else if (g_step <= 200)
    {
        float dist = -5.f * (g_step - 100);
        PointF rotateCenter(850.f, 300.f);
        g1.ResetTransform();
        g1.RotateTransform(30.f);
        g1.TranslateTransform(1650.f, -300.f + dist);
        OnDisplay(g1);
    }
}

Ответы (0 шт):