用cocos2d-x模拟单摆运动的程序
来源:互联网 发布:法甲德佩数据 编辑:程序博客网 时间:2024/05/01 14:53
需求
物理原理课需要制作关于单摆在在不同摆角下运动状态的课程报告,所以就想着做出一个有图形界面的单摆演示程序。由于图形界面只有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, 120), 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, Vec2(screenSize.width / 2.0f, 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
0 0
- 用cocos2d-x模拟单摆运动的程序
- Cocos2d-x 实现运动的尾巴效果
- Cocos2d-x 实现运动的尾巴效果
- Cocos2d-x加速度计实例:运动的小球
- Cocos2d-X 物体重复运动的实现
- 【cocos2d-x游戏开发】图片的“运动”
- cocos2d-x 3.2 椭圆运动
- java3D的单摆
- 一个简单的单摆
- cocos2d-x ActionManager控制精灵的暂停运动
- Cocos2d-X 背景层循环运动效果的具体实现
- Cocos2d-x 强制设置运动刚体的位置
- Cocos2d-x实战项目开发:运动的小球
- cocos2d-x学习之一:cocos2d-x程序的生命周期
- cocos2d-x 运动中的加速度效果
- cocos2d-x 运动中的加速度效果
- cocos2d-x实现node圆弧运动
- cocos2d-x 运动中的加速度效果
- Java排序算法
- 如何让iOS 保持界面流畅?这些技巧你知道吗
- 【转】Qt中Ui名字空间以及setupUi函数的原理和实现
- c#学前准备
- eclipse 代码覆盖率工具EclEmma
- 用cocos2d-x模拟单摆运动的程序
- Visual BCD Editor - Windows 7, Windows 10/8/Vista
- 2015年12月App Store提交审核流程(Xcode7,iOS9)
- <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>标签再使用时报错
- POJ 1488 TEX Quotes(模拟水题)
- 数据结构实验之查找五:平方之哈希表
- iOS中创建UITableViewCell的正确姿态
- 纯C语言的工作有前(钱)景吗?
- 数据结构C++实现——二叉树