Triggering animation loop

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Boris
Posts: 14
Joined: Sun Oct 17, 2004 6:58 pm

Triggering animation loop

Post by Boris »

I am trying to change animation loop depending on keypress.
Here is keypress code:

Code: Select all

	if(controls & C_UP)
	{
		start=true;
		moving = controls & C_UP ? MOVESPEED : -MOVESPEED;

		if(controls & C_LEFT + C_RIGHT) {
		p1_rotate += controls & C_RIGHT ? ROTSPEED : (360.0f-ROTSPEED);
		if(p1_rotate>=360.0f)
			p1_rotate -= 360.0f;
		p1->setRotation(core::vector3df(0,p1_rotate,0));
	}
	}
	else
		start=false;

So, start variable is used to triger animation loop in main section:

Code: Select all

	mesh = smgr->getMesh("sydney.md2");
	p1 = smgr->addAnimatedMeshSceneNode(mesh);
	p1->setPosition(core::vector3df(0,0,0));
	scene::ISceneNode* p1_target = smgr->addEmptySceneNode(p1);
	p1_target->setPosition(core::vector3df(1,0,0));

	p1->setMaterialFlag(video::EMF_LIGHTING, false);
	p1->setAnimationSpeed(30);
	p1->setMaterialTexture(0, driver->getTexture("sydney.bmp"));

	if (start)
	{
    	p1->setFrameLoop(320, 360);
	}
	else
	{
	p1->setFrameLoop(0, 320);
	}
But it is not working (probably because each cycle new loop is triggered and it allways stays on first frame of each animation).

So, how do I do it?

Thanks!
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

I think the error is in your if statements:

if(controls & C_UP)

You have to use it like this:

if(controls && C_UP)

(well, C/C++ basics...)
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Boris
Posts: 14
Joined: Sun Oct 17, 2004 6:58 pm

Post by Boris »

But my controls have been working fine, they even send a value of that boolean.
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Well, boolean in C/C++ doesn't mean true and false at all...
false is 0 and true is all other values (1, 2, 3, etc...)
So if you have two values you can have different results with "&" and "&&" !!!
For example:

Code: Select all

int a = 10, b = 5;
printf("%d", a & b);  // output: 0
printf("%d", a && b); // output: 1
You see, same values - different outputs !!!
The "&" is a logical "AND"-combination of the two values.
And the "&&" is a comparsion (the "AND" you whant to use).

It's similar to "=" and "==" !!!
If you whant to compare two values if they're equal you have to do it like this:

if(a == b)

If you use it like this:

if(a = b)

a get's the value of b and if after this a != 0 (a <> 0) the result is true !!!

