My first pong in Irrlicht

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
finalsayan
Posts: 5
Joined: Wed Sep 03, 2008 4:10 am
Contact:

My first pong in Irrlicht

Post by finalsayan »

I everybody,
yesterday I try to make my first pong.
By the way i found some problem and I think that the way I construct the game is completely wrong :lol:

First of all I was not able to do it in 2D O_o
How is it possible to create a 2D node? Because I have seen a lot of 3d examples and tutorial and I have understood the way of managing 3d nodes, but what about 2d?

So I decided to make it using the 3D functions of the library. So first I create 2 bars, 1 ball, and other 2 supplementary bars that represent the upper limit and the down limit of the game

The ball can only move following some simple directions.
In the main loop I simply update the position of the ball by taking his position and updating it according to the current direction. I feel that it is very cpu consuming...

thank you for your comments :)

These are the functions needed to catch user input, detect a collision, to change the direction of the ball, to move the bars

Code: Select all

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

using namespace irr;

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

#define VELOCITA 0.01
#define UPLIMIT 30
#define DOWNLIMIT -30


//
class MyEventReceiver: public IEventReceiver {
public:
	// This is the one method that we have to implement
	virtual bool OnEvent(const SEvent& event) {
		// Remember whether each key is down or up
		if (event.EventType == irr::EET_KEY_INPUT_EVENT)
			KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;

		return false;
	}

	// This is used to check whether a key is being held down
	virtual bool IsKeyDown(EKEY_CODE keyCode) const {
		return KeyIsDown[keyCode];
	}

	MyEventReceiver() {
		for (u32 i = 0; i < KEY_KEY_CODES_COUNT; ++i)
			KeyIsDown[i] = false;
	}

private:
	// We use this array to store the current state of each key
	bool KeyIsDown[KEY_KEY_CODES_COUNT];
};

//detect collision of two general nodes
bool collisiondetection(scene::ISceneNode * n1, scene::ISceneNode * n2) {

	core::aabbox3d<f32> box1 = n1->getTransformedBoundingBox();
	core::aabbox3d<f32> box2 = n2->getTransformedBoundingBox();

	if (box1.intersectsWithBox(box2)) {
		return true;
	} else
		return false;

}

//Move the bars on user input
void muovibarre(scene::ISceneNode * p1, scene::ISceneNode * p2,
		MyEventReceiver receiver) {


	core::vector3df poscorr = p1->getPosition();
	if (receiver.IsKeyDown(irr::KEY_KEY_W) && poscorr.Y < UPLIMIT) {
		//printf("key pressed W");

		poscorr.Y = poscorr.Y + VELOCITA;
		p1->setPosition(poscorr);
	} else if (receiver.IsKeyDown(irr::KEY_KEY_S) && poscorr.Y > DOWNLIMIT) {
		//printf("key pressed S");

		poscorr.Y = poscorr.Y - VELOCITA;
		p1->setPosition(poscorr);
	}

	core::vector3df poscorr2 = p2->getPosition();
	if (receiver.IsKeyDown(irr::KEY_KEY_O) && poscorr2.Y < UPLIMIT) {
		//printf("key pressed W");

		poscorr2.Y = poscorr2.Y + VELOCITA;
		p2->setPosition(poscorr2);
	} else if (receiver.IsKeyDown(irr::KEY_KEY_L) && poscorr2.Y > DOWNLIMIT) {
		//printf("key pressed S");

		poscorr2.Y = poscorr2.Y - VELOCITA;
		p2->setPosition(poscorr2);
	}

}

