ball that rolls in the direction its moving

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
hessiess
Posts: 47
Joined: Wed Mar 12, 2008 8:39 pm

ball that rolls in the direction its moving

Post by hessiess »

I've been trying to create a ball that rolls in the direction its moving. the following code partly works, left and right movement is always correct. however up/down movement the ball sometimes rolls on its side or backwards to the direction of travel dependant on the horizontal position. diagonal movement never works correctly.

from my understanding, Euler angles are applied one after the outher, so i dont know why this isn't working. all movement code is located in the move_ball method of the movable_ball class

Code: Select all

#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace std;



// ball
class movable_ball {
	scene::ISceneNode	*ball;
	core::vector3df 	old_loc;
	float			angle_step;
	int switchh;

public:
// constructor	
	movable_ball()
	{
		ball 		= NULL;
		old_loc 	= core::vector3df(0,0,0);
		angle_step	= NULL;
	}
	
//overloaded constructor
	movable_ball(scene::ISceneManager* smgr, video::IVideoDriver* driver, core::vector3df sloc)
	{

		angle_step	= (4 * 3.142) / 360;
 		ball		= smgr->addSphereSceneNode();
		int switchh = 0;

		if (ball)
		{
			ball->setPosition(sloc);
			ball->setScale(core::vector3df(0.4,0.4,0.4));
			ball->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
			ball->setMaterialFlag(video::EMF_LIGHTING, false);
		}
	}

	void move_ball(core::vector3df loc)
	{
		if(switchh == 0)
			switchh = 1;
		else
			switchh = 0;
	// set position
		ball->setPosition(loc);
	// calculate movement delta
		core::vector3df mov_delta = loc - old_loc;

	// calculate rotation for X accsis
	if(switchh == 1)
	{
		for(int angle = -30; angle < 31; angle ++)
		{
			float dist_moved_min = angle_step * angle;
			float dist_moved_max = angle_step * (angle +1);

			if(mov_delta.X > dist_moved_min && mov_delta.X < dist_moved_max)
			{
			// fix speed bug when angle is negative
				if(mov_delta.X < 0)
					angle += 1;
			// apply rotation
				core::vector3df ball_rot = ball->getRotation();
				ball->setRotation(core::vector3df(ball_rot.X,ball_rot.Y,ball_rot.Z -= angle));

				break;
			}
		}
	} // end
	else
	{
	// calculate rotation for Y accsis
		for(int angle = -30; angle < 31; angle ++)
		{
			float dist_moved_min = angle_step * angle;
			float dist_moved_max = angle_step * (angle +1);

			if(mov_delta.Z > dist_moved_min && mov_delta.Z < dist_moved_max)
			{
			// fix speed bug when angle is negative
				if(mov_delta.Z < 0)
					angle += 1;
			// apply rotation
				core::vector3df ball_rot = ball->getRotation();
				ball->setRotation(core::vector3df(ball_rot.X += angle,ball_rot.Y,ball_rot.Z));

				break;
			}
		}

		old_loc	= loc;
	}
	}
};

// main function
int main()
{ 
	IrrlichtDevice* device = createDevice(video::EDT_OPENGL, core::dimension2d<s32>(640, 480),
		16, false, false, false, 0/*&receiver*/);

	if (device == 0)
		return 1; // could not create selected driver.


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


	movable_ball ball = movable_ball(smgr, driver,core::vector3df(0,0,0));


// camera
	scene::ICameraSceneNode * cam = smgr->addCameraSceneNode();
	cam -> setPosition(core::vector3df(0,40,0));
	cam -> setTarget(core::vector3df(0,39,0.1));
// main loop
	int lastFPS = -1;

	
	core::vector3df loc(0,0,0);
	core::vector3df accselaration(0.1,0,0.06);
	while(device->run())
	{
		loc += accselaration;

		if(loc.Z > 30)
		{
			accselaration.Z -= accselaration.Z*2;
		}
		if(loc.Z < -20)
		{
			accselaration.Z -= accselaration.Z*2;
		}
		if(loc.X > 35)
		{
			accselaration.X -= accselaration.X*2;
		}
		if(loc.X < -35)
		{
			accselaration.X -= accselaration.X*2;
		}

	// move ball
		ball.move_ball(loc);

	// render
		driver->beginScene(true, true, video::SColor(255,0,0,0));
		smgr->drawAll();
		driver->endScene();
	}

	device->drop();
	return 0;
}
thanks in advance.
Post Reply