Topic: Smoothly move the M3Object3d with custom behavior
In my maratis project I have invisible Target object, and Camera, which has Follow Target behavior and Looks At target behavior.
I want to move target from my C++ code, thus force Camera follows this object.
I want to achieve effect of smooth moving the camera.
I create custom MoveTo behavior. Objects are initialized with new position , and the time during which they have to move. (If you familiar with cocos2d actions - I want to realize analogue of CCMoveTo for maratis).
I add behavior to my target object:
target = scene->getObjectByName("Target");
float animationDuration = 1.5;
MoveToBehaviour *moveToBeh = new MoveToBehaviour(target, categoryTargetPosition, animationDuration);
target->addBehavior( moveToBeh );
// delete behavior after delay
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, animationDuration*1.1 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
target->deleteBehavior(0);
});
When this code executed, the camera instantly move to new position, without smooth movement.
What I'm doing wrong?
How to do this correctly?
Does MBehavior::update() is called periodically by engine , or should I manually call MBehavior::update() on every frame?
Code of MoveTo behavior class:
#ifndef _MB_MOVETO_H
#define _MB_MOVETO_H
#include <sys/time.h>
class MoveToBehaviour : public MBehavior
{
public:
// constructors / destructors
MoveToBehaviour(MObject3d * parentObject, MVector3 _pos, float _tm);
MoveToBehaviour(MoveToBehaviour & behavior, MObject3d * parentObject);
~MoveToBehaviour(void);
private:
float tm, elapsedTime;
MVector3 pos;
MVector3 initialPos;
struct timeval lastCallTime;
// M
public:
// destroy
void destroy(void);
// get new
static MBehavior * getNew(MObject3d * parentObject);
// get copy
MBehavior * getCopy(MObject3d * parentObject);
// name
static const char * getStaticName(void){ return "MoveTo"; }
const char * getName(void){ return getStaticName(); }
// events
void update(void);
void runEvent(int param){}
// variables
unsigned int getVariablesNumber(void);
MVariable getVariable(unsigned int id);
};
#endif
.cpp:
#include <MEngine.h>
#include "MoveToBehaviour.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Init
/////////////////////////////////////////////////////////////////////////////////////////////////////////
MoveToBehaviour::MoveToBehaviour(MObject3d * parentObject, MVector3 _pos, float _tm) :
MBehavior(parentObject),
tm (_tm),
pos (_pos),
elapsedTime (0.0)
{
gettimeofday(&lastCallTime, NULL);
initialPos = MVector3();
if (parentObject) {
initialPos = parentObject->getPosition();
}
}
MoveToBehaviour::MoveToBehaviour(MoveToBehaviour & behavior, MObject3d * parentObject) :
MBehavior(parentObject),
tm (behavior.tm),
pos (behavior.pos),
elapsedTime (behavior.elapsedTime),
lastCallTime(behavior.lastCallTime),
initialPos (behavior.initialPos)
{}
MoveToBehaviour::~MoveToBehaviour(void) {}
void MoveToBehaviour::destroy(void)
{
delete this;
}
MBehavior * MoveToBehaviour::getNew(MObject3d * parentObject)
{
return new MoveToBehaviour(parentObject, MVector3() , 0.0 );
}
MBehavior * MoveToBehaviour::getCopy(MObject3d * parentObject)
{
return new MoveToBehaviour(*this, parentObject);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Variables
/////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned int MoveToBehaviour::getVariablesNumber(void){
return 2;
}
MVariable MoveToBehaviour::getVariable(unsigned int id)
{
switch(id)
{
default:
return MVariable("NULL", NULL, M_VARIABLE_NULL);
case 0:
return MVariable("time", &tm, M_VARIABLE_FLOAT);
case 1:
return MVariable("moveToPosition", &pos, M_VARIABLE_VEC3);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void MoveToBehaviour::update(void)
{
if (elapsedTime >= tm*1000.0) {
return;
}
MEngine * engine = MEngine::getInstance();
MGame * game = engine->getGame();
MLevel * level = engine->getLevel();
MScene * scene = level->getCurrentScene();
MObject3d * parent = getParentObject();
long lastMillis = lastCallTime.tv_sec * 1000 + lastCallTime.tv_usec / 1000;
struct timeval tv ;
gettimeofday(&tv, NULL);
long millis = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
long dt = millis - lastMillis;
lastCallTime = tv;
MVector3 dpos = (pos - initialPos) * ( ((float)dt) / (tm*1000.0) );
MVector3 newPosition = parent->getPosition() + dpos;
parent->setPosition( newPosition );
parent->updateMatrix();
elapsedTime += dt;
if (elapsedTime >= tm*1000.0) {
parent->setPosition( pos );
parent->updateMatrix();
}
}
Last edited by Petr (2012-09-07 09:11:50)