Well as I told you, it's C/C++ basics... ;)
(and even a little bit off topic, but meanwhile I doesn't care ;) )
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Boris
Posts: 14
Joined: Sun Oct 17, 2004 6:58 pm

Post by Boris »

Ok, I get the point, but it still doesn't help with my initial question (tried both ways, none of them worked).
C'mon guys, it shouldn't be too hard to answer this!
Koogz

Post by Koogz »

I can't beleive noone can answer this!
mm765
Posts: 172
Joined: Fri May 28, 2004 10:12 am

Post by mm765 »

and i cant believe that someone posts this question with so much missing information and expects an answer...

-where are those code-parts located (within the main loop or the event receiver or at initialization time) ?
- of which datatype is controls ?
- of which datatype is C_UP ?
- what do they contain ?
and so on... ever thought about posting the complete code somewhere ?

oh and "its not working" is a very good error description by the way </irony>
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

well it's still sarcasm mm765 but at least you spelled Irony correctly this time :P
Boris
Posts: 14
Joined: Sun Oct 17, 2004 6:58 pm

Post by Boris »

Thanks for sarcasm/irony. Here is complete code:

Code: Select all


/*
This code is based off of the Movement tutorial, with stuff from the Quake3Map tutorial
and Boogle's 3rd Person Camera code thrown in.
*/
#include <stdio.h>
#include <wchar.h>
#include <irrlicht.h>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")


/*
I like to define controls as powers of 2, so I can squash them all bitwise onto a single
int. This makes it really easy to deal with and probably also makes it nice and fast. :)X
*/
#define C_UP	1
#define C_DOWN	2
#define C_LEFT	4
#define C_RIGHT	8

#define C_CAML	16
#define C_CAMR	32

#define MOVESPEED	5.0f	// how fast p1 and the camera move
#define ROTSPEED	2.0f	// how fast p1 rotates
#define HEIGHT		0.0f	// how high camera hovers over center of target

scene::ICameraSceneNode* camera;
scene::IAnimatedMeshSceneNode* p1;
IrrlichtDevice* device = 0;
float cam_rotate=0;
float p1_rotate=0;
float moving=0;
bool start=false;
unsigned int controls=0;

/*
Read the keys, and use them to set the bits of (controls).
*/
class MyEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
		if (event.EventType == irr::EET_KEY_INPUT_EVENT)
		{
			unsigned int k=0;

			switch(event.KeyInput.Key) {
			case(KEY_UP):
					k=C_UP;
					break;
		//	case(KEY_DOWN):
			//		k=C_DOWN;
				//	break;
			case(KEY_LEFT):
					k=C_LEFT;
					break;
			case(KEY_RIGHT):
					k=C_RIGHT;
					break;
			case(KEY_KEY_A):
					k=C_CAML;
					break;
			case(KEY_KEY_S):
					k=C_CAMR;
					break;
			}

			if(k) {
				if(event.KeyInput.PressedDown)
					controls |= k;
				else
					controls ^= k;
				return true;
			}
		}

		return false;
	}
};

/*
Parse the controls to move p1.
*/
void resolve_controls_RE() {
	/*
	Resident Evil -style controls; up=forward, down=back, left & right = rotate
	Nice and simple. :)X
	*/
	if(controls & C_UP)
	{
		start=true;
		moving = controls && C_UP ? MOVESPEED : -MOVESPEED;

		if(controls & C_LEFT + C_RIGHT) {
		p1_rotate += controls & C_RIGHT ? ROTSPEED : (360.0f-ROTSPEED);
		if(p1_rotate>=360.0f)
			p1_rotate -= 360.0f;
		p1->setRotation(core::vector3df(0,p1_rotate,0));
	}
	}
	else
		start=false;
	

	if(controls & C_CAML + C_CAMR)
		cam_rotate = controls & C_CAMR ? ROTSPEED : -ROTSPEED;
}

void resolve_controls_WW() {
	/*
	Wind Waker -style controls; direction pressed makes you go in that direction relative
	to the camera. Not so nice and simple, and also not quite working right. :(X
	*/
	p1_rotate=0;
	switch(controls & C_UP+C_DOWN+C_LEFT+C_RIGHT) {
	case(C_UP+C_LEFT):
		p1_rotate+=45.0f;
	case(C_LEFT):
		p1_rotate+=45.0f;
	case(C_DOWN+C_LEFT):
		p1_rotate+=45.0f;
	case(C_DOWN):
		p1_rotate+=45.0f;
	case(C_DOWN+C_RIGHT):
		p1_rotate+=45.0f;
	case(C_RIGHT):
		p1_rotate+=45.0f;
	case(C_UP+C_RIGHT):
		p1_rotate+=45.0f;
	case(C_UP):
		core::matrix4 matty;
		matty.buildCameraLookAtMatrixLH(camera->getPosition(),camera->getTarget(),camera->getUpVector());
		p1_rotate+=matty.getRotationDegrees().Z+270.0f;
		while(p1_rotate>=360.0f) {
			p1_rotate-=360.0f;
		}
		float foo = p1->getRotation().Y-p1_rotate;
		if(foo<0)
			foo=-foo;
		if(foo<45.0f || foo>360.0f-45.0f)
			moving = MOVESPEED;
		if(foo>ROTSPEED || foo>360.0f-ROTSPEED) {
			if(foo<180.0f)
				if(p1->getRotation().Y>p1_rotate)
					p1->setRotation(p1->getRotation() + core::vector3df(0,360.0f-ROTSPEED*2,0));
				else
					p1->setRotation(p1->getRotation() + core::vector3df(0,ROTSPEED*2,0));
			else
				if(p1->getRotation().Y<p1_rotate)
					p1->setRotation(p1->getRotation() + core::vector3df(0,360.0f-ROTSPEED*2,0));
				else
					p1->setRotation(p1->getRotation() + core::vector3df(0,ROTSPEED*2,0));
			if(p1->getRotation().Y>=360.0f)
				p1->setRotation(p1->getRotation() - core::vector3df(0,360.0f,0));
		}
	}

	if(controls & C_CAML + C_CAMR)
		cam_rotate = controls & C_CAMR ? ROTSPEED : -ROTSPEED;
}

