Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / C++ Новый топик    Ответить
 Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Подскажите в чем ошибка?

1. У меня не поворачивается эллипс см. в коде строки 248-251, 305-317, 326-339, 403-414, 480-490.

2. И у меня не отображается надпись - строки 302,303 - аналогичная проблема с поворотом в ключевых кадрах.
+

#include <windows.h>
#include <windowsX.h>
#include <tchar.h>
#include <gdiplus.h>
#include <vector>
#include <gdiplusgraphics.h>    
#include <gdiplusheaders.h>
#include "Math.h"
#define ID_TIMER    1
#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 MyWindowsProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
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 RotateTransform(REAL angle, MatrixOrder order);
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 WINAPI _tWinMain(HINSTANCE hInctance, HINSTANCE, LPTSTR lpszCmdLine, int nCmdShow) {
    WNDCLASSEX wndcls = { sizeof(WNDCLASSEX) };
    wndcls.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
    wndcls.lpfnWndProc = MyWindowsProc;
    wndcls.hInstance = hInctance;
    wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndcls.hbrBackground = NULL; // (HBRUSH)GetStockObject(WHITE_BRUSH); // извлекает дескриптор предопределенного пера из wingdi.h
    wndcls.lpszMenuName = NULL;
    wndcls.lpszClassName = TEXT("MainWindow");
    wndcls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (0 == RegisterClassEx(&wndcls)) {
        return -1;
    }

    Status stRet = GdiplusStartup(&gdiToken, &gdiStartupInput, NULL);
    imgRoad = new Bitmap(L"road.jpg");

    hWnd = CreateWindowEx(0, TEXT("MainWindow"), TEXT("KGG3_animation"), WS_OVERLAPPEDWINDOW, 50, 50, 1400, 800, NULL, NULL, hInctance, NULL);
    if (hWnd == NULL) {
        return -1;
    }
    ShowWindow(hWnd, nCmdShow);
    //imgTrain = new Bitmap(L"my_train.jpg");
    imgTextureMetall = new Bitmap(L"texture.jpeg");
    //UpdateWindow(hWnd);

    if (Ok == stRet) {
        while (GetMessage(&msg, NULL, 0, 0))
        {
            if (bRet == -1) {
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    GdiplusShutdown(gdiToken);
    return (int)msg.wParam;
}

/* ----------------------------------------------------- */
LRESULT CALLBACK MyWindowsProc(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, ID_TIMER, 50, NULL);  // 3-ий параметр - частота изменения кадров 40мс; 4-ый - функция обратного вызова. 
        return 0; //Если NULL, то посылается сообщение WM_TIMER

    case WM_TIMER:
        indexCurrentFrame = (indexCurrentFrame + 1) % framesCount;
        IncrementT(framesCount);
        gifTrain->SelectActiveFrame(&FrameDimensionTime, indexCurrentFrame);
        InvalidateRect(hWnd, NULL, FALSE);
        return 0;

    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps); // получили дескриптор устройства по hWnd
        OnDisplay(hdc);
        EndPaint(hWnd, &ps);
        return 0;

        HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy);
    }

    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
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);
}
PointF Tween(const PointF& A, const PointF& B, float t) {
    return PointF(A.X * (1.f - t) + B.X * t, A.Y * (1.f - t) + B.Y * t);
}
void Tween(const PointF* A, const PointF* B, PointF* P, int count, float t) {
    for (int i = 0; i < count; ++i) {
        P[i] = Tween(A[i], B[i], t);
    }
}
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 RotateTransform(float angle)
{
}

void RotateTransformAngle(float angle)
{
}

void RotateTransform(float angle, MatrixOrder order)
{
}