//Move the ball according to the current direction
void muovipallino(scene::ISceneNode * node, float coeff, int dir) {

	//1 vado verso destra
	//2 vado verso sinistra
	//remind:  <-----x
	//					^
	//					|
	//					|
	//					y
	core::vector3df posizione;
	if (dir == 1) {

		posizione = node->getPosition();
		posizione.X = posizione.X - VELOCITA;
		if (coeff == 1)
			posizione.Y = posizione.Y + VELOCITA;
		else if (coeff == -1)
			posizione.Y = posizione.Y - VELOCITA;
		node->setPosition(posizione);

	} else {

		posizione = node->getPosition();
		posizione.X = posizione.X + VELOCITA;
		if (coeff == 1)
			posizione.Y = posizione.Y + VELOCITA;
		else if (coeff == -1)
			posizione.Y = posizione.Y - VELOCITA;
		node->setPosition(posizione);
	}

}

//Update the direction of the ball after a collision
void collideandupdate(scene::ISceneNode * node, scene::ISceneNode * p1,
		scene::ISceneNode * p2, scene::ISceneNode * uplimit,
		scene::ISceneNode * downlimit, MyEventReceiver receiver, float* coeff,
		int* dir) {

	//Collisione con P1
	if (collisiondetection(node, p1) && !(receiver.IsKeyDown(irr::KEY_KEY_W)
			|| receiver.IsKeyDown(irr::KEY_KEY_S))) {

		*dir = 1;

	}
	if (collisiondetection(node, p1) && receiver.IsKeyDown(irr::KEY_KEY_W)) {

		*dir = 1;
		*coeff = -1;
	}
	if (collisiondetection(node, p1) && receiver.IsKeyDown(irr::KEY_KEY_S)) {
		*dir = 1;
		*coeff = 1;
	}

	//Collisione con P2
	if (collisiondetection(node, p2) && !(receiver.IsKeyDown(irr::KEY_KEY_O)
			|| receiver.IsKeyDown(irr::KEY_KEY_L))) {

		*dir = 0;

	}
	if (collisiondetection(node, p2) && receiver.IsKeyDown(irr::KEY_KEY_O)) {

		*dir = 0;
		*coeff = -1;

	}
	if (collisiondetection(node, p2) && receiver.IsKeyDown(irr::KEY_KEY_L)) {

		*dir = 0;
		*coeff = 1;
	}


	 if (collisiondetection(node, uplimit)) {
		 *coeff = -1;
		 printf("collision uplimit");
	 }
	 if (collisiondetection(node, downlimit)) {
		 *coeff = 1;
		 printf("collision downlimit");
	 }

}
Finally this is the main that just puts the objects in the space

Code: Select all

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"
		" (f) NullDevice\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;
	case 'f':
		driverType = video::EDT_NULL;
		break;
	default:
		return 0;
	}

	// create device
	MyEventReceiver receiver;

	IrrlichtDevice* device = createDevice(driverType, core::dimension2d<s32>(
			420, 300), 16, false, false, false, &receiver);

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


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

	scene::ISceneNode * node = smgr->addSphereSceneNode();
	if (node) {
		node->setPosition(core::vector3df(0, 0, 1));
		node->setScale(core::vector3df(0.3, 0.3, 0.3));
		//node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
		node->setMaterialFlag(video::EMF_LIGHTING, false);
	}

	scene::ISceneNode * p1 = smgr->addCubeSceneNode();
	if (p1) {
		p1->setPosition(core::vector3df(48, 0, 1));
		p1->setScale(core::vector3df(0.1, 1, 0.1));
		//p1->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
		p1->setMaterialFlag(video::EMF_LIGHTING, false);
	}

	scene::ISceneNode * p2 = smgr->addCubeSceneNode();

	if (p2) {
		p2->setPosition(core::vector3df(-48, 0, 1));
		p2->setScale(core::vector3df(0.1, 1, 0.1));
		//p2->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
		p2->setMaterialFlag(video::EMF_LIGHTING, false);
	}

	scene::ISceneNode * uplimit = smgr->addCubeSceneNode();
	scene::ISceneNode * downlimit = smgr->addCubeSceneNode();

	if (uplimit) {
		uplimit->setPosition(core::vector3df(0, 35, 1));
		uplimit->setScale(core::vector3df(10, 0.1, 0.1));
		//uplimit->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
		uplimit->setMaterialFlag(video::EMF_LIGHTING, false);
	}
	if (downlimit) {
		downlimit->setPosition(core::vector3df(0, -35, 1));
		downlimit->setScale(core::vector3df(10, 0.1, 0.1));
		//downlimit->setMaterialTexture(0, driver->getTexture("../../media/t351sml.jpg"));
		downlimit->setMaterialFlag(video::EMF_LIGHTING, false);
	}

	video::ITexture* images = driver->getTexture("../../media/pong.bmp");

	scene::ICameraSceneNode * cam = smgr->addCameraSceneNode(0,
			core::vector3df(0, 0, 50), core::vector3df(0, 0, 0), 1);

	float coeff = 0;
	int dir = 1;
	while (device->run()) {

		driver->beginScene(true, true, video::SColor(255, 113, 113, 133));

		//draw background
		driver->draw2DImage(images, core::position2d<s32>(0,0));

		//Verify if there is a collision
		collideandupdate(node, p1, p2, uplimit, downlimit, receiver, &coeff,
				&dir);

		//Move the ball
		muovipallino(node, coeff, dir);
		//Move the bars
		muovibarre(p1, p2, receiver);

		smgr->drawAll(); // draw the 3d scene

		driver->endScene();

	}

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

	return 0;
}
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Hey, that's pretty nice. Congratulations on getting that done so fast!
How is it possible to create a 2D node?
It depends what you mean. All Irrlicht "nodes" are 3d entities, so a "2D node" is somewhat of an oxymoron. There are some 2D methods, but I guess you already know about them, since you're using one. ;)

