WoW like camera control & character movement (work in pr

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
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

WoW like camera control & character movement (work in pr

Post by JonChaos »

This here shall be an example of how to create a World of Warcraft like following camera.
The idea came from the thread Nightbird has posted on these forums.
http://irrlicht.sourceforge.net/phpBB2/ ... php?t=3245
Its about a NWN like Camera control but its not really finished yet.

Atm its in a very early stage but its planned to be a complete tutorial at the end.

Source can be downloadet @ :
http://www.loaditup.de/files//wow-like-camera.zip ( OLD VERSION )
( beware: work in progress -> not a finished tutorial yet )

Current version :
http://www.loaditup.de/135627.html


Work left to do:
- Smoth zoom in & out
- Maximum zoom Range ( done )
- 1st Person mode
- Minimum Zoom Range ( done )
- turning the character ( done )
- movement depending on the turned character ( done )
- Camera movement only when mousebuttens are pressed & the mouse is moved ( done )
- Camera movement up and down ( done )
- limit Camera movement up / down
- the Camera should stick behind the Players back


Any ideas , suggestions or links are very welcome.
For me its mainly a possibility to learn more about the irrlicht engine.
( This is in no way another - "i have a booombastic idea so lets make wow2 and earn $$$" thread - its just about learning how to do things with irrlicht and maybe creating another nice tutorial which might help people who are planning a rpg)
Last edited by JonChaos on Thu Oct 11, 2007 9:08 pm, edited 3 times in total.
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

Here is the first update to the main.cpp file.
The following changes have been implemented:

If the left mousebutton is pressed the camera can be rotated around the model.
If the left mousebutton is released the camera moves back.
The rotation amount is determined by deltax , so if you move the mouse a litle bit the rotation is only a little bit.

If the right mousebutton is pressed the model is rotated.

If the middle mousebutton is pressed the zoomrange is resetted.
There is a min and maximum zoom range.

Still a lot of things to do...



Code: Select all

/*
This tutorial will show how to implement a camera and character display which is a copy of the
one used in World of Warcraft.
Its purpose is to offer the Community an example for a camera and movement system for rpg or 
as a base to develop theyr own movement/camera system.

It is based on the irrlicht Tutorial 12 and 
NightBirds NWN Camera example http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=3245

Atm its all a bitt messy and very unclean but its still work in progress , althought comments 
or suggestions are always welcome.
You can contact me in the Irrlicht Forums
Username: Jonchaos
or per Email
Antharon@Hotmail.com
*/
#include <irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")
//****************************************************
//*													 *
//****************************************************
#define CAMERASPEED 0.1f		// Camerarotationspeed
#define CHARROTATIONSPEED 3.0f
#define PI 3.14159265f			
#define WIDTH 640				// screen width
#define HEIGHT 480				// screen height
#define STARTDISTANCE 35		// cam distance start
#define STARTANGLE 0.0f			// cam angle
#define MAXZOOMRANGE 100
#define MINZOOMRANGE 30
//****************************************************
//*													 *
//****************************************************
class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver(scene::ISceneNode* terrain ,
					scene::IAnimatedMeshSceneNode* ptrCharacter,
					IrrlichtDevice* ptrDevice,
					scene::ICameraSceneNode* ptrCamera)
	{
		// store pointer to terrain so we can change its drawing mode
		this->Terrain = terrain;
		this->Character = ptrCharacter;
		this->device = ptrDevice;
		this->pCamera = ptrCamera;
		this->CamRotationAngleY = STARTANGLE;
		this->distance = STARTDISTANCE;
		this->bIsRunning = false;	
		this->CameraRotating = false;
		this->CharacterRotating = false;
	}
	
	void Update() 
	{ 
		if (!pCamera || !Character) return;
		
		if (m_lastTargetPos != Character->getPosition()) 
		{
			m_updated = true;
			m_lastTargetPos = Character->getPosition();
		}
		
		if (m_updated) 
		{
			m_updated = false;
			irr::core::vector3df m_Camerapos = m_lastTargetPos;
			m_Camerapos.X += distance*sin(CamRotationAngleY);
			m_Camerapos.Z += distance*cos(CamRotationAngleY);
			m_Camerapos.Y += distance;
			pCamera->setPosition(m_Camerapos);
			pCamera->setTarget(m_lastTargetPos);
		}
}
	bool OnEvent(SEvent event)
	{		
		Update();

		if (event.EventType == EET_MOUSE_INPUT_EVENT) 
			{
				switch (event.MouseInput.Event) 
				{
					case EMIE_MOUSE_WHEEL:  // zooming						
						// tbd: find a way to smoth zooming						
						distance *= (((-event.MouseInput.Wheel)+1)/2+.5f);
						if (distance >= MAXZOOMRANGE ) 
							distance = MAXZOOMRANGE; 
						if (distance <= MINZOOMRANGE ) 
						{
							distance = MINZOOMRANGE; 
							// tbd: switch to 1st person
						}							
						return true;
						break;
						
					case EMIE_LMOUSE_PRESSED_DOWN:  // Manual Camera Rotation
						this->CameraRotating = true;
						return true;
						break;

					case EMIE_RMOUSE_PRESSED_DOWN:	// character rotation
						this->CharacterRotating = true;
						return true;
						break;

					case EMIE_MOUSE_MOVED:
						if (this->CameraRotating || this->CharacterRotating)
						{
							int DeltaX = event.MouseInput.X - OldMouseX;
							int DeltaY = event.MouseInput.Y - OldMouseY;
							OldMouseX = event.MouseInput.X;
							OldMouseY = event.MouseInput.Y;	
						
							if (this->CameraRotating)
							{
								// Kamera rotieren							
								if (DeltaX > 0)
								{
									CamRotationAngleY += (DeltaX*CAMERASPEED);
									while (CamRotationAngleY > 2*PI)
										CamRotationAngleY -= 2*PI;
								}
								else
								{
									CamRotationAngleY += (DeltaX*CAMERASPEED);
									while (CamRotationAngleY < 2*PI)
										CamRotationAngleY += 2*PI;
								}
								// tbd: cam rotation up/down
								if (DeltaY > 0)
								{
								
								}
								else
								{
								
								}

							}

							if (this->CharacterRotating)
							{   // tbd: rotation depending on value of DeltaX
								if (DeltaX > 0)
								{	
									irr::core::vector3df RotVect; 
									RotVect =  Character->getRotation();
									RotVect.Y = RotVect.Y + CHARROTATIONSPEED;								
									Character->setRotation(RotVect); 																	
								}
								else
								{
									irr::core::vector3df RotVect; 
									RotVect =  Character->getRotation();
									RotVect.Y = RotVect.Y - CHARROTATIONSPEED;								
									Character->setRotation(RotVect); 								
								}
							}												
						}					
						return true;
						break;
					
					case EMIE_MMOUSE_PRESSED_DOWN:									
						this->distance = STARTDISTANCE;						
						return true;
						break;
						
					case EMIE_LMOUSE_LEFT_UP:	// stop manual camera rotation							
						this->CameraRotating = false;
						CamRotationAngleY = STARTANGLE;
						return true;
						break;
						// Kamera wieder in urspr. position						

					case EMIE_RMOUSE_LEFT_UP:	// stop character rotation
						this->CharacterRotating = false;
						return true;
						break;

				} ;
		}
		
		if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
		{
			switch (event.KeyInput.Key)
			{
			case irr::KEY_KEY_W: // switch wire frame mode
				Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe);
				Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false);
				return true;
			case irr::KEY_KEY_P: // switch wire frame mode
				Terrain->setMaterialFlag(video::EMF_POINTCLOUD, !Terrain->getMaterial(0).PointCloud);
				Terrain->setMaterialFlag(video::EMF_WIREFRAME, false);
				return true;
			case irr::KEY_KEY_D: // toggle detail map
				Terrain->setMaterialType(
					Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? 
					video::EMT_DETAIL_MAP : video::EMT_SOLID);
				return true;
			case irr::KEY_ESCAPE:
				this->device->closeDevice(); 
				return true;
			}
		}		
		if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown  )
		{   // tbd: change walkkey input			
			switch (event.KeyInput.Key)
			{		
			case irr::KEY_UP:
				Charpos	= Character->getPosition(); 
				Charpos.X = Charpos.X - 10.0f ;
				Character->setPosition(Charpos); 
				if (!this->bIsRunning)
				{
					Character->setMD2Animation(scene::EMAT_RUN); 
					this->bIsRunning = true;
				}
				return true;			
			case irr::KEY_DOWN: 
				Charpos	= Character->getPosition(); 
				Charpos.X = Charpos.X + 10.0f ;
				Character->setPosition(Charpos); 
				if (!this->bIsRunning)
				{
					Character->setMD2Animation(scene::EMAT_RUN); 
					this->bIsRunning = true;
				}
				return true;
			case irr::KEY_LEFT:  
				Charpos	= Character->getPosition(); 
				Charpos.Z = Charpos.Z - 10.0f ;
				Character->setPosition(Charpos); 
				if (!this->bIsRunning)
				{
					Character->setMD2Animation(scene::EMAT_RUN); 
					this->bIsRunning = true;
				}
				return true;
			case irr::KEY_RIGHT: 
				Charpos	= Character->getPosition(); 
				Charpos.Z = Charpos.Z + 10.0f ;
				Character->setPosition(Charpos); 
				if (!this->bIsRunning)
				{
					Character->setMD2Animation(scene::EMAT_RUN); 
					this->bIsRunning = true;
				}				
				return true;			
			}
		}		
		
		// if one of the walk keys is lifted -> stop run animation
		if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
		{
			switch (event.KeyInput.Key)
			{		
			case irr::KEY_UP:
				this->bIsRunning = false;
				Character->setMD2Animation(scene::EMAT_STAND);
				return true;			
			case irr::KEY_DOWN: 
				this->bIsRunning = false;
				Character->setMD2Animation(scene::EMAT_STAND);
				return true;
			case irr::KEY_LEFT:  
				this->bIsRunning = false;
				Character->setMD2Animation(scene::EMAT_STAND);
				return true;
			case irr::KEY_RIGHT: 
				this->bIsRunning = false;
				Character->setMD2Animation(scene::EMAT_STAND);			
				return true;			
			}
		}
		return false;
	}
