CSceneNodeAnimatorCameraRTS

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
monkeycracks
Posts: 1029
Joined: Thu Apr 06, 2006 12:45 am
Location: Tennesee, USA
Contact:

CSceneNodeAnimatorCameraRTS

Post by monkeycracks »

.h

Code: Select all

#pragma once

#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace gui;
using namespace io;

class CSceneNodeAnimatorCameraRTS : public ISceneNodeAnimator
{
public:
	CSceneNodeAnimatorCameraRTS(f32 pMoveSpeed = 5.0f, bool pEnableKeys = true, ICursorControl* pCursorControl = NULL, rect<s32> pMouseRect = rect<s32>(50, 50, 1024-50, 768-50));
	~CSceneNodeAnimatorCameraRTS();

	virtual bool hasFinished(void) const;
	virtual bool isEventReceiverEnabled() const;
	virtual bool OnEvent(const SEvent& event);

	virtual ESCENE_NODE_ANIMATOR_TYPE getType() const;

	virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0);

	virtual void animateNode(ISceneNode* node, u32 timeMs);

private:
	bool mFirstRun;
	bool mKeysEnabled;
	bool mKeys[KEY_KEY_CODES_COUNT];

	f32 mMoveSpeed;

	unsigned int mLastAnimationTime;

	ICursorControl* mCursorControl;

	rect<s32> mMouseRect;
};  
.cpp

Code: Select all

#include "CSceneNodeAnimatorCameraRTS.h"

CSceneNodeAnimatorCameraRTS::CSceneNodeAnimatorCameraRTS(f32 pMoveSpeed, bool pEnableKeys, ICursorControl* pCursorControl, rect<s32> pMouseRect) : mFirstRun(true), mKeysEnabled(pEnableKeys), mMoveSpeed(pMoveSpeed), mCursorControl(pCursorControl), mMouseRect(pMouseRect)
{
	for(int i = 0; i < KEY_KEY_CODES_COUNT; ++i)
		mKeys[i] = false;

	if(mCursorControl)
		mCursorControl->grab();
}

CSceneNodeAnimatorCameraRTS::~CSceneNodeAnimatorCameraRTS()
{
	if(mCursorControl)
		mCursorControl->drop();
}

bool CSceneNodeAnimatorCameraRTS::hasFinished(void) const
{
	return false;
}

bool CSceneNodeAnimatorCameraRTS::isEventReceiverEnabled() const
{
	return true;
}

bool CSceneNodeAnimatorCameraRTS::OnEvent(const SEvent& event)
{
	if(event.EventType == EET_KEY_INPUT_EVENT)
	{
		mKeys[event.KeyInput.Key] = event.KeyInput.PressedDown;
		return true;
	}

	return false;
}

ESCENE_NODE_ANIMATOR_TYPE CSceneNodeAnimatorCameraRTS::getType() const
{
	return ESNAT_UNKNOWN;
}

ISceneNodeAnimator* CSceneNodeAnimatorCameraRTS::createClone(ISceneNode* node, ISceneManager* newManager)
{
	return new CSceneNodeAnimatorCameraRTS();
}

void CSceneNodeAnimatorCameraRTS::animateNode(ISceneNode* node, u32 timeMs)
{
	if (!node || node->getType() != ESNT_CAMERA)
		return;

	if(mFirstRun)
	{
		mLastAnimationTime = timeMs;
		mFirstRun = false;
	}
	f32 timeDiff = (f32) (timeMs - mLastAnimationTime);
	mLastAnimationTime = timeMs;

	ICameraSceneNode* Camera = static_cast<ICameraSceneNode*>(node);
	vector3df pos = Camera->getPosition();
	
	vector2di curspos = mCursorControl?mCursorControl->getPosition():vector2di(0, 0);
	dimension2du screensize = Camera->getSceneManager()->getVideoDriver()->getScreenSize();

	if((mKeysEnabled && mKeys[KEY_KEY_W]) || (mCursorControl && mMouseRect.UpperLeftCorner.Y > curspos.Y))
		pos.Z+=mMoveSpeed*timeDiff; 

	if((mKeysEnabled && mKeys[KEY_KEY_S]) || (mCursorControl && mMouseRect.LowerRightCorner.Y < curspos.Y))
		pos.Z-=mMoveSpeed*timeDiff;

	if((mKeysEnabled && mKeys[KEY_KEY_A]) || (mCursorControl && mMouseRect.UpperLeftCorner.X > curspos.X))
		pos.X-=mMoveSpeed*timeDiff;

	if((mKeysEnabled && mKeys[KEY_KEY_D]) || (mCursorControl && mMouseRect.LowerRightCorner.X < curspos.X))
		pos.X+=mMoveSpeed*timeDiff;

	node->setPosition(pos);
	Camera->setTarget(vector3df(pos.X, pos.Y-2, pos.Z+2)); 
}
usage

