Character control and animation transition sample

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Character control and animation transition sample

Post by doqkhanh »

Hi there, this is my class with some hard code to demo new animation feature in Irrlicht 1.4 called: Animation Transitions

http://www.irrlicht3d.org/wiki/index.ph ... tionSystem
How To Use The New Animation System

This tutorial will show you how to use the new animation system in Irrlicht 1.4

Note: this only applies with bone based formats (eg b3d, ms3d, x)
Transitions

Transitions are for blending from one animation into another. eg when a characters stops running, instead of just jumping to an idle animation, if you use a transition it will blend the animations together and make it look natural.

To use it, call:

Node->setTransitionTime( TimeOfBlendInSeconds );

Joint control will automatically be enabled (the blending needs it), so you must also call:

Node->animateJoints();

Before the drawAll
We have 2 files here, named CCharacter.h and CCharacter.cpp, I have been using ninja free model at:

Code: Select all

http://www.psionic3d.co.uk/downloads/ninja.zip
To use these classes:
1. Create a new instance in your main

Code: Select all

	//Main character
	CCharacter* viethero;
2. Init new character

Code: Select all

	//Setup viethero character
	viethero = new CCharacter(game->getDevice(),game->getSceneManager(),game->getVideoDriver(),"Media\\Model\\Ninja\\ninja.b3d");

	viethero->setPosition(irr::core::vector3df(1275.0f, 60.0f, 2675.0f));

3. In render loop, try to call

Code: Select all

	//Control main character
	viethero->move(targetPoint);
4. On any event, such as mouse click on terrain try to set

Code: Select all

targetPoint = collisionPoint;
viethero->walk();
Happy Irrlicht Coding !

Code: Select all

/*
 ***********************************************
 * Character control
 * *********************************************
 * file name: CCharacter.h
 * encoding: UTF-8
 * tab size: 8
 * indentation: 4
 * created on: 8:55 PM 3/17/2008
 * init by: Do Quoc Khanh - doqkhanh
 * created by: FOSP Team
 * copyright: FOS Project
 */

#pragma once
#include <irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

class CCharacter : public irr::scene::IAnimationEndCallBack 
{
private:
	float fSpeed;
	scene::IAnimatedMeshSceneNode* node;


public:
	enum eAttacktype{
		MagicAttack,
		PowerAttack,
		DownswipeAttack
	};

	enum eState{
		Run,
		Walk, 
		Attack,
		Idle
	};	
	
	eAttacktype curAttackType;
	eState curState;
	eState oldState;

public:
	CCharacter(IrrlichtDevice* device, irr::scene::ISceneManager *smgr,irr::video::IVideoDriver *videodriver, char* meshPath);
	~CCharacter(void);
	
	void setState(eState newState);
	void setPosition(core::vector3df pos);
	void setRotate(core::vector3df rot);
	
	core::vector3df getPosition();
	core::vector3df getRotate();
	eState getState();
	irr::scene::IAnimatedMeshSceneNode* getMesh();
	irr::scene::IAnimatedMeshSceneNode* getNode();

	void run();
	void walk();
	void attack(eAttacktype);
	void idle();

	void move(core::vector3df pos);
	void update();

	void remove();

	void OnAnimationEnd(IAnimatedMeshSceneNode* node);
};

Code: Select all

/*
 ***********************************************
 * Character control
 * *********************************************
 * file name: CCharacter.h
 * encoding: UTF-8
 * tab size: 8
 * indentation: 4
 * created on: 9:03 PM 3/17/2008
 * init by: Do Quoc Khanh - doqkhanh
 * created by: FOSP Team
 * copyright: FOS Project
 */
#include "CCharacter.h"

#include <irrlicht.h>
#define ANIMATION_SPEED 5
irr::scene::IAnimatedMeshSceneNode* CCharacter::getMesh()
{
	return node;
}