private:
	bool bIsRunning;
	scene::ISceneNode* Terrain;
	scene::IAnimatedMeshSceneNode* Character;
	IrrlichtDevice* device;


	scene::ICameraSceneNode* pCamera;

	irr::core::vector3df m_lastTargetPos;
	
	irr::core::vector3df Charpos;

	bool m_updated;
	float distance;

	bool CameraRotating;
	bool CharacterRotating;

	float CamRotationAngleY;

	int OldMouseX;
	int OldMouseY;
};
//****************************************************
//*	int main()										 *
//****************************************************
int main()
{
	// let user select driver type
	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		" (otherKey) exit\n\n");

	char i;
	std::cin >> i;

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		default: return 1;
	}	

	// create device

	IrrlichtDevice* device = createDevice(driverType, core::dimension2d<s32>(WIDTH,HEIGHT));

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

	
	/*
	First, we add standard stuff to the scene: A nice irrlicht engine
	logo, a small help text, a user controlled camera, and we disable
	the mouse cursor.
	*/   

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

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

	// add irrlicht logo
	env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
		core::position2d<s32>(10,10));

	//set other font
	env->getSkin()->setFont(env->getFont("../../media/fontlucida.png"));

	// add some help text
	gui::IGUIStaticText* text = env->addStaticText(
		L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map",
		core::rect<s32>(10,440,250,475), true, true, 0, -1, true);

	// add camera
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();

	camera->setPosition(core::vector3df(1900*2,255*2,3700*2));
	camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
	camera->setFarValue(12000.0f);

	//mouse cursor
	device->getCursorControl()->setVisible(true);
	device->getCursorControl()->setPosition(0,0);  

	// add terrain scene node
	scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( 
		"../../media/terrain-heightmap.bmp",
		0,										// parent node
		-1,										// node id
		core::vector3df(0.f, 0.f, 0.f),			// position
		core::vector3df(0.f, 0.f, 0.f),			// rotation
		core::vector3df(40.f, 4.4f, 40.f),		// scale
		video::SColor ( 255, 255, 255, 255 ),	// vertexColor,
		5,										// maxLOD
		scene::ETPS_17,							// patchSize
		4										// smoothFactor
		);

	terrain->setMaterialFlag(video::EMF_LIGHTING, false);

	terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));
	terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));
	
	terrain->setMaterialType(video::EMT_DETAIL_MAP);

	terrain->scaleTexture(1.0f, 20.0f);
	//terrain->setDebugDataVisible ( true );

	/*
	To be able to do collision with the terrain, we create a triangle selector.
	If you want to know what triangle selectors do, just take a look into the 
	collision tutorial. The terrain triangle selector works together with the
	terrain. To demonstrate this, we create a collision response animator 
	and attach it to the camera, so that the camera will not be able to fly 
	through the terrain.
	*/

	// create triangle selector for the terrain	
	scene::ITriangleSelector* selector
		= smgr->createTerrainTriangleSelector(terrain, 0);
	terrain->setTriangleSelector(selector);
	selector->drop();

	scene::IAnimatedMeshSceneNode* Character = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/sydney.md2"));
	
	// create collision response animator and attach it to the Character
	scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
		selector, Character, core::vector3df(60,100,60),
		core::vector3df(0,-100,0), 
		core::vector3df(0,50,0));
	Character->addAnimator(anim); 	
	anim->drop();

	// create event receiver
	MyEventReceiver receiver(terrain,Character,device,camera);
	device->setEventReceiver(&receiver);

