键盘响应和回调的结合

响应键盘操作需要定义一个从osgGA::GUIEventHandle派生出来的类,结合自定义的回调类callBack实现对坦克模型的前进、后退,以及炮塔的旋转操作。

键盘响应类keyboardEventHandle与回调类callBack是如何通信的呢?这里我们需要在定义一个用户自定义的类,将对模型的操作的数据封装进去。

用户自定义数据类tankInputDeviceType。

tankInputDeviceType.h

#pragma once
#include <osg/Node>
#include <osgSim/DOFTransform>
#include "myFindNodeVisitor.h"

#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgSimd.lib")
#else
#pragma comment(lib,"osg.lib")
#pragma comment(lib,"osgSim.lib")
#endif

class tankInputDeviceType
{
public:
	//构造函数,传递一个结点指针,获得osgSim::DOFTransform*类型的炮塔结点指针并保存起来
	tankInputDeviceType(osg::Node& node):m_forward(false),m_backward(false),m_turretLeft(false),m_turretRight(false)
	{
		myFindNodeVisitor findNode("turret");
		node.accept(findNode);
		osgSim::DOFTransform* turretNode = dynamic_cast<osgSim::DOFTransform*>(findNode.getFirst());
		if (turretNode)
		{
			m_turretNode = turretNode;
		}
		else
		{
			std::cout<<"tankInputDeviceType::tankInputDeviceType(osg::Node& node):"<<std::endl<<"findNode failed"<<std::endl;
		}
		
	}
	//重载构造函数,传递一个结点指针,获得osgSim::DOFTransform*类型的炮塔结点指针并保存起来
	tankInputDeviceType(osg::Transform& node):m_forward(false),m_backward(false),m_turretLeft(false),m_turretRight(false)
	{
		myFindNodeVisitor findNode("turret");
		node.accept(findNode);
		osgSim::DOFTransform* turretNode = dynamic_cast<osgSim::DOFTransform*>(findNode.getFirst());
		if (turretNode)
		{
			m_turretNode = turretNode;
		}
		else
		{
			std::cout<<"tankInputDeviceType::tankInputDeviceType(osg::Node& node):"<<std::endl<<"findNode failed"<<std::endl;
		}

	}
	//对于坦克的前进、后退,炮塔的左旋转、右旋转的设置
	inline void setForward(bool b){m_forward = b;m_backward = false;}
	inline void setBackward(bool b){m_backward = b;m_forward = false;}
	inline void setTurretLeft(bool b){m_turretLeft = b;m_backward = false;}
	inline void setTurretRight(bool b){m_turretRight = b;m_turretLeft = false;}

	inline bool getForward(){return m_forward;}
	inline bool getBackward(){return m_backward;}
	inline bool getTurretLeft(){return m_turretLeft;}
	inline bool getTurretRight(){return m_turretRight;}
	inline osgSim::DOFTransform* getTurretNode(){return m_turretNode;}

protected:
	bool m_forward;
	bool m_backward;
	bool m_turretLeft;
	bool m_turretRight;
	osgSim::DOFTransform* m_turretNode;
};


这里的“myFindNodeVisitor.h”在《DOF和MultiSwitch的使用》这篇博客中有源代码,这里就不赘述了。

keyboardEventHandle.h

#pragma once
#include <osgGA/GUIEventHandler>
#include "tankInputDeviceType.h"

#ifdef _DEBUG
#pragma comment(lib,"osgGAd.lib")
#else
#pragma comment(lib,"osgGA.lib")
#endif
class keyboardEventHandle:public osgGA::GUIEventHandler
{
public:
	
	// 构造函数,初始化m_tankInputDeviceData数据成员
	keyboardEventHandle(tankInputDeviceType* tankInputDeviceData):m_tankInputDeviceData(tankInputDeviceData){}
	//重载handle函数,使其响应键盘事件
	virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);

protected:
	
	tankInputDeviceType* m_tankInputDeviceData;
};

bool keyboardEventHandle::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
{
	switch (ea.getEventType())
	{
	case osgGA::GUIEventAdapter::KEYDOWN:
		{
			switch(ea.getKey())
			{
			case 'w':
				m_tankInputDeviceData->setForward(true);
				return true;
			case 's':
				m_tankInputDeviceData->setBackward(true);
				return true;
			case 'q':
				m_tankInputDeviceData->setTurretLeft(true);
				return true;
			case 'e':
				m_tankInputDeviceData->setTurretRight(true);
				return true;
			default:
				return false;

			}
		}
	case osgGA::GUIEventAdapter::KEYUP:
		{
			switch(ea.getKey())
			{
			case 'w':
				m_tankInputDeviceData->setForward(false);
				return true;
			case 's':
				m_tankInputDeviceData->setBackward(false);
				return true;
			case 'q':
				m_tankInputDeviceData->setTurretLeft(false);
				return true;
			case 'e':
				m_tankInputDeviceData->setTurretRight(false);
				return true;
			default:
				return false;
			}
		}
		
	default:
		return false;
	}
}