If you use an orthographic camera, then all your nodes are (sort of) 2D, since there's no perspective. If you're going for a toony/retro soccer game, then you may want to consider using an orthographic camera.

I feel that it is very cpu consuming...
It looks fine to me. I can't see anything inefficient in the architecture.

If you mean that it's consuming all of your CPU (or all of 1 core) then sure, that's a result of sitting in a tight while() loop. It's not Irrlicht doing that; you can remove all of the rendering, and it'll still eat all the CPU.

If you want to cut down the CPU load, then you can either sleep for a short period, or (probably better) turn on vsync in the createDevice() call.

The first enhancement that I'd suggest is to make the movement framerate independent.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
finalsayan
Posts: 5
Joined: Wed Sep 03, 2008 4:10 am
Contact:

Post by finalsayan »


The first enhancement that I'd suggest is to make the movement framerate independent.
thank you for the suggestion :) I will try
ehenkes
Posts: 47
Joined: Sun Aug 03, 2008 2:52 pm
Location: Germany
Contact:

Post by ehenkes »

Quite good approach.

My proposals:

Open irr sub-namespaces to improve readability:

Code: Select all

using namespace irr; using namespace core; using namespace scene;
using namespace video; using namespace io; using namespace gui;
Don't use #define; alternatively use C++ constants and float for VELOCITA:

Code: Select all

const f32 VELOCITA  =     0.01f;
const s32 UPLIMIT   =    30;
const s32 DOWNLIMIT =   -30;
use floats for vector3df:

Code: Select all

uplimit->setPosition(vector3df(0.0f, 35.0f, 1.0f));
uplimit->setScale(vector3df(10.0f, 0.1f, 0.1f));
use C++ cout instead of printf(...):

Code: Select all

std::cout << "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"
	 << " (f) NullDevice\n (otherKey) exit\n\n" << std::endl;
//...
std::cout << "collision uplimit"   << std::endl;
ehenkes
Posts: 47
Joined: Sun Aug 03, 2008 2:52 pm
Location: Germany
Contact:

Post by ehenkes »

I changed the code a little bit, increased speed of the bars, checked if X>50 or X<-50 and counted the hits for left and right player. Without textures it looks like the classical style.

Code: Select all

// Pong.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
//
#include "stdafx.h"
#include <irrlicht.h>
#include <iostream>

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

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