CCharacter::CCharacter(IrrlichtDevice* device, irr::scene::ISceneManager *smgr,irr::video::IVideoDriver *videodriver, char* meshPath)
{
	node = smgr->addAnimatedMeshSceneNode(smgr->getMesh(meshPath));
	node->setMaterialFlag(video::EMF_LIGHTING, false);

	fSpeed = 0.4f;

	curState = CCharacter::eState::Idle;
	oldState = CCharacter::eState::Idle;

	curAttackType = CCharacter::eAttacktype::MagicAttack;

	node->setJointMode(irr::scene::EJUOR_CONTROL);
	node->setTransitionTime(0.5);
	
	idle();
}

CCharacter::~CCharacter(void)
{
	node->remove();
}

void CCharacter::setState(eState newState)
{
	oldState = curState;
	curState = newState;
}

void CCharacter::setPosition(core::vector3df pos)
{
	node->setPosition(pos);
}

void CCharacter::setRotate(core::vector3df rot)
{
	node->setRotation(rot);
}

	
core::vector3df CCharacter::getPosition()
{
	return node->getPosition();
}

core::vector3df CCharacter::getRotate()
{
	return node->getRotation();
}

CCharacter::eState CCharacter::getState()
{
	return curState;
}


void CCharacter::run()
{
	setState(CCharacter::eState::Run);
	
	node->setAnimationSpeed(ANIMATION_SPEED);
	node->setLoopMode(true);
	node->setFrameLoop(1,14);
}

void CCharacter::walk()
{
	setState(CCharacter::eState::Walk);
	
	node->setAnimationSpeed(ANIMATION_SPEED);
	node->setLoopMode(true);
	node->setFrameLoop(1,14);
}

void CCharacter::idle()
{
	setState(CCharacter::eState::Idle);
	
	node->setAnimationSpeed(ANIMATION_SPEED);
	node->setLoopMode(true);
	node->setFrameLoop(206,300);
}


void CCharacter::attack(eAttacktype attackType)
{
	setState(CCharacter::eState::Attack);
	switch (attackType)
	{
		case eAttacktype::PowerAttack :
		{	
			node->setAnimationSpeed(ANIMATION_SPEED);
			node->setLoopMode(false);
			node->setFrameLoop(45,59);
			node->setAnimationEndCallback(this);
			return;
		} 	

		case eAttacktype::DownswipeAttack:
		{	
			node->setAnimationSpeed(ANIMATION_SPEED);
			node->setLoopMode(false);
			node->setFrameLoop(60,68);
			node->setAnimationEndCallback(this);
			return;
		} 

		case eAttacktype::MagicAttack:
		{	
			node->setAnimationSpeed(ANIMATION_SPEED);
			node->setLoopMode(false);
			node->setFrameLoop(69,72);
			node->setAnimationEndCallback(this);
			return;
		} 

	}

}


core::vector3df faceTarget(irr::core::vector3df targetpos, irr::core::vector3df nodepos) {

  core::vector3df posDiff = targetpos - nodepos;
  f32 degree = nodepos.Y; //keep current rotation if nothing to do
  posDiff.normalize();

  if (posDiff.X != 0.0f || posDiff.Z != 0.0f)
    degree = atan2(posDiff.X,posDiff.Z) * core::RADTODEG;

  return core::vector3df(0,degree,0);
} 


void moveto(irr::scene::ISceneNode *node, //node to move
            irr::core::vector3df vel) //velocity vector
{
    irr::core::matrix4 m;
    m.setRotationDegrees(node->getRotation());
    m.transformVect(vel);
    node->setPosition(node->getPosition() + vel);
    node->updateAbsolutePosition();
} 

void CCharacter::move(core::vector3df pos)
{
	// Avoid complex operation in next step
	if(getState() != CCharacter::eState::Walk && getState() != CCharacter::eState::Run)
		return;

	if (node->getPosition().getDistanceFrom(pos) < 4)
	{
		idle();
	}
	else
	{
		node->setRotation(	faceTarget(pos, node->getPosition()) );
		moveto(node, core::vector3df(0,0,fSpeed));
	}

	this->node->animateJoints() ;
}

void CCharacter::update()
{
	//Do nothing
}

void CCharacter::OnAnimationEnd(IAnimatedMeshSceneNode* node)
{
    idle();
} 

void CCharacter::remove()
{
	node->remove();
}