int main()
{
	MyEventReceiver receiver;

	device = createDevice(video::EDT_DIRECTX8, core::dimension2d<s32>(800, 600),
		16, true, false, false ,&receiver);

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

	/*
	Make the background go!
	*/
	//device->getFileSystem()->addZipFileArchive("map-20kdm2.pk3");
	scene::IAnimatedMesh* mesh = smgr->getMesh("town5.3ds");
	scene::ISceneNode* bg = smgr->addOctTreeSceneNode(mesh->getMesh(0));
	bg->setPosition(core::vector3df(-1000,-100,-100));

	/*
	Triangle Selecty-ness on the background
	*/
	scene::ITriangleSelector* selector = 0;
	selector = smgr->createOctTreeTriangleSelector(mesh->getMesh(0), bg, 128);
	bg->setTriangleSelector(selector);
	selector->drop();

	/*
	Make the player character
	*/
	mesh = smgr->getMesh("sydney.md2");
	p1 = smgr->addAnimatedMeshSceneNode(mesh);
	p1->setPosition(core::vector3df(0,0,0));
	scene::ISceneNode* p1_target = smgr->addEmptySceneNode(p1);
	p1_target->setPosition(core::vector3df(1,0,0));

	p1->setMaterialFlag(video::EMF_LIGHTING, false);
	p1->setFrameLoop(320, 360);
	p1->setAnimationSpeed(30);
	p1->setMaterialTexture(0, driver->getTexture("sydney.bmp"));

	

	/*
	Set collision for player character
	*/
	core::vector3df dimensions = mesh->getBoundingBox().MaxEdge - mesh->getBoundingBox().MinEdge;
	scene::ISceneNodeAnimator* collision = smgr->createCollisionResponseAnimator(selector,p1,dimensions/2.0f);
	p1->addAnimator(collision);

	/*
	Make the camera go!
	*/
	camera = smgr->addCameraSceneNode(0, core::vector3df(-10,HEIGHT,0), core::vector3df(0,0,100));

	/*
	Set collision for camera
	*/
	collision = smgr->createCollisionResponseAnimator(
		selector,camera,core::vector3df(20,20,20),
		core::vector3df(0,0,0), 0.0f,
		core::vector3df(0,0,0));
	camera->addAnimator(collision);

	collision->drop();
	
	irr::video::ITexture *crosshairTexture = driver->getTexture("gui2.bmp");
	driver->makeColorKeyTexture(crosshairTexture,irr::core::position2d<irr::s32>(0,0));


device->getCursorControl()->setVisible(false);

	/*
	Main game loop
	*/
	while(device->run())
	{
		driver->beginScene(true, true, video::SColor(255,90,90,156));
		smgr->drawAll();

		//core::position2d<s32> m = device->getCursorControl()->getPosition();


		//	irr::core::position2d<irr::s32> crosshairLocation = device->getCursorControl()->getPosition();
			//crosshairLocation.X = 500;
			//crosshairLocation.Y = 0;

			// draw the crosshair
			driver->draw2DImage(crosshairTexture,core::position2d<s32>(673,0),
				irr::core::rect<irr::s32>(0,0,127,350),0,
				irr::video::SColor(255,255,255,255),true);




		driver->endScene();
				if (start)//this is problematic part!!
	{
					
    	p1->setFrameLoop(320, 360);
	}
	else
	{
		
	p1->setFrameLoop(0, 320);
	}
	

		int fps = driver->getFPS();

		wchar_t tmp[1024];
		swprintf(tmp, 1024, L"Following Camera Example - Irrlicht Engine (%s)(fps:%d)(%2.2f)(%2.2f)(%2.2f)", 
			driver->getName(), fps,p1_rotate,p1->getRotation().Y,p1_rotate-p1->getRotation().Y);
		device->setWindowCaption(tmp);

		/*
		Set control scheme here; 
		RE = Resident Evil -style
		WW = Wind Waker -style
		*/
		resolve_controls_RE();

		/*
		p1_target is an empty node that floats 1.0f in front of p1. It's used just like a
		camera's target to determine which way p1 is facing, and since it's already 1.0f away,
		it doesn't have to be normalized. Is there a better way to do this?
		Set p1_movedir to the direction p1 is facing, then move in that direction!
		*/
		core::vector3df p1_movedir = p1_target->getAbsolutePosition() - p1->getPosition();
		if(moving) {
			p1->setPosition(p1->getPosition()+(p1_movedir*moving));
			moving=0;
		}

		/*
		That's it for moving the player. Now here's the stuff for moving the camera.
		While we want to camera to look directly at p1, we want its movement to be based on
		a point HEIGHT above p1.
		*/
		camera->setTarget(p1->getPosition());
		f64 distance = camera->getPosition().getDistanceFrom(camera->getTarget()+core::vector3df(0,HEIGHT,0));
		core::vector3df cam_movedir = (camera->getTarget()+core::vector3df(0,HEIGHT,0))-camera->getPosition();
		cam_movedir.normalize();

		/*
		The camera tries to stay between 50.0f and 50.0f+MOVESPEED from HEIGHT above p1;
		if it tried to stay at exactly 50.0f, it would freak out and jiggle too much.
		*/
		if(distance>(90.0f+MOVESPEED))
			camera->setPosition(camera->getPosition()+(cam_movedir*MOVESPEED));
		else if(distance<90.0f)
			camera->setPosition(camera->getPosition()-(cam_movedir*MOVESPEED));

		/*
		The camera rotation stuff cheats a little, because instead of rotating it perfectly
		around p1, it just moves the camera left or right relatively, and lets the camera
		automatically adjust to the right distance.
		*/
		if(cam_rotate) {
			core::vector3df crossy = (camera->getTarget()-camera->getPosition()).crossProduct(camera->getUpVector());
			crossy.normalize();
			camera->setPosition(camera->getPosition()-crossy*cam_rotate);
			cam_rotate=0;
		}
	}

	/*
	In the end, delete the Irrlicht device.
	*/
	device->drop();
	
	return 0;
}

You know what I need.
Thanks again.
Boris
Posts: 14
Joined: Sun Oct 17, 2004 6:58 pm

Post by Boris »

I hope I explained it properly this time.
Still nothing?
mm765
Posts: 172
Joined: Fri May 28, 2004 10:12 am

Post by mm765 »

two things:
1st you have a && somewhere instead of a & (probably due to testing)
2nd: your problem is, that the setframeloop() method is called after each frame so that the animation is reset to the first animationframe each time.
you need to change it so that the setframeloop is executed only if thje value of start has changed since the last frame.
Boris
Posts: 14
Joined: Sun Oct 17, 2004 6:58 pm

Post by Boris »

you need to change it so that the setframeloop is executed only if thje value of start has changed since the last frame.
I know that! That is realy what I was looking for help with!
Anyone?
mm765
Posts: 172
Joined: Fri May 28, 2004 10:12 am

Post by mm765 »

the easiest way would probably be to add a constructor to myeventreceiver that takes p1 as a parameter and then set the frameloop directly instead of the start variable. this would only be executed when a key is pressed so it would do the trick.

other than that it would actually be best to reorganize your code completely to encapsulate your own stuff into a class which could then inherit from eventreceiver and that would make things a lot easier.
Post Reply