const f32 VELOCITY  =  0.5f;
const s32 UPLIMIT   =    30;
const s32 DOWNLIMIT =   -30;
f32 velocity  =  VELOCITY;
s32 hits1 = 0;
s32 hits2 = 0;

class MyEventReceiver: public IEventReceiver 
{
   public:
		 virtual bool OnEvent(const SEvent& event) 
		 {
		  	if (event.EventType == EET_KEY_INPUT_EVENT)
					KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
				return false;
		 }

		 virtual bool IsKeyDown(EKEY_CODE keyCode) const 
		 {
		   return KeyIsDown[keyCode];
		 }

		 MyEventReceiver() 
		 {
				for (u32 i = 0; i < KEY_KEY_CODES_COUNT; ++i)
		 	    KeyIsDown[i] = false;
		 }
  private:
		 bool KeyIsDown[KEY_KEY_CODES_COUNT];
};

//detect collision 
bool isCollision(ISceneNode* n1, ISceneNode* n2) 
{
   aabbox3d<f32> box1 = n1->getTransformedBoundingBox();
   aabbox3d<f32> box2 = n2->getTransformedBoundingBox();

   if (box1.intersectsWithBox(box2)) 
      return true;
	 else
      return false;
}

//move the bars according to user input
void moveBar(ISceneNode* bar1, ISceneNode* bar2, MyEventReceiver receiver) 
{
   const f32 SPEEDFACTOR = 2.0f; 
	 vector3df poscorr = bar1->getPosition();
   if (receiver.IsKeyDown(KEY_KEY_W) && poscorr.Y < UPLIMIT) 
	 {
      poscorr.Y = poscorr.Y + SPEEDFACTOR*velocity;
      bar1->setPosition(poscorr);
   } 
	 else if (receiver.IsKeyDown(KEY_KEY_S) && poscorr.Y > DOWNLIMIT) 
	 {
      poscorr.Y = poscorr.Y - SPEEDFACTOR*velocity;
      bar1->setPosition(poscorr);
   }

   vector3df poscorr2 = bar2->getPosition();
   if (receiver.IsKeyDown(KEY_KEY_O) && poscorr2.Y < UPLIMIT) 
	 {
      poscorr2.Y = poscorr2.Y + SPEEDFACTOR*velocity;
      bar2->setPosition(poscorr2);
   } 
	 else if (receiver.IsKeyDown(KEY_KEY_L) && poscorr2.Y > DOWNLIMIT) 
	 {
      poscorr2.Y = poscorr2.Y - SPEEDFACTOR*velocity;
      bar2->setPosition(poscorr2);
   }
}

//move the ball according to the current direction
void moveBall(ISceneNode* ball, float coeff, int dir) 
{
   vector3df pos = ball->getPosition();
	 if (dir == 1) 
	 {
      pos.X -= velocity;
      pos.Y += coeff*velocity;
	 } 
	 else 
	 {
      pos.X += velocity;
      pos.Y += coeff*velocity;
	 } 
	 
	 if ( (pos.X < -50) || (pos.X > 50) )
   {
		 if (pos.X < -50) ++hits1;
		 if (pos.X >  50) ++hits2;
	   pos.X = 0;
		 dir   = -dir;
	 }
	 ball->setPosition(pos);
}