// create skybox
	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

	smgr->addSkyBoxSceneNode(
		driver->getTexture("../../media/irrlicht2_up.jpg"),
		driver->getTexture("../../media/irrlicht2_dn.jpg"),
		driver->getTexture("../../media/irrlicht2_lf.jpg"),
		driver->getTexture("../../media/irrlicht2_rt.jpg"),
		driver->getTexture("../../media/irrlicht2_ft.jpg"),
		driver->getTexture("../../media/irrlicht2_bk.jpg"));

	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);


/* Model Teil */
/*
		To make to model look right we set the frames between which the animation
		should loop, rotate the model around 180 degrees, and adjust the animation speed
		and the texture.
		To set the right animation (frames and speed), we would also be able to just
		call "anms->setMD2Animation(scene::EMAT_RUN)" for the 'run' animation 
		instead of "setFrameLoop" and "setAnimationSpeed",
		but this only works with MD2 animations, and so you know how to start other animations.
		but it a good advice to use not hardcoded frame-numbers...
		*/
		Character->setMaterialFlag(video::EMF_LIGHTING, false);

		Character->setFrameLoop(160, 183);
		Character->setAnimationSpeed(40);		
		Character->setMD2Animation(scene::EMAT_STAND);
		Character->setRotation(core::vector3df(0,180.0f,0));
		Character->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp"));

		Character->setPosition(core::vector3df(1900*2,255*2,3700*2)) ;

	/*
	That's it, draw everything. Now you know how to use terrain in Irrlicht.
	*/

	int lastFPS = -1;

		

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, 0 );

		smgr->drawAll();
		env->drawAll();

		driver->endScene();

		// display frames per second in window title
		int fps = driver->getFPS();
		if (lastFPS != fps)
		{
			core::stringw str = L"WoW like Camera&Character - Irrlicht Engine [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;
			// Also print terrain height of current camera position
			// We can use camera position because terrain is located at coordinate origin
			str += " Height: ";
			str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z);

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	}

	device->drop();
	
	return 0;
}
dejai
Posts: 522
Joined: Sat Apr 21, 2007 9:00 am

Post by dejai »

I can see you have put in a lot of work, it would be nice to include the lib, irrlicht.dll and the include folder in your source download though Good Job keep up the good work.
Programming Blog: http://www.uberwolf.com
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Notes for anyone trying to use this:

MyEventReceiver() needs this added:

Code: Select all

      this->OldMouseX = 0; 
      this->OldMouseY = 0; 
Find this code block:

