Snake game with irrlicht

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.
pibeytor
Posts: 17
Joined: Thu Nov 01, 2007 2:13 pm

Snake game with irrlicht

Post by pibeytor »

well this what i've done so far..

it's supposed that when you press down one key( W,A,D or S) the esphere has to move to that direction without holding the key..

my code just move one tap at the time...

and another question...

how can i do in order to make other spheres appear at a random place and follow the " head of the snake "

Code: Select all


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

using namespace irr;

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


scene::ISceneNode* node = 0;
IrrlichtDevice* device = 0;
bool teclas[256]={false};

class MyEventReceiver : public IEventReceiver{

public:	
	virtual bool OnEvent(const SEvent& event)	{ 
 

	if (node != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&& !event.KeyInput.PressedDown){		
		switch(event.KeyInput.Key)
		{
		case KEY_KEY_A:		
		case KEY_KEY_D:			
			{				
				core::vector3df v = node->getPosition();
				v.X += event.KeyInput.Key == KEY_KEY_A ? 2.0f : -2.0f;
				node->setPosition(v);	
								
			}			
			return true;


		case KEY_KEY_W:
		case KEY_KEY_S:			
			{				
				core::vector3df v = node->getPosition();
				v.Y += event.KeyInput.Key == KEY_KEY_W ? 2.0f : -2.0f;
				node->setPosition(v);

			}			
			return true;		
		}
	} 
return false;  
}  
};

 
int main()
{	MyEventReceiver receiver;

	// create device

	IrrlichtDevice* device = createDevice(irr::video::EDT_DIRECT3D9,irr::core::dimension2d<irr::s32>(640,480),32,false,false,false,&receiver);
	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();


	node = smgr->addSphereSceneNode();
	node->setPosition(core::vector3df(0,0,0));
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
	node->setMaterialFlag(video::EMF_LIGHTING, false);


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

	int lastFPS = -1;

	while(device->run())
	{
		driver->beginScene(true, true, video::SColor(0,0,100,200));
	
		smgr->drawAll(); // draw the 3d scene
		device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo)

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
			core::stringw tmp(L"Movement Example - Irrlicht Engine [");
			tmp += driver->getName();
			tmp += L"] fps: "; 
			tmp += fps;

			device->setWindowCaption(tmp.c_str());
			lastFPS = fps;
		}
		//node->setPosition(node->getPosition() + core::vector3df(0.01f,0,0) );
	}

	device->drop();
	
	return 0;
}


Last edited by pibeytor on Wed Jan 23, 2008 7:16 am, edited 1 time in total.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

You have to?
pibeytor
Posts: 17
Joined: Thu Nov 01, 2007 2:13 pm

Post by pibeytor »

yes.. it's for my school project...

we have to use lists or whatever they are called..

so i need something to start.. but i need help..
Andreas
Posts: 166
Joined: Sun Oct 31, 2004 7:15 am
Location: Münster / Germany
Contact:

Post by Andreas »

I guess a good start would be to show us what you've got so far. Did you copy&paste the tutorials? Did you take a look at the irrlicht API? Or did you maybe program a little game (with irrlicht?) before?

If not, these are the places to start:
http://irrlicht.sourceforge.net/tut001.html
http://irrlicht.sourceforge.net/docu/
http://irrlicht.sourceforge.net/docu/cl ... 1list.html

I'm sure there are enough people here willing to help, but i guess no one is interested in doing your homework for you. :wink:
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Post by greenya »

pibeytor wrote:so i need something to start.. but i need help..
http://en.wikipedia.org/wiki/Snake_%28video_game%29
rogerborg
Admin
Posts: 3590
Joined: Mon Oct 09, 2006 9:36 am
Location: Scotland - gonnae no slag aff mah Engleesh
Contact:

Post by rogerborg »

Indeed. STFW would be my initial response, particularly as we already advised you to be explicit with your questions.

I suggest that you post your full, unabridged, unedited project requirements, plus whatever you've produced on your own so far. If you show that you've put in some work of your own and gone as far as you can yourself, then maybe someone will feel inclined to help you out.
Please upload candidate patches to the tracker.
Need help now? IRC to #irrlicht on irc.freenode.net
How To Ask Questions The Smart Way
pibeytor
Posts: 17
Joined: Thu Nov 01, 2007 2:13 pm

Post by pibeytor »

i've added my code in the first post..
i hope someone can help me out...
greenya
Posts: 1012
Joined: Sun Jan 21, 2007 1:46 pm
Location: Ukraine
Contact:

Re: Snake game with irrlicht

Post by greenya »

I do not write the code instead of you.
But i will try to explain in details how you can snake-it :)
pibeytor wrote: it's supposed that when you press down one key( W,A,D or S) the esphere has to move to that direction without holding the key..
my code just move one tap at the time...
You should have a variable storing current direction.
For example:

Code: Select all

int snakeDirection = 0; // 0=left, 1=top, 2=right, 3=bottom;
Then each time when you need to move your snake, you check this value and adjust its coordinates properly.
For example:

Code: Select all