void updateDirectionAfterCollison(ISceneNode* ball, ISceneNode* bar1, ISceneNode* bar2, ISceneNode* uplimit,
  ISceneNode* downlimit, MyEventReceiver receiver, float* coeff, int* dir) 
{
   //Collision with bar1
   if (isCollision(ball, bar1) && !(receiver.IsKeyDown(KEY_KEY_W) || receiver.IsKeyDown(KEY_KEY_S))) 
	 {
      *dir = 1;
   }
   if (isCollision(ball, bar1) && receiver.IsKeyDown(KEY_KEY_W)) 
	 {
      *dir = 1;
      *coeff = -1;
   }
   if (isCollision(ball, bar1) && receiver.IsKeyDown(KEY_KEY_S)) 
	 {
      *dir = 1;
      *coeff = 1;
   }

   //Collision with bar2
   if (isCollision(ball, bar2) && !(receiver.IsKeyDown(KEY_KEY_O)
         || receiver.IsKeyDown(KEY_KEY_L))) 
	 {
      *dir = 0;
   }
   if (isCollision(ball, bar2) && receiver.IsKeyDown(KEY_KEY_O)) 
	 {
      *dir = 0;
      *coeff = -1;
   }
   if (isCollision(ball, bar2) && receiver.IsKeyDown(KEY_KEY_L)) 
	 {
      *dir = 0;
      *coeff = 1;
   }

   if (isCollision(ball, uplimit)) 
	 {
       *coeff = -1;
			 std::cout << "collision uplimit"   << std::endl;
   }
   if (isCollision(ball, downlimit)) 
	 {
       *coeff = 1;
       std::cout << "collision downlimit" << std::endl;
   }
}

int main() 
{
   E_DRIVER_TYPE driverType = EDT_DIRECT3D9;

	 std::cout << "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"
	 << " (f) NullDevice\n (otherKey) exit\n\n" << std::endl;

   char i;
   std::cin >> i;

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

   // create device
   MyEventReceiver receiver;

   IrrlichtDevice* device = createDevice(driverType, dimension2d<s32>(420, 300), 
		 16, false, false, true, &receiver);
   if (device == 0) return 1; // could not create selected driver.
   IVideoDriver* driver = device->getVideoDriver();
   ISceneManager* smgr  = device->getSceneManager();

   ISceneNode* ball = smgr->addSphereSceneNode();
   if (ball) 
	 {
      ball->setPosition(vector3df(0.0f, 0.0f, 1.0f));
      ball->setScale(vector3df(0.3f, 0.3f, 0.3f));
      ball->setMaterialFlag(EMF_LIGHTING, false);
   }

   ISceneNode* bar1 = smgr->addCubeSceneNode();
   if (bar1) 
	 {
      bar1->setPosition(vector3df(48.0f, 0.0f, 1.0f));
      bar1->setScale(vector3df(0.1f, 1.0f, 0.1f));
      bar1->setMaterialFlag(EMF_LIGHTING, false);
   }

   ISceneNode* bar2 = smgr->addCubeSceneNode();
   if (bar2) 
	 {
      bar2->setPosition(vector3df(-48.0f, 0.0f, 1.0f));
      bar2->setScale(vector3df(0.1f, 1.0f, 0.1f));
      bar2->setMaterialFlag(EMF_LIGHTING, false);
   }

   ISceneNode* uplimit   = smgr->addCubeSceneNode();
   ISceneNode* downlimit = smgr->addCubeSceneNode();

   if (uplimit) 
	 {
      uplimit->setPosition(vector3df(0.0f, 35.0f, 1.0f));
      uplimit->setScale(vector3df(10.0f, 0.1f, 0.1f));
      uplimit->setMaterialFlag(EMF_LIGHTING, false);
   }
   if (downlimit) 
	 {
      downlimit->setPosition(vector3df(0.0f, -35.0f, 1.0f));
      downlimit->setScale(vector3df(10.0f, 0.1f, 0.1f));
      downlimit->setMaterialFlag(EMF_LIGHTING, false);
   }

   ICameraSceneNode* cam = smgr->addCameraSceneNode(0, vector3df(0,0,50), vector3df(0,0,0), 1);

   float coeff = 0;
   int dir = 1;
   while (device->run()) 
	 {
     driver->beginScene(true, true, SColor(255, 113, 113, 133));
				updateDirectionAfterCollison(ball, bar1, bar2, uplimit, downlimit, receiver, &coeff, &dir);
				moveBall(ball, coeff, dir);
				moveBar(bar1, bar2, receiver);
				smgr->drawAll(); // draw the 3d scene
     driver->endScene();

		 s32 fps = driver->getFPS();
		 stringw str = L"PONG   FPS: "; 
		 str += fps;
		 str += L"   Left:  ";
		 str += hits1;
		 str += L"   Right: ";
		 str += hits2;
		 device->setWindowCaption(str.c_str());
   }
   device->drop();

   return 0;
} 
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