irr::scene::IAnimatedMeshSceneNode* CCharacter::getNode()
{
	return node;	
}
Last edited by doqkhanh on Thu Jun 12, 2008 1:00 pm, edited 1 time in total.
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

Nice work! :)
There's something is fantastic, there's nothing is absolute.
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

A compiled example, and possibly some screenshots, would definitely be cool and probably bump up the interest.
TheQuestion = 2B || !2B
huydotnet
Posts: 81
Joined: Tue Sep 25, 2007 12:26 pm
Location: Danang, Vietnam

Post by huydotnet »

http://fosengine.googlecode.com/files/D ... %20May.rar
here is the binary, move the ninja with right mouse button
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Post by doqkhanh »

And please notice the difference in:
http://code.google.com/p/fosengine/source/detail?r=113

I fixed a error with animation in idle status.
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

I've tried it . Here is my screneshot, and little demo.Thanks doqkhanh ! This is very userful in my project.
screenshot :
Image
Demo :
http://www.4shared.com/file/49373783/32 ... onWin.html
There's something is fantastic, there's nothing is absolute.
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

this is cool. an animation clip based character controller.

i haven't implemented the code yet, from the looks of it the class can definitely fit into the fight (taekwondo sparring) match currently under development.
Image
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

Hi doqkhanh, quick question.

Will this code work with the camera?

I will be setting up a test code for a cut-scene, in there I will need to control characters and camera.

I'm looking for a sample b3d file having character and camera animation. Let me know if you have done this kind of test or think it is possible to implement.

Thank you.
Image
doqkhanh
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan
Contact:

Post by doqkhanh »

Hi, my class just control the Ninja character only.
You can get Ninja position and rotation to control your camera.
dlangdev wrote:Hi doqkhanh, quick question.

Will this code work with the camera?

I will be setting up a test code for a cut-scene, in there I will need to control characters and camera.

I'm looking for a sample b3d file having character and camera animation. Let me know if you have done this kind of test or think it is possible to implement.

Thank you.
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

It looks like it can be done if the code is modified to fit the cut-scene, though.

thanks, I have an idea now how to approach this problem.
Image
wuallen
Posts: 67
Joined: Thu Jan 25, 2007 3:07 am
Location: Shanghai

Post by wuallen »

incredible, I LOVE LOVE this blending.
pera
Posts: 460
Joined: Wed May 14, 2008 1:05 pm
Location: Novi Sad, Serbia
Contact:

Post by pera »

Im using this code it is just what I need - and it is great implementation.
Really perfect. Thanks for sharing! (Ill put your link in comment header)

One thing though, I had to move this line
this->node->animateJoints();
before return from function to animate idle state.

You return from move() function if state is other then walk/run, and idle state was just frozen ninja.

EDIT: Ahh I see you changed that! That would have saved my time! Maybe you should edit first post and add changes to the given code?
theOneAwaited
Posts: 12
Joined: Fri Aug 14, 2009 10:03 am
Location: Netherlands

Post by theOneAwaited »

I love your character animation sample and it really helped me learn alot about how the engine works. Thanks for posting it!

I am new to Irrlicht and I know the character animation sample you posted is rather old, but I was wondering:

why does the character not walk level with the ground?

I know this sample isn't supposed to address that issue, but I was wondering if you could help me figure out how to adjust the character's Y position so he is level with the ground when walking.

I tried terrain->getPosition(characterpos.X, characterPos.Z) to get the Y, but when I pass that to the character, he doesn't move forward anymore like he is still collidiing with the terrain.

Thanks in advance!
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

Here my code ( in device->run() loop):
//Control main character
viethero->move(targetPoint);
viethero->setPosition(vector3df(viethero->getPosition().X,
terrain->getHeight(viethero->getPosition().X,viethero->getPosition().Z)
,viethero->getPosition().Z));
//
There's something is fantastic, there's nothing is absolute.
trivtn
Posts: 132
Joined: Tue Jan 17, 2006 12:30 pm
Location: Viet Nam
Contact:

Post by trivtn »

There's something is fantastic, there's nothing is absolute.
Post Reply