Code: Select all

                     if (this->CameraRotating)
                     {
                        // Kamera rotieren                     
                        if (DeltaX > 0)
and change it to this:

Code: Select all

                     if (this->CameraRotating)
                     {
                        m_updated = true;

                        // Kamera rotieren                     
                        if (DeltaX > 0)
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

rogerborg wrote: MyEventReceiver() needs this added:

Code: Select all

      this->OldMouseX = 0; 
      this->OldMouseY = 0; 
done :)

rogerborg wrote: Find this code block:

Code: Select all

                     if (this->CameraRotating)
                     {
                        // Kamera rotieren                     
                        if (DeltaX > 0)
and change it to this:

Code: Select all

                     if (this->CameraRotating)
                     {
                        m_updated = true;

                        // Kamera rotieren                     
                        if (DeltaX > 0)
m_updated wont be neccesary in the next version. Its left from the code Nightbird posted.
Expect an minor update in a few hours.

@Rogerborg
Thx for the input. The more good ideas i recieve the faster this tutorial will be finished :)
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

Here is the new version with some minor changes:

- The character can now move in more than one direction
- Fixed flickering on movement
- Update() is now called in the main loop
- Run animation stopps properly if no movement key is pressed
- charactermodel isnt displayed anymore @ minimal zoomdistance ( 1st person )
- rogerborgs suggestions included

@ dejai
To use it you can extract the folder in my first post to /irrlicht/examples/ then everything should run fine ( at least with windows versions ).
I will provide a complete zip with everything needet if most of the todo's are done.

Code: Select all

/*
This tutorial will show how to implement a camera and character display which is a copy of the
one used in World of Warcraft.
Its purpose is to offer the Community an example for a camera and movement system for rpg or 
as a base to develop theyr own movement/camera system.

It is based on the irrlicht Tutorial 12 and 
NightBirds NWN Camera example http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=3245

Atm its all a bitt messy and very unclean but its still work in progress , althought comments 
or suggestions are always welcome.
You can contact me in the Irrlicht Forums
Username: Jonchaos
or per Email
Antharon@Hotmail.com
*/
#include <irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")
//****************************************************
//*													 *
//****************************************************
#define CAMERASPEED 0.1f		// Camerarotationspeed
#define CHARROTATIONSPEED 3.0f
#define PI 3.14159265f			
#define WIDTH 640				// screen width
#define HEIGHT 480				// screen height
#define STARTDISTANCE 35		// cam distance start
#define STARTANGLE 0.0f			// cam angle
#define MAXZOOMRANGE 100
#define MINZOOMRANGE 30
//****************************************************
//*													 *
//****************************************************
class MyEventReceiver : public IEventReceiver
{
public:

	MyEventReceiver(scene::ISceneNode* terrain ,
					scene::IAnimatedMeshSceneNode* ptrCharacter,
					IrrlichtDevice* ptrDevice,
					scene::ICameraSceneNode* ptrCamera)
	{
		// store pointer to terrain so we can change its drawing mode
		this->Terrain = terrain;
		this->Character = ptrCharacter;
		this->device = ptrDevice;
		this->pCamera = ptrCamera;
		this->CamRotationAngleY = STARTANGLE;
		this->distance = STARTDISTANCE;
		this->bIsRunning = false;				// is the character running ?
		this->bRunDirectU = false;
		this->bRunDirectD = false;
		this->bRunDirectL = false;
		this->bRunDirectR = false;
		this->CameraRotating = false;
		this->CharacterRotating = false;
		this->OldMouseX = 0;
		this->OldMouseY = 0;
		this->IsAnimatingRun = false;
		this->bFirstPerson = false;
	}
	
	void Update() 
	{ 
		if (!pCamera || !Character) return;
		
		if (m_lastTargetPos != Character->getPosition()) 
		{
			m_updated = true;
			m_lastTargetPos = Character->getPosition();
		}
		
		if (m_updated) 
		{
			m_updated = false;
			irr::core::vector3df m_Camerapos = m_lastTargetPos;
			m_Camerapos.X += distance*sin(CamRotationAngleY);
			m_Camerapos.Z += distance*cos(CamRotationAngleY);
			m_Camerapos.Y += distance;
			pCamera->setPosition(m_Camerapos);
			pCamera->setTarget(m_lastTargetPos);
		}

	if (this->bIsRunning)
		this->StartRunAnimation(); 
	else		
		this->StopRunAnimation(); 


}

void DoRunning()
{
	// tbd : Character Movement depending on character rotation
	if (this->bIsRunning)
	{
		if (this->bRunDirectU) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.X = Charpos.X - 1.0f ;
			Character->setPosition(Charpos); 
		}

		if (this->bRunDirectD) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.X = Charpos.X + 1.0f ;
			Character->setPosition(Charpos); 
		}

		if (this->bRunDirectL) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.Z = Charpos.Z - 1.0f ;
			Character->setPosition(Charpos); 
		}
	
		if (this->bRunDirectR) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.Z = Charpos.Z + 1.0f ;
			Character->setPosition(Charpos); 
		}
	this->Update(); 
	}
}

	bool OnEvent(SEvent event)
	{				
		if (event.EventType == EET_MOUSE_INPUT_EVENT) 
			{
				switch (event.MouseInput.Event) 
				{
					case EMIE_MOUSE_WHEEL:  // zooming						
						// tbd: find a way to smoth zooming	
						distance *= (((-event.MouseInput.Wheel)+1)/2+.5f);
						if (this->bFirstPerson) 
						{
							if (distance > MINZOOMRANGE ) 
							{
								this->bFirstPerson = false;
								Character->setVisible(true);
							} 	
							if (distance < MINZOOMRANGE)
								distance = MINZOOMRANGE;
						}
						else
						{							
							if (distance >= MAXZOOMRANGE ) 
								distance = MAXZOOMRANGE; 
							if (distance < MINZOOMRANGE ) 
							{
								distance = MINZOOMRANGE;    // tbd: switch to 1st person							
								this->bFirstPerson = true;
								Character->setVisible(false);
							}			
						}						
						return true;
						break;
						
					case EMIE_LMOUSE_PRESSED_DOWN:  // Manual Camera Rotation
						this->CameraRotating = true;
						return true;
						break;

					case EMIE_RMOUSE_PRESSED_DOWN:	// character rotation
						this->CharacterRotating = true;
						return true;
						break;

					case EMIE_MOUSE_MOVED:
						if (this->CameraRotating || this->CharacterRotating)
						{
							int DeltaX = event.MouseInput.X - OldMouseX;
							int DeltaY = event.MouseInput.Y - OldMouseY;
							OldMouseX = event.MouseInput.X;
							OldMouseY = event.MouseInput.Y;	
						
							if (this->CameraRotating)
							{
								m_updated = true;

								// Kamera rotieren							
								if (DeltaX > 0)
								{
									CamRotationAngleY += (DeltaX*CAMERASPEED);
									while (CamRotationAngleY > 2*PI)
										CamRotationAngleY -= 2*PI;
								}
								else
								{
									CamRotationAngleY += (DeltaX*CAMERASPEED);
									while (CamRotationAngleY < 2*PI)
										CamRotationAngleY += 2*PI;
								}
								// tbd: cam rotation up/down
								if (DeltaY > 0)
								{
								
								}
								else
								{
								
								}

							}

							if (this->CharacterRotating)
							{   // tbd: rotation depending on value of DeltaX
								if (DeltaX > 0)
								{	
									irr::core::vector3df RotVect; 
									RotVect =  Character->getRotation();
									RotVect.Y = RotVect.Y + CHARROTATIONSPEED;								
									Character->setRotation(RotVect); 																	
								}
								else
								{
									irr::core::vector3df RotVect; 
									RotVect =  Character->getRotation();
									RotVect.Y = RotVect.Y - CHARROTATIONSPEED;								
									Character->setRotation(RotVect); 								
								}
							}												
						}					
						return true;
						break;
					
					case EMIE_MMOUSE_PRESSED_DOWN:									
						this->distance = STARTDISTANCE;						
						return true;
						break;
						
					case EMIE_LMOUSE_LEFT_UP:	// stop manual camera rotation							
						this->CameraRotating = false;
						CamRotationAngleY = STARTANGLE;
						return true;
						break;
						// Kamera wieder in urspr. position						

					case EMIE_RMOUSE_LEFT_UP:	// stop character rotation
						this->CharacterRotating = false;
						return true;
						break;

				} ;
		}
		
		if (event.EventType == irr::EET_KEY_INPUT_EVENT)
		{
			switch (event.KeyInput.Key)
			{
			case irr::KEY_KEY_W: // switch wire frame mode
				Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe);
				Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false);
				return true;
			case irr::KEY_KEY_P: // switch wire frame mode
				Terrain->setMaterialFlag(video::EMF_POINTCLOUD, !Terrain->getMaterial(0).PointCloud);
				Terrain->setMaterialFlag(video::EMF_WIREFRAME, false);
				return true;
			case irr::KEY_KEY_D: // toggle detail map
				Terrain->setMaterialType(
					Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ? 
					video::EMT_DETAIL_MAP : video::EMT_SOLID);
				return true;
			case irr::KEY_ESCAPE:	// quit tutorial
				this->device->closeDevice(); 
				return true;
			}
		}		

		if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown  )
		{   			
			switch (event.KeyInput.Key)
			{		
			case irr::KEY_UP:							
				this->bRunDirectU = true;			
				this->bIsRunning = true;								
				return true;			
			case irr::KEY_DOWN: 				
				this->bRunDirectD = true;												
				this->bIsRunning = true;			
				return true;
			case irr::KEY_LEFT:  			
				this->bRunDirectL = true;												
				this->bIsRunning = true;			
				return true;
			case irr::KEY_RIGHT: 
				this->bRunDirectR = true;											
				this->bIsRunning = true;				
				return true;			
			}
		}		
		
		// if one of the walk keys is lifted and no other walk key is pressed -> stop run animation
		if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
		{
			switch (event.KeyInput.Key)
			{		
			case irr::KEY_UP:					
				this->bRunDirectU = false;	
				if (!(this->bRunDirectR || this->bRunDirectL || this->bRunDirectD))
					this->bIsRunning = false;									
				return true;			
			case irr::KEY_DOWN: 						
				this->bRunDirectD = false;	
				if (!(this->bRunDirectR || this->bRunDirectL || this->bRunDirectU))
					this->bIsRunning = false;														
				return true;
			case irr::KEY_LEFT:  		
				this->bRunDirectL = false;
				if (!(this->bRunDirectR || this->bRunDirectU || this->bRunDirectD))
					this->bIsRunning = false;																		
				return true;
			case irr::KEY_RIGHT: 				
				this->bRunDirectR = false;
				if (!(this->bRunDirectL || this->bRunDirectU || this->bRunDirectD))
					this->bIsRunning = false;																				
				return true;			
			}
		}		
		return false;
	}