switch (snakeDirection)
{
case 0: // left
snakePosition.X--;
break;
case 1: // top
snakePosition.Y--;
...
When user presses the key (W,A,S or D) you do proper changing of snakeDirection value.
For example:

Code: Select all

...
case KEY_KEY_A: // left
{            
snakeDirection = 0;
return true;
}
...

pibeytor wrote: and another question...

how can i do in order to make other spheres appear at a random place and follow the " head of the snake "
Store all spheres in an array. For example if maximum length of your snake can be 20, than you can allocate array with 20 elements inside. Each element -- is a pointer on the scene::ISceneNode.
initialization
Init first pointer (the head of the snake) with correct scene node (sphere). All other (19 elements) set to NULL -- this is the way how you will know that this element is empty.
growing
Then, when you need to grow snake -- you just filling first empty element in the array with a pointer to newly created sphere.
moving
Each time you need to move the snake, you moving its head (first element of the array) using snakeDirection only the head -- so you update snakePosition -- it is position of the head. Because you do not need to know all other positions since snake moves "as snake" :)
So in short:

Code: Select all

// move the snake spheres to its head
for (int i=19; i>=1; i--)
{
if (snakeArray[i] != NULL)
{
snakeArray[i]->setPosition( snakeArray[i-1]->getPosition() );
}
}
// move head of the snake
snakeArray[0]->setPosition(vector3df(snakeDirection.X,0,snakeDirection.Z));
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Please note that this move code is frame rate dependant. You''ll have to move into the desired direction by speed/timeDelta (where timeDelta is calculated with the ITimer).
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Better to not update the first post like that as it just causes a bit of confusion, just add on your new questions to the end of the thread ;)
Image Image Image
pibeytor
Posts: 17
Joined: Thu Nov 01, 2007 2:13 pm

Post by pibeytor »

thnx greenya

but i still dont understand how change the direction.
i dont know were tu place the code.. inside my event receiver or inside the main..

or i have to make another function named snakedirection? and call it from there?
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Post by randomMesh »

pibeytor wrote:...or i have to make another function named snakedirection? and call it from there?
Maybe this helps.

There is one thing you have to figure out for yourself:
If new snake parts are added, they are placed on the top of all others, wich means you only can see one.

Just place it correctly upon creation and the Snake::move() method will work.

Good luck.

Code: Select all

#include <irrlicht.h>


class Snake
{
private:

	irr::IrrlichtDevice* device;
	
	irr::u8 snakeDirection; // 0 left / 1 up / 2 right / 3 down
	
	irr::f32 snakeSpeed;
	
	irr::f32 snakeRadius;
	
	irr::core::array<irr::scene::ISceneNode*> snakeParts;
	
public:
	Snake(irr::IrrlichtDevice* device) :
		device(device),
		snakeDirection(0),
		snakeSpeed(50.0f),
		snakeRadius(10.0f)
	{
		//make head
		addPart();
	}
	
	void move(const irr::f32 elapsed) const
	{
		irr::u32 parts = snakeParts.size();
		--parts;

		irr::u32 i;
		for (i = parts; i >= 1; i--)
			snakeParts[i]->setPosition(snakeParts[i-1]->getAbsolutePosition()); 

		// move head of the snake
		irr::core::vector3df headPos = snakeParts[0]->getAbsolutePosition();
		switch (snakeDirection)
		{
			case 0: headPos.X = headPos.X - snakeSpeed* elapsed; break;
			case 1: headPos.Z = headPos.Z + snakeSpeed* elapsed;break;
			case 2: headPos.X = headPos.X + snakeSpeed* elapsed;break;
			case 3: headPos.Z = headPos.Z - snakeSpeed* elapsed;break;
		}
		snakeParts[0]->setPosition(headPos);
	}

	void addPart()
	{	
		irr::scene::ISceneNode* newPart = device->getSceneManager()->addSphereSceneNode(snakeRadius); 
		newPart->setMaterialFlag(irr::video::EMF_LIGHTING, false);

		this->snakeParts.push_back(newPart);
	}

	void setSnakeDirection(irr::u8 direction)
	{
		this->snakeDirection = direction;
	}
	
	const irr::u8 getSnakeDirection() const { return this->snakeDirection; }
};




class EventHandler : public irr::IEventReceiver
{
private:
	Snake& snake;

public:
	EventHandler(Snake& snake) :
		snake(snake)
	{
	}

	bool OnEvent(const irr::SEvent& event)
	{

		if (event.EventType == irr::EET_KEY_INPUT_EVENT && !event.KeyInput.PressedDown)
		{
			switch (event.KeyInput.Key)
			{
				case irr::KEY_LEFT:
					if (snake.getSnakeDirection() != 2)
						snake.setSnakeDirection(0);
					return true;
				case irr::KEY_UP:
					if (snake.getSnakeDirection() != 3)
						snake.setSnakeDirection(1);
					return true;
				case irr::KEY_RIGHT:
					if (snake.getSnakeDirection() != 0)
						snake.setSnakeDirection(2);
					return true;
				case irr::KEY_DOWN:
					if (snake.getSnakeDirection() != 1)
						snake.setSnakeDirection(3);
					return true;

				case irr::KEY_SPACE:
					snake.addPart();
					return true;
				
				default: return false;
			}
        }

		return false;
	}

};

