Убрать мерцание и изменить/добавить характер анимации
Основная проблема в подавлении мерцания!!! И сложность у меня сейчас еще возникает (не знаю как сделать) чтобы сделать на третьем кадре факт уменьшения изображения до середины временного интервала а потом обратное его увеличение (по характеру графика параболы). И помимо всего-прочего у меня анимация почему-то прекратила повторяться (то есть не бесконечный интервал повтора, а один).
#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);
}
}