One good way of making an animation is by simulating a physical system and illustrating the variables in that system using a dynamically changing graphical display. The classic such physical system is a simple gravity pendulum.
For this task, create a simple physical model of a pendulum and animate it.
wxPendulumDlg.hpp
#ifndef __wxPendulumDlg_h__ #define __wxPendulumDlg_h__ // --------------------- /// @author Martin Ettl /// @date 2013-02-03 // --------------------- #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include <wx/wx.h> #include <wx/dialog.h> #else #include <wx/wxprec.h> #endif #include <wx/timer.h> #include <wx/dcbuffer.h> #include <cmath> class wxPendulumDlgApp : public wxApp { public: bool OnInit(); int OnExit(); }; class wxPendulumDlg : public wxDialog { public: wxPendulumDlg(wxWindow *parent, wxWindowID id = 1, const wxString &title = wxT("wxPendulum"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxSUNKEN_BORDER | wxCAPTION | wxRESIZE_BORDER | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxCLOSE_BOX); virtual ~wxPendulumDlg(); // Event handler void wxPendulumDlgPaint(wxPaintEvent& event); void wxPendulumDlgSize(wxSizeEvent& event); void OnTimer(wxTimerEvent& event); private: // a pointer to a timer object wxTimer *m_timer; unsigned int m_uiLength; double m_Angle; double m_AngleVelocity; enum wxIDs { ID_WXTIMER1 = 1001, ID_DUMMY_VALUE_ }; void OnClose(wxCloseEvent& event); void CreateGUIControls(); DECLARE_EVENT_TABLE() }; #endif // __wxPendulumDlg_h__
wxPendulumDlg.cpp
// --------------------- /// @author Martin Ettl /// @date 2013-02-03 // --------------------- #include "wxPendulumDlg.hpp" #include <wx/pen.h> IMPLEMENT_APP(wxPendulumDlgApp) bool wxPendulumDlgApp::OnInit() { wxPendulumDlg* dialog = new wxPendulumDlg(NULL); SetTopWindow(dialog); dialog->Show(true); return true; } int wxPendulumDlgApp::OnExit() { return 0; } BEGIN_EVENT_TABLE(wxPendulumDlg, wxDialog) EVT_CLOSE(wxPendulumDlg::OnClose) EVT_SIZE(wxPendulumDlg::wxPendulumDlgSize) EVT_PAINT(wxPendulumDlg::wxPendulumDlgPaint) EVT_TIMER(ID_WXTIMER1, wxPendulumDlg::OnTimer) END_EVENT_TABLE() wxPendulumDlg::wxPendulumDlg(wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &position, const wxSize& size, long style) : wxDialog(parent, id, title, position, size, style) { CreateGUIControls(); } wxPendulumDlg::~wxPendulumDlg() { } void wxPendulumDlg::CreateGUIControls() { SetIcon(wxNullIcon); SetSize(8, 8, 509, 412); Center(); m_uiLength = 200; m_Angle = M_PI/2.; m_AngleVelocity = 0; m_timer = new wxTimer(); m_timer->SetOwner(this, ID_WXTIMER1); m_timer->Start(20); } void wxPendulumDlg::OnClose(wxCloseEvent& WXUNUSED(event)) { Destroy(); } void wxPendulumDlg::wxPendulumDlgPaint(wxPaintEvent& WXUNUSED(event)) { SetBackgroundStyle(wxBG_STYLE_CUSTOM); wxBufferedPaintDC dc(this); // Get window dimensions wxSize sz = GetClientSize(); // determine the center of the canvas const wxPoint center(wxPoint(sz.x / 2, sz.y / 2)); // create background color wxColour powderblue = wxColour(176,224,230); // draw powderblue background dc.SetPen(powderblue); dc.SetBrush(powderblue); dc.DrawRectangle(0, 0, sz.x, sz.y); // draw lines wxPen Pen(*wxBLACK_PEN); Pen.SetWidth(1); dc.SetPen(Pen); dc.SetBrush(*wxBLACK_BRUSH); double angleAccel, dt = 0.15; angleAccel = (-9.81 / m_uiLength) * sin(m_Angle); m_AngleVelocity += angleAccel * dt; m_Angle += m_AngleVelocity * dt; int anchorX = sz.x / 2, anchorY = sz.y / 4; int ballX = anchorX + (int)(sin(m_Angle) * m_uiLength); int ballY = anchorY + (int)(cos(m_Angle) * m_uiLength); dc.DrawLine(anchorX, anchorY, ballX, ballY); dc.SetBrush(*wxGREY_BRUSH); dc.DrawEllipse(anchorX - 3, anchorY - 4, 7, 7); dc.SetBrush(wxColour(255,255,0)); // yellow dc.DrawEllipse(ballX - 7, ballY - 7, 20, 20); } void wxPendulumDlg::wxPendulumDlgSize(wxSizeEvent& WXUNUSED(event)) { Refresh(); } void wxPendulumDlg::OnTimer(wxTimerEvent& WXUNUSED(event)) { // force refresh Refresh(); }
Content is available under GNU Free Documentation License 1.2.