用cocos2d-x模拟单摆运动的程序

用cocos2d-x模拟单摆运动的程序,第1张

概述需求 物理原理课需要制作关于单摆在在不同摆角下运动状态的课程报告,所以就想着做出一个有图形界面的单摆演示程序。由于图形界面只有cocos2d-学的还算可以,所以就用这个来做(实际上用MFC或者用WPF做效果会更好一点?……) 理论基础 周期求解 单摆在偏角不太大的情况(高中课本认为小于5°均可)下,单摆的运动可以近似地视为简谐运动。 周期公式 T0=2πlg−−√ 但是在摆角较大时该公式误差很大。 需求

物理原理课需要制作关于单摆在在不同摆角下运动状态的课程报告,所以就想着做出一个有图形界面的单摆演示程序。由于图形界面只有cocos2d-学的还算可以,所以就用这个来做(实际上用MFC或者用WPF做效果会更好一点?……)

理论基础 周期求解

单摆在偏角不太大的情况(高中课本认为小于5°均可)下,单摆的运动可以近似地视为简谐运动。
周期公式
T0=2πlg
但是在摆角较大时该公式误差很大。所以需要引入其他的公式。
在刘凤祥《单摆运动周期的近似解》中得出一个近似周期公式
T=T010.062Θ2
程序使用该公式求得单摆的近似周期。

瞬时角速度

推导出瞬时角速度的微分方程,然后用龙格库塔法求解,在程序中求得瞬时角速度。
直接上图……

有了瞬时角速度之后就可以用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模拟单摆运动的程序所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1075438.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-26
下一篇2022-05-26

发表评论

登录后才能评论

评论列表(0条)

    保存