void OnDisplay(HDC hdc) {
    Graphics g(hdc);
    Rect rectInstance;
    g.GetVisibleClipBounds(&rectInstance);
    Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g);
    Graphics drawingBoard(&backBuffer);
    drawingBoard.Clear(Color::White);
    drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
    Matrix affinMatrix;

    /*-- общие атрибуты --*/
    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);
    TextureBrush textureBrush(imgTextureMetall);
    Pen greenPen(Color(0, 150, 0));
    Pen redPen(Color(255, 0, 0));
    Pen blackPen(Color(0, 0, 0));
    Pen orangePen(Color::Orange);
    Pen yellowPen(Color::Yellow);
    Pen WhitePen(Color(255, 255, 255));
    Pen texturePen(&textureBrush, 15);
    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));
    Pen BrushPen(Color(68, 36, 4));
    Pen BluePen(Color(56, 44, 144));
    Color windowsColors[4] = {
        Color::MediumTurquoise,
        Color::SkyBlue,
        Color::MediumTurquoise,
        Color::SteelBlue,
    };
    int n = 4;
    int wheels = 4; // кол-во колес

    //линейный градиент
    LinearGradientBrush pthGrBrush(Rect(200, 200, 300, 150), Color::White, Color::White, 45.f);
    LinearGradientBrush pthGrBrush2(Rect(200, 200, 300, 150), Color::White, Color::White, 45.f);
    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 };

    //составное перо
    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);
    WrapMode wrapMode = WrapModeTile;

    // дорога
    drawingBoard.DrawLine(&texturePen, 0, 488, 1400, 488);
    RectF rectim(100.f, 520.f, 400.f, 200.f);
    drawingBoard.DrawImage(gifTrain, rectim);

    /* ---------------- ПЕРВЫЙ КЛЮЧЕВОЙ КАДР ---------------- */
    if (stage == 0 && t == 0) {
        /*-- левая половина рисунка --*/

        // Большой Эллипс
        Matrix* m;
        PointF pointsc(120, 90);
        CopyPointFToVector(pointsc, startKeyVector);
        affinMatrix.RotateAt(1, PointF(pointsc.X, pointsc.Y));

        //голубой корпус
        PointF points[4] = { PointF(190, 410), PointF(150, 310), PointF(450, 310), PointF(400, 410) };
        // +4
        CopyArrToVector(points, startKeyVector, 4);
        drawingBoard.FillPolygon(&DarkTurquoiseBrown, points, 4);
        drawingBoard.DrawPolygon(&blackPen, points, 4);

        //оконтовочный бортик (голубой)
        PointF pointsa[4] = { PointF(120, 300), PointF(480, 300), PointF(480, 320), PointF(120, 320) };
        // +4
        CopyArrToVector(pointsa, startKeyVector, 4);
        drawingBoard.FillPolygon(&DarkCyanBrown, pointsa, 4);
        drawingBoard.DrawPolygon(&blackPen, pointsa, 4);

        //серая антенна
        PointF pointsb[4] = { PointF(350, 300), PointF(510, 140), PointF(513, 143), PointF(355, 300) };
        // +4
        CopyArrToVector(pointsb, startKeyVector, 4);
        drawingBoard.FillPolygon(&DarkGrayBrush, pointsb, 4);
        drawingBoard.DrawPolygon(&blackPen, pointsb, 4);
        drawingBoard.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);
        // +4
        PointF centerPointWindow(295, 410);  // координаты центра для окна
        // +1
        PathGradientBrush pthGrBrush(windowsPoints, 5); // кисть градиента контура
        pthGrBrush.SetCenterPoint(centerPointWindow);
        pthGrBrush.SetInterpolationColors(colors, pos, 5);
        pthGrBrush.SetSurroundColors(windowsColors, &n);
        drawingBoard.FillPolygon(&pthGrBrush, windowsPoints, 5);
        drawingBoard.DrawPolygon(&blackPen, windowsPoints, 5);

        // колеса
        float gap = 75.f; // расстояние между колесами
        PointF centerPointWheel1(190, 440);  // центр колеса
        PointF centerPointWheel2(263, 440);  // центр колеса
        PointF centerPointWheel3(337, 440);  // центр колеса
        PointF centerPointWheel4(410, 440);  // центр колеса
        CopyPointFToVector(centerPointWheel1, startKeyVector);
        CopyPointFToVector(centerPointWheel2, startKeyVector);
        CopyPointFToVector(centerPointWheel3, startKeyVector);
        CopyPointFToVector(centerPointWheel4, startKeyVector);



        // Надпись
        Font font(L"Courier", 25.f, FontStyleBold);
        drawingBoard.DrawString(L"СССР", -1, &font, PointF(250, 330), &SaddleBrownBrush);

        P = new Gdiplus::PointF[startKeyVector.size()];
        A = new Gdiplus::PointF[startKeyVector.size()];
        B = new Gdiplus::PointF[startKeyVector.size()];
        for (int i = 0; i < startKeyVector.size(); ++i) {
            A[i] = startKeyVector[i];
            B[i] = startKeyVector[i];
        }

        affinMatrix.Translate(300.f, -100.f);
        affinMatrix.Scale(k_sizeX, k_sizeY);
        affinMatrix.TransformPoints(B, startKeyVector.size());
        affinMatrix.TransformPoints(P, startKeyVector.size());
        g.RotateTransform(90);
        g.DrawImage(&backBuffer, rectInstance);
    }
    else
        //----------------------------------------------------------------------------- stage == 0 && t <= 1.f
        if (stage == 0 && t <= 1) {
            Tween(A, B, P, startKeyVector.size(), t);
            int _i = 0;

            //Большой Эллипс
            Matrix m;
            PointF pointsc = { PointF(P[_i].X, P[_i].Y) };
            for (int i = 0; i < wheels; i++) {
                float kx = 1 - ((1 - k_sizeX) * t);
                float ky = 1 - ((1 - k_sizeY) * t);
                g.RotateTransform(90);
                drawingBoard.FillEllipse(&SaddleBrownBrush, float(pointsc.X - sizeWheel.X * kx), float(pointsc.Y - sizeWheel.Y * ky), sizeWheel.X * kx * 2, sizeWheel.Y * ky * 4);
                drawingBoard.DrawEllipse(&BrushPen, float(pointsc.X - sizeWheel.X * kx), float(pointsc.Y - sizeWheel.Y * ky), sizeWheel.X * kx * 2, sizeWheel.Y * ky * 4);
                //affinMatrix.RotateAt(0.52, PointF(pointsc[i].X, pointsc[i].Y));
                //drawingBoard.FillPolygon(&SaddleBrownBrush, pointsc, 1);
                //drawingBoard.DrawPolygon(&redPen, pointsc, 1);
            }
            _i += 1;

            //голубой корпус
            PointF points[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            drawingBoard.FillPolygon(&DarkTurquoiseBrown, points, 4);
            drawingBoard.DrawPolygon(&blackPen, points, 4);
            _i += 4;

            //оконтовочный бортик (голубой)
            PointF pointsa[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            _i += 4;
            drawingBoard.FillPolygon(&DarkCyanBrown, pointsa, 4);
            drawingBoard.DrawPolygon(&blackPen, pointsa, 4);

            //серая антенна
            PointF pointsb[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            _i += 4;
            drawingBoard.FillPolygon(&DarkGrayBrush, pointsb, 4);
            drawingBoard.DrawPolygon(&blackPen, pointsb, 4);
            drawingBoard.DrawCurve(&CompPen, pointsb, 4);

            //линейный градиент 1
            PointF windowsPoints[5] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y), PointF(P[_i + 4].X, P[_i + 4].Y) };
            _i += 4;
            PointF centerPointWindow(P[_i].X, P[_i].Y); // координаты центра для окна
            _i += 1;
            PathGradientBrush pthGrBrush(windowsPoints, 5); // кисть градиента контура
            pthGrBrush.SetCenterPoint(centerPointWindow);
            pthGrBrush.SetInterpolationColors(colors, pos, 5);
            pthGrBrush.SetSurroundColors(windowsColors, &n);
            drawingBoard.FillPolygon(&pthGrBrush, windowsPoints, 5);
            drawingBoard.DrawPolygon(&blackPen, windowsPoints, 5);

            // колеса
            PointF centerPointWheel1[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            for (int i = 0; i < wheels; i++) {
                float kx = 1 - ((1 - k_sizeX) * t);
                float ky = 1 - ((1 - k_sizeY) * t);
                Rect rectWheel(centerPointWheel1[i].X - sizeWheel.X * kx / 2, centerPointWheel1[i].Y - sizeWheel.Y * ky / 2, sizeWheel.X * kx, sizeWheel.Y * ky);
                drawingBoard.FillEllipse(&SaddleBrownBrush, rectWheel);
                drawingBoard.DrawEllipse(&BrushPen, rectWheel);
                drawingBoard.FillEllipse(&WhiteBrush, float(centerPointWheel1[i].X - sizeWheel.X * kx / 3), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 3), sizeWheel.X * kx * 0.65, sizeWheel.Y * ky * 0.65);
                drawingBoard.DrawEllipse(&BrushPen, float(centerPointWheel1[i].X - sizeWheel.X * kx / 3), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 3), sizeWheel.X * kx * 0.65, sizeWheel.Y * ky * 0.65);
                drawingBoard.FillEllipse(&SaddleBrownBrush, float(centerPointWheel1[i].X - sizeWheel.X * kx / 5), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 5), sizeWheel.X * kx * 0.4, sizeWheel.Y * ky * 0.4);
                drawingBoard.DrawEllipse(&BrushPen, float(centerPointWheel1[i].X - sizeWheel.X * kx / 5), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 5), sizeWheel.X * kx * 0.4, sizeWheel.Y * ky * 0.4);
            }
            _i += 4;

            g.DrawImage(&backBuffer, rectInstance);
        }
    /* ---------------- ВТОРОЙ КЛЮЧЕВОЙ КАДР ---------------- */
    //----------------------------------------------------------------------------- stage == 1 && t <= 1.f
        else if (stage == 1 && 0 <= t <= 1) {
            int _i = 0;
            if (t == 0) {
                for (int i = 0; i < startKeyVector.size(); ++i) {
                    A[i] = B[i];
                }
                affinMatrix.Translate(300.f, 300.f);
                affinMatrix.TransformPoints(B, startKeyVector.size());
            }
            Tween(A, B, P, startKeyVector.size(), t);

            //Большой Эллипс
            Matrix m;
            PointF pointsc = { PointF(P[_i].X, P[_i].Y) };
            for (int i = 0; i < wheels; i++) {
                float kx = k_sizeX;
                float ky = k_sizeY;
                g.RotateTransform(90);
                drawingBoard.FillEllipse(&SaddleBrownBrush, float(pointsc.X - sizeWheel.X * kx), float(pointsc.Y - sizeWheel.Y * ky), sizeWheel.X * kx * 2, sizeWheel.Y * ky * 4);
                drawingBoard.DrawEllipse(&BrushPen, float(pointsc.X - sizeWheel.X * kx), float(pointsc.Y - sizeWheel.Y * ky), sizeWheel.X * kx * 2, sizeWheel.Y * ky * 4);
                //drawingBoard.FillPolygon(&DarkCyanBrown, pointsc, 1);
                //drawingBoard.DrawPolygon(&redPen, pointsc, 1);
            }
            _i += 1;

            //голубой корпус
            PointF points[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            drawingBoard.FillPolygon(&DarkTurquoiseBrown, points, 4);
            drawingBoard.DrawPolygon(&blackPen, points, 4);
            _i += 4;

            //оконтовочный бортик (голубой)
            PointF pointsa[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            _i += 4;
            drawingBoard.FillPolygon(&DarkCyanBrown, pointsa, 4);
            drawingBoard.DrawPolygon(&blackPen, pointsa, 4);

            //серая антенна
            PointF pointsb[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            _i += 4;
            drawingBoard.FillPolygon(&DarkGrayBrush, pointsb, 4);
            drawingBoard.DrawPolygon(&blackPen, pointsb, 4);
            drawingBoard.DrawCurve(&CompPen, pointsb, 4);

            //линейный градиент 1
            PointF windowsPoints[5] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y), PointF(P[_i + 4].X, P[_i + 4].Y) };
            _i += 4;
            PointF centerPointWindow(P[_i].X, P[_i].Y); // координаты центра для окна
            _i += 1;
            PathGradientBrush pthGrBrush(windowsPoints, 5); // кисть градиента контура
            pthGrBrush.SetCenterPoint(centerPointWindow);
            pthGrBrush.SetInterpolationColors(colors, pos, 5);
            pthGrBrush.SetSurroundColors(windowsColors, &n);
            drawingBoard.FillPolygon(&pthGrBrush, windowsPoints, 5);
            drawingBoard.DrawPolygon(&blackPen, windowsPoints, 5);

            // колеса
            PointF centerPointWheel1[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            for (int i = 0; i < wheels; i++) {
                float kx = k_sizeX;
                float ky = k_sizeY;
                Rect rectWheel(centerPointWheel1[i].X - sizeWheel.X * kx / 2, centerPointWheel1[i].Y - sizeWheel.Y * ky / 2, sizeWheel.X * kx, sizeWheel.Y * ky);
                drawingBoard.FillEllipse(&SaddleBrownBrush, rectWheel);
                drawingBoard.DrawEllipse(&BrushPen, rectWheel);
                drawingBoard.FillEllipse(&WhiteBrush, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.65), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.65), sizeWheel.X * kx * 0.65, sizeWheel.Y * ky * 0.65);
                drawingBoard.DrawEllipse(&BrushPen, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.65), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.65), sizeWheel.X * kx * 0.65, sizeWheel.Y * ky * 0.65);
                drawingBoard.FillEllipse(&SaddleBrownBrush, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.4), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.4), sizeWheel.X * kx * 0.4, sizeWheel.Y * ky * 0.4);
                drawingBoard.DrawEllipse(&BrushPen, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.4), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.4), sizeWheel.X * kx * 0.4, sizeWheel.Y * ky * 0.4);
            }
            _i += 4;
            g.DrawImage(&backBuffer, rectInstance);
        }

    /* ---------------- ТРЕТИЙ КЛЮЧЕВОЙ КАДР ---------------- */
    //----------------------------------------------------------------------------- stage == 2 && t <= 1.f
        else if (stage == 2 && 0 <= t <= 1) {
            int _i = 0;
            if (t == 0) {
                for (int i = 0; i < startKeyVector.size(); ++i) {
                    A[i] = B[i];
                }
                affinMatrix.Translate(250, 0);
                affinMatrix.RotateAt(90, PointF(850.f, 250.f));
                //affinMatrix.RotateTransform(90);
                affinMatrix.TransformPoints(B, startKeyVector.size());
            }
            Tween(A, B, P, startKeyVector.size(), t);

            //Большой Эллипс
            Matrix m;
            PointF pointsc = { PointF(P[_i].X, P[_i].Y) };
            for (int i = 0; i < wheels; i++) {
                float kx = k_sizeX;
                float ky = k_sizeY;
                drawingBoard.FillEllipse(&SaddleBrownBrush, float(pointsc.X - sizeWheel.X * kx), float(pointsc.Y - sizeWheel.Y * ky), sizeWheel.X * kx * 2, sizeWheel.Y * ky * 4);
                drawingBoard.DrawEllipse(&BrushPen, float(pointsc.X - sizeWheel.X * kx), float(pointsc.Y - sizeWheel.Y * ky), sizeWheel.X * kx * 2, sizeWheel.Y * ky * 4);
                //drawingBoard.FillPolygon(&DarkCyanBrown, pointsc, 1);
                //drawingBoard.DrawPolygon(&redPen, pointsc, 1);
            }
            _i += 1;

            //голубой корпус
            PointF points[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            drawingBoard.FillPolygon(&DarkTurquoiseBrown, points, 4);
            drawingBoard.DrawPolygon(&blackPen, points, 4);
            _i += 4;

            //оконтовочный бортик (голубой)
            PointF pointsa[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            _i += 4;
            drawingBoard.FillPolygon(&DarkCyanBrown, pointsa, 4);
            drawingBoard.DrawPolygon(&blackPen, pointsa, 4);

            //серая антенна
            PointF pointsb[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            _i += 4;
            drawingBoard.FillPolygon(&DarkGrayBrush, pointsb, 4);
            drawingBoard.DrawPolygon(&blackPen, pointsb, 4);
            drawingBoard.DrawCurve(&CompPen, pointsb, 4);

            //линейный градиент 1
            PointF windowsPoints[5] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y), PointF(P[_i + 4].X, P[_i + 4].Y) };
            _i += 4;
            PointF centerPointWindow(P[_i].X, P[_i].Y); // координаты центра для окна
            _i += 1;
            PathGradientBrush pthGrBrush(windowsPoints, 5); // кисть градиента контура
            pthGrBrush.SetCenterPoint(centerPointWindow);
            pthGrBrush.SetInterpolationColors(colors, pos, 5);
            pthGrBrush.SetSurroundColors(windowsColors, &n);
            drawingBoard.FillPolygon(&pthGrBrush, windowsPoints, 5);
            drawingBoard.DrawPolygon(&blackPen, windowsPoints, 5);

            // колеса
            PointF centerPointWheel1[4] = { PointF(P[_i].X, P[_i].Y), PointF(P[_i + 1].X, P[_i + 1].Y), PointF(P[_i + 2].X, P[_i + 2].Y), PointF(P[_i + 3].X, P[_i + 3].Y) };
            for (int i = 0; i < wheels; i++) {
                float kx = k_sizeX;
                float ky = k_sizeY;
                Rect rectWheel(centerPointWheel1[i].X - sizeWheel.X * kx / 2, centerPointWheel1[i].Y - sizeWheel.Y * ky / 2, sizeWheel.X * kx, sizeWheel.Y * ky);
                drawingBoard.FillEllipse(&SaddleBrownBrush, rectWheel);
                drawingBoard.DrawEllipse(&BrushPen, rectWheel);
                drawingBoard.FillEllipse(&WhiteBrush, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.65), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.65), sizeWheel.X * kx * 0.65, sizeWheel.Y * ky * 0.65);
                drawingBoard.DrawEllipse(&BrushPen, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.65), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.65), sizeWheel.X * kx * 0.65, sizeWheel.Y * ky * 0.65);
                drawingBoard.FillEllipse(&SaddleBrownBrush, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.4), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.4), sizeWheel.X * kx * 0.4, sizeWheel.Y * ky * 0.4);
                drawingBoard.DrawEllipse(&BrushPen, float(centerPointWheel1[i].X - sizeWheel.X * kx / 2 * 0.4), float(centerPointWheel1[i].Y - sizeWheel.Y * ky / 2 * 0.4), sizeWheel.X * kx * 0.4, sizeWheel.Y * ky * 0.4);
            }
            _i += 4;

            g.DrawImage(&backBuffer, rectInstance);
        }
    /* ---------------------- КОНЕЦ ------------------------- */
        else {
            t = -1;
            k_sizeX = 0.6; k_sizeY = 0.6;
            startKeyVector.clear();
            affinMatrix.Reset();
        }
}