回调类tankCallBack

tankCallBack.h

#pragma once
#include <osg/NodeCallback>
#include <osg/PositionAttitudeTransform>
#include "tankInputDeviceType.h"

#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#else
#pragma comment(lib,"osg.lib")
#endif

class tankCallBack:public osg::NodeCallback
{
public:
	tankCallBack(tankInputDeviceType *tankInputData):m_tankInputData(tankInputData){}
	virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
	{ 
		//模型前进
		if (m_tankInputData->getForward())
		{
			osg::PositionAttitudeTransform* pos = dynamic_cast<osg::PositionAttitudeTransform*>(node);
			if (pos)
			{
				tankPos = pos->getPosition();
				tankPos += osg::Vec3(0.0f,0.01f,0.0f);
				pos->setPosition(tankPos);
			}
		}
		//后退
		if (m_tankInputData->getBackward())
		{
			osg::PositionAttitudeTransform* pos = dynamic_cast<osg::PositionAttitudeTransform*>(node);
			if (pos)
			{
				tankPos = pos->getPosition();
				tankPos -= osg::Vec3(0.0f,0.01f,0.0f);
				pos->setPosition(tankPos);
			}
		}
		//炮塔左旋转
		if (m_tankInputData->getTurretLeft())
		{
			tankRot = m_tankInputData->getTurretNode()->getCurrentHPR();
			tankRot += osg::Vec3(0.001f,0,0);
			m_tankInputData->getTurretNode()->setCurrentHPR(tankRot);
		}
		//炮塔右旋转
		if (m_tankInputData->getTurretRight())
		{
			tankRot = m_tankInputData->getTurretNode()->getCurrentHPR();
			tankRot -= osg::Vec3(0.001f,0,0);
			m_tankInputData->getTurretNode()->setCurrentHPR(tankRot);
		}
		
		traverse(node,nv);
	}
protected:
	tankInputDeviceType* m_tankInputData;
	osg::Vec3 tankRot;
	osg::Vec3 tankPos;
};

main.cpp

#include "tankCallBack.h"
#include "tankInputDeviceType.h"
#include "keyboardEventHandle.h"

#include <osgDB/readfile>
#include <osgViewer/Viewer>
#include <osg/Group>
#include <osg/Node>
#include <osg/PositionAttitudeTransform>
#include <iostream>

#ifdef _DEBUG
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgDBd.lib")
#pragma comment(lib,"osgViewerd.lib")
#else
#pragma comment(lib,"osg.lib")
#pragma comment(lib,"osgDB.lib")
#pragma commnet(lib,"osgViewer.lib")
#endif
int main()
{
	//载入坦克模型和地形模型
	osg::ref_ptr<osg::Group> root = new osg::Group;
	osg::ref_ptr<osg::Node> tank = osgDB::readNodeFile("/T72-tank/t72-tank_des.flt");
	osg::ref_ptr<osg::Node> land = osgDB::readNodeFile("/T72-tank/JoeDirt.flt");
	if (!land.get())
	{
		std::cout<<"land node load error"<<std::endl;
		return -1;
	}
	if (!tank.get())
	{
		std::cout<<"tank node load error"<<std::endl;
		return -1;
	}
	osg::PositionAttitudeTransform* tankPos = new osg::PositionAttitudeTransform;
	tankPos->setPosition(osg::Vec3(10,10,8));
	tankPos->addChild(tank.get());
	root->addChild(land.get());
	root->addChild(tankPos);

	//声明用户自定义数据类实例,用这个类对象分别初始化回调类和键盘响应类
	tankInputDeviceType* tankData = new tankInputDeviceType(*tankPos);
	keyboardEventHandle* keyEH = new keyboardEventHandle(tankData);
	tankCallBack* callBack = new tankCallBack(tankData);
	//安装回调类
	tankPos->setUpdateCallback(callBack);
	//循环仿真
	osgViewer::Viewer myViewer;
	myViewer.addEventHandler(keyEH);
	myViewer.setSceneData(root.get());
	myViewer.realize();
	myViewer.run();
}


移动前和炮塔为旋转

移动加炮塔旋转。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值