private:
	bool bIsRunning;	
	bool bRunDirectU;
	bool bRunDirectD;
	bool bRunDirectL;
	bool bRunDirectR;

	bool bFirstPerson;
	scene::ISceneNode* Terrain;
	scene::IAnimatedMeshSceneNode* Character;
	IrrlichtDevice* device;


	scene::ICameraSceneNode* pCamera;

	irr::core::vector3df m_lastTargetPos;
	
	irr::core::vector3df Charpos;

	bool m_updated;
	float distance;

	bool CameraRotating;
	bool CharacterRotating;

	float CamRotationAngleY;

	int OldMouseX;
	int OldMouseY;

	bool IsAnimatingRun;

	void StartRunAnimation()
	{
		if (!this->IsAnimatingRun)
		{
			Character->setMD2Animation(scene::EMAT_RUN); 	
			this->IsAnimatingRun = true;
		}
	};


	void StopRunAnimation()
	{
		if (this->IsAnimatingRun)
		{
			Character->setMD2Animation(scene::EMAT_STAND);	
			this->IsAnimatingRun = false;
		}
	};
};
//****************************************************
//*	int main()										 *
//****************************************************
int main()
{
	// let user select driver type
	video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		" (otherKey) exit\n\n");

	char i;
	std::cin >> i;

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		default: return 1;
	}	

	// create device

	IrrlichtDevice* device = createDevice(driverType, core::dimension2d<s32>(WIDTH,HEIGHT));

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

	
	/*
	First, we add standard stuff to the scene: A nice irrlicht engine
	logo, a small help text, a user controlled camera, and we disable
	the mouse cursor.
	*/   

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

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

	// add irrlicht logo
	env->addImage(driver->getTexture("../../media/irrlichtlogo2.png"),
		core::position2d<s32>(10,10));

	//set other font
	env->getSkin()->setFont(env->getFont("../../media/fontlucida.png"));

	// add some help text
	gui::IGUIStaticText* text = env->addStaticText(
		L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map",
		core::rect<s32>(10,440,250,475), true, true, 0, -1, true);

	// add camera
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();

	camera->setPosition(core::vector3df(1900*2,255*2,3700*2));
	camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
	camera->setFarValue(12000.0f);

	//mouse cursor
	device->getCursorControl()->setVisible(true);
	device->getCursorControl()->setPosition(1,1);  

	// add terrain scene node
	scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode( 
		"../../media/terrain-heightmap.bmp",
		0,										// parent node
		-1,										// node id
		core::vector3df(0.f, 0.f, 0.f),			// position
		core::vector3df(0.f, 0.f, 0.f),			// rotation
		core::vector3df(40.f, 4.4f, 40.f),		// scale
		video::SColor ( 255, 255, 255, 255 ),	// vertexColor,
		5,										// maxLOD
		scene::ETPS_17,							// patchSize
		4										// smoothFactor
		);

	terrain->setMaterialFlag(video::EMF_LIGHTING, false);
	terrain->setMaterialTexture(0, driver->getTexture("../../media/terrain-texture.jpg"));
	terrain->setMaterialTexture(1, driver->getTexture("../../media/detailmap3.jpg"));	
	terrain->setMaterialType(video::EMT_DETAIL_MAP);
	terrain->scaleTexture(1.0f, 20.0f);	

	/*
	To be able to do collision with the terrain, we create a triangle selector.
	If you want to know what triangle selectors do, just take a look into the 
	collision tutorial. The terrain triangle selector works together with the
	terrain. To demonstrate this, we create a collision response animator 
	and attach it to the camera, so that the character wont fall throught the terrain.
	*/

	// create triangle selector for the terrain	
	scene::ITriangleSelector* selector
		= smgr->createTerrainTriangleSelector(terrain, 0);
	terrain->setTriangleSelector(selector);
	selector->drop();

	scene::IAnimatedMeshSceneNode* Character = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/sydney.md2"));
	
	// create collision response animator and attach it to the Character
	scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
		selector, Character, core::vector3df(60,100,60),
		core::vector3df(0,-100,0), 
		core::vector3df(0,50,0));
	Character->addAnimator(anim); 	
	anim->drop();

	// create event receiver
	MyEventReceiver receiver(terrain,Character,device,camera);
	device->setEventReceiver(&receiver);

// create skybox
	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
	smgr->addSkyBoxSceneNode(
		driver->getTexture("../../media/irrlicht2_up.jpg"),
		driver->getTexture("../../media/irrlicht2_dn.jpg"),
		driver->getTexture("../../media/irrlicht2_lf.jpg"),
		driver->getTexture("../../media/irrlicht2_rt.jpg"),
		driver->getTexture("../../media/irrlicht2_ft.jpg"),
		driver->getTexture("../../media/irrlicht2_bk.jpg"));
	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

/* Model Teil */
		Character->setMaterialFlag(video::EMF_LIGHTING, false);

		Character->setFrameLoop(160, 183);
		Character->setAnimationSpeed(40);		
		Character->setMD2Animation(scene::EMAT_STAND);
		Character->setRotation(core::vector3df(0,180.0f,0));
		Character->setMaterialTexture(0, driver->getTexture("../../media/sydney.bmp"));
		Character->setPosition(core::vector3df(1900*2,255*2,3700*2)) ;

	
	// That's it, draw everything.
	int lastFPS = -1;

	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, 0 );

		smgr->drawAll();
		env->drawAll();

		driver->endScene();

		// display frames per second in window title
		int fps = driver->getFPS();
		if (lastFPS != fps)
		{
			core::stringw str = L"WoW like Camera&Character - Irrlicht Engine [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;
			// Also print terrain height of current camera position
			// We can use camera position because terrain is located at coordinate origin
			str += " Height: ";
			str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z);

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
		receiver.Update();
		receiver.DoRunning();
	}

	device->drop();
	
	return 0;
}
fukuda
Posts: 23
Joined: Mon May 14, 2007 6:32 pm
Location: Barcelona, Spain

Post by fukuda »

