最近研究Irrlicht引擎,做了个demon,包含如下功能:
1)地图中央有一架3D坦克
2)坦克可以前进、后退、旋转
3)第一人称视角
4)视角随坦克同步移动、旋转
5)可以用-/+键调节坦克的速度
6)灯光效果
7)前进后退可以与旋转同时进行
8)运动过程中加减速立即生效
9)实现了简单的碰撞效果,使坦克能在地图中上下楼
以下是实现坦克移动的核心代码:
#include "CSceneNodeAnimatorFlyFree.h"
#include "os.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
namespace irr
{
namespace scene
{
//! constructor
CSceneNodeAnimatorFlyFree::CSceneNodeAnimatorFlyFree(const core::vector3df& startPoint,u32 now, const core::vector3df& direction, irr::f32 straightSpeed, core::vector3df& rotateSpeed)
: Start(startPoint), StartTime(now), LastAnimationTime(0), firstUpdate(true),StraightSpeed(straightSpeed),RotateSpeed(rotateSpeed),Camera(0),Distance(0),Hight(0)
{
#ifdef _DEBUG
setDebugName("CSceneNodeAnimatorFlyFree");
#endif
Direction = direction;
Direction.normalize();
}
//! make the direction more friendly with the rotation
void makeItSmooth(core::vector3df& direction, core::vector3df& rotation)
{
core::vector3df currentPos(0,0,0);
core::vector3df newDir = direction;
newDir.Y = 0;
//if( event.KeyInput.Key == KEY_KEY_W )
{
if( rotation.Y > 90 && rotation.Y <= 270
|| fmod(rotation.Y,360.0f) > -270 && fmod(rotation.Y , 360) <= -90
)
{
newDir.X = (-1) * tan(rotation.Y / 180.0 * M_PI);
newDir.Z = (-1);
}
else
{
newDir.X = tan(rotation.Y / 180.0 * M_PI);
newDir.Z = 1;
}
}
if(direction.X * newDir.X + direction.Z * newDir.Z >= 0)
{
direction += newDir;
}
else
{
direction -= newDir;
}
direction.normalize();
}
//! animates a scene node
void CSceneNodeAnimatorFlyFree::animateNode(ISceneNode* node, u32 timeMs)
{
if (!node)
return;
if(firstUpdate)
{
LastAnimationTime = StartTime;
firstUpdate = false;
}
u32 diffTime = timeMs - LastAnimationTime;
if (diffTime != 0)
{
core::vector3df rot = node->getRotation();
core::vector3df pos = node->getPosition();
if( RotateSpeed != core::vector3df(0,0,0) )
{
rot += RotateSpeed * diffTime;
if (rot.X>360.f)
rot.X=fmodf(rot.X, 360.f);
if (rot.Y>360.f)
rot.Y=fmodf(rot.Y, 360.f);
if (rot.Z>360.f)
rot.Z=fmodf(rot.Z, 360.f);
if (rot.X<-360.f)
rot.X=fmodf(rot.X, -360.f);
if (rot.Y<-360.f)
rot.Y=fmodf(rot.Y, -360.f);
if (rot.Z<-360.f)
rot.Z=fmodf(rot.Z, -360.f);
node->setRotation(rot);
makeItSmooth(Direction, rot);
}
core::vector3df rel = Direction * diffTime * StraightSpeed;
pos += rel;
node->setPosition(pos);
// move the camema, current version doesn't change 'Y'
if(Camera && Camera->getType() == ESNT_CAMERA)
{
core::vector3df cameraPos = Camera->getPosition();
if(rot.Y >= -90 && rot.Y < 90)
{
cameraPos.X = pos.X - Distance * sin(rot.Y / 180.0 * M_PI);
cameraPos.Z = pos.Z - Distance * cos(rot.Y / 180.0 * M_PI);
}
else
{
cameraPos.X = pos.X - Distance * sin((180.0 - rot.Y) / 180.0 * M_PI);
cameraPos.Z = pos.Z + Distance * cos((180.0 - rot.Y) / 180.0 * M_PI);
}
cameraPos.Y = pos.Y + Hight;
Camera->setPosition(cameraPos);
}
LastAnimationTime = timeMs;
}
}
//! Writes attributes of the scene node animator.
void CSceneNodeAnimatorFlyFree::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
out->addVector3d("Direction", Direction);
}
//! Reads attributes of the scene node animator.
void CSceneNodeAnimatorFlyFree::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
Direction = in->getAttributeAsVector3d("Direction");
}
ISceneNodeAnimator* CSceneNodeAnimatorFlyFree::createClone(ISceneNode* node, ISceneManager* newManager)
{
CSceneNodeAnimatorFlyFree * newAnimator =
new CSceneNodeAnimatorFlyFree(Start,StartTime, Direction, StraightSpeed, RotateSpeed);
return newAnimator;
}
void CSceneNodeAnimatorFlyFree::resetDirection(core::vector3df& direction)
{
Direction = direction;
Direction.normalize();
}
void CSceneNodeAnimatorFlyFree::resetRotateSpeed(core::vector3df& rotateSpeed)
{
RotateSpeed = rotateSpeed;
}
void CSceneNodeAnimatorFlyFree::resetStraightSpeed(irr::f32 straightSpeed)
{
StraightSpeed = straightSpeed;
}
core::vector3df CSceneNodeAnimatorFlyFree::getDirection()
{
return Direction;
}
core::vector3df CSceneNodeAnimatorFlyFree::getRotateSpeed()
{
return RotateSpeed;
}
irr::f32 CSceneNodeAnimatorFlyFree::getStraightSpeed()
{
return StraightSpeed;
}
void CSceneNodeAnimatorFlyFree::setCamera(scene::ICameraSceneNode* camera)
{
Camera = camera;
}
void CSceneNodeAnimatorFlyFree::setDistanceFromCamera(f32 distance)
{
Distance = distance;
}
void CSceneNodeAnimatorFlyFree::setHightFromCamera(f32 hight)
{
Hight = hight;
}
} // end namespace scene
} // end namespace irr