
物理原理课需要制作关于单摆在在不同摆角下运动状态的课程报告,所以就想着做出一个有图形界面的单摆演示程序。由于图形界面只有cocos2d-学的还算可以,所以就用这个来做(实际上用MFC或者用WPF做效果会更好一点?……)
理论基础 周期求解单摆在偏角不太大的情况(高中课本认为小于5°均可)下,单摆的运动可以近似地视为简谐运动。
周期公式
但是在摆角较大时该公式误差很大。所以需要引入其他的公式。
在刘凤祥《单摆运动周期的近似解》中得出一个近似周期公式
程序使用该公式求得单摆的近似周期。
推导出瞬时角速度的微分方程,然后用龙格库塔法求解,在程序中求得瞬时角速度。
直接上图……
有了瞬时角速度之后就可以用update函数移动摆球并表现在图形界面中。
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__#include "cocos2d.h"#include "ui/CocosGUI.h"#include "Consts.h"class HelloWorld : public cocos2d::Layer{public: enum kState { kState_Stop,kState_Running,kState_Paused }; HelloWorld(); ~HelloWorld(); static cocos2d::Scene* createScene(); virtual bool init(); CREATE_FUNC(HelloWorld);public: voID slIDerEvent(cocos2d::Ref* sender,cocos2d::ui::SlIDer::EventType type); voID textFIEldEvent(cocos2d::Ref* sender,cocos2d::ui::TextFIEld::EventType type); voID StarttouchEvent(cocos2d::Ref* sender,cocos2d::ui::Widget::touchEventType type); voID PausetouchEvent(cocos2d::Ref* sender,cocos2d::ui::Widget::touchEventType type);public: virtual voID update(float delta);protected: cocos2d::CustomCommand _customCommand;private: double _startAngel,_l,_T; int _halfT; double _currentAngel,_currentW,_currentTime; kState _state; cocos2d::Vec2 _ballPos,_vertexPos,_graphVertexPos;private: cocos2d::ui::Text * m_TText; cocos2d::ui::Text * m_WText; cocos2d::ui::Text * m_AngelText; cocos2d::ui::Text * m_CurrentAngelText; cocos2d::ui::SlIDer * m_AngelSlIDer; cocos2d::ui::TextFIEld * m_LTextFIEld; cocos2d::ui::button * m_Pausebutton; cocos2d::Sprite * m_ball; cocos2d::DrawNode * m_drawNode; cocos2d::DrawNode * m_graphNode;private: double getW(); double getT();};#endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h"#include "cocostudio/CocoStudio.h"#include "ui/CocosGUI.h"// draw#include "renderer/CCRenderer.h"#include "renderer/CCCustomCommand.h"USING_NS_CC;using namespace cocostudio::timeline;using namespace cocos2d::ui;HelloWorld::HelloWorld(){ m_TText = nullptr; m_WText = nullptr; m_AngelText = nullptr; m_CurrentAngelText = nullptr; m_AngelSlIDer = nullptr; m_LTextFIEld = nullptr; _vertexPos = Vec2(300,550); _graphVertexPos = Vec2(300,120);}HelloWorld::~HelloWorld(){}Scene* HelloWorld::createScene(){ auto scene = Scene::create(); auto layer = HelloWorld::create(); scene->addChild(layer); return scene;}bool HelloWorld::init(){ if ( !Layer::init() ) { return false; } // init variables _state = kState_Stop; // DrawNode m_drawNode = DrawNode::create(); this->addChild(m_drawNode,10); m_graphNode = DrawNode::create(); this->addChild(m_graphNode,9); m_graphNode->drawline(Vec2(0,120),Vec2(600,color4F::RED); m_graphNode->drawline(Vec2(300,0),Vec2(300,240),color4F::RED); m_graphNode->drawPoint(_vertexPos,20,color4F::BLUE); // init UI auto rootNode = csloader::createNode("MainScene.csb"); addChild(rootNode); m_TText = static_cast<ui::Text*>(rootNode->getChildByname("Panel_RT")->getChildByname("Text_T_Data")); m_WText = static_cast<ui::Text*>(rootNode->getChildByname("Panel_RT")->getChildByname("Text_W_Data")); m_CurrentAngelText = static_cast<ui::Text*>(rootNode->getChildByname("Panel_RT")->getChildByname("Text_CurrentAngel_Data")); m_AngelText = static_cast<ui::Text*>(rootNode->getChildByname("Panel_RB")->getChildByname("Text_Angel_Data")); m_AngelSlIDer = static_cast<ui::SlIDer*>(rootNode->getChildByname("Panel_RB")->getChildByname("SlIDer_Angel")); m_AngelSlIDer->setMaxPercent(90); m_AngelSlIDer->addEventListener(CC_CALLBACK_2(HelloWorld::slIDerEvent,this)); m_LTextFIEld = static_cast<ui::TextFIEld*>(rootNode->getChildByname("Panel_RB")->getChildByname("TextFIEld_l")); m_LTextFIEld->addEventListener(CC_CALLBACK_2(HelloWorld::textFIEldEvent,this)); auto startBtn = static_cast<ui::button*>(rootNode->getChildByname("Panel_RB")->getChildByname("button_Start")); startBtn->addtouchEventListener(CC_CALLBACK_2(HelloWorld::StarttouchEvent,this)); m_Pausebutton = static_cast<ui::button*>(rootNode->getChildByname("Panel_RB")->getChildByname("button_Pause")); m_Pausebutton->addtouchEventListener(CC_CALLBACK_2(HelloWorld::PausetouchEvent,this)); // init Sprite m_ball = Sprite::create("ball.png"); m_ball->setAnchorPoint(Vec2(0.5,0.5)); m_ball->setposition(_vertexPos); this->addChild(m_ball); return true;}voID HelloWorld::slIDerEvent(Ref *pSender,cocos2d::ui::SlIDer::EventType type){ if(type == SlIDer::EventType::ON_PERCENTAGE_CHANGED) { SlIDer* slIDer = dynamic_cast<SlIDer*>(pSender); int percent = slIDer->getPercent(); m_AngelText->setString(StringUtils::format("%d",percent)); _startAngel = (double)percent / 180 * PI; _currentAngel = _startAngel; _ballPos = Vec2(_vertexPos.x + _l * 100 * sin(_currentAngel),_vertexPos.y - _l * 100 * cos(_currentAngel)); m_ball->setposition(_ballPos); }}voID HelloWorld::textFIEldEvent(Ref *pSender,cocos2d::ui::TextFIEld::EventType type){ switch (type) { case TextFIEld::EventType::ATTACH_WITH_IME: { TextFIEld* textFIEld = dynamic_cast<TextFIEld*>(pSender);/* Size screenSize = Director::getInstance()->getWinSize(); textFIEld->runAction(Moveto::create(0.225f,Vec2(screenSize.wIDth / 2.0f,screenSize.height / 2.0f + textFIEld->getContentSize().height / 2.0f))); */ } break; case TextFIEld::EventType::DETACH_WITH_IME: { TextFIEld* textFIEld = dynamic_cast<TextFIEld*>(pSender);/* Size screenSize = Director::getInstance()->getWinSize(); textFIEld->runAction(Moveto::create(0.175f,screenSize.height / 2.0f))); */ } break; case TextFIEld::EventType::INSERT_TEXT: { TextFIEld * textFIEld = dynamic_cast<TextFIEld*>(pSender); std::string str = textFIEld->getString(); int num = atoi(str.c_str()); log("%d",num); _l = num; } break; case TextFIEld::EventType::DELETE_BACKWARD: break; default: break; }}voID HelloWorld::StarttouchEvent(Ref *pSender,Widget::touchEventType type){ switch (type) { case Widget::touchEventType::BEGAN: break; case Widget::touchEventType::MOVED: break; case Widget::touchEventType::ENDED: { _currentAngel = _startAngel; _currentW = 0; _currentTime = 0; _state = kState_Running; m_Pausebutton->setTitleText("PAUSE"); // set T _T = getT(); m_TText->setText(StringUtils::format("%lf",_T)); this->scheduleUpdate(); } break; case Widget::touchEventType::CANCELED: break; default: break; }}voID HelloWorld::PausetouchEvent(Ref *pSender,Widget::touchEventType type){ switch (type) { case Widget::touchEventType::BEGAN: break; case Widget::touchEventType::MOVED: break; case Widget::touchEventType::ENDED: { if(_state == kState_Running) { _state = kState_Paused; this->unscheduleUpdate(); auto button = dynamic_cast<ui::button*>(pSender); button->setTitleText("RESUME"); } else if(_state == kState_Paused) { _state = kState_Running; this->scheduleUpdate(); auto button = dynamic_cast<ui::button*>(pSender); button->setTitleText("PAUSE"); } } break; case Widget::touchEventType::CANCELED: break; default: break; }}voID HelloWorld::update(float delta){ // double W = getW(); // update data double k1,k2,k3,k4,l1,l2,l3,l4; { k1 = _currentW; l1 = -(G / _l) * sin(_currentAngel); k2 = _currentW + delta * l1 / 2.0; l2 = -(G / _l) * sin(_currentAngel + delta * k1 / 2.0); k3 = _currentW + delta * l2 / 2.0; l3 = -(G / _l) * sin(_currentAngel + delta * k2 / 2.0); k4 = _currentW + delta * l3; l4 = -(G / _l) *sin(_currentAngel * delta * k3); _currentTime += (double)delta; _currentAngel += delta * (k1 + 2 * k2 + 2 * k3 + k4) / 6.0; log("%lf",_currentAngel); _currentW += delta * (l1 + 2 * l2 + 2 * l3 + l4) / 6.0; } m_WText->setText(StringUtils::format("%.4lf",_currentW)); m_CurrentAngelText->setText(StringUtils::format("%.1lf",_currentAngel / PI * 180)); // draw _ballPos = Vec2(_vertexPos.x + _l * 100 * sin(_currentAngel),_vertexPos.y - _l * 100 * cos(_currentAngel)); m_ball->setposition(_ballPos); m_drawNode->clear(); m_drawNode->drawline(_vertexPos,_ballPos,color4F::BLUE); // graph m_graphNode->drawPoint(Vec2(_graphVertexPos.x + _currentAngel * 200,_graphVertexPos.y + _currentW * 50),2,color4F::RED);}double HelloWorld::getW(){ double W; W = sqrt(2 / _l*_l) * sqrt(9.8*_l*(cos(_currentAngel) - cos(_startAngel))); if (_halfT % 2 == 0) W = -W; return W;}double HelloWorld::getT(){ double T;// double T1,T2,T3;// T3 = sqrt(_l / G);// T1 = 2 * PI * sqrt(_l / G);// T2 = 1 - 0.062*_startAngel*_startAngel; T = (2 * PI * sqrt(_l / G)) / (1 - 0.062*_startAngel*_startAngel);// T = T1 / T2; return T;}程序截图以及下载
下载地址:
http://download.csdn.net/detail/jjhfen00/9330825
以上是内存溢出为你收集整理的用cocos2d-x模拟单摆运动的程序全部内容,希望文章能够帮你解决用cocos2d-x模拟单摆运动的程序所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)