void moveBar(ISceneNode* bar1, ISceneNode* bar2, MyEventReceiver receiver)
AHHHHHH :shock:
void updateDirectionAfterCollison(ISceneNode* ball, ISceneNode* bar1, ISceneNode* bar2, ISceneNode* uplimit,
ISceneNode* downlimit, MyEventReceiver receiver, float* coeff, int* dir)
AHHHHHHHHH :shock:

Please, for god's sake, do this instead:
void moveBar(ISceneNode* bar1, ISceneNode* bar2, const MyEventReceiver& receiver)
void updateDirectionAfterCollison(ISceneNode* ball, ISceneNode* bar1, ISceneNode* bar2, ISceneNode* uplimit,
ISceneNode* downlimit, const MyEventReceiver& receiver, float* coeff, int* dir)
I'm gonna have nightmares for weeks...
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
ehenkes
Posts: 47
Joined: Sun Aug 03, 2008 2:52 pm
Location: Germany
Contact:

Post by ehenkes »

Yes, you are right! It is recommendable to transfer parameters by C++ style reference. The basic source code is typical C-style. Hence, some pointers in functions could also be replaced.
dejai
Posts: 522
Joined: Sat Apr 21, 2007 9:00 am

Post by dejai »

Nice :D
Last edited by dejai on Wed Nov 19, 2008 6:41 am, edited 1 time in total.
Programming Blog: http://www.uberwolf.com
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

dejai wrote:Note: vsync may not always be the best option however, in first person shooters or any game that requires really quick reaction time.
Hmm, well there are also quite a lot of other things that you have to take into account. For example, Valve used v-sync because of the motion blurring that they were putting on the scene. They also recommend it for the 360, for some reason that I forget.
TheQuestion = 2B || !2B
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Fact check:

vsync is only really meaningful for CRT monitors. For LCD devices, the 'refresh frequency' is notional. The effect of 'syncing' to an LCD output is entirely dependent on the underlying libraries, drivers, and the pre-processing firmware on the display itself.

Turning on vsync is likely to stall rendering to match the notional 'refresh' rate for your output device, but it's not guaranteed, and you shouldn't rely on it to produce any particular frame rate for a LCD display. It won't stop tearing, since tearing on a LCD is down to the batching of data at some point in the software/firmware pipeline, rather than to missing the (reliable) blank period in the scan of a CRT beam; LCD are actually worse than CRTs in that respect.

That said, my personal view is to turn on vsync anyway because:

1) On CRTs (a few hardcore gamers still use them) you won't see a higher rate anyway.

2) LCDs typically have a response time of 5 - 8ms, which is on the order of the 16ms frequency of a 60fps 'sync'. There's little point in trying to push updates more frequently than about 60fps (16ms), since the absolute time different in updates drops off rapidly.

There's no harm in trying to push updates more frequently (data in excess of what the pipeline can process will just be dropped), but any performance benefit may be wishful thinking. Us normal mortals take ~180ms to react to visual stimuli, so in the absolute best case, you'll react in 190ms rather than 196ms.

Your input device will likely effect your reaction time by more than that, so if you really care about those last few milliseconds, then instead of dropping $300 (every 6 months) on the latest 3d card, spend $50 or so (once) on a 1Mhz Razer mouse or equivalent.

Incidentally, I hope we're all aware that if you're playing on an LCD - particularly an LCD TV - and want minimum reaction time (rather than maximum frame rate) that you should run at the native resolution, since any decrease in the time between updates from rendering at a lower resolution is likely to be dwarfed by the increased output lag due to the output being scaled by the device's firmware.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
GameDude
Posts: 498
Joined: Thu May 24, 2007 12:24 am

Post by GameDude »

Pretty cool
Post Reply