I just tested your last code update, it compiles well, but the .exe crashes with all the options. :(
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

fukuda wrote:I just tested your last code update, it compiles well, but the .exe crashes with all the options. :(
Shouldnt crash.
What system & configuration do you use ?

I compiled it with msvstudio2005 on vista64 and it runs on the same machine and on a winxp ( 32 ) machine without problems.

Where have you put the project ?
Its assumed that its located in /Irrlicht/Examples/ProjectFolder

// edit
Another source for problems might be the irrlicht version your using.
I compiled and run it with 1.3.1.

Atm i'm still working on the next minor update.
When its ready ill upload a standalone folder with no need to place it in the irrlicht/examples folder.
Hope this solves some problems.
fukuda
Posts: 23
Joined: Mon May 14, 2007 6:32 pm
Location: Barcelona, Spain

Post by fukuda »

I use windows xp,
I compiled the .cpp with Dev-C++ in my own projects path,
I configured the project to link the libraries and I'm using 1.3.1 vesion :?

Code: Select all

/*
This tutorial will show how to implement a camera and character display which is a copy of the
one used in World of Warcraft.
Its purpose is to offer the Community an example for a camera and movement system for rpg or
as a base to develop theyr own movement/camera system.

It is based on the irrlicht Tutorial 12 and
NightBirds NWN Camera example http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=3245

Atm its all a bitt messy and very unclean but its still work in progress , althought comments
or suggestions are always welcome.
You can contact me in the Irrlicht Forums
Username: Jonchaos
or per Email
Antharon@Hotmail.com
*/
#include <IRR/irrlicht.h>
#include <iostream>

using namespace irr;

#pragma comment(lib, "Irrlicht.lib")
//****************************************************
//*                                        *
//****************************************************
#define CAMERASPEED 0.1f      // Camerarotationspeed
#define CHARROTATIONSPEED 3.0f
#define PI 3.14159265f         
#define WIDTH 640            // screen width
#define HEIGHT 480            // screen height
#define STARTDISTANCE 35      // cam distance start
#define STARTANGLE 0.0f         // cam angle
#define MAXZOOMRANGE 100
#define MINZOOMRANGE 30
//****************************************************
//*                                        *
//****************************************************
class MyEventReceiver : public IEventReceiver
{
public:

   MyEventReceiver(scene::ISceneNode* terrain ,
               scene::IAnimatedMeshSceneNode* ptrCharacter,
               IrrlichtDevice* ptrDevice,
               scene::ICameraSceneNode* ptrCamera)
   {
      // store pointer to terrain so we can change its drawing mode
      this->Terrain = terrain;
      this->Character = ptrCharacter;
      this->device = ptrDevice;
      this->pCamera = ptrCamera;
      this->CamRotationAngleY = STARTANGLE;
      this->distance = STARTDISTANCE;
      this->bIsRunning = false;            // is the character running ?
      this->bRunDirectU = false;
      this->bRunDirectD = false;
      this->bRunDirectL = false;
      this->bRunDirectR = false;
      this->CameraRotating = false;
      this->CharacterRotating = false;
      this->OldMouseX = 0;
      this->OldMouseY = 0;
      this->IsAnimatingRun = false;
      this->bFirstPerson = false;
   }
   
   void Update()
   {
      if (!pCamera || !Character) return;
      
      if (m_lastTargetPos != Character->getPosition())
      {
         m_updated = true;
         m_lastTargetPos = Character->getPosition();
      }
      
      if (m_updated)
      {
         m_updated = false;
         irr::core::vector3df m_Camerapos = m_lastTargetPos;
         m_Camerapos.X += distance*sin(CamRotationAngleY);
         m_Camerapos.Z += distance*cos(CamRotationAngleY);
         m_Camerapos.Y += distance;
         pCamera->setPosition(m_Camerapos);
         pCamera->setTarget(m_lastTargetPos);
      }

   if (this->bIsRunning)
      this->StartRunAnimation();
   else      
      this->StopRunAnimation();


}

void DoRunning()
{
   // tbd : Character Movement depending on character rotation
   if (this->bIsRunning)
   {
      if (this->bRunDirectU)
      {
         Charpos   = Character->getPosition();
         Charpos.X = Charpos.X - 1.0f ;
         Character->setPosition(Charpos);
      }

      if (this->bRunDirectD)
      {
         Charpos   = Character->getPosition();
         Charpos.X = Charpos.X + 1.0f ;
         Character->setPosition(Charpos);
      }

      if (this->bRunDirectL)
      {
         Charpos   = Character->getPosition();
         Charpos.Z = Charpos.Z - 1.0f ;
         Character->setPosition(Charpos);
      }
   
      if (this->bRunDirectR)
      {
         Charpos   = Character->getPosition();
         Charpos.Z = Charpos.Z + 1.0f ;
         Character->setPosition(Charpos);
      }
   this->Update();
   }
}

   bool OnEvent(SEvent event)
   {            
      if (event.EventType == EET_MOUSE_INPUT_EVENT)
         {
            switch (event.MouseInput.Event)
            {
               case EMIE_MOUSE_WHEEL:  // zooming                  
                  // tbd: find a way to smoth zooming   
                  distance *= (((-event.MouseInput.Wheel)+1)/2+.5f);
                  if (this->bFirstPerson)
                  {
                     if (distance > MINZOOMRANGE )
                     {
                        this->bFirstPerson = false;
                        Character->setVisible(true);
                     }    
                     if (distance < MINZOOMRANGE)
                        distance = MINZOOMRANGE;
                  }
                  else
                  {                     
                     if (distance >= MAXZOOMRANGE )
                        distance = MAXZOOMRANGE;
                     if (distance < MINZOOMRANGE )
                     {
                        distance = MINZOOMRANGE;    // tbd: switch to 1st person                     
                        this->bFirstPerson = true;
                        Character->setVisible(false);
                     }         
                  }                  
                  return true;
                  break;
                  
               case EMIE_LMOUSE_PRESSED_DOWN:  // Manual Camera Rotation
                  this->CameraRotating = true;
                  return true;
                  break;

               case EMIE_RMOUSE_PRESSED_DOWN:   // character rotation
                  this->CharacterRotating = true;
                  return true;
                  break;

               case EMIE_MOUSE_MOVED:
                  if (this->CameraRotating || this->CharacterRotating)
                  {
                     int DeltaX = event.MouseInput.X - OldMouseX;
                     int DeltaY = event.MouseInput.Y - OldMouseY;
                     OldMouseX = event.MouseInput.X;
                     OldMouseY = event.MouseInput.Y;   
                  
                     if (this->CameraRotating)
                     {
                        m_updated = true;

                        // Kamera rotieren                     
                        if (DeltaX > 0)
                        {
                           CamRotationAngleY += (DeltaX*CAMERASPEED);
                           while (CamRotationAngleY > 2*PI)
                              CamRotationAngleY -= 2*PI;
                        }
                        else
                        {
                           CamRotationAngleY += (DeltaX*CAMERASPEED);
                           while (CamRotationAngleY < 2*PI)
                              CamRotationAngleY += 2*PI;
                        }
                        // tbd: cam rotation up/down
                        if (DeltaY > 0)
                        {
                        
                        }
                        else
                        {
                        
                        }

                     }

                     if (this->CharacterRotating)
                     {   // tbd: rotation depending on value of DeltaX
                        if (DeltaX > 0)
                        {   
                           irr::core::vector3df RotVect;
                           RotVect =  Character->getRotation();
                           RotVect.Y = RotVect.Y + CHARROTATIONSPEED;                        
                           Character->setRotation(RotVect);                                                    
                        }
                        else
                        {
                           irr::core::vector3df RotVect;
                           RotVect =  Character->getRotation();
                           RotVect.Y = RotVect.Y - CHARROTATIONSPEED;                        
                           Character->setRotation(RotVect);                         
                        }
                     }                                    
                  }               
                  return true;
                  break;
               
               case EMIE_MMOUSE_PRESSED_DOWN:                           
                  this->distance = STARTDISTANCE;                  
                  return true;
                  break;
                  
               case EMIE_LMOUSE_LEFT_UP:   // stop manual camera rotation                     
                  this->CameraRotating = false;
                  CamRotationAngleY = STARTANGLE;
                  return true;
                  break;
                  // Kamera wieder in urspr. position                  

               case EMIE_RMOUSE_LEFT_UP:   // stop character rotation
                  this->CharacterRotating = false;
                  return true;
                  break;

            } ;
      }
      
      if (event.EventType == irr::EET_KEY_INPUT_EVENT)
      {
         switch (event.KeyInput.Key)
         {
         case irr::KEY_KEY_W: // switch wire frame mode
            Terrain->setMaterialFlag(video::EMF_WIREFRAME, !Terrain->getMaterial(0).Wireframe);
            Terrain->setMaterialFlag(video::EMF_POINTCLOUD, false);
            return true;
         case irr::KEY_KEY_P: // switch wire frame mode
            Terrain->setMaterialFlag(video::EMF_POINTCLOUD, !Terrain->getMaterial(0).PointCloud);
            Terrain->setMaterialFlag(video::EMF_WIREFRAME, false);
            return true;
         case irr::KEY_KEY_D: // toggle detail map
            Terrain->setMaterialType(
               Terrain->getMaterial(0).MaterialType == video::EMT_SOLID ?
               video::EMT_DETAIL_MAP : video::EMT_SOLID);
            return true;
         case irr::KEY_ESCAPE:   // quit tutorial
            this->device->closeDevice();
            return true;
         }
      }      

      if (event.EventType == irr::EET_KEY_INPUT_EVENT && event.KeyInput.PressedDown  )
      {            
         switch (event.KeyInput.Key)
         {      
         case irr::KEY_UP:                     
            this->bRunDirectU = true;         
            this->bIsRunning = true;                        
            return true;         
         case irr::KEY_DOWN:             
            this->bRunDirectD = true;                                    
            this->bIsRunning = true;         
            return true;
         case irr::KEY_LEFT:           
            this->bRunDirectL = true;                                    
            this->bIsRunning = true;         
            return true;
         case irr::KEY_RIGHT:
            this->bRunDirectR = true;                                 
            this->bIsRunning = true;            
            return true;         
         }
      }      
      
      // if one of the walk keys is lifted and no other walk key is pressed -> stop run animation
      if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
      {
         switch (event.KeyInput.Key)
         {      
         case irr::KEY_UP:               
            this->bRunDirectU = false;   
            if (!(this->bRunDirectR || this->bRunDirectL || this->bRunDirectD))
               this->bIsRunning = false;                           
            return true;         
         case irr::KEY_DOWN:                   
            this->bRunDirectD = false;   
            if (!(this->bRunDirectR || this->bRunDirectL || this->bRunDirectU))
               this->bIsRunning = false;                                          
            return true;
         case irr::KEY_LEFT:        
            this->bRunDirectL = false;
            if (!(this->bRunDirectR || this->bRunDirectU || this->bRunDirectD))
               this->bIsRunning = false;                                                      
            return true;
         case irr::KEY_RIGHT:             
            this->bRunDirectR = false;
            if (!(this->bRunDirectL || this->bRunDirectU || this->bRunDirectD))
               this->bIsRunning = false;                                                            
            return true;         
         }
      }      
      return false;
   }
private:
   bool bIsRunning;   
   bool bRunDirectU;
   bool bRunDirectD;
   bool bRunDirectL;
   bool bRunDirectR;

   bool bFirstPerson;
   scene::ISceneNode* Terrain;
   scene::IAnimatedMeshSceneNode* Character;
   IrrlichtDevice* device;


   scene::ICameraSceneNode* pCamera;

   irr::core::vector3df m_lastTargetPos;
   
   irr::core::vector3df Charpos;

   bool m_updated;
   float distance;

   bool CameraRotating;
   bool CharacterRotating;

   float CamRotationAngleY;

   int OldMouseX;
   int OldMouseY;

   bool IsAnimatingRun;

   void StartRunAnimation()
   {
      if (!this->IsAnimatingRun)
      {
         Character->setMD2Animation(scene::EMAT_RUN);    
         this->IsAnimatingRun = true;
      }
   };


   void StopRunAnimation()
   {
      if (this->IsAnimatingRun)
      {
         Character->setMD2Animation(scene::EMAT_STAND);   
         this->IsAnimatingRun = false;
      }
   };
};
//****************************************************
//*   int main()                               *
//****************************************************
int main()
{
   // let user select driver type
   video::E_DRIVER_TYPE driverType = video::EDT_DIRECT3D9;

   printf("Please select the driver you want for this example:\n"\
      " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
      " (d) Software Renderer\n (e) Burning's Software Renderer\n"\
      " (otherKey) exit\n\n");

   char i;
   std::cin >> i;

   switch(i)
   {
      case 'a': driverType = video::EDT_DIRECT3D9;break;
      case 'b': driverType = video::EDT_DIRECT3D8;break;
      case 'c': driverType = video::EDT_OPENGL;   break;
      case 'd': driverType = video::EDT_SOFTWARE; break;
      case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
      default: return 1;
   }   

   // create device

   IrrlichtDevice* device = createDevice(driverType, core::dimension2d<s32>(WIDTH,HEIGHT));

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

   
   /*
   First, we add standard stuff to the scene: A nice irrlicht engine
   logo, a small help text, a user controlled camera, and we disable
   the mouse cursor.
   */   

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

   driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);

  /* // add irrlicht logo
   env->addImage(driver->getTexture("irrlichtlogo2.png"),
      core::position2d<s32>(10,10));

   //set other font
   env->getSkin()->setFont(env->getFont("fontlucida.png"));

   // add some help text
   gui::IGUIStaticText* text = env->addStaticText(
      L"Press 'W' to change wireframe mode\nPress 'D' to toggle detail map",
      core::rect<s32>(10,440,250,475), true, true, 0, -1, true);
   */
   // add camera
   scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();

   camera->setPosition(core::vector3df(1900*2,255*2,3700*2));
   camera->setTarget(core::vector3df(2397*2,343*2,2700*2));
   camera->setFarValue(12000.0f);

   //mouse cursor
   device->getCursorControl()->setVisible(true);
   device->getCursorControl()->setPosition(1,1); 
   /*
   // add terrain scene node
   scene::ITerrainSceneNode* terrain = smgr->addTerrainSceneNode(
      "terrain-heightmap.bmp",
      0,                              // parent node
      -1,                              // node id
      core::vector3df(0.f, 0.f, 0.f),         // position
      core::vector3df(0.f, 0.f, 0.f),         // rotation
      core::vector3df(40.f, 4.4f, 40.f),      // scale
      video::SColor ( 255, 255, 255, 255 ),   // vertexColor,
      5,                              // maxLOD
      scene::ETPS_17,                     // patchSize
      4                              // smoothFactor
      );

   terrain->setMaterialFlag(video::EMF_LIGHTING, false);
   terrain->setMaterialTexture(0, driver->getTexture("terrain-texture.jpg"));
   terrain->setMaterialTexture(1, driver->getTexture("detailmap3.jpg"));   
   terrain->setMaterialType(video::EMT_DETAIL_MAP);
   terrain->scaleTexture(1.0f, 20.0f);   
   */
   /*
   To be able to do collision with the terrain, we create a triangle selector.
   If you want to know what triangle selectors do, just take a look into the
   collision tutorial. The terrain triangle selector works together with the
   terrain. To demonstrate this, we create a collision response animator
   and attach it to the camera, so that the character wont fall throught the terrain.
   */

   /*// create triangle selector for the terrain   
   scene::ITriangleSelector* selector
      = smgr->createTerrainTriangleSelector(terrain, 0);
   terrain->setTriangleSelector(selector);
   selector->drop();

   scene::IAnimatedMeshSceneNode* Character = smgr->addAnimatedMeshSceneNode(smgr->getMesh("../../media/sydney.md2"));
   
   // create collision response animator and attach it to the Character
   scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
      selector, Character, core::vector3df(60,100,60),
      core::vector3df(0,-100,0),
      core::vector3df(0,50,0));
   Character->addAnimator(anim);    
   anim->drop();*/

   // create event receiver
   MyEventReceiver receiver(NULL,NULL,device,camera);
   device->setEventReceiver(&receiver);

/*// create skybox
   driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
   smgr->addSkyBoxSceneNode(
      driver->getTexture("irrlicht2_up.jpg"),
      driver->getTexture("irrlicht2_dn.jpg"),
      driver->getTexture("irrlicht2_lf.jpg"),
      driver->getTexture("irrlicht2_rt.jpg"),
      driver->getTexture("irrlicht2_ft.jpg"),
      driver->getTexture("irrlicht2_bk.jpg"));
   driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

/* Model Teil *//*
      Character->setMaterialFlag(video::EMF_LIGHTING, false);

      Character->setFrameLoop(160, 183);
      Character->setAnimationSpeed(40);      
      Character->setMD2Animation(scene::EMAT_STAND);
      Character->setRotation(core::vector3df(0,180.0f,0));
      Character->setMaterialTexture(0, driver->getTexture("sydney.bmp"));
      Character->setPosition(core::vector3df(1900*2,255*2,3700*2)) ;

   */
   // That's it, draw everything.
   int lastFPS = -1;

   while(device->run())
   if (device->isWindowActive())
   {
      driver->beginScene(true, true, 0 );

      smgr->drawAll();
      env->drawAll();

      driver->endScene();

      // display frames per second in window title
      int fps = driver->getFPS();
      if (lastFPS != fps)
      {
         core::stringw str = L"WoW like Camera&Character - Irrlicht Engine [";
         str += driver->getName();
         str += "] FPS:";
         str += fps;
         // Also print terrain height of current camera position
         // We can use camera position because terrain is located at coordinate origin
         str += " Height: ";
        // str += terrain->getHeight(camera->getAbsolutePosition().X, camera->getAbsolutePosition().Z);

         device->setWindowCaption(str.c_str());
         lastFPS = fps;
      }
      receiver.Update();
      receiver.DoRunning();
   }

   device->drop();
   
   return 0;
}
as you can see, I commented out some parts, but it still gives an error (the needed files are in the same folder as the project)
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

fukuda wrote: as you can see, I commented out some parts, but it still gives an error (the needed files are in the same folder as the project)
The files aren't needet at all because you commented out all the file loading.
Maybe now there are problems in the main() when it calls

receiver.Update();
receiver.DoRunning();

both functions use a pointer to the Character scene node.
Don't know if they like a NULL pointer.
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

I uploadet the newest version.
In the .rar file is everything needet to run / compile ( dll , lib , include , source , vc8 project ).


The link can be found in post#1


// edit
If someone is experienced in doing 3d math and has a bit spare time i would appreciate help on the following 2 topics:
- character movement depending on the character rotation
- limiting the camera rotation up/down
JonChaos
Posts: 15
Joined: Thu Aug 24, 2006 2:03 pm
Location: Saarland , Germany

Post by JonChaos »

Here is a minor update.
Walkdirection is now calculated based on the character rotation.
Code is a reimplementation from JReuschel1's Code from http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=19282

Code: Select all

void DoRunning()
{
	if (this->bIsRunning)
	{
		float Rotation;
		irr::core::vector3df CharRotation;
		
		CharRotation = this->Character->getRotation();
		Rotation = CharRotation.Y;

		if (this->bRunDirectU) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.X = Charpos.X + ( RUNSPEED * cos(Rotation*PI/180));
			Charpos.Z = Charpos.Z - ( RUNSPEED * sin(Rotation*PI/180));
			Character->setPosition(Charpos); 
		}

		if (this->bRunDirectD) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.X = Charpos.X - ( RUNSPEED * cos(Rotation*PI/180));
			Charpos.Z = Charpos.Z + ( RUNSPEED * sin(Rotation*PI/180));
			Character->setPosition(Charpos); 
		}

		if (this->bRunDirectL) 
		{			
			Charpos	= Character->getPosition(); 
			Charpos.X = Charpos.X - ( RUNSPEED * cos(Rotation*PI/180+3.1416/2)) ;
			Charpos.Z = Charpos.Z + ( RUNSPEED * sin(Rotation*PI/180+3.1416/2)) ;
			Character->setPosition(Charpos);			
		}
	
		if (this->bRunDirectR) 
		{
			Charpos	= Character->getPosition(); 
			Charpos.X = Charpos.X + ( RUNSPEED * cos(Rotation*PI/180+3.1416/2));
			Charpos.Z = Charpos.Z - ( RUNSPEED * sin(Rotation*PI/180+3.1416/2));
			Character->setPosition(Charpos); 
		}
	this->Update(); 
	}
}
TJBaldy
Posts: 16
Joined: Fri Dec 02, 2011 3:06 pm

Re: WoW like camera control & character movement (work in pr

Post by TJBaldy »

I know this thread is years old but I was wondering if anyone with a bit of experience could help with this code? Because this camera seems pretty sweet if I could get it to work. I've got it down to one error but not sure how to fix it:

IntelliSense: object of abstract class type "MyEventReceiver" is not allowed

Created from this code:

Code: Select all

MyEventReceiver receiver(NULL,NULL,device,camera);
Thanks, TJ :)
CuteAlien
Admin
Posts: 9670
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: WoW like camera control & character movement (work in pr

Post by CuteAlien »

Please if you report errors use compile-errors and not IntelliSense messages :-) And always copy-paste them exactly.

But in this case it's probably OnEvent which now needs a const-ref parameter for SEvent. Like: bool OnEvent(const SEvent& event)
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
Post Reply