基于OGRE实现一个简单的3D游戏(软件工程作业2)
基于OGRE实现一个简单的3D游戏(软件工程作业2)
学号:2011211910
同组博客链接:http://thefrp.sinaapp.com/
题目:
实现一个3D游戏
最终效果:
游戏截图:
游戏说明:
用WASD控制兽人前左右后移动,空格跳跃,Q拿起武器,鼠标左键和右键为攻击。没击杀一个机器人敌人,就会出现新的机器人敌人,无限模式。
学习体会:
- 了解了基本的OGRE知识
- 熟悉了C++编程
- 结对编程的乐趣还有队友之间的协助,事半功倍
- 第一次学习了有关游戏编程的东西,有一种创造的成就感
代码:
CharacterSample.h
#ifndef __Character_H__
#define __Character_H__
#include"SdkSample.h"
#include"SinbadCharacterController.h"
usingnamespaceOgre;
usingnamespaceOgreBites;
class_OgreSampleClassExportSample_Character:publicSdkSample
{
public:
Sample_Character()
{
mInfo["Title"]="Character";
mInfo["Description"]="A demo showing 3rd-person character control and use of TagPoints.";
mInfo["Thumbnail"]="thumb_char.png";
mInfo["Category"]="Animation";
mInfo["Help"]="Use the WASD keys to move Sinbad, and the space bar to jump. "
"Use mouse to look around and mouse wheel to zoom. Press Q to take out or put back "
"Sinbad's swords. With the swords equipped, you can left click to slice vertically or "
"right click to slice horizontally. When the swords are not equipped, press E to "
"start/stop a silly dance routine.";
}
bool frameRenderingQueued(constFrameEvent& evt)
{
// let character update animations and camera
mChara->addTime(evt.timeSinceLastFrame);
returnSdkSample::frameRenderingQueued(evt);
}
bool keyPressed(const OIS::KeyEvent& evt)
{
// relay input events to character controller
if(!mTrayMgr->isDialogVisible()) mChara->injectKeyDown(evt);
returnSdkSample::keyPressed(evt);
}
bool keyReleased(const OIS::KeyEvent& evt)
{
// relay input events to character controller
if(!mTrayMgr->isDialogVisible()) mChara->injectKeyUp(evt);
returnSdkSample::keyReleased(evt);
}
#if (OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS) || (OGRE_PLATFORM == OGRE_PLATFORM_ANDROID)
bool touchPressed(const OIS::MultiTouchEvent& evt)
{
// relay input events to character controller
if(!mTrayMgr->isDialogVisible()) mChara->injectMouseDown(evt);
returnSdkSample::touchPressed(evt);
}
bool touchMoved(const OIS::MultiTouchEvent& evt)
{
// relay input events to character controller
if(!mTrayMgr->isDialogVisible()) mChara->injectMouseMove(evt);
returnSdkSample::touchMoved(evt);
}
#else
bool mouseMoved(const OIS::MouseEvent& evt)
{
// relay input events to character controller
if(!mTrayMgr->isDialogVisible()) mChara->injectMouseMove(evt);
returnSdkSample::mouseMoved(evt);
}
bool mousePressed(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
// relay input events to character controller
if(!mTrayMgr->isDialogVisible()) mChara->injectMouseDown(evt, id);
returnSdkSample::mousePressed(evt, id);
}
#endif
protected:
void setupContent()
{
// set background and some fog
mViewport->setBackgroundColour(ColourValue(1.0f,1.0f,0.8f));
mSceneMgr->setFog(Ogre::FOG_LINEAR,ColourValue(1.0f,1.0f,0.8f),0,15,100);
// set shadow properties
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
mSceneMgr->setShadowColour(ColourValue(0.5,0.5,0.5));
mSceneMgr->setShadowTextureSize(1024);
mSceneMgr->setShadowTextureCount(1);
// disable default camera control so the character can do its own
mCameraMan->setStyle(CS_MANUAL);
// use a small amount of ambient lighting
mSceneMgr->setAmbientLight(ColourValue(0.3,0.3,0.3));
// add a bright light above the scene
Light* light = mSceneMgr->createLight();
light->setType(Light::LT_POINT);
light->setPosition(-10,40,20);
light->setSpecularColour(ColourValue::White);
// create a floor mesh resource
MeshManager::getSingleton().createPlane("floor",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Plane(Vector3::UNIT_Y,0),200,200,10,10,true,1,10,10,Vector3::UNIT_Z);
// create a floor entity, give it a material, and place it at the origin
Entity* floor = mSceneMgr->createEntity("Floor","floor");
floor->setMaterialName("Examples/Instancing/Misc/Grass");
floor->setCastShadows(false);
mSceneMgr->getRootSceneNode()->attachObject(floor);
// LogManager::getSingleton().logMessage("creating sinbad");
// create our character controller
mChara =newSinbadCharacterController(mCamera);
// LogManager::getSingleton().logMessage("toggling stats");
mTrayMgr->toggleAdvancedFrameStats();
// LogManager::getSingleton().logMessage("creating panel");
StringVector items;
items.push_back("Help");
ParamsPanel* help = mTrayMgr->createParamsPanel(TL_TOPLEFT,"HelpMessage",100, items);
help->setParamValue("Help","H / F1");
// LogManager::getSingleton().logMessage("all done");
}
void cleanupContent()
{
// clean up character controller and the floor mesh
if(mChara)
{
delete mChara;
mChara =0;
}
MeshManager::getSingleton().remove("floor");
}
SinbadCharacterController* mChara;
};
#endif
SinbadCharacterController.h
#ifndef __Sinbad_H__
#define __Sinbad_H__
#include"Ogre.h"
#include"OIS.h"
#include<cstdlib>
usingnamespaceOgre;
#define NUM_ANIMS 13// number of animations the character has
#define CHAR_HEIGHT 5// height of character's center of mass above ground
#define CAM_HEIGHT 2// height of camera above character's center of mass
#define RUN_SPEED 17// character running speed in units per second
#define TURN_SPEED 500.0f// character turning in degrees per second
#define ANIM_FADE_SPEED 7.5f// animation crossfade speed in % of full weight per second
#define JUMP_ACCEL 30.0f// character jump acceleration in upward units per squared second
#define GRAVITY 90.0f// gravity in downward units per squared second
classSinbadCharacterController
{
private:
// all the animations our character has, and a null ID
// some of these affect separate body parts and will be blended together
enumAnimID
{
ANIM_IDLE_BASE,
ANIM_IDLE_TOP,
ANIM_RUN_BASE,
ANIM_RUN_TOP,
ANIM_HANDS_CLOSED,
ANIM_HANDS_RELAXED,
ANIM_DRAW_SWORDS,
ANIM_SLICE_VERTICAL,
ANIM_SLICE_HORIZONTAL,
ANIM_DANCE,
ANIM_JUMP_START,
ANIM_JUMP_LOOP,
ANIM_JUMP_END,
ANIM_NONE
};
public:
SinbadCharacterController(Camera* cam)
{
setupBody(cam->getSceneManager());
setupCamera(cam);
setupAnimations();
}
void addTime(Real deltaTime)
{
updateBody(deltaTime);
updateAnimations(deltaTime);
updateCamera(deltaTime);
}
void injectKeyDown(const OIS::KeyEvent& evt)
{
if(evt.key == OIS::KC_Q &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// take swords out (or put them back, since it's the same animation but reversed)
setTopAnimation(ANIM_DRAW_SWORDS,true);
mTimer =0;
}
elseif(evt.key == OIS::KC_E &&!mSwordsDrawn)
{
if(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP)
{
// start dancing
setBaseAnimation(ANIM_DANCE,true);
setTopAnimation(ANIM_NONE);
// disable hand animation because the dance controls hands
mAnims[ANIM_HANDS_RELAXED]->setEnabled(false);
}
elseif(mBaseAnimID == ANIM_DANCE)
{
// stop dancing
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
// re-enable hand animation
mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
}
}
// keep track of the player's intended direction
elseif(evt.key == OIS::KC_W) mKeyDirection.z =-1;
elseif(evt.key == OIS::KC_A) mKeyDirection.x =-1;
elseif(evt.key == OIS::KC_S) mKeyDirection.z =1;
elseif(evt.key == OIS::KC_D) mKeyDirection.x =1;
elseif(evt.key == OIS::KC_SPACE &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// jump if on ground
setBaseAnimation(ANIM_JUMP_START,true);
setTopAnimation(ANIM_NONE);
mTimer =0;
}
if(!mKeyDirection.isZeroLength()&& mBaseAnimID == ANIM_IDLE_BASE)
{
// start running if not already moving and the player wants to move
setBaseAnimation(ANIM_RUN_BASE,true);
if(mTopAnimID == ANIM_IDLE_TOP) setTopAnimation(ANIM_RUN_TOP,true);
}
}
void injectKeyUp(const OIS::KeyEvent& evt)
{
// keep track of the player's intended direction
if(evt.key == OIS::KC_W && mKeyDirection.z ==-1) mKeyDirection.z =0;
elseif(evt.key == OIS::KC_A && mKeyDirection.x ==-1) mKeyDirection.x =0;
elseif(evt.key == OIS::KC_S && mKeyDirection.z ==1) mKeyDirection.z =0;
elseif(evt.key == OIS::KC_D && mKeyDirection.x ==1) mKeyDirection.x =0;
if(mKeyDirection.isZeroLength()&& mBaseAnimID == ANIM_RUN_BASE)
{
// stop running if already moving and the player doesn't want to move
setBaseAnimation(ANIM_IDLE_BASE);
if(mTopAnimID == ANIM_RUN_TOP) setTopAnimation(ANIM_IDLE_TOP);
}
}
#if (OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS) || (OGRE_PLATFORM == OGRE_PLATFORM_ANDROID)
void injectMouseMove(const OIS::MultiTouchEvent& evt)
{
// update camera goal based on mouse movement
updateCameraGoal(-0.05f* evt.state.X.rel,-0.05f* evt.state.Y.rel,-0.0005f* evt.state.Z.rel);
}
void injectMouseDown(const OIS::MultiTouchEvent& evt)
{
if(mSwordsDrawn &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// if swords are out, and character's not doing something weird, then SLICE!
setTopAnimation(ANIM_SLICE_VERTICAL,true);
mTimer =0;
}
}
#else
void injectMouseMove(const OIS::MouseEvent& evt)
{
// update camera goal based on mouse movement
updateCameraGoal(-0.05f* evt.state.X.rel,-0.05f* evt.state.Y.rel,-0.0005f* evt.state.Z.rel);
}
void injectMouseDown(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
if(mSwordsDrawn &&(mTopAnimID == ANIM_IDLE_TOP || mTopAnimID == ANIM_RUN_TOP))
{
// if swords are out, and character's not doing something weird, then SLICE!
if(id == OIS::MB_Left) setTopAnimation(ANIM_SLICE_VERTICAL,true);
elseif(id == OIS::MB_Right) setTopAnimation(ANIM_SLICE_HORIZONTAL,true);
mTimer =0;
//碰撞检测
AxisAlignedBox mSword1box = mBodyNode->_getWorldAABB();
AxisAlignedBox robotbox = node->_getWorldAABB();
if(mSword1box.intersects(robotbox))
{
//相交
//dra->setVisible(0);
node->setPosition( rand()%50,0,rand()%50);//rand() % 100,rand() % 100,0);
}
}
}
#endif
private:
void setupBody(SceneManager* sceneMgr)
{
// create main model
mBodyNode = sceneMgr->getRootSceneNode()->createChildSceneNode(Vector3::UNIT_Y * CHAR_HEIGHT);
mBodyEnt = sceneMgr->createEntity("SinbadBody","Sinbad.mesh");
mBodyNode->attachObject(mBodyEnt);
// create swords and attach to sheath
LogManager::getSingleton().logMessage("Creating swords");
mSword1 = sceneMgr->createEntity("SinbadSword1","Sword.mesh");
mSword2 = sceneMgr->createEntity("SinbadSword2","Sword.mesh");
mBodyEnt->attachObjectToBone("Sheath.L", mSword1);
mBodyEnt->attachObjectToBone("Sheath.R", mSword2);
//sceneMgr->getRootSceneNode()->attachObject(sceneMgr->createEntity("Head", "ogrehead.mesh"));
// and finally... omg it's a DRAGON!
dra = sceneMgr->createEntity("Robot","robot.mesh");
//sceneMgr->getRootSceneNode()->attachObject(dra);
node = sceneMgr->getRootSceneNode()->createChildSceneNode("RobotNode",Vector3(20,0,0));
node->attachObject(dra);
node->scale(0.1,0.1,0.1);
LogManager::getSingleton().logMessage("Creating the chains");
// create a couple of ribbon trails for the swords, just for fun
NameValuePairListparams;
params["numberOfChains"]="2";
params["maxElements"]="80";
mSwordTrail =(RibbonTrail*)sceneMgr->createMovableObject("RibbonTrail",¶ms);
mSwordTrail->setMaterialName("Examples/LightRibbonTrail");
mSwordTrail->setTrailLength(20);
mSwordTrail->setVisible(false);
sceneMgr->getRootSceneNode()->attachObject(mSwordTrail);
for(int i =0; i <2; i++)
{
mSwordTrail->setInitialColour(i,1,0.8,0);
mSwordTrail->setColourChange(i,0.75,1.25,1.25,1.25);
mSwordTrail->setWidthChange(i,1);
mSwordTrail->setInitialWidth(i,0.5);
}
mKeyDirection =Vector3::ZERO;
mVerticalVelocity =0;
}
void setupAnimations()
{
// this is very important due to the nature of the exported animations
mBodyEnt->getSkeleton()->setBlendMode(ANIMBLEND_CUMULATIVE);
String animNames[]=
{"IdleBase","IdleTop","RunBase","RunTop","HandsClosed","HandsRelaxed","DrawSwords",
"SliceVertical","SliceHorizontal","Dance","JumpStart","JumpLoop","JumpEnd"};
// populate our animation list
for(int i =0; i < NUM_ANIMS; i++)
{
mAnims[i]= mBodyEnt->getAnimationState(animNames[i]);
mAnims[i]->setLoop(true);
mFadingIn[i]=false;
mFadingOut[i]=false;
}
// start off in the idle state (top and bottom together)
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
// relax the hands since we're not holding anything
mAnims[ANIM_HANDS_RELAXED]->setEnabled(true);
mSwordsDrawn =false;
}
void setupCamera(Camera* cam)
{
// create a pivot at roughly the character's shoulder
mCameraPivot = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
// this is where the camera should be soon, and it spins around the pivot
mCameraGoal = mCameraPivot->createChildSceneNode(Vector3(0,0,15));
// this is where the camera actually is
mCameraNode = cam->getSceneManager()->getRootSceneNode()->createChildSceneNode();
mCameraNode->setPosition(mCameraPivot->getPosition()+ mCameraGoal->getPosition());
mCameraPivot->setFixedYawAxis(true);
mCameraGoal->setFixedYawAxis(true);
mCameraNode->setFixedYawAxis(true);
// our model is quite small, so reduce the clipping planes
cam->setNearClipDistance(0.1);
cam->setFarClipDistance(100);
mCameraNode->attachObject(cam);
mPivotPitch =0;
}
void updateBody(Real deltaTime)
{
mGoalDirection =Vector3::ZERO;// we will calculate this
if(mKeyDirection !=Vector3::ZERO && mBaseAnimID != ANIM_DANCE)
{
// calculate actually goal direction in world based on player's key directions
mGoalDirection += mKeyDirection.z * mCameraNode->getOrientation().zAxis();
mGoalDirection += mKeyDirection.x * mCameraNode->getOrientation().xAxis();
mGoalDirection.y =0;
mGoalDirection.normalise();
Quaternion toGoal = mBodyNode->getOrientation().zAxis().getRotationTo(mGoalDirection);
// calculate how much the character has to turn to face goal direction
Real yawToGoal = toGoal.getYaw().valueDegrees();
// this is how much the character CAN turn this frame
Real yawAtSpeed = yawToGoal /Math::Abs(yawToGoal)* deltaTime * TURN_SPEED;
// reduce "turnability" if we're in midair
if(mBaseAnimID == ANIM_JUMP_LOOP) yawAtSpeed *=0.2f;
// turn as much as we can, but not more than we need to
if(yawToGoal <0) yawToGoal = std::min<Real>(0, std::max<Real>(yawToGoal, yawAtSpeed));//yawToGoal = Math::Clamp<Real>(yawToGoal, yawAtSpeed, 0);
elseif(yawToGoal >0) yawToGoal = std::max<Real>(0, std::min<Real>(yawToGoal, yawAtSpeed));//yawToGoal = Math::Clamp<Real>(yawToGoal, 0, yawAtSpeed);
mBodyNode->yaw(Degree(yawToGoal));
// move in current body direction (not the goal direction)
mBodyNode->translate(0,0, deltaTime * RUN_SPEED * mAnims[mBaseAnimID]->getWeight(),
Node::TS_LOCAL);
}
if(mBaseAnimID == ANIM_JUMP_LOOP)
{
// if we're jumping, add a vertical offset too, and apply gravity
mBodyNode->translate(0, mVerticalVelocity * deltaTime,0,Node::TS_LOCAL);
mVerticalVelocity -= GRAVITY * deltaTime;
Vector3 pos = mBodyNode->getPosition();
if(pos.y <= CHAR_HEIGHT)
{
// if we've hit the ground, change to landing state
pos.y = CHAR_HEIGHT;
mBodyNode->setPosition(pos);
setBaseAnimation(ANIM_JUMP_END,true);
mTimer =0;
}
}
}
void updateAnimations(Real deltaTime)
{
Real baseAnimSpeed =1;
Real topAnimSpeed =1;
mTimer += deltaTime;
if(mTopAnimID == ANIM_DRAW_SWORDS)
{
// flip the draw swords animation if we need to put it back
topAnimSpeed = mSwordsDrawn ?-1:1;
// half-way through the animation is when the hand grasps the handles...
if(mTimer >= mAnims[mTopAnimID]->getLength()/2&&
mTimer - deltaTime < mAnims[mTopAnimID]->getLength()/2)
{
// so transfer the swords from the sheaths to the hands
mBodyEnt->detachAllObjectsFromBone();
mBodyEnt->attachObjectToBone(mSwordsDrawn ?"Sheath.L":"Handle.L", mSword1);
mBodyEnt->attachObjectToBone(mSwordsDrawn ?"Sheath.R":"Handle.R", mSword2);
// change the hand state to grab or let go
mAnims[ANIM_HANDS_CLOSED]->setEnabled(!mSwordsDrawn);
mAnims[ANIM_HANDS_RELAXED]->setEnabled(mSwordsDrawn);
// toggle sword trails
if(mSwordsDrawn)
{
mSwordTrail->setVisible(false);
mSwordTrail->removeNode(mSword1->getParentNode());
mSwordTrail->removeNode(mSword2->getParentNode());
}
else
{
mSwordTrail->setVisible(true);
mSwordTrail->addNode(mSword1->getParentNode());
mSwordTrail->addNode(mSword2->getParentNode());
}
}
if(mTimer >= mAnims[mTopAnimID]->getLength())
{
// animation is finished, so return to what we were doing before
if(mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
else
{
setTopAnimation(ANIM_RUN_TOP);
mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
}
mSwordsDrawn =!mSwordsDrawn;
}
}
elseif(mTopAnimID == ANIM_SLICE_VERTICAL || mTopAnimID == ANIM_SLICE_HORIZONTAL)
{
if(mTimer >= mAnims[mTopAnimID]->getLength())
{
// animation is finished, so return to what we were doing before
if(mBaseAnimID == ANIM_IDLE_BASE) setTopAnimation(ANIM_IDLE_TOP);
else
{
setTopAnimation(ANIM_RUN_TOP);
mAnims[ANIM_RUN_TOP]->setTimePosition(mAnims[ANIM_RUN_BASE]->getTimePosition());
}
}
// don't sway hips from side to side when slicing. that's just embarrassing.
if(mBaseAnimID == ANIM_IDLE_BASE) baseAnimSpeed =0;
}
elseif(mBaseAnimID == ANIM_JUMP_START)
{
if(mTimer >= mAnims[mBaseAnimID]->getLength())
{
// takeoff animation finished, so time to leave the ground!
setBaseAnimation(ANIM_JUMP_LOOP,true);
// apply a jump acceleration to the character
mVerticalVelocity = JUMP_ACCEL;
}
}
elseif(mBaseAnimID == ANIM_JUMP_END)
{
if(mTimer >= mAnims[mBaseAnimID]->getLength())
{
// safely landed, so go back to running or idling
if(mKeyDirection ==Vector3::ZERO)
{
setBaseAnimation(ANIM_IDLE_BASE);
setTopAnimation(ANIM_IDLE_TOP);
}
else
{
setBaseAnimation(ANIM_RUN_BASE,true);
setTopAnimation(ANIM_RUN_TOP,true);
}
}
}
// increment the current base and top animation times
if(mBaseAnimID != ANIM_NONE) mAnims[mBaseAnimID]->addTime(deltaTime * baseAnimSpeed);
if(mTopAnimID != ANIM_NONE) mAnims[mTopAnimID]->addTime(deltaTime * topAnimSpeed);
// apply smooth transitioning between our animations
fadeAnimations(deltaTime);
}
void fadeAnimations(Real deltaTime)
{
for(int i =0; i < NUM_ANIMS; i++)
{
if(mFadingIn[i])
{
// slowly fade this animation in until it has full weight
Real newWeight = mAnims[i]->getWeight()+ deltaTime * ANIM_FADE_SPEED;
mAnims[i]->setWeight(Math::Clamp<Real>(newWeight,0,1));
if(newWeight >=1) mFadingIn[i]=false;
}
elseif(mFadingOut[i])
{
// slowly fade this animation out until it has no weight, and then disable it
Real newWeight = mAnims[i]->getWeight()- deltaTime * ANIM_FADE_SPEED;
mAnims[i]->setWeight(Math::Clamp<Real>(newWeight,0,1));
if(newWeight <=0)
{
mAnims[i]->setEnabled(false);
mFadingOut[i]=false;
}
}
}
}
void updateCamera(Real deltaTime)
{
// place the camera pivot roughly at the character's shoulder
mCameraPivot->setPosition(mBodyNode->getPosition()+Vector3::UNIT_Y * CAM_HEIGHT);
// move the camera smoothly to the goal
Vector3 goalOffset = mCameraGoal->_getDerivedPosition()- mCameraNode->getPosition();
mCameraNode->translate(goalOffset * deltaTime *9.0f);
// always look at the pivot
mCameraNode->lookAt(mCameraPivot->_getDerivedPosition(),Node::TS_WORLD);
}
void updateCameraGoal(Real deltaYaw,Real deltaPitch,Real deltaZoom)
{
mCameraPivot->yaw(Degree(deltaYaw),Node::TS_WORLD);
// bound the pitch
if(!(mPivotPitch + deltaPitch >25&& deltaPitch >0)&&
!(mPivotPitch + deltaPitch <-60&& deltaPitch <0))
{
mCameraPivot->pitch(Degree(deltaPitch),Node::TS_LOCAL);
mPivotPitch += deltaPitch;
}
Real dist = mCameraGoal->_getDerivedPosition().distance(mCameraPivot->_getDerivedPosition());
Real distChange = deltaZoom * dist;
// bound the zoom
if(!(dist + distChange <8&& distChange <0)&&
!(dist + distChange >25&& distChange >0))
{
mCameraGoal->translate(0,0, distChange,Node::TS_LOCAL);
}
}
void setBaseAnimation(AnimID id,bool reset =false)
{
if(mBaseAnimID >=0&& mBaseAnimID < NUM_ANIMS)
{
// if we have an old animation, fade it out
mFadingIn[mBaseAnimID]=false;
mFadingOut[mBaseAnimID]=true;
}
mBaseAnimID = id;
if(id != ANIM_NONE)
{
// if we have a new animation, enable it and fade it in
mAnims[id]->setEnabled(true);
mAnims[id]->setWeight(0);
mFadingOut[id]=false;
mFadingIn[id]=true;
if(reset) mAnims[id]->setTimePosition(0);
}
}
void setTopAnimation(AnimID id,bool reset =false)
{
if(mTopAnimID >=0&& mTopAnimID < NUM_ANIMS)
{
// if we have an old animation, fade it out
mFadingIn[mTopAnimID]=false;
mFadingOut[mTopAnimID]=true;
}
mTopAnimID = id;
if(id != ANIM_NONE)
{
// if we have a new animation, enable it and fade it in
mAnims[id]->setEnabled(true);
mAnims[id]->setWeight(0);
mFadingOut[id]=false;
mFadingIn[id]=true;
if(reset) mAnims[id]->setTimePosition(0);
}
}
SceneNode* mBodyNode;
SceneNode*node;
SceneNode* mCameraPivot;
SceneNode* mCameraGoal;
SceneNode* mCameraNode;
Real mPivotPitch;
Entity* mBodyEnt;
Entity* mSword1;
Entity* mSword2;
Entity* dra;
RibbonTrail* mSwordTrail;
AnimationState* mAnims[NUM_ANIMS];// master animation list
AnimID mBaseAnimID;// current base (full- or lower-body) animation
AnimID mTopAnimID;// current top (upper-body) animation
bool mFadingIn[NUM_ANIMS];// which animations are fading in
bool mFadingOut[NUM_ANIMS];// which animations are fading out
bool mSwordsDrawn;
Vector3 mKeyDirection;// player's local intended direction based on WASD keys
Vector3 mGoalDirection;// actual intended direction in world-space
Real mVerticalVelocity;// for jumping
Real mTimer;// general timer to see how long animations have been playing
};
#endif
CharacterSample.cpp
#include"SamplePlugin.h"
#include"CharacterSample.h"
usingnamespaceOgre;
usingnamespaceOgreBites;
#ifndef OGRE_STATIC_LIB
SamplePlugin* sp;
Sample* s;
Sample* e;
//Sample* s1;
extern"C"_OgreSampleExportvoid dllStartPlugin()
{
s =newSample_Character;
//s1 = new Sample_Character;
//e = new Sample_SkeletalAnimation;
sp = OGRE_NEW SamplePlugin(s->getInfo()["Title"]+" Sample");
sp->addSample(s);
//sp->addSample(s1);
//sp->addSample(e);
Root::getSingleton().installPlugin(sp);
}
extern"C"_OgreSampleExportvoid dllStopPlugin()
{
Root::getSingleton().uninstallPlugin(sp);
OGRE_DELETE sp;
delete s;
//delete s1;
//delete e;
}
#endif
参考资料:
中文OGRE参考网站
OGRE官方文档(英文)
OGRE3D游戏开发框架指南(中文电子书)
[PR]Apress.Pro.OGRE.3D.Programming(英文电子书)