1 // This is a Demo of the Irrlicht Engine (c) 2005-2009 by N.Gebhardt.
2 // This file is not documented.
3 
4 #include "CDemo.h"
5 
CDemo(bool f,bool m,bool s,bool a,bool v,bool fsaa,video::E_DRIVER_TYPE d)6 CDemo::CDemo(bool f, bool m, bool s, bool a, bool v, bool fsaa, video::E_DRIVER_TYPE d)
7 : fullscreen(f), music(m), shadows(s), additive(a), vsync(v), aa(fsaa),
8  driverType(d), device(0),
9 #ifdef USE_IRRKLANG
10 	irrKlang(0), ballSound(0), impactSound(0),
11 #endif
12 #ifdef USE_SDL_MIXER
13 	stream(0), ballSound(0), impactSound(0),
14 #endif
15  currentScene(-2), backColor(0), statusText(0), inOutFader(0),
16  quakeLevelMesh(0), quakeLevelNode(0), skyboxNode(0), model1(0), model2(0),
17  campFire(0), metaSelector(0), mapSelector(0), sceneStartTime(0),
18  timeForThisScene(0)
19 {
20 }
21 
22 
~CDemo()23 CDemo::~CDemo()
24 {
25 	if (mapSelector)
26 		mapSelector->drop();
27 
28 	if (metaSelector)
29 		metaSelector->drop();
30 
31 #ifdef USE_IRRKLANG
32 	if (irrKlang)
33 		irrKlang->drop();
34 #endif
35 }
36 
37 
run()38 void CDemo::run()
39 {
40 	core::dimension2d<u32> resolution (800, 600);
41 
42 	if ( driverType == video::EDT_BURNINGSVIDEO || driverType == video::EDT_SOFTWARE )
43 	{
44 		resolution.Width = 640;
45 		resolution.Height = 480;
46 	}
47 
48 	irr::SIrrlichtCreationParameters params;
49 	params.DriverType=driverType;
50 	params.WindowSize=resolution;
51 	params.Bits=32;
52 	params.Fullscreen=fullscreen;
53 	params.Stencilbuffer=shadows;
54 	params.Vsync=vsync;
55 	params.AntiAlias=aa?8:0;
56 	params.EventReceiver=this;
57 
58 	device = createDeviceEx(params);
59 	if (!device)
60 		return;
61 
62 	if (device->getFileSystem()->existFile("irrlicht.dat"))
63 		device->getFileSystem()->addFileArchive("irrlicht.dat");
64 	else
65 		device->getFileSystem()->addFileArchive("../../media/irrlicht.dat");
66 	if (device->getFileSystem()->existFile("map-20kdm2.pk3"))
67 		device->getFileSystem()->addFileArchive("map-20kdm2.pk3");
68 	else
69 		device->getFileSystem()->addFileArchive("../../media/map-20kdm2.pk3");
70 
71 	video::IVideoDriver* driver = device->getVideoDriver();
72 	scene::ISceneManager* smgr = device->getSceneManager();
73 	gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
74 
75 	device->setWindowCaption(L"Irrlicht Engine Demo");
76 
77 	// set ambient light
78 	smgr->setAmbientLight ( video::SColorf ( 0x00c0c0c0 ) );
79 
80 	wchar_t tmp[255];
81 
82 	// draw everything
83 
84 	s32 now = 0;
85 	s32 lastfps = 0;
86 	sceneStartTime = device->getTimer()->getTime();
87 	while(device->run() && driver)
88 	{
89 		if (device->isWindowActive())
90 		{
91 			#ifdef USE_IRRKLANG
92 			// update 3D position for sound engine
93 			scene::ICameraSceneNode* cam = smgr->getActiveCamera();
94 			if (cam && irrKlang)
95 				irrKlang->setListenerPosition(cam->getAbsolutePosition(), cam->getTarget());
96 			#endif
97 
98 			// load next scene if necessary
99 			now = device->getTimer()->getTime();
100 			if (now - sceneStartTime > timeForThisScene && timeForThisScene!=-1)
101 				switchToNextScene();
102 
103 			createParticleImpacts();
104 
105 			driver->beginScene(timeForThisScene != -1, true, backColor);
106 
107 			smgr->drawAll();
108 			guienv->drawAll();
109 			driver->endScene();
110 
111 			// write statistics
112 			const s32 nowfps = driver->getFPS();
113 
114 			swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio/s",
115 						driver->getName(), driver->getFPS(),
116 						driver->getPrimitiveCountDrawn(1) * (1.f / 1000000.f));
117 
118 			statusText->setText(tmp);
119 			if ( nowfps != lastfps )
120 			{
121 				device->setWindowCaption(tmp);
122 				lastfps = nowfps;
123 			}
124 		}
125 	}
126 
127 	device->drop();
128 }
129 
130 
OnEvent(const SEvent & event)131 bool CDemo::OnEvent(const SEvent& event)
132 {
133 	if (!device)
134 		return false;
135 
136 	if (event.EventType == EET_KEY_INPUT_EVENT &&
137 		event.KeyInput.Key == KEY_ESCAPE &&
138 		event.KeyInput.PressedDown == false)
139 	{
140 		// user wants to quit.
141 		if (currentScene < 3)
142 			timeForThisScene = 0;
143 		else
144 			device->closeDevice();
145 	}
146 	else
147 	if (((event.EventType == EET_KEY_INPUT_EVENT &&
148 		event.KeyInput.Key == KEY_SPACE &&
149 		event.KeyInput.PressedDown == false) ||
150 		(event.EventType == EET_MOUSE_INPUT_EVENT &&
151 		 event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP)) &&
152 		currentScene == 3)
153 	{
154 		// shoot
155 		shoot();
156 	}
157 	else
158 	if (event.EventType == EET_KEY_INPUT_EVENT &&
159 		event.KeyInput.Key == KEY_F9 &&
160 		event.KeyInput.PressedDown == false)
161 	{
162 		video::IImage* image = device->getVideoDriver()->createScreenShot();
163 		if (image)
164 		{
165 			device->getVideoDriver()->writeImageToFile(image, "screenshot.bmp");
166 			device->getVideoDriver()->writeImageToFile(image, "screenshot.png");
167 			device->getVideoDriver()->writeImageToFile(image, "screenshot.tga");
168 			device->getVideoDriver()->writeImageToFile(image, "screenshot.ppm");
169 			device->getVideoDriver()->writeImageToFile(image, "screenshot.jpg");
170 			device->getVideoDriver()->writeImageToFile(image, "screenshot.pcx");
171 			image->drop();
172 		}
173 	}
174 	else
175 	if (device->getSceneManager()->getActiveCamera())
176 	{
177 		device->getSceneManager()->getActiveCamera()->OnEvent(event);
178 		return true;
179 	}
180 
181 	return false;
182 }
183 
184 
switchToNextScene()185 void CDemo::switchToNextScene()
186 {
187 	currentScene++;
188 	if (currentScene > 3)
189 		currentScene = 1;
190 
191 	scene::ISceneManager* sm = device->getSceneManager();
192 	scene::ISceneNodeAnimator* sa = 0;
193 	scene::ICameraSceneNode* camera = 0;
194 
195 	camera = sm->getActiveCamera();
196 	if (camera)
197 	{
198 		sm->setActiveCamera(0);
199 		camera->remove();
200 		camera = 0;
201 	}
202 
203 	switch(currentScene)
204 	{
205 	case -1: // loading screen
206 		timeForThisScene = 0;
207 		createLoadingScreen();
208 		break;
209 
210 	case 0: // load scene
211 		timeForThisScene = 0;
212 		loadSceneData();
213 		break;
214 
215 	case 1: // panorama camera
216 		{
217 			currentScene += 1;
218 			//camera = sm->addCameraSceneNode(0, core::vector3df(0,0,0), core::vector3df(-586,708,52));
219 			//camera->setTarget(core::vector3df(0,400,0));
220 
221 			core::array<core::vector3df> points;
222 
223 			points.push_back(core::vector3df(-931.473755f, 138.300003f, 987.279114f)); // -49873
224 			points.push_back(core::vector3df(-847.902222f, 136.757553f, 915.792725f)); // -50559
225 			points.push_back(core::vector3df(-748.680420f, 152.254501f, 826.418945f)); // -51964
226 			points.push_back(core::vector3df(-708.428406f, 213.569580f, 784.466675f)); // -53251
227 			points.push_back(core::vector3df(-686.217651f, 288.141174f, 762.965576f)); // -54015
228 			points.push_back(core::vector3df(-679.685059f, 365.095612f, 756.551453f)); // -54733
229 			points.push_back(core::vector3df(-671.317871f, 447.360107f, 749.394592f)); // -55588
230 			points.push_back(core::vector3df(-669.468445f, 583.335632f, 747.711853f)); // -56178
231 			points.push_back(core::vector3df(-667.611267f, 727.313232f, 746.018250f)); // -56757
232 			points.push_back(core::vector3df(-665.853210f, 862.791931f, 744.436096f)); // -57859
233 			points.push_back(core::vector3df(-642.649597f, 1026.047607f, 724.259827f)); // -59705
234 			points.push_back(core::vector3df(-517.793884f, 838.396790f, 490.326050f)); // -60983
235 			points.push_back(core::vector3df(-474.387299f, 715.691467f, 344.639984f)); // -61629
236 			points.push_back(core::vector3df(-444.600250f, 601.155701f, 180.938095f)); // -62319
237 			points.push_back(core::vector3df(-414.808899f, 479.691406f, 4.866660f)); // -63048
238 			points.push_back(core::vector3df(-410.418945f, 429.642242f, -134.332687f)); // -63757
239 			points.push_back(core::vector3df(-399.837585f, 411.498383f, -349.350983f)); // -64418
240 			points.push_back(core::vector3df(-390.756653f, 403.970093f, -524.454407f)); // -65005
241 			points.push_back(core::vector3df(-334.864227f, 350.065491f, -732.397400f)); // -65701
242 			points.push_back(core::vector3df(-195.253387f, 349.577209f, -812.475891f)); // -66335
243 			points.push_back(core::vector3df(16.255573f, 363.743134f, -833.800415f)); // -67170
244 			points.push_back(core::vector3df(234.940964f, 352.957825f, -820.150696f)); // -67939
245 			points.push_back(core::vector3df(436.797668f, 349.236450f, -816.914185f)); // -68596
246 			points.push_back(core::vector3df(575.236206f, 356.244812f, -719.788513f)); // -69166
247 			points.push_back(core::vector3df(594.131042f, 387.173828f, -609.675598f)); // -69744
248 			points.push_back(core::vector3df(617.615234f, 412.002899f, -326.174072f)); // -70640
249 			points.push_back(core::vector3df(606.456848f, 403.221954f, -104.179291f)); // -71390
250 			points.push_back(core::vector3df(610.958252f, 407.037750f, 117.209778f)); // -72085
251 			points.push_back(core::vector3df(597.956909f, 395.167877f, 345.942200f)); // -72817
252 			points.push_back(core::vector3df(587.383118f, 391.444519f, 566.098633f)); // -73477
253 			points.push_back(core::vector3df(559.572449f, 371.991333f, 777.689453f)); // -74124
254 			points.push_back(core::vector3df(423.753204f, 329.990051f, 925.859741f)); // -74941
255 			points.push_back(core::vector3df(247.520050f, 252.818954f, 935.311829f)); // -75651
256 			points.push_back(core::vector3df(114.756012f, 199.799759f, 805.014160f));
257 			points.push_back(core::vector3df(96.783348f, 181.639481f, 648.188110f));
258 			points.push_back(core::vector3df(97.865623f, 138.905975f, 484.812561f));
259 			points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f));
260 			points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f));
261 			points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f));
262 
263 			timeForThisScene = (points.size()-3)* 1000;
264 
265 			camera = sm->addCameraSceneNode(0, points[0], core::vector3df(0 ,400,0));
266 			//camera->setTarget(core::vector3df(0,400,0));
267 
268 			sa = sm->createFollowSplineAnimator(device->getTimer()->getTime(),
269 				points);
270 			camera->addAnimator(sa);
271 			sa->drop();
272 
273 			model1->setVisible(false);
274 			model2->setVisible(false);
275 			campFire->setVisible(false);
276 			inOutFader->fadeIn(7000);
277 		}
278 		break;
279 
280 	case 2:	// down fly anim camera
281 		camera = sm->addCameraSceneNode(0, core::vector3df(100,40,-80), core::vector3df(844,670,-885));
282 		sa = sm->createFlyStraightAnimator(core::vector3df(94, 1002, 127),
283 			core::vector3df(108, 15, -60), 10000, true);
284 		camera->addAnimator(sa);
285 		timeForThisScene = 9900;
286 		model1->setVisible(true);
287 		model2->setVisible(false);
288 		campFire->setVisible(false);
289 		sa->drop();
290 		break;
291 
292 	case 3: // interactive, go around
293 		{
294 			model1->setVisible(true);
295 			model2->setVisible(true);
296 			campFire->setVisible(true);
297 			timeForThisScene = -1;
298 
299 			SKeyMap keyMap[9];
300 			keyMap[0].Action = EKA_MOVE_FORWARD;
301 			keyMap[0].KeyCode = KEY_UP;
302 			keyMap[1].Action = EKA_MOVE_FORWARD;
303 			keyMap[1].KeyCode = KEY_KEY_W;
304 
305 			keyMap[2].Action = EKA_MOVE_BACKWARD;
306 			keyMap[2].KeyCode = KEY_DOWN;
307 			keyMap[3].Action = EKA_MOVE_BACKWARD;
308 			keyMap[3].KeyCode = KEY_KEY_S;
309 
310 			keyMap[4].Action = EKA_STRAFE_LEFT;
311 			keyMap[4].KeyCode = KEY_LEFT;
312 			keyMap[5].Action = EKA_STRAFE_LEFT;
313 			keyMap[5].KeyCode = KEY_KEY_A;
314 
315 			keyMap[6].Action = EKA_STRAFE_RIGHT;
316 			keyMap[6].KeyCode = KEY_RIGHT;
317 			keyMap[7].Action = EKA_STRAFE_RIGHT;
318 			keyMap[7].KeyCode = KEY_KEY_D;
319 
320 			keyMap[8].Action = EKA_JUMP_UP;
321 			keyMap[8].KeyCode = KEY_KEY_J;
322 
323 			camera = sm->addCameraSceneNodeFPS(0, 100.0f, .4f, -1, keyMap, 9, false, 3.f);
324 			camera->setPosition(core::vector3df(108,140,-140));
325 			camera->setFarValue(5000.0f);
326 
327 			scene::ISceneNodeAnimatorCollisionResponse* collider =
328 				sm->createCollisionResponseAnimator(
329 				metaSelector, camera, core::vector3df(25,50,25),
330 				core::vector3df(0, quakeLevelMesh ? -10.f : 0.0f,0),
331 					core::vector3df(0,45,0), 0.005f);
332 
333 			camera->addAnimator(collider);
334 			collider->drop();
335 		}
336 		break;
337 	}
338 
339 	sceneStartTime = device->getTimer()->getTime();
340 }
341 
342 
loadSceneData()343 void CDemo::loadSceneData()
344 {
345 	// load quake level
346 
347 	video::IVideoDriver* driver = device->getVideoDriver();
348 	scene::ISceneManager* sm = device->getSceneManager();
349 
350 	// Quake3 Shader controls Z-Writing
351 	sm->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
352 
353 	quakeLevelMesh = (scene::IQ3LevelMesh*) sm->getMesh("maps/20kdm2.bsp");
354 
355 	if (quakeLevelMesh)
356 	{
357 		u32 i;
358 
359 		//move all quake level meshes (non-realtime)
360 		core::matrix4 m;
361 		m.setTranslation(core::vector3df(-1300,-70,-1249));
362 
363 		for ( i = 0; i != scene::quake3::E_Q3_MESH_SIZE; ++i )
364 			sm->getMeshManipulator()->transform(quakeLevelMesh->getMesh(i), m);
365 
366 		quakeLevelNode = sm->addOctreeSceneNode(
367 				quakeLevelMesh->getMesh( scene::quake3::E_Q3_MESH_GEOMETRY));
368 		if (quakeLevelNode)
369 		{
370 			//quakeLevelNode->setPosition(core::vector3df(-1300,-70,-1249));
371 			quakeLevelNode->setVisible(true);
372 
373 			// create map triangle selector
374 			mapSelector = sm->createOctreeTriangleSelector(quakeLevelMesh->getMesh(0),
375 				quakeLevelNode, 128);
376 
377 			// if not using shader and no gamma it's better to use more lighting, because
378 			// quake3 level are usually dark
379 			quakeLevelNode->setMaterialType ( video::EMT_LIGHTMAP_M4 );
380 
381 			// set additive blending if wanted
382 			if (additive)
383 				quakeLevelNode->setMaterialType(video::EMT_LIGHTMAP_ADD);
384 		}
385 
386 		// the additional mesh can be quite huge and is unoptimized
387 		scene::IMesh * additional_mesh = quakeLevelMesh->getMesh ( scene::quake3::E_Q3_MESH_ITEMS );
388 
389 		for ( i = 0; i!= additional_mesh->getMeshBufferCount (); ++i )
390 		{
391 			scene::IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i );
392 			const video::SMaterial &material = meshBuffer->getMaterial();
393 
394 			//! The ShaderIndex is stored in the material parameter
395 			s32 shaderIndex = (s32) material.MaterialTypeParam2;
396 
397 			// the meshbuffer can be rendered without additional support, or it has no shader
398 			const scene::quake3::IShader *shader = quakeLevelMesh->getShader ( shaderIndex );
399 			if ( 0 == shader )
400 			{
401 				continue;
402 			}
403 			// Now add the MeshBuffer(s) with the current Shader to the Manager
404 			sm->addQuake3SceneNode ( meshBuffer, shader );
405 		}
406 	}
407 
408 	// load sydney model and create 2 instances
409 
410 	scene::IAnimatedMesh* mesh = 0;
411 	mesh = sm->getMesh("../../media/sydney.md2");
412 	if (mesh)
413 	{
414 		model1 = sm->addAnimatedMeshSceneNode(mesh);
415 		if (model1)
416 		{
417 			model1->setMaterialTexture(0, driver->getTexture("../../media/spheremap.jpg"));
418 			model1->setPosition(core::vector3df(100,40,-80));
419 			model1->setScale(core::vector3df(2,2,2));
420 			model1->setMD2Animation(scene::EMAT_STAND);
421 			model1->setMaterialFlag(video::EMF_LIGHTING, false);
422 			model1->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
423 			model1->setMaterialType(video::EMT_SPHERE_MAP);
424 			model1->addShadowVolumeSceneNode();
425 		}
426 
427 		model2 = sm->addAnimatedMeshSceneNode(mesh);
428 		if (model2)
429 		{
430 			model2->setPosition(core::vector3df(180,15,-60));
431 			model2->setScale(core::vector3df(2,2,2));
432 			model2->setMD2Animation(scene::EMAT_RUN);
433 			model2->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/sydney.bmp"));
434 			model2->setMaterialFlag(video::EMF_LIGHTING, true);
435 			model2->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
436 			model2->addShadowVolumeSceneNode();
437 		}
438 	}
439 
440 	scene::ISceneNodeAnimator* anim = 0;
441 
442 	// create sky box
443 	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
444 	skyboxNode = sm->addSkyBoxSceneNode(
445 		driver->getTexture("../../media/irrlicht2_up.jpg"),
446 		driver->getTexture("../../media/irrlicht2_dn.jpg"),
447 		driver->getTexture("../../media/irrlicht2_lf.jpg"),
448 		driver->getTexture("../../media/irrlicht2_rt.jpg"),
449 		driver->getTexture("../../media/irrlicht2_ft.jpg"),
450 		driver->getTexture("../../media/irrlicht2_bk.jpg"));
451 	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
452 
453 	// create walk-between-portals animation
454 
455 	core::vector3df waypoint[2];
456 	waypoint[0].set(-150,40,100);
457 	waypoint[1].set(350,40,100);
458 
459 	if (model2)
460 	{
461 		anim = device->getSceneManager()->createFlyStraightAnimator(
462 			waypoint[0], waypoint[1], 2000, true);
463 		model2->addAnimator(anim);
464 		anim->drop();
465 	}
466 
467 	// create animation for portals;
468 
469 	core::array<video::ITexture*> textures;
470 	for (s32 g=1; g<8; ++g)
471 	{
472 		core::stringc tmp("../../media/portal");
473 		tmp += g;
474 		tmp += ".bmp";
475 		video::ITexture* t = driver->getTexture( tmp );
476 		textures.push_back(t);
477 	}
478 
479 	anim = sm->createTextureAnimator(textures, 100);
480 
481 	// create portals
482 
483 	scene::IBillboardSceneNode* bill = 0;
484 
485 	for (int r=0; r<2; ++r)
486 	{
487 		bill = sm->addBillboardSceneNode(0, core::dimension2d<f32>(100,100),
488 			waypoint[r]+ core::vector3df(0,20,0));
489 		bill->setMaterialFlag(video::EMF_LIGHTING, false);
490 		bill->setMaterialTexture(0, driver->getTexture("../../media/portal1.bmp"));
491 		bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
492 		bill->addAnimator(anim);
493 	}
494 
495 	anim->drop();
496 
497 	// create cirlce flying dynamic light with transparent billboard attached
498 
499 	scene::ILightSceneNode* light = 0;
500 
501 	light = sm->addLightSceneNode(0,
502 		core::vector3df(0,0,0),	video::SColorf(1.0f, 1.0f, 1.f, 1.0f), 500.f);
503 
504 	anim = sm->createFlyCircleAnimator(
505 		core::vector3df(100,150,80), 80.0f, 0.0005f);
506 
507 	light->addAnimator(anim);
508 	anim->drop();
509 
510 	bill = device->getSceneManager()->addBillboardSceneNode(
511 		light, core::dimension2d<f32>(40,40));
512 	bill->setMaterialFlag(video::EMF_LIGHTING, false);
513 	bill->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp"));
514 	bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
515 
516 	// create meta triangle selector with all triangles selectors in it.
517 	metaSelector = sm->createMetaTriangleSelector();
518 	metaSelector->addTriangleSelector(mapSelector);
519 
520 	// create camp fire
521 
522 	campFire = sm->addParticleSystemSceneNode(false);
523 	campFire->setPosition(core::vector3df(100,120,600));
524 	campFire->setScale(core::vector3df(2,2,2));
525 
526 	scene::IParticleEmitter* em = campFire->createBoxEmitter(
527 		core::aabbox3d<f32>(-7,0,-7,7,1,7),
528 		core::vector3df(0.0f,0.06f,0.0f),
529 		80,100, video::SColor(1,255,255,255),video::SColor(1,255,255,255), 800,2000);
530 
531 	em->setMinStartSize(core::dimension2d<f32>(20.0f, 10.0f));
532 	em->setMaxStartSize(core::dimension2d<f32>(20.0f, 10.0f));
533 	campFire->setEmitter(em);
534 	em->drop();
535 
536 	scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector();
537 	campFire->addAffector(paf);
538 	paf->drop();
539 
540 	campFire->setMaterialFlag(video::EMF_LIGHTING, false);
541 	campFire->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
542 	campFire->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp"));
543 	campFire->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
544 
545 	// load music
546 
547 	#ifdef USE_IRRKLANG
548 	if (music)
549 		startIrrKlang();
550 	#endif
551 	#ifdef USE_SDL_MIXER
552 	if (music)
553 		startSound();
554 	#endif
555 }
556 
557 
createLoadingScreen()558 void CDemo::createLoadingScreen()
559 {
560 	core::dimension2d<u32> size = device->getVideoDriver()->getScreenSize();
561 
562 	device->getCursorControl()->setVisible(false);
563 
564 	// setup loading screen
565 
566 	backColor.set(255,90,90,156);
567 
568 	// create in fader
569 
570 	inOutFader = device->getGUIEnvironment()->addInOutFader();
571 	inOutFader->setColor(backColor,	video::SColor ( 0, 230, 230, 230 ));
572 
573 	// irrlicht logo
574 	device->getGUIEnvironment()->addImage(device->getVideoDriver()->getTexture("../../media/irrlichtlogo2.png"),
575 		core::position2d<s32>(5,5));
576 
577 	// loading text
578 
579 	const int lwidth = size.Width - 20;
580 	const int lheight = 16;
581 
582 	core::rect<int> pos(10, size.Height-lheight-10, 10+lwidth, size.Height-10);
583 
584 	device->getGUIEnvironment()->addImage(pos);
585 	statusText = device->getGUIEnvironment()->addStaticText(L"Loading...",	pos, true);
586 	statusText->setOverrideColor(video::SColor(255,205,200,200));
587 
588 	// load bigger font
589 
590 	device->getGUIEnvironment()->getSkin()->setFont(
591 		device->getGUIEnvironment()->getFont("../../media/fonthaettenschweiler.bmp"));
592 
593 	// set new font color
594 
595 	device->getGUIEnvironment()->getSkin()->setColor(gui::EGDC_BUTTON_TEXT,
596 		video::SColor(255,100,100,100));
597 }
598 
599 
shoot()600 void CDemo::shoot()
601 {
602 	scene::ISceneManager* sm = device->getSceneManager();
603 	scene::ICameraSceneNode* camera = sm->getActiveCamera();
604 
605 	if (!camera || !mapSelector)
606 		return;
607 
608 	SParticleImpact imp;
609 	imp.when = 0;
610 
611 	// get line of camera
612 
613 	core::vector3df start = camera->getPosition();
614 	core::vector3df end = (camera->getTarget() - start);
615 	end.normalize();
616 	start += end*8.0f;
617 	end = start + (end * camera->getFarValue());
618 
619 	core::triangle3df triangle;
620 
621 	core::line3d<f32> line(start, end);
622 
623 	// get intersection point with map
624 	scene::ISceneNode* hitNode;
625 	if (sm->getSceneCollisionManager()->getCollisionPoint(
626 		line, mapSelector, end, triangle, hitNode))
627 	{
628 		// collides with wall
629 		core::vector3df out = triangle.getNormal();
630 		out.setLength(0.03f);
631 
632 		imp.when = 1;
633 		imp.outVector = out;
634 		imp.pos = end;
635 	}
636 	else
637 	{
638 		// doesnt collide with wall
639 		core::vector3df start = camera->getPosition();
640 		core::vector3df end = (camera->getTarget() - start);
641 		end.normalize();
642 		start += end*8.0f;
643 		end = start + (end * camera->getFarValue());
644 	}
645 
646 	// create fire ball
647 	scene::ISceneNode* node = 0;
648 	node = sm->addBillboardSceneNode(0,
649 		core::dimension2d<f32>(25,25), start);
650 
651 	node->setMaterialFlag(video::EMF_LIGHTING, false);
652 	node->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/fireball.bmp"));
653 	node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
654 
655 	f32 length = (f32)(end - start).getLength();
656 	const f32 speed = 0.6f;
657 	u32 time = (u32)(length / speed);
658 
659 	scene::ISceneNodeAnimator* anim = 0;
660 
661 	// set flight line
662 
663 	anim = sm->createFlyStraightAnimator(start, end, time);
664 	node->addAnimator(anim);
665 	anim->drop();
666 
667 	anim = sm->createDeleteAnimator(time);
668 	node->addAnimator(anim);
669 	anim->drop();
670 
671 	if (imp.when)
672 	{
673 		// create impact note
674 		imp.when = device->getTimer()->getTime() + (time - 100);
675 		Impacts.push_back(imp);
676 	}
677 
678 	// play sound
679 	#ifdef USE_IRRKLANG
680 	if (ballSound)
681 		irrKlang->play2D(ballSound);
682 	#endif
683 	#ifdef USE_SDL_MIXER
684 	if (ballSound)
685 		playSound(ballSound);
686 	#endif
687 }
688 
689 
createParticleImpacts()690 void CDemo::createParticleImpacts()
691 {
692 	u32 now = device->getTimer()->getTime();
693 	scene::ISceneManager* sm = device->getSceneManager();
694 
695 	for (s32 i=0; i<(s32)Impacts.size(); ++i)
696 		if (now > Impacts[i].when)
697 		{
698 			// create smoke particle system
699 			scene::IParticleSystemSceneNode* pas = 0;
700 
701 			pas = sm->addParticleSystemSceneNode(false, 0, -1, Impacts[i].pos);
702 
703 			pas->setParticleSize(core::dimension2d<f32>(10.0f, 10.0f));
704 
705 			scene::IParticleEmitter* em = pas->createBoxEmitter(
706 				core::aabbox3d<f32>(-5,-5,-5,5,5,5),
707 				Impacts[i].outVector, 20,40, video::SColor(50,255,255,255),video::SColor(50,255,255,255),
708 				1200,1600, 20);
709 
710 			pas->setEmitter(em);
711 			em->drop();
712 
713 			scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector();
714 			pas->addAffector(paf);
715 			paf->drop();
716 
717 			pas->setMaterialFlag(video::EMF_LIGHTING, false);
718 			pas->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
719 			pas->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/smoke.bmp"));
720 			pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
721 
722 			scene::ISceneNodeAnimator* anim = sm->createDeleteAnimator(2000);
723 			pas->addAnimator(anim);
724 			anim->drop();
725 
726 			// play impact sound
727 			#ifdef USE_IRRKLANG
728 			if (irrKlang)
729 			{
730 				irrklang::ISound* sound =
731 					irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true);
732 
733 				if (sound)
734 				{
735 					// adjust max value a bit to make to sound of an impact louder
736 					sound->setMinDistance(400);
737 					sound->drop();
738 				}
739 			}
740 			#endif
741 
742 			#ifdef USE_SDL_MIXER
743 			if (impactSound)
744 				playSound(impactSound);
745 			#endif
746 
747 			// delete entry
748 			Impacts.erase(i);
749 			i--;
750 		}
751 }
752 
753 
754 #ifdef USE_IRRKLANG
startIrrKlang()755 void CDemo::startIrrKlang()
756 {
757 	irrKlang = irrklang::createIrrKlangDevice();
758 
759 	if (!irrKlang)
760 		return;
761 
762 	// play music
763 
764 	irrklang::ISound* snd = irrKlang->play2D("../../media/IrrlichtTheme.ogg", true, false, true);
765 	if ( !snd )
766 		snd = irrKlang->play2D("IrrlichtTheme.ogg", true, false, true);
767 
768 	if (snd)
769 	{
770 		snd->setVolume(0.5f); // 50% volume
771 		snd->drop();
772 	}
773 
774 	// preload both sound effects
775 
776 	ballSound = irrKlang->getSoundSource("../../media/ball.wav");
777 	impactSound = irrKlang->getSoundSource("../../media/impact.wav");
778 }
779 #endif
780 
781 
782 #ifdef USE_SDL_MIXER
startSound()783 void CDemo::startSound()
784 {
785 	stream = NULL;
786 	ballSound = NULL;
787 	impactSound = NULL;
788 
789 	SDL_Init(SDL_INIT_AUDIO);
790 
791 	if (Mix_OpenAudio(22050, AUDIO_S16, 2, 128))
792 		return;
793 
794 	stream = Mix_LoadMUS("../../media/IrrlichtTheme.ogg");
795 	if (stream)
796 		Mix_PlayMusic(stream, -1);
797 
798 	ballSound = Mix_LoadWAV("../../media/ball.wav");
799 	impactSound = Mix_LoadWAV("../../media/impact.wav");
800 }
801 
playSound(Mix_Chunk * sample)802 void CDemo::playSound(Mix_Chunk *sample)
803 {
804 	if (sample)
805 		Mix_PlayChannel(-1, sample, 0);
806 }
807 
pollSound(void)808 void CDemo::pollSound(void)
809 {
810 	SDL_Event event;
811 
812 	while (SDL_PollEvent(&event))
813 		;
814 }
815 #endif
816