int main()
{
	irr::IrrlichtDevice* device = irr::createDevice(irr::video::EDT_OPENGL);
	if (device == 0) return 1;

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

	EventHandler event(snake);
	device->setEventReceiver(&event);

	irr::scene::ICameraSceneNode* camera = smgr->addCameraSceneNode();
	camera->setPosition(irr::core::vector3df(0.0f, 200.0f, 0.0f));
	
	//Timer
	irr::ITimer* timer = device->getTimer();
	irr::u32 then = timer->getTime();
	irr::u32 now = 0;
	irr::f32 elapsed = 0.0f;

	while (device->run())
	{
		//compute time since last frame
		now = timer->getTime();
		elapsed = (now - then) / 1000.f;
		then = now;
		
		if (device->isWindowActive())
		{
			driver->beginScene(true, true, irr::video::SColor(255, 0, 0, 0));
			snake.move(elapsed);
			smgr->drawAll();
			driver->endScene();
		}
	}
	
	device->drop();
	return 0;
}

Last edited by randomMesh on Wed Jan 23, 2008 11:59 pm, edited 1 time in total.
pibeytor
Posts: 17
Joined: Thu Nov 01, 2007 2:13 pm

Post by pibeytor »

Just place it correctly upon creation and the Snake::move() method will work.
are you telling me that if i combine both codes the snake will work?
i'm trying to do that..
randomMesh
Posts: 1186
Joined: Fri Dec 29, 2006 12:04 am

Post by randomMesh »

pibeytor wrote:
Just place it correctly upon creation and the Snake::move() method will work.
are you telling me that if i combine both codes the snake will work?
No. My code is a stand alone one.

Just wanted to give you an idea how to organize data in classes and move in a frame rate independent way.

As for the positioning of the new snake part i suggest you store the direction of the last part upon creation somehow and then set it to the opposite direction. There is a private variable snakeRadius, which will help.

Note that i changed the type of snakeSpeed from u32 to f32.
Btw.: The moving seems strange since it is a top-down view and a static camera.
pibeytor
Posts: 17
Joined: Thu Nov 01, 2007 2:13 pm

Post by pibeytor »

So far, so good my snake can move with the directional keys. but i'm dont really know how to feed it and make it grow..

Code: Select all

#include <irrlicht.h>
#include <iostream>
#include <cstdlib>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")

scene::ISceneNode* snake = 0;
IrrlichtDevice* device = 0;
//bool teclas[256]={false};

int snakeDirection=rand()%5;
//float snakePosition=0;

class MyEventReceiver : public IEventReceiver
{
public:	
	virtual bool OnEvent(const SEvent& event)	
	{ 
 	if (snake != 0 && event.EventType == irr::EET_KEY_INPUT_EVENT&& !event.KeyInput.PressedDown){		
				
		if(event.KeyInput.Key==KEY_UP){
				snakeDirection=0;//up
				return true;
		}
		
		if(event.KeyInput.Key==KEY_DOWN){
				snakeDirection=1;//down
				return true;
		}
		
		if(event.KeyInput.Key==KEY_LEFT){
				snakeDirection=2;//left;
				return true;
		}
		
		if(event.KeyInput.Key==KEY_RIGHT){
				snakeDirection=3;//right
				return true;
		}
			
	} 
return false;  
}  
};

 int main()
{	
	MyEventReceiver receiver;

	// create device

	IrrlichtDevice* device = createDevice(irr::video::EDT_DIRECT3D9,irr::core::dimension2d<irr::s32>(640,480),32,false,false,false,&receiver);
	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();

//snake head
	snake = smgr->addSphereSceneNode();
	snake->setPosition(core::vector3df(0,0,0));
	snake->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
	snake->setMaterialFlag(video::EMF_LIGHTING, false);

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

	int lastFPS = -1;

	while(device->run())
	{
		driver->beginScene(true, true, video::SColor(0,0,100,200));
				
		smgr->drawAll(); // draw the 3d scene
		device->getGUIEnvironment()->drawAll(); // draw the gui environment (the logo)

		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
			core::stringw tmp(L"ULTIMATE SNAKE [");
			tmp += driver->getName();
			tmp += L"] fps: "; 
			tmp += fps;

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

		// snake movement
		switch (snakeDirection){ 

			case 0: // top 
				snake->setPosition(snake->getPosition() + core::vector3df(0,0.1f,0) ); 
				break; 
			case 1: // down
				snake->setPosition(snake->getPosition() - core::vector3df(0,0.1f,0) );
				break;
			case 2://left
				snake->setPosition(snake->getPosition() + core::vector3df(0.1f,0,0) );
				break;
			case 3://right
				snake->setPosition(snake->getPosition() - core::vector3df(0.1f,0,0) );
				break;
					
			return true;		
		}//end switch 
	}

	device->drop();
	
	return 0;
}

Post Reply