Code: Select all

ISceneNodeAnimator* anim = new CSceneNodeAnimatorCameraRTS();
ICameraSceneNode* Camera = SceneMgr->addCameraSceneNode();
	Camera->setFarValue(10000.0f);
	Camera->setPosition(vector3df(100, 1600, 100));
	Camera->addAnimator(anim);
	anim->drop();
usage with mouse control

Code: Select all

ISceneNodeAnimator* anim = new CSceneNodeAnimatorCameraRTS(5, false, Device->getCursorControl(), rect<s32>(25, 25, SCREENX-25, SCREENY-25));
	Camera = SceneMgr->addCameraSceneNode();
	Camera->setFarValue(10000.0f);
	Camera->setPosition(vector3df(100, 2500, 100));
	Camera->addAnimator(anim);
	anim->drop();
It's simple, but I'll keep adding to it as I need more done.

Todo:
Rotation and zoom

Constructive criticism/feedback appreciated :D
Last edited by monkeycracks on Sat Jan 02, 2010 11:13 am, edited 1 time in total.
Nox
Posts: 304
Joined: Wed Jan 14, 2009 6:23 pm

Post by Nox »

It would be nice if the rect where the sliding by mouse could be defined by the programmer and i guess "createClone" should create a copy of the camera with the same parameters. Not just a new camera without parameters. This way it might be possible that your camera is beeing copied and loose control but im not really sure about that.
Another little thing: is it useful to disable the mouse and giving mousecontrol? Or is it useful to enable the mouse but set the mousecontrol to zero? I guess not so bool pEnableMouse seems to be redundant to me.
By the way i guess i would shrink your AnimateNode code to:

Code: Select all

void CSceneNodeAnimatorCameraRTS::animateNode(ISceneNode* node, u32 timeMs) 
{ 
   if (!node || node->getType() != ESNT_CAMERA) 
      return; 

   if(mFirstRun) 
   { 
      mLastAnimationTime	= timeMs; 
      mFirstRun				= false;
   } 
   mLastAnimationTime = timeMs; 

   ICameraSceneNode* Camera   = static_cast<ICameraSceneNode*>(node); 
   f32 timeDiff               = (f32) (timeMs - mLastAnimationTime); 
   vector3df pos              = Camera->getPosition(); 
   vector2di curspos          = (mCursorControl ? mCursorControl->getPosition() : vector2di(0)); 

   if(mKeys[KEY_KEY_W] || (mCursorControl && slide_rect.UpperLeftCorner.Y < curspos.Y))
      pos.Z += mMoveSpeed*timeDiff; 

   if(mKeys[KEY_KEY_S] || (mCursorControl && slide_rect.LowerRightCorner.Y > curspos.Y))
      pos.Z -= mMoveSpeed*timeDiff; 

   if(mKeys[KEY_KEY_A] || (mCursorControl && slide_rect.UpperLeftCorner.X < curspos.X))
      pos.X -= mMoveSpeed*timeDiff; 

   if(mKeys[KEY_KEY_D] || (mCursorControl && slide_rect.LowerRightCorner.X > curspos.X))
      pos.X += mMoveSpeed*timeDiff; 

   node->setPosition(pos); 
   Camera->setTarget(vector3df(pos.X, pos.Y - 2, pos.Z + 2)); 
}
this is just a guess not a "must have". A lookat vector and flexible keybinding would be nice features.

But your code is a really nice example of using the ISceneNodeAnimator system :) .
monkeycracks
Posts: 1029
Joined: Thu Apr 06, 2006 12:45 am
Location: Tennesee, USA
Contact:

Post by monkeycracks »

Thanks for the pointers. I've gotta stop writing code when I've been up for so long :P

Fixes posted.
Post Reply