Сообщение было отредактировано: 8 фев 21, 23:36
8 фев 21, 22:34    [22277753]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Изопропил
Member

Откуда:
Сообщений: 31564
xamelione25,

копипаст некачественный ))

надпись выводится только для первого ключевого кадра
а t==0 случается не часто
if (stage == 0 && t == 0) {


а это что
else if (stage == 1 && 0 <= t <= 1) {
???


вдумчиво перепиши OnDisplay() и настанет счастье
9 фев 21, 08:43    [22277834]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Изопропил,

я уже решил эту проблему, у меня сейчас проблема осталась только в том что я не могу убрать мерцание (оно только распространяется на саму прорисованную картинку, кроме гифки)

и на третьем кадре применить афинное преобразование, тобишь чтобы оно в процессе перемещения дополнительно еще уменьшалось а потом обратно увеличивалось по характеру графика параболы...

+
#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 DrawProc(HWND);
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 _tWinMain(HINSTANCE hInctance, HINSTANCE, LPTSTR lpszCmdLine, 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 = hInctance;
    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"road.jpg");
    HWND hWnd = CreateWindow(TEXT("MyWindowClass"), TEXT("MyWindowTitle"), WS_OVERLAPPEDWINDOW, 500, 500, 2000, 1500, 0, 0, hInctance, 0);
    if (hWnd == NULL) {
        return -1;
    }
    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_CREATE:
        gifTrain = Image::FromFile(L"Lunohod.gif");
        indexCurrentFrame = 0;
        if (NULL != gifTrain) {
            framesCount = gifTrain->GetFrameCount(&FrameDimensionTime);
        }
        SetTimer(hWnd, 1, 50, 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);
        //DrawProc(hWnd);
        ValidateRect(hWnd, 0);
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    case WM_ERASEBKGND:								// подавить мерцание
        return 1;

    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);
}

PointF Tween(const PointF& A, const PointF& B, float t) {
    return PointF(A.X * (1.f - t) + B.X * t, A.Y * (1.f - t) + B.Y * t);
}
void Tween(const PointF* A, const PointF* B, PointF* P, int count, float t) {
    for (int g_step = 0; g_step < count; ++g_step) {
        P[g_step] = Tween(A[g_step], B[g_step], t);
    }
}

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(HDC hdc)
{
    Gdiplus::Graphics g(hdc);
    Rect rectInstance;
    g.GetVisibleClipBounds(&rectInstance);
    Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g);
    Graphics drawingBoard(&backBuffer);
    drawingBoard.Clear(Color::White);
    drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
    drawingBoard.DrawImage(&backBuffer, rectInstance);  // копируем с офлайнового холста на онлайновый
    Matrix affinMatrix;

    // дорога
    TextureBrush textureBrush(imgTextureMetall);
    Pen texturePen(&textureBrush, 15);
    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);
    LinearGradientBrush pthGrBrush2(Rect(200, 200, 300, 150), Color::White, Color::White, 45.f);
    g.DrawImage(&backBuffer, rectInstance);

    P = new PointF[startKeyVector.size()];
    A = new PointF[startKeyVector.size()];
    B = new PointF[startKeyVector.size()];
    for (int g_step = 0; g_step < startKeyVector.size(); ++g_step) {
        A[g_step] = startKeyVector[g_step];
        B[g_step] = startKeyVector[g_step];
    }

    // заставляем крутиться на 360 градусов вокруг точки 
    if (g_step < 50)
    {
        Rect rectInstance;
        g.GetVisibleClipBounds(&rectInstance);
        Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g);
        Graphics drawingBoard(&backBuffer);
        drawingBoard.Clear(Color::White);
        drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
        drawingBoard.DrawImage(&backBuffer, rectInstance);  // копируем с офлайнового холста на онлайновый
        Matrix affinMatrix;
        g.DrawImage(&backBuffer, rectInstance);

        float angl = 360.f * g_step / 50;
        g.ResetTransform();
        g.TranslateTransform(600.f, 500.f);
        g.RotateTransform(angl);
        Tween(A, B, P, startKeyVector.size(), t);
        OnDisplay(g);
    }

    // заставляем двигаться горизонтально
    else if (g_step < 130)
    {
        Rect rectInstance;
        g.GetVisibleClipBounds(&rectInstance);
        Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g);
        Graphics drawingBoard(&backBuffer);
        drawingBoard.Clear(Color::White);
        drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
        drawingBoard.DrawImage(&backBuffer, rectInstance);  // копируем с офлайнового холста на онлайновый
        Matrix affinMatrix;
        g.DrawImage(&backBuffer, rectInstance);

        float dist = 5.f * (g_step - 50);
        g.ResetTransform();
        g.TranslateTransform(600.f + dist, 500.f);
        OnDisplay(g);
    }

    // поворачиваем на 30 градусов и заставляем двигаться наклонно
    else if (g_step <= 200)
    {
        Rect rectInstance;
        g.GetVisibleClipBounds(&rectInstance);
        Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g);
        Graphics drawingBoard(&backBuffer);
        drawingBoard.Clear(Color::White);
        drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
        drawingBoard.DrawImage(&backBuffer, rectInstance);  // копируем с офлайнового холста на онлайновый
        Matrix affinMatrix;
        g.DrawImage(&backBuffer, rectInstance);

        float dist = -5.f * (g_step - 100);
        PointF rotateCenter(850.f, 300.f);
        g.ResetTransform();
        g.RotateTransform(30.f);
        g.TranslateTransform(1650.f, -300.f + dist);
        OnDisplay(g);
    }
}

// рисуем свою картинку в начале координат
void OnDisplay(Gdiplus::Graphics& g)
{
    Rect rectInstance;
    g.GetVisibleClipBounds(&rectInstance);
    Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g);
    Graphics drawingBoard(&backBuffer);
    drawingBoard.Clear(Color::White);
    drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);
    drawingBoard.DrawImage(&backBuffer, rectInstance);  // копируем с офлайнового холста на онлайновый
    Matrix affinMatrix;

    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;
    int wheels = 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);
    WrapMode wrapMode = WrapModeTile;

    //голубой корпус
    PointF points[4] = { PointF(190, 410), PointF(150, 310), PointF(450, 310), PointF(400, 410) };
    // +4
    CopyArrToVector(points, startKeyVector, 4);
    g.FillPolygon(&DarkTurquoiseBrown, points, 4);
    g.DrawPolygon(&blackPen, points, 4);

    //оконтовочный бортик (голубой)
    PointF pointsa[4] = { PointF(120, 300), PointF(480, 300), PointF(480, 320), PointF(120, 320) };
    // +4
    CopyArrToVector(pointsa, startKeyVector, 4);
    g.FillPolygon(&DarkCyanBrown, pointsa, 4);
    g.DrawPolygon(&blackPen, pointsa, 4);

    //серая антенна
    PointF pointsb[4] = { PointF(350, 300), PointF(510, 140), PointF(513, 143), PointF(355, 300) };
    // +4
    CopyArrToVector(pointsb, startKeyVector, 4);
    g.FillPolygon(&DarkGrayBrush, pointsb, 4);
    g.DrawPolygon(&blackPen, pointsb, 4);
    g.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);
    // +4
    PointF centerPointWindow(295, 410);  // координаты центра для окна
    // +1
    PathGradientBrush pthGrBrush(windowsPoints, 5); // кисть градиента контура
    pthGrBrush.SetCenterPoint(centerPointWindow);
    pthGrBrush.SetInterpolationColors(colors, pos, 5);
    pthGrBrush.SetSurroundColors(windowsColors, &n);
    g.FillPolygon(&pthGrBrush, windowsPoints, 5);
    g.DrawPolygon(&blackPen, windowsPoints, 5);

    // Надпись
    Font font(L"Courier", 25.f, FontStyleBold);
    g.DrawString(L"СССР", -1, &font, PointF(250, 330), &SaddleBrownBrush);

    // Эллипсы
    g.RotateTransform(-30);
    g.TranslateTransform(0.0f, 0.0f);
    g.DrawEllipse(&BrushPen, -110, 25, 150, 300);
    g.FillEllipse(&BlueBrush, -110, 25, 150, 300);
    g.RotateTransform(68);
    g.DrawEllipse(&BrushPen, 435, -45, 70, 30);
    g.FillEllipse(&DarkGrayBrush, 435, -45, 70, 30);
    g.DrawEllipse(&BrushPen, 444, -75, 60, 26);
    g.FillEllipse(&DarkGrayBrush, 444, -75, 60, 26);
    g.DrawEllipse(&BrushPen, 453, -100, 50, 22);
    g.FillEllipse(&DarkGrayBrush, 453, -100, 50, 22);
    g.DrawEllipse(&BrushPen, 461, -120, 40, 18);
    g.FillEllipse(&DarkGrayBrush, 461, -120, 40, 18);
    g.DrawEllipse(&BrushPen, 468, -136, 30, 14);
    g.FillEllipse(&DarkGrayBrush, 468, -136, 30, 14);

    g.RotateTransform(0); //Колеса
    // Колесо1
    g.RotateTransform(0);
    g.DrawEllipse(&BrushPen, 375, 200, 70, 70);
    g.FillEllipse(&SaddleBrownBrush, 375, 200, 70, 70);
    g.DrawEllipse(&BrushPen, 390, 215, 40, 40);
    g.FillEllipse(&WhiteBrush, 390, 215, 40, 40);
    g.DrawEllipse(&BrushPen, 397.5, 222.5, 25, 25);
    g.FillEllipse(&BrunBrown, 397.5, 222.5, 25, 25);
    // Колесо2
    g.DrawEllipse(&BrushPen, 435, 155, 70, 70);
    g.FillEllipse(&SaddleBrownBrush, 435, 155, 70, 70);
    g.DrawEllipse(&BrushPen, 450, 170, 40, 40);
    g.FillEllipse(&WhiteBrush, 450, 170, 40, 40);
    g.DrawEllipse(&BrushPen, 457.5, 177.5, 25, 25);
    g.FillEllipse(&BrunBrown, 457.5, 177.5, 25, 25);
    // Колесо3
    g.DrawEllipse(&BrushPen, 495, 110, 70, 70);
    g.FillEllipse(&SaddleBrownBrush, 495, 110, 70, 70);
    g.DrawEllipse(&BrushPen, 510, 125, 40, 40);
    g.FillEllipse(&WhiteBrush, 510, 125, 40, 40);
    g.DrawEllipse(&BrushPen, 517.5, 132.5, 25, 25);
    g.FillEllipse(&BrunBrown, 517.5, 132.5, 25, 25);
    // Колесо4
    g.DrawEllipse(&BrushPen, 555, 65, 70, 70);
    g.FillEllipse(&SaddleBrownBrush, 555, 65, 70, 70);
    g.DrawEllipse(&BrushPen, 570, 80, 40, 40);
    g.FillEllipse(&WhiteBrush, 570, 80, 40, 40);
    g.DrawEllipse(&BrushPen, 577.5, 87.5, 25, 25);
    g.FillEllipse(&BrunBrown, 577.5, 87.5, 25, 25);
    g.TranslateTransform(0.0f, 0.0f);
}
11 фев 21, 23:35    [22279788]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 7650
xamelione25,
Если мерцает, то смотреть частоту кадров и вывод в буфер за экраном и потом быстрое переключение. Плюс XOR.
Если анимацию добавлять, то уже будет месиво. Надо ООП подключать.
12 фев 21, 07:52    [22279854]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
mayton
Member

Откуда: loopback
Сообщений: 51016
xamelione25, дружище. Твой код желательно отрефакторить. Очень много копи-пасты по прежнему остается.
Сложно сопровождать и исправлять ошибки когда логика в нескольких местах. Возникает много вопросов
типа "это одна и та-же логика" или "похожая" и т.д.

Не пренебрегай рефакторингом даже в учебных проектах.
12 фев 21, 18:16    [22280186]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
mayton,

mayton
Очень много копи-пасты по прежнему остается.
не отрицаю....

mayton
Твой код желательно отрефакторить.
время время время... я еще не силен в c++ ... все по аналогии делаю, сложно еще ...

по идее у меня мерцание должно было исчезнуть при изменении с g1 на drawingBoard

в секторе
OnDisplay(Gdiplus::Graphics& g1)
где FillPolygon и DrawPolygon прописываются

но вместо этого - у меня просто все исчезает!

+
#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);
    }
}
12 фев 21, 20:57    [22280270]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Изопропил
Member

Откуда:
Сообщений: 31564
xamelione25
но вместо этого - у меня просто все исчезает!

напиши с чистого листа самый простой код OnDisplay
без оптимизации типа GetVisibleClipBounds,
погоняй простое изображение по экрану

Мерцание/дрожание всё равно останется - Gdi+ - не лучший инструмент для анимации,
рассмотри OpenGL
14 фев 21, 12:42    [22280738]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Изопропил,

у меня gdi+ по заданию требуется использовать
14 фев 21, 13:12    [22280744]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

xamelione25
у меня gdi+ по заданию требуется использовать

Тогда не заливай background, мерцать будет нечему.

Posted via ActualForum NNTP Server 1.5

14 фев 21, 13:33    [22280750]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Dimitry Sibiryakov,

да вот фон и гифка у меня то не мерцают!!!

у меня само растровое изображение мерцает
14 фев 21, 13:47    [22280756]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

xamelione25
у меня само растровое изображение мерцает

Потому что оно слишком долго рисуется и от WM_ERASEBACKGROUND до полного его вывода
проходит больше 0,03 секунды. Как уже сказали: начни с нуля и постепенно увеличивай
количество элементов.

Posted via ActualForum NNTP Server 1.5

14 фев 21, 13:52    [22280760]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Dimitry Sibiryakov,

Я не допонимаю ... Это как "постепенно увеличивай"???
14 фев 21, 14:15    [22280766]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921

xamelione25
Это как "постепенно увеличивай"???

Начни с одного колеса. Как только оно будет нормально работать - добавишь второе.

Posted via ActualForum NNTP Server 1.5

14 фев 21, 14:23    [22280767]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
PetroNotC Sharp
Member

Откуда:
Сообщений: 7650
xamelione25
Dimitry Sibiryakov,

Я не допонимаю ... Это как "постепенно увеличивай"???

бить код на куски. Ключевые слова - паттерны программирования\ООП\модульность.
Функция void OnDisplay(HDC hdc) {
не должна быть 1500 строк кода.
Она должна влазить в экран монитора.
14 фев 21, 14:28    [22280769]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 52921
xamelione25
// рисуем свою картинку в начале координат
void  OnDisplay(Gdiplus::Graphics& g1)
{
      Rect rectInstance;
      g1.GetVisibleClipBounds(&rectInstance);
      Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g1);

Давай прикинемся, что я не знаю GDI+, а ты его знаешь. И я задаю вопрос новичка: что
делает backBuffer и зачем он тут нужен?

Сообщение было отредактировано: 14 фев 21, 14:41
14 фев 21, 14:47    [22280772]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Пётр Седов
Member

Откуда: Санкт-Петербург
Сообщений: 700
xamelione25
но вместо этого - у меня просто все исчезает!
У вас какая-то полная хрень с double buffering. Если делать это вручную, то сначала рисуем всё в back buffer, потом одним махом копируем содержимое back buffer-а в окно. Чего в вашем коде не наблюдается. Попробуйте для начала выкинуть свою реализацию double buffering (объекты backBuffer, drawingBoard) и просто указывайте extended style WS_EX_COMPOSITED при создании окна.

xamelione25
у меня gdi+ по заданию требуется использовать
Странно. Я просто не понимаю, зачем нужен GDI+. Если нужна простенькая графика (прямоугольники, текст, растровые картинки), то GDI хватит. Если надо отрисовывать анимации с частотой 50-60 кадров в секунду на большие pixel-ные площади, то надо использовать графический API с аппаратным ускорением: OpenGL или Direct3D. В таких API есть операция типа «нарисовать пачку текстурированных треугольников» (реализованная в видео-карте), и обычно вся графика строится на базе этой операции (как в играх например). Если нужна какая-то серьёзная векторная графика, то имеет смысл использовать библиотеки типа Cairo или AGG. В Qt что-то есть. А вот зачем нужен GDI+ -- не понимаю.

xamelione25
    g1.DrawString(L"СССР", -1, &font, PointF(250, 330), &SaddleBrownBrush);
Какая у вас ЭВМ, товарищ? Искра?
15 фев 21, 04:15    [22280903]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Пётр Седов,

можете мне показать на примере как повернуть эллипс - у меня особая сложность возникает в повороте эллипса в анимации
15 фев 21, 09:09    [22280930]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Изопропил
Member

Откуда:
Сообщений: 31564
xamelione25,

ущербна идея вместо поворота и сдвига системы координат вычислять координаты отрезков,вершин полигонов и центров окружностей (affinMatrix.TransformPoints) и затем интерполировать координаты (Tween)

выбросьте чужой многократно скопипащеный с массой ошибок код
15 фев 21, 18:41    [22281311]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
mayton
Member

Откуда: loopback
Сообщений: 51016
Дружище xamelione25.

Я подытожу общее мнение форума. Скорее всего оно - works as designed - работает как запрограммировано.
А как оно должно работать по заданию никто-ж не знает. А сведенья ты дал скудные. Без иллюстраций
и чертежей.

Дам совет. Уже не из области разработки а скорее из тестирования и трабл-шутинга.

Выброси из кода (закомментарь) логику которая ломает траекторию фигур. В ней нет гладкости и фигуры
могут столь резко дергаться и вылетать за границы кадра что ошибка будет иметь совсем
другую природу.

Вот это

if (g_step < 50) ..... 


Проверь у себя и докажи что логика корректна хотя-бы для 1 типа движения и дальше уже перейдем к другим
траекториям.
15 фев 21, 20:54    [22281367]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Изопропил
Member

Откуда:
Сообщений: 31564
mayton,

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


Нет в этом коде вращения фигур, есть вычисление координат вершин полигонов, нет фигуры как объекта
15 фев 21, 21:10    [22281377]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
Пётр Седов
Member

Откуда: Санкт-Петербург
Сообщений: 700
xamelione25, я попробовал заменить CreateWindow на CreateWindowEx и указать первым параметром WS_EX_COMPOSITED, но чего-то double buffering нормально не заработал. Поэтому можно сделать вручную:
...
void OnDisplay(HDC hdc, Rect paintBounds); // дополнительный параметр
...
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    ...
    case WM_PAINT:
    {
        // ps и hdc лучше делать локальными переменными
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        Rect paintBounds;
        paintBounds.X = ps.rcPaint.left;
        paintBounds.Y = ps.rcPaint.top;
        paintBounds.Width = ps.rcPaint.right - ps.rcPaint.left;
        paintBounds.Height = ps.rcPaint.bottom - ps.rcPaint.top;
        OnDisplay(hdc, paintBounds);
        EndPaint(hWnd, &ps);
        break;
    }
    ...
}
...
// рисуем свою картинку в начале координат
void OnDisplay(Gdiplus::Graphics& g1)
{
    // это всё не нужно, убираем
    //Rect rectInstance;
    //g1.GetVisibleClipBounds(&rectInstance);
    //Bitmap backBuffer(rectInstance.Width, rectInstance.Height, &g1);
    //Graphics drawingBoard(&backBuffer);
    //drawingBoard.SetSmoothingMode(SmoothingModeAntiAlias);

    // остальное без изменений, рисуем на g1
    ...
}

void OnDisplay(HDC hdc, Rect paintBounds)
{
    Graphics g1(hdc);
    Bitmap backBuffer(paintBounds.Width, paintBounds.Height, &g1);
    Graphics drawingBoard(&backBuffer);
    drawingBoard.TranslateTransform(-paintBounds.X, -paintBounds.Y);
    drawingBoard.DrawImage(imgRoad, Rect(0, 0, 2123, 2123)); // координаты от балды

    // дорога
    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);
    drawingBoard.DrawImage(&backBuffer, Rect(0, 0, 2123, 2123)); // координаты от балды

    // заставляем крутиться на 360 градусов вокруг точки 
    if (g_step < 50)
    {
        float angl = 360.f * g_step / 50;
        // не надо drawingBoard.ResetTransform()
        drawingBoard.TranslateTransform(600.f, 500.f);
        drawingBoard.RotateTransform(angl);
        OnDisplay(drawingBoard);
    }

    // заставляем двигаться горизонтально
    else if (g_step < 130)
    {
        float dist = 5.f * (g_step - 50);
        // не надо drawingBoard.ResetTransform()
        drawingBoard.TranslateTransform(600.f + dist, 500.f);
        OnDisplay(drawingBoard);
    }

    // поворачиваем на 30 градусов и заставляем двигаться наклонно
    else if (g_step <= 200)
    {
        float dist = -5.f * (g_step - 100);
        PointF rotateCenter(850.f, 300.f);
        // не надо drawingBoard.ResetTransform()
        drawingBoard.RotateTransform(30.f);
        drawingBoard.TranslateTransform(1650.f, -300.f + dist);
        OnDisplay(drawingBoard);
    }

    drawingBoard.Flush(FlushIntentionSync); // может, и не нужно; хрен его знает
    g1.DrawImage(&backBuffer, paintBounds.X, paintBounds.Y);
}
Back buffer должен быть один единственный на время отрисовки.

GDI+ кстати не самый худший вариант для обучения. Могли бы заставить делать что-нибудь на Borland-овском BGI :).

xamelione25
можете мне показать на примере как повернуть эллипс - у меня особая сложность возникает в повороте эллипса в анимации
А в чём проблема с эллипсами? У меня вроде всё нормально рисуется:

К сообщению приложен файл. Размер - 20Kb
16 фев 21, 03:32    [22281415]     Ответить | Цитировать Сообщить модератору
 Re: Поворот эллипса в аннимации RotateTransform. Афинные преобразования GDI+. Поворот надписи  [new]
xamelione25
Member

Откуда:
Сообщений: 70
Пётр Седов,

Вопрос уже решен!!! Там был вопрос в том что у меня при запуске анимации в первом варианте было мерцание (там рисовался рисунок, а потом производились с ним анимационные манипуляции), а в другом варианте было то что не эллипс не разворачивался синхронно в процессе анимации вместе с остальными элементами.

Сейчас остался вопрос только в том как сделать не последовательное выполнение анимационных эффектов, а параллельное

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);
    //Matrix affinMatrix;
    // дорога
    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);

    // заставляем крутиться на 360 градусов вокруг точки 
    if (g_step < 50)
    {
        float angl = 360.f * g_step / 50;
        drawingBoard.ResetTransform();
        drawingBoard.TranslateTransform(700.f, 500.f);
        drawingBoard.RotateTransform(angl);
        OnDisplay(drawingBoard);
    }

    // заставляем двигаться горизонтально
    else if (g_step < 100)
    {
        float dist = 5.f * (g_step - 50);
        drawingBoard.TranslateTransform(700.f + dist, 500.f);
        OnDisplay(drawingBoard);
    }

    // поворачиваем на 30 градусов и заставляем двигаться наклонно
    else if (g_step < 150)
    {
        float dist = 5.f * (g_step - 100);
        drawingBoard.ResetTransform();
        drawingBoard.TranslateTransform(950.f + dist, 500.f - dist);
        //drawingBoard.RotateTransform(g_step);
        drawingBoard.ScaleTransform(1+dist/1000, 1+dist/1000);

        OnDisplay(drawingBoard);
    }

    else if (g_step < 200)
    {
        float dist = 5.f * (g_step - 100);
        drawingBoard.ResetTransform();
        drawingBoard.TranslateTransform(700.f + dist, 500.f);
        drawingBoard.ScaleTransform(-3 + dist/100, -3 + dist/100);
        drawingBoard.RotateTransform(100.f + g_step);
        drawingBoard.TranslateTransform(-250, -40);
        OnDisplay(drawingBoard);
    }

    else if (g_step = 200)
    {
        g_step = -1;
        startKeyVector.clear();
        drawingBoard.ResetTransform();
    }

    g1.DrawImage(&backBuffer, rectInstance);
}


Мне нужно, чтобы анимационные эффекты, которые приписаны в 3 и 4 кадрах, отображались все совместно, а не друг за другом - последовательно

Сообщение было отредактировано: 16 фев 21, 03:52
16 фев 21, 03:59    [22281416]     Ответить | Цитировать Сообщить модератору
Все форумы / C++ Ответить