CDemo.cpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. // This is a Demo of the Irrlicht Engine (c) 2005-2009 by N.Gebhardt.
  2. // This file is not documented.
  3. #include "CDemo.h"
  4. // RakNet includes
  5. #include "GetTime.h"
  6. #include "MessageIdentifiers.h"
  7. #include "RakNetTypes.h"
  8. #include "Itoa.h"
  9. #include "RakNetSmartPtr.h"
  10. #include "miniupnpc.h"
  11. #include "upnpcommands.h"
  12. #include "upnperrors.h"
  13. CDemo::CDemo(bool f, bool m, bool s, bool a, bool v, bool fsaa, video::E_DRIVER_TYPE d, core::stringw &_playerName)
  14. : fullscreen(f), music(m), shadows(s), additive(a), vsync(v), aa(fsaa),
  15. driverType(d), device(0), playerName(_playerName),
  16. #ifdef USE_IRRKLANG
  17. irrKlang(0), ballSound(0), impactSound(0),
  18. #endif
  19. #ifdef USE_SDL_MIXER
  20. stream(0), ballSound(0), impactSound(0),
  21. #endif
  22. currentScene(-2), backColor(0), statusText(0), inOutFader(0),
  23. quakeLevelMesh(0), quakeLevelNode(0), skyboxNode(0), model1(0), model2(0),
  24. campFire(0), metaSelector(0), mapSelector(0), sceneStartTime(0),
  25. timeForThisScene(0), whenOutputMessageStarted(0), isConnectedToNATPunchthroughServer(false)
  26. {
  27. for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
  28. KeyIsDown[i] = false;
  29. }
  30. CDemo::~CDemo()
  31. {
  32. if (mapSelector)
  33. mapSelector->drop();
  34. if (metaSelector)
  35. metaSelector->drop();
  36. #ifdef USE_IRRKLANG
  37. if (irrKlang)
  38. irrKlang->drop();
  39. #endif
  40. }
  41. void CDemo::run()
  42. {
  43. core::dimension2d<u32> resolution ( 800, 600 );
  44. if ( driverType == video::EDT_BURNINGSVIDEO || driverType == video::EDT_SOFTWARE )
  45. {
  46. resolution.Width = 640;
  47. resolution.Height = 480;
  48. }
  49. irr::SIrrlichtCreationParameters params;
  50. params.DriverType=driverType;
  51. params.WindowSize=resolution;
  52. params.Bits=32;
  53. params.Fullscreen=fullscreen;
  54. params.Stencilbuffer=shadows;
  55. params.Vsync=vsync;
  56. params.AntiAlias=aa;
  57. params.EventReceiver=this;
  58. device = createDeviceEx(params);
  59. if (!device)
  60. return;
  61. if (device->getFileSystem()->existFile("irrlicht.dat"))
  62. device->getFileSystem()->addFileArchive("irrlicht.dat", true, true, io::EFAT_ZIP);
  63. else
  64. device->getFileSystem()->addFileArchive(IRRLICHT_MEDIA_PATH "irrlicht.dat", true, true, io::EFAT_ZIP);
  65. if (device->getFileSystem()->existFile("map-20kdm2.pk3"))
  66. device->getFileSystem()->addFileArchive("map-20kdm2.pk3", true, true, io::EFAT_ZIP);
  67. else
  68. device->getFileSystem()->addFileArchive(IRRLICHT_MEDIA_PATH "map-20kdm2.pk3", true, true, io::EFAT_ZIP);
  69. video::IVideoDriver* driver = device->getVideoDriver();
  70. scene::ISceneManager* smgr = device->getSceneManager();
  71. gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
  72. device->setWindowCaption(L"Irrlicht Engine Demo");
  73. // set ambient light
  74. smgr->setAmbientLight ( video::SColorf ( 0x00c0c0c0 ) );
  75. // wchar_t tmp[255];
  76. // RakNet startup
  77. char dest[1024];
  78. memset(dest,0,sizeof(dest));
  79. wcstombs(dest, playerName.c_str(), playerName.size());
  80. InstantiateRakNetClasses();
  81. // Hook RakNet stuff into this class
  82. playerReplica->playerName=RakNet::RakString(dest);
  83. playerReplica->demo=this;
  84. replicaManager3->demo=this;
  85. CalculateSyndeyBoundingBox();
  86. // draw everything
  87. s32 now = 0;
  88. sceneStartTime = device->getTimer()->getTime();
  89. while(device->run() && driver)
  90. {
  91. // RakNet: Render even if not active, multiplayer never stops
  92. //if (device->isWindowActive())
  93. {
  94. #ifdef USE_IRRKLANG
  95. // update 3D position for sound engine
  96. scene::ICameraSceneNode* cam = smgr->getActiveCamera();
  97. if (cam && irrKlang)
  98. irrKlang->setListenerPosition(cam->getAbsolutePosition(), cam->getTarget());
  99. #endif
  100. // load next scene if necessary
  101. now = device->getTimer()->getTime();
  102. if (now - sceneStartTime > timeForThisScene && timeForThisScene!=-1)
  103. switchToNextScene();
  104. createParticleImpacts();
  105. driver->beginScene(timeForThisScene != -1, true, backColor);
  106. smgr->drawAll();
  107. guienv->drawAll();
  108. driver->endScene();
  109. /*
  110. // write statistics
  111. static s32 lastfps = 0;
  112. s32 nowfps = driver->getFPS();
  113. swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio",
  114. driver->getName(),
  115. driver->getFPS(),
  116. (f32) driver->getPrimitiveCountDrawn( 1 ) * ( 1.f / 1000000.f )
  117. );
  118. if ( nowfps != lastfps )
  119. {
  120. device->setWindowCaption ( tmp );
  121. lastfps = nowfps;
  122. }
  123. */
  124. RakNet::RakString curMsg = GetCurrentMessage();
  125. if (curMsg.IsEmpty()==false)
  126. {
  127. wchar_t dest[1024];
  128. memset(dest,0,sizeof(dest));
  129. mbstowcs(dest, curMsg.C_String(), curMsg.GetLength());
  130. statusText->setText(dest);
  131. }
  132. else
  133. {
  134. // statusText->setText(tmp);
  135. statusText->setText(0);
  136. }
  137. }
  138. // RakNet per tick update
  139. UpdateRakNet();
  140. }
  141. // RakNet shutdown
  142. DeinitializeRakNetClasses();
  143. device->drop();
  144. }
  145. bool CDemo::OnEvent(const SEvent& event)
  146. {
  147. if (!device)
  148. return false;
  149. // Remember whether each key is down or up
  150. if (event.EventType == irr::EET_KEY_INPUT_EVENT)
  151. KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
  152. if (event.EventType == EET_KEY_INPUT_EVENT &&
  153. event.KeyInput.Key == KEY_ESCAPE &&
  154. event.KeyInput.PressedDown == false)
  155. {
  156. // user wants to quit.
  157. // if (currentScene < 3)
  158. // timeForThisScene = 0;
  159. // else
  160. //device->closeDevice();
  161. // RakNet: Escape to get the mouse back
  162. if (GetSceneManager()->getActiveCamera()->isVisible())
  163. {
  164. device->getCursorControl()->setVisible(true);
  165. GetSceneManager()->getActiveCamera()->setVisible(false);
  166. }
  167. else
  168. {
  169. device->closeDevice();
  170. }
  171. }
  172. else
  173. if (
  174. // RakNet: Use space to jump, not shoot
  175. // (event.EventType == EET_KEY_INPUT_EVENT &&
  176. // event.KeyInput.Key == KEY_SPACE &&
  177. // event.KeyInput.PressedDown == false) ||
  178. (event.EventType == EET_MOUSE_INPUT_EVENT &&
  179. event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) &&
  180. //currentScene == 3
  181. currentScene == 1
  182. )
  183. {
  184. // RakNet: Click without focus to get focus back
  185. if (GetSceneManager()->getActiveCamera()->isVisible()==false)
  186. {
  187. device->getCursorControl()->setVisible(false);
  188. GetSceneManager()->getActiveCamera()->setVisible(true);
  189. }
  190. else
  191. {
  192. // shoot
  193. shoot();
  194. }
  195. }
  196. else
  197. if (event.EventType == EET_KEY_INPUT_EVENT &&
  198. event.KeyInput.Key == KEY_F9 &&
  199. event.KeyInput.PressedDown == false)
  200. {
  201. video::IImage* image = device->getVideoDriver()->createScreenShot();
  202. if (image)
  203. {
  204. device->getVideoDriver()->writeImageToFile(image, "screenshot.bmp");
  205. device->getVideoDriver()->writeImageToFile(image, "screenshot.png");
  206. device->getVideoDriver()->writeImageToFile(image, "screenshot.tga");
  207. device->getVideoDriver()->writeImageToFile(image, "screenshot.ppm");
  208. device->getVideoDriver()->writeImageToFile(image, "screenshot.jpg");
  209. device->getVideoDriver()->writeImageToFile(image, "screenshot.pcx");
  210. image->drop();
  211. }
  212. }
  213. else
  214. if (device->getSceneManager()->getActiveCamera())
  215. {
  216. device->getSceneManager()->getActiveCamera()->OnEvent(event);
  217. return true;
  218. }
  219. return false;
  220. }
  221. void CDemo::switchToNextScene()
  222. {
  223. currentScene++;
  224. //if (currentScene > 3)
  225. if (currentScene > 1)
  226. currentScene = 1;
  227. scene::ISceneManager* sm = device->getSceneManager();
  228. scene::ISceneNodeAnimator* sa = 0;
  229. scene::ICameraSceneNode* camera = 0;
  230. camera = sm->getActiveCamera();
  231. if (camera)
  232. {
  233. sm->setActiveCamera(0);
  234. camera->remove();
  235. camera = 0;
  236. }
  237. switch(currentScene)
  238. {
  239. case -1: // loading screen
  240. timeForThisScene = 0;
  241. createLoadingScreen();
  242. break;
  243. case 0: // load scene
  244. timeForThisScene = 0;
  245. loadSceneData();
  246. break;
  247. /*
  248. case 1: // panorama camera
  249. {
  250. currentScene += 1;
  251. //camera = sm->addCameraSceneNode(0, core::vector3df(0,0,0), core::vector3df(-586,708,52));
  252. //camera->setTarget(core::vector3df(0,400,0));
  253. core::array<core::vector3df> points;
  254. points.push_back(core::vector3df(-931.473755f, 138.300003f, 987.279114f)); // -49873
  255. points.push_back(core::vector3df(-847.902222f, 136.757553f, 915.792725f)); // -50559
  256. points.push_back(core::vector3df(-748.680420f, 152.254501f, 826.418945f)); // -51964
  257. points.push_back(core::vector3df(-708.428406f, 213.569580f, 784.466675f)); // -53251
  258. points.push_back(core::vector3df(-686.217651f, 288.141174f, 762.965576f)); // -54015
  259. points.push_back(core::vector3df(-679.685059f, 365.095612f, 756.551453f)); // -54733
  260. points.push_back(core::vector3df(-671.317871f, 447.360107f, 749.394592f)); // -55588
  261. points.push_back(core::vector3df(-669.468445f, 583.335632f, 747.711853f)); // -56178
  262. points.push_back(core::vector3df(-667.611267f, 727.313232f, 746.018250f)); // -56757
  263. points.push_back(core::vector3df(-665.853210f, 862.791931f, 744.436096f)); // -57859
  264. points.push_back(core::vector3df(-642.649597f, 1026.047607f, 724.259827f)); // -59705
  265. points.push_back(core::vector3df(-517.793884f, 838.396790f, 490.326050f)); // -60983
  266. points.push_back(core::vector3df(-474.387299f, 715.691467f, 344.639984f)); // -61629
  267. points.push_back(core::vector3df(-444.600250f, 601.155701f, 180.938095f)); // -62319
  268. points.push_back(core::vector3df(-414.808899f, 479.691406f, 4.866660f)); // -63048
  269. points.push_back(core::vector3df(-410.418945f, 429.642242f, -134.332687f)); // -63757
  270. points.push_back(core::vector3df(-399.837585f, 411.498383f, -349.350983f)); // -64418
  271. points.push_back(core::vector3df(-390.756653f, 403.970093f, -524.454407f)); // -65005
  272. points.push_back(core::vector3df(-334.864227f, 350.065491f, -732.397400f)); // -65701
  273. points.push_back(core::vector3df(-195.253387f, 349.577209f, -812.475891f)); // -66335
  274. points.push_back(core::vector3df(16.255573f, 363.743134f, -833.800415f)); // -67170
  275. points.push_back(core::vector3df(234.940964f, 352.957825f, -820.150696f)); // -67939
  276. points.push_back(core::vector3df(436.797668f, 349.236450f, -816.914185f)); // -68596
  277. points.push_back(core::vector3df(575.236206f, 356.244812f, -719.788513f)); // -69166
  278. points.push_back(core::vector3df(594.131042f, 387.173828f, -609.675598f)); // -69744
  279. points.push_back(core::vector3df(617.615234f, 412.002899f, -326.174072f)); // -70640
  280. points.push_back(core::vector3df(606.456848f, 403.221954f, -104.179291f)); // -71390
  281. points.push_back(core::vector3df(610.958252f, 407.037750f, 117.209778f)); // -72085
  282. points.push_back(core::vector3df(597.956909f, 395.167877f, 345.942200f)); // -72817
  283. points.push_back(core::vector3df(587.383118f, 391.444519f, 566.098633f)); // -73477
  284. points.push_back(core::vector3df(559.572449f, 371.991333f, 777.689453f)); // -74124
  285. points.push_back(core::vector3df(423.753204f, 329.990051f, 925.859741f)); // -74941
  286. points.push_back(core::vector3df(247.520050f, 252.818954f, 935.311829f)); // -75651
  287. points.push_back(core::vector3df(114.756012f, 199.799759f, 805.014160f));
  288. points.push_back(core::vector3df(96.783348f, 181.639481f, 648.188110f));
  289. points.push_back(core::vector3df(97.865623f, 138.905975f, 484.812561f));
  290. points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f));
  291. points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f));
  292. points.push_back(core::vector3df(99.612457f, 102.463669f, 347.603210f));
  293. timeForThisScene = (points.size()-3)* 1000;
  294. camera = sm->addCameraSceneNode(0, points[0], core::vector3df(0 ,400,0));
  295. //camera->setTarget(core::vector3df(0,400,0));
  296. sa = sm->createFollowSplineAnimator(device->getTimer()->getTime(),
  297. points);
  298. camera->addAnimator(sa);
  299. sa->drop();
  300. model1->setVisible(false);
  301. model2->setVisible(false);
  302. campFire->setVisible(false);
  303. inOutFader->fadeIn(7000);
  304. }
  305. break;
  306. case 2: // down fly anim camera
  307. camera = sm->addCameraSceneNode(0, core::vector3df(100,40,-80), core::vector3df(844,670,-885));
  308. sa = sm->createFlyStraightAnimator(core::vector3df(94, 1002, 127),
  309. core::vector3df(108, 15, -60), 10000, true);
  310. camera->addAnimator(sa);
  311. timeForThisScene = 9900;
  312. model1->setVisible(true);
  313. model2->setVisible(false);
  314. campFire->setVisible(false);
  315. sa->drop();
  316. break;
  317. */
  318. // case 3: // interactive, go around
  319. case 1: // interactive, go around
  320. {
  321. if (model1)
  322. model1->setVisible(true);
  323. if (model2)
  324. model2->setVisible(true);
  325. campFire->setVisible(true);
  326. timeForThisScene = -1;
  327. SKeyMap keyMap[9];
  328. keyMap[0].Action = EKA_MOVE_FORWARD;
  329. keyMap[0].KeyCode = KEY_UP;
  330. keyMap[1].Action = EKA_MOVE_FORWARD;
  331. keyMap[1].KeyCode = KEY_KEY_W;
  332. keyMap[2].Action = EKA_MOVE_BACKWARD;
  333. keyMap[2].KeyCode = KEY_DOWN;
  334. keyMap[3].Action = EKA_MOVE_BACKWARD;
  335. keyMap[3].KeyCode = KEY_KEY_S;
  336. keyMap[4].Action = EKA_STRAFE_LEFT;
  337. keyMap[4].KeyCode = KEY_LEFT;
  338. keyMap[5].Action = EKA_STRAFE_LEFT;
  339. keyMap[5].KeyCode = KEY_KEY_A;
  340. keyMap[6].Action = EKA_STRAFE_RIGHT;
  341. keyMap[6].KeyCode = KEY_RIGHT;
  342. keyMap[7].Action = EKA_STRAFE_RIGHT;
  343. keyMap[7].KeyCode = KEY_KEY_D;
  344. keyMap[8].Action = EKA_JUMP_UP;
  345. //keyMap[8].KeyCode = KEY_KEY_J;
  346. keyMap[8].KeyCode = KEY_SPACE;
  347. // Last parameter is jump speed
  348. // Tweaked so you can get up ladders
  349. camera = sm->addCameraSceneNodeFPS(0, 100.0f, .4f, -1, keyMap, 9, false, 2.05f);
  350. camera->setPosition(core::vector3df(108,140,-140));
  351. scene::ISceneNodeAnimatorCollisionResponse* collider =
  352. sm->createCollisionResponseAnimator(
  353. metaSelector, camera, core::vector3df(25,CAMERA_HEIGHT,25),
  354. core::vector3df(0, quakeLevelMesh ? -10.f : 0.0f,0),
  355. core::vector3df(0,45,0), 0.005f);
  356. camera->addAnimator(collider);
  357. collider->drop();
  358. }
  359. break;
  360. }
  361. sceneStartTime = device->getTimer()->getTime();
  362. }
  363. void CDemo::loadSceneData()
  364. {
  365. // load quake level
  366. video::IVideoDriver* driver = device->getVideoDriver();
  367. scene::ISceneManager* sm = device->getSceneManager();
  368. // Quake3 Shader controls Z-Writing
  369. sm->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);
  370. quakeLevelMesh = (scene::IQ3LevelMesh*) sm->getMesh("maps/20kdm2.bsp");
  371. if (quakeLevelMesh)
  372. {
  373. u32 i;
  374. //move all quake level meshes (non-realtime)
  375. core::matrix4 m;
  376. m.setTranslation ( core::vector3df(-1300,-70,-1249) );
  377. for ( i = 0; i!= scene::quake3::E_Q3_MESH_SIZE; ++i )
  378. {
  379. sm->getMeshManipulator()->transform ( quakeLevelMesh->getMesh(i), m );
  380. }
  381. quakeLevelNode = sm->addOctreeSceneNode(
  382. quakeLevelMesh->getMesh( scene::quake3::E_Q3_MESH_GEOMETRY)
  383. );
  384. if (quakeLevelNode)
  385. {
  386. //quakeLevelNode->setPosition(core::vector3df(-1300,-70,-1249));
  387. quakeLevelNode->setVisible(true);
  388. // create map triangle selector
  389. mapSelector = sm->createOctreeTriangleSelector(quakeLevelMesh->getMesh(0),
  390. quakeLevelNode, 128);
  391. // if not using shader and no gamma it's better to use more lighting, because
  392. // quake3 level are usually dark
  393. quakeLevelNode->setMaterialType ( video::EMT_LIGHTMAP_M4 );
  394. // set additive blending if wanted
  395. if (additive)
  396. quakeLevelNode->setMaterialType(video::EMT_LIGHTMAP_ADD);
  397. }
  398. // the additional mesh can be quite huge and is unoptimized
  399. scene::IMesh * additional_mesh = quakeLevelMesh->getMesh ( scene::quake3::E_Q3_MESH_ITEMS );
  400. for ( i = 0; i!= additional_mesh->getMeshBufferCount (); ++i )
  401. {
  402. scene::IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer ( i );
  403. const video::SMaterial &material = meshBuffer->getMaterial();
  404. //! The ShaderIndex is stored in the material parameter
  405. s32 shaderIndex = (s32) material.MaterialTypeParam2;
  406. // the meshbuffer can be rendered without additional support, or it has no shader
  407. const scene::quake3::IShader *shader = quakeLevelMesh->getShader ( shaderIndex );
  408. if ( 0 == shader )
  409. {
  410. continue;
  411. }
  412. // Now add the MeshBuffer(s) with the current Shader to the Manager
  413. sm->addQuake3SceneNode ( meshBuffer, shader );
  414. }
  415. }
  416. // load sydney model and create 2 instances
  417. /*
  418. scene::IAnimatedMesh* mesh = 0;
  419. mesh = sm->getMesh(IRRLICHT_MEDIA_PATH "sydney.md2");
  420. if (mesh)
  421. {
  422. model1 = sm->addAnimatedMeshSceneNode(mesh);
  423. if (model1)
  424. {
  425. model1->setMaterialTexture(0, driver->getTexture(IRRLICHT_MEDIA_PATH "spheremap.jpg"));
  426. model1->setPosition(core::vector3df(100,40,-80));
  427. model1->setScale(core::vector3df(2,2,2));
  428. model1->setMD2Animation(scene::EMAT_STAND);
  429. model1->setMaterialFlag(video::EMF_LIGHTING, false);
  430. model1->setMaterialType(video::EMT_SPHERE_MAP);
  431. model1->addShadowVolumeSceneNode();
  432. model1->setAutomaticCulling ( scene::EAC_BOX );
  433. }
  434. model2 = sm->addAnimatedMeshSceneNode(mesh);
  435. if (model2)
  436. {
  437. model2->setPosition(core::vector3df(180,15,-60));
  438. model2->setScale(core::vector3df(2,2,2));
  439. model2->setMD2Animation(scene::EMAT_RUN);
  440. model2->setMaterialTexture(0, device->getVideoDriver()->getTexture(IRRLICHT_MEDIA_PATH "sydney.bmp"));
  441. model2->setMaterialFlag(video::EMF_LIGHTING, true);
  442. model2->addShadowVolumeSceneNode();
  443. model2->setAutomaticCulling ( scene::EAC_BOX );
  444. }
  445. }
  446. */
  447. scene::ISceneNodeAnimator* anim = 0;
  448. // create sky box
  449. driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);
  450. skyboxNode = sm->addSkyBoxSceneNode(
  451. driver->getTexture(IRRLICHT_MEDIA_PATH "irrlicht2_up.jpg"),
  452. driver->getTexture(IRRLICHT_MEDIA_PATH "irrlicht2_dn.jpg"),
  453. driver->getTexture(IRRLICHT_MEDIA_PATH "irrlicht2_lf.jpg"),
  454. driver->getTexture(IRRLICHT_MEDIA_PATH "irrlicht2_rt.jpg"),
  455. driver->getTexture(IRRLICHT_MEDIA_PATH "irrlicht2_ft.jpg"),
  456. driver->getTexture(IRRLICHT_MEDIA_PATH "irrlicht2_bk.jpg"));
  457. driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
  458. //driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);
  459. // create walk-between-portals animation
  460. core::vector3df waypoint[2];
  461. waypoint[0].set(-150,40,100);
  462. waypoint[1].set(350,40,100);
  463. if (model2)
  464. {
  465. anim = device->getSceneManager()->createFlyStraightAnimator(waypoint[0],
  466. waypoint[1], 2000, true);
  467. model2->addAnimator(anim);
  468. anim->drop();
  469. }
  470. // create animation for portals;
  471. core::array<video::ITexture*> textures;
  472. for (s32 g=1; g<8; ++g)
  473. {
  474. core::stringc tmp(IRRLICHT_MEDIA_PATH "portal");
  475. tmp += g;
  476. tmp += ".bmp";
  477. video::ITexture* t = driver->getTexture( tmp );
  478. textures.push_back(t);
  479. }
  480. anim = sm->createTextureAnimator(textures, 100);
  481. // create portals
  482. scene::IBillboardSceneNode* bill = 0;
  483. for (int r=0; r<2; ++r)
  484. {
  485. bill = sm->addBillboardSceneNode(0, core::dimension2d<f32>(100,100),
  486. waypoint[r]+ core::vector3df(0,20,0));
  487. bill->setMaterialFlag(video::EMF_LIGHTING, false);
  488. bill->setMaterialTexture(0, driver->getTexture(IRRLICHT_MEDIA_PATH "portal1.bmp"));
  489. bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
  490. bill->addAnimator(anim);
  491. }
  492. anim->drop();
  493. // create cirlce flying dynamic light with transparent billboard attached
  494. scene::ILightSceneNode* light = 0;
  495. light = sm->addLightSceneNode(0,
  496. core::vector3df(0,0,0), video::SColorf(1.0f, 1.0f, 1.f, 1.0f), 500.f);
  497. anim = sm->createFlyCircleAnimator(
  498. core::vector3df(100,150,80), 80.0f, 0.0005f);
  499. light->addAnimator(anim);
  500. anim->drop();
  501. bill = device->getSceneManager()->addBillboardSceneNode(
  502. light, core::dimension2d<f32>(40,40));
  503. bill->setMaterialFlag(video::EMF_LIGHTING, false);
  504. bill->setMaterialTexture(0, driver->getTexture(IRRLICHT_MEDIA_PATH "particlewhite.bmp"));
  505. bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
  506. // create meta triangle selector with all triangles selectors in it.
  507. metaSelector = sm->createMetaTriangleSelector();
  508. metaSelector->addTriangleSelector(mapSelector);
  509. // create camp fire
  510. campFire = sm->addParticleSystemSceneNode(false);
  511. campFire->setPosition(core::vector3df(100,120,600));
  512. campFire->setScale(core::vector3df(2,2,2));
  513. scene::IParticleEmitter* em = campFire->createBoxEmitter(
  514. core::aabbox3d<f32>(-7,0,-7,7,1,7),
  515. core::vector3df(0.0f,0.06f,0.0f),
  516. 80,100, video::SColor(0,255,255,255),video::SColor(0,255,255,255), 800,2000);
  517. em->setMinStartSize(core::dimension2d<f32>(20.0f, 10.0f));
  518. em->setMaxStartSize(core::dimension2d<f32>(20.0f, 10.0f));
  519. campFire->setEmitter(em);
  520. em->drop();
  521. scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector();
  522. campFire->addAffector(paf);
  523. paf->drop();
  524. campFire->setMaterialFlag(video::EMF_LIGHTING, false);
  525. campFire->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false);
  526. campFire->setMaterialTexture(0, driver->getTexture(IRRLICHT_MEDIA_PATH "fireball.bmp"));
  527. campFire->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
  528. // load music
  529. #ifdef USE_IRRKLANG
  530. if (music)
  531. startIrrKlang();
  532. #endif
  533. #ifdef USE_SDL_MIXER
  534. if (music)
  535. startSound();
  536. #endif
  537. }
  538. void CDemo::createLoadingScreen()
  539. {
  540. core::dimension2d<u32> size = device->getVideoDriver()->getScreenSize();
  541. device->getCursorControl()->setVisible(false);
  542. // setup loading screen
  543. backColor.set(255,90,90,156);
  544. // create in fader
  545. inOutFader = device->getGUIEnvironment()->addInOutFader();
  546. inOutFader->setColor(backColor, video::SColor ( 0, 230, 230, 230 ));
  547. // irrlicht logo
  548. device->getGUIEnvironment()->addImage(device->getVideoDriver()->getTexture("../../media/irrlichtlogo2.png"),
  549. core::position2d<s32>(5,5));
  550. // loading text
  551. const int lwidth = size.Width - 20;
  552. const int lheight = 16;
  553. core::rect<int> pos(10, size.Height-lheight-10, 10+lwidth, size.Height-10);
  554. device->getGUIEnvironment()->addImage(pos);
  555. statusText = device->getGUIEnvironment()->addStaticText(L"Loading...", pos, true);
  556. statusText->setOverrideColor(video::SColor(255,205,200,200));
  557. // load bigger font
  558. device->getGUIEnvironment()->getSkin()->setFont(
  559. device->getGUIEnvironment()->getFont(IRRLICHT_MEDIA_PATH "fonthaettenschweiler.bmp"));
  560. // set new font color
  561. device->getGUIEnvironment()->getSkin()->setColor(gui::EGDC_BUTTON_TEXT,
  562. video::SColor(255,100,100,100));
  563. }
  564. void CDemo::CalculateSyndeyBoundingBox(void)
  565. {
  566. // Find the extents of the player character's model (for networking collision checks)
  567. scene::IAnimatedMesh* mesh = 0;
  568. scene::ISceneManager *sm = device->getSceneManager();
  569. mesh = sm->getMesh(IRRLICHT_MEDIA_PATH "sydney.md2");
  570. irr::scene::IAnimatedMeshSceneNode* model;
  571. model = sm->addAnimatedMeshSceneNode(mesh, 0);
  572. model->setScale(core::vector3df(2,2,2));
  573. // Bounding box changed in Irrlicht 1.5.1
  574. core::aabbox3df modelBoundingBox = model->getMesh()->getBoundingBox();
  575. // core::aabbox3df modelBoundingBox = model->getBoundingBox();
  576. core::vector3df minEdgeExtended = modelBoundingBox.MinEdge;
  577. core::vector3df maxEdgeExtended = modelBoundingBox.MaxEdge;
  578. minEdgeExtended.X-=BALL_DIAMETER/2;
  579. minEdgeExtended.Y-=BALL_DIAMETER/2;
  580. minEdgeExtended.Z-=BALL_DIAMETER/2;
  581. maxEdgeExtended.X+=BALL_DIAMETER/2;
  582. maxEdgeExtended.Y+=BALL_DIAMETER/2;
  583. maxEdgeExtended.Z+=BALL_DIAMETER/2;
  584. syndeyBoundingBox.MinEdge=minEdgeExtended;
  585. syndeyBoundingBox.MaxEdge=maxEdgeExtended;
  586. model->remove();
  587. };
  588. // RakNet - Precalculate bounding box of Sydney.md2, since our own player's model is never loaded
  589. // This only works on the assumption that all players have the same model
  590. const core::aabbox3df& CDemo::GetSyndeyBoundingBox(void) const
  591. {
  592. return syndeyBoundingBox;
  593. }
  594. void CDemo::PlayDeathSound(core::vector3df position)
  595. {
  596. if (irrKlang)
  597. {
  598. irrklang::ISound* sound =
  599. irrKlang->play3D(impactSound, position, false, false, true);
  600. if (sound)
  601. {
  602. // adjust max value a bit to make to sound of an impact louder
  603. sound->setMinDistance(400);
  604. sound->drop();
  605. }
  606. }
  607. }
  608. void CDemo::EnableInput(bool enabled)
  609. {
  610. scene::ICameraSceneNode* camera = GetSceneManager()->getActiveCamera();
  611. camera->setInputReceiverEnabled(enabled);
  612. }
  613. // RakNet - change shoot from assuming the camera, to taking any starting location
  614. // This way the same function can be called from the network
  615. RakNet::TimeMS CDemo::shootFromOrigin(core::vector3df camPosition, core::vector3df camAt)
  616. {
  617. scene::ISceneManager* sm = device->getSceneManager();
  618. scene::ICameraSceneNode* camera = sm->getActiveCamera();
  619. if (!camera || !mapSelector)
  620. return 0;
  621. SParticleImpact imp;
  622. imp.when = 0;
  623. // get line of camera
  624. core::vector3df start = camPosition;
  625. core::vector3df end = (camAt);
  626. //end.normalize();
  627. start += end*8.0f;
  628. end = start + (end * camera->getFarValue());
  629. core::triangle3df triangle;
  630. core::line3d<f32> line(start, end);
  631. // get intersection point with map
  632. scene::ISceneNode* hitNode;
  633. if (sm->getSceneCollisionManager()->getCollisionPoint(
  634. line, mapSelector, end, triangle, hitNode))
  635. {
  636. // collides with wall
  637. core::vector3df out = triangle.getNormal();
  638. out.setLength(0.03f);
  639. imp.when = 1;
  640. imp.outVector = out;
  641. imp.pos = end;
  642. }
  643. else
  644. {
  645. // doesnt collide with wall
  646. core::vector3df start = camPosition;
  647. core::vector3df end = (camAt);
  648. //end.normalize();
  649. start += end*8.0f;
  650. end = start + (end * camera->getFarValue());
  651. }
  652. // create fire ball
  653. scene::ISceneNode* node = 0;
  654. node = sm->addBillboardSceneNode(0,
  655. core::dimension2d<f32>(BALL_DIAMETER,BALL_DIAMETER), start);
  656. node->setMaterialFlag(video::EMF_LIGHTING, false);
  657. node->setMaterialTexture(0, device->getVideoDriver()->getTexture(IRRLICHT_MEDIA_PATH "fireball.bmp"));
  658. node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
  659. f32 length = (f32)(end - start).getLength();
  660. const f32 speed = SHOT_SPEED;
  661. u32 time = (u32)(length / speed);
  662. scene::ISceneNodeAnimator* anim = 0;
  663. // set flight line
  664. anim = sm->createFlyStraightAnimator(start, end, time);
  665. node->addAnimator(anim);
  666. anim->drop();
  667. anim = sm->createDeleteAnimator(time);
  668. node->addAnimator(anim);
  669. anim->drop();
  670. if (imp.when)
  671. {
  672. // create impact note
  673. imp.when = device->getTimer()->getTime() + (time - 100);
  674. Impacts.push_back(imp);
  675. }
  676. // play sound
  677. #ifdef USE_IRRKLANG
  678. if (ballSound)
  679. {
  680. // irrKlang->play2D(ballSound);
  681. // RakNet: Make the sound 3d so others can hear it from the proper origin
  682. irrklang::ISound* sound =
  683. irrKlang->play3D(ballSound, node->getPosition(), false, false, true);
  684. if (sound)
  685. {
  686. // adjust max value a bit to make to sound of an impact louder
  687. sound->setMinDistance(400);
  688. sound->drop();
  689. }
  690. }
  691. #endif
  692. #ifdef USE_SDL_MIXER
  693. if (ballSound)
  694. playSound(ballSound);
  695. #endif
  696. return (RakNet::TimeMS) time;
  697. }
  698. void CDemo::shoot()
  699. {
  700. if (playerReplica->IsDead())
  701. return;
  702. scene::ISceneManager* sm = device->getSceneManager();
  703. scene::ICameraSceneNode* camera = sm->getActiveCamera();
  704. core::vector3df camPosition = camera->getPosition();
  705. core::vector3df camAt = (camera->getTarget() - camPosition);
  706. camAt.normalize();
  707. BallReplica *br = new BallReplica;
  708. br->demo=this;
  709. br->position=camPosition;
  710. br->shotDirection=camAt;
  711. br->shotLifetime=RakNet::GetTimeMS() + shootFromOrigin(camPosition, camAt);
  712. replicaManager3->Reference(br);
  713. }
  714. void CDemo::createParticleImpacts()
  715. {
  716. u32 now = device->getTimer()->getTime();
  717. scene::ISceneManager* sm = device->getSceneManager();
  718. for (s32 i=0; i<(s32)Impacts.size(); ++i)
  719. if (now > Impacts[i].when)
  720. {
  721. // create smoke particle system
  722. scene::IParticleSystemSceneNode* pas = 0;
  723. pas = sm->addParticleSystemSceneNode(false, 0, -1, Impacts[i].pos);
  724. pas->setParticleSize(core::dimension2d<f32>(10.0f, 10.0f));
  725. scene::IParticleEmitter* em = pas->createBoxEmitter(
  726. core::aabbox3d<f32>(-5,-5,-5,5,5,5),
  727. Impacts[i].outVector, 20,40, video::SColor(0,255,255,255),video::SColor(0,255,255,255),
  728. 1200,1600, 20);
  729. pas->setEmitter(em);
  730. em->drop();
  731. scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector();
  732. pas->addAffector(paf);
  733. paf->drop();
  734. pas->setMaterialFlag(video::EMF_LIGHTING, false);
  735. pas->setMaterialTexture(0, device->getVideoDriver()->getTexture(IRRLICHT_MEDIA_PATH "smoke.bmp"));
  736. pas->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA);
  737. scene::ISceneNodeAnimator* anim = sm->createDeleteAnimator(2000);
  738. pas->addAnimator(anim);
  739. anim->drop();
  740. // play impact sound
  741. #ifdef USE_IRRKLANG
  742. if (irrKlang)
  743. {
  744. irrklang::ISound* sound =
  745. irrKlang->play3D(impactSound, Impacts[i].pos, false, false, true);
  746. if (sound)
  747. {
  748. // adjust max value a bit to make to sound of an impact louder
  749. sound->setMinDistance(400);
  750. sound->drop();
  751. }
  752. }
  753. #endif
  754. #ifdef USE_SDL_MIXER
  755. if (impactSound)
  756. playSound(impactSound);
  757. #endif
  758. // delete entry
  759. Impacts.erase(i);
  760. i--;
  761. }
  762. }
  763. /// RakNet stuff
  764. void CDemo::UpdateRakNet(void)
  765. {
  766. RakNet::SystemAddress facilitatorSystemAddress(DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP, DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_PORT);
  767. RakNet::Packet *packet;
  768. RakNet::TimeMS curTime = RakNet::GetTimeMS();
  769. RakNet::RakString targetName;
  770. for (packet=rakPeer->Receive(); packet; rakPeer->DeallocatePacket(packet), packet=rakPeer->Receive())
  771. {
  772. if (strcmp(packet->systemAddress.ToString(false),DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP)==0)
  773. {
  774. targetName="NATPunchthroughServer";
  775. }
  776. else
  777. {
  778. targetName=packet->systemAddress.ToString(true);
  779. }
  780. switch (packet->data[0])
  781. {
  782. case ID_IP_RECENTLY_CONNECTED:
  783. {
  784. PushMessage(RakNet::RakString("This IP address recently connected from ") + targetName + RakNet::RakString("."));
  785. if (packet->systemAddress==facilitatorSystemAddress)
  786. PushMessage("Multiplayer will not work without the NAT punchthrough server!");
  787. }
  788. break;
  789. case ID_INCOMPATIBLE_PROTOCOL_VERSION:
  790. {
  791. PushMessage(RakNet::RakString("Incompatible protocol version from ") + targetName + RakNet::RakString("."));
  792. if (packet->systemAddress==facilitatorSystemAddress)
  793. PushMessage("Multiplayer will not work without the NAT punchthrough server!");
  794. }
  795. break;
  796. case ID_DISCONNECTION_NOTIFICATION:
  797. {
  798. PushMessage(RakNet::RakString("Disconnected from ") + targetName + RakNet::RakString("."));
  799. if (packet->systemAddress==facilitatorSystemAddress)
  800. isConnectedToNATPunchthroughServer=false;
  801. }
  802. break;
  803. case ID_CONNECTION_LOST:
  804. {
  805. PushMessage(RakNet::RakString("Connection to ") + targetName + RakNet::RakString(" lost."));
  806. if (packet->systemAddress==facilitatorSystemAddress)
  807. isConnectedToNATPunchthroughServer=false;
  808. }
  809. break;
  810. case ID_NO_FREE_INCOMING_CONNECTIONS:
  811. {
  812. PushMessage(RakNet::RakString("No free incoming connections to ") + targetName + RakNet::RakString("."));
  813. if (packet->systemAddress==facilitatorSystemAddress)
  814. PushMessage("Multiplayer will not work without the NAT punchthrough server!");
  815. }
  816. break;
  817. case ID_NEW_INCOMING_CONNECTION:
  818. {
  819. if (fullyConnectedMesh2->IsHostSystem())
  820. {
  821. PushMessage(RakNet::RakString("Sending player list to new connection"));
  822. fullyConnectedMesh2->StartVerifiedJoin(packet->guid);
  823. }
  824. }
  825. break;
  826. case ID_FCM2_VERIFIED_JOIN_START:
  827. {
  828. DataStructures::List<RakNet::SystemAddress> addresses;
  829. DataStructures::List<RakNet::RakNetGUID> guids;
  830. fullyConnectedMesh2->GetVerifiedJoinRequiredProcessingList(packet->guid, addresses, guids);
  831. for (unsigned int i=0; i < guids.Size(); i++)
  832. natPunchthroughClient->OpenNAT(guids[i], facilitatorSystemAddress);
  833. }
  834. break;
  835. case ID_FCM2_VERIFIED_JOIN_FAILED:
  836. {
  837. PushMessage(RakNet::RakString("Failed to join game session"));
  838. }
  839. break;
  840. case ID_FCM2_VERIFIED_JOIN_CAPABLE:
  841. {
  842. fullyConnectedMesh2->RespondOnVerifiedJoinCapable(packet, true, 0);
  843. }
  844. break;
  845. case ID_FCM2_VERIFIED_JOIN_ACCEPTED:
  846. {
  847. DataStructures::List<RakNet::RakNetGUID> systemsAccepted;
  848. bool thisSystemAccepted;
  849. fullyConnectedMesh2->GetVerifiedJoinAcceptedAdditionalData(packet, &thisSystemAccepted, systemsAccepted, 0);
  850. if (thisSystemAccepted)
  851. PushMessage("Game join request accepted\n");
  852. else
  853. PushMessage(RakNet::RakString("System %s joined the mesh\n", systemsAccepted[0].ToString()));
  854. // DataStructures::List<RakNetGUID> participantList;
  855. // fullyConnectedMesh2->GetParticipantList(participantList);
  856. for (unsigned int i=0; i < systemsAccepted.Size(); i++)
  857. replicaManager3->PushConnection(replicaManager3->AllocConnection(rakPeer->GetSystemAddressFromGuid(systemsAccepted[i]), systemsAccepted[i]));
  858. }
  859. break;
  860. case ID_CONNECTION_REQUEST_ACCEPTED:
  861. {
  862. PushMessage(RakNet::RakString("Connection request to ") + targetName + RakNet::RakString(" accepted."));
  863. if (packet->systemAddress==facilitatorSystemAddress)
  864. {
  865. isConnectedToNATPunchthroughServer=true;
  866. // Open UPNP.
  867. struct UPNPDev * devlist = 0;
  868. devlist = upnpDiscover(1000, 0, 0, 0);
  869. if (devlist)
  870. {
  871. char lanaddr[64]; /* my ip address on the LAN */
  872. struct UPNPUrls urls;
  873. struct IGDdatas data;
  874. if (UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))==1)
  875. {
  876. // External port is the port people will be connecting to us on. This is our port as seen by the directory server
  877. // Internal port is the port RakNet was internally started on
  878. char eport[32], iport[32];
  879. natPunchthroughClient->GetUPNPPortMappings(eport, iport, facilitatorSystemAddress);
  880. int r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
  881. eport, iport, lanaddr, 0, "UDP", 0);
  882. if(r==UPNPCOMMAND_SUCCESS)
  883. {
  884. // UPNP done
  885. }
  886. }
  887. }
  888. // Query cloud for other running game instances
  889. RakNet::CloudQuery cloudQuery;
  890. cloudQuery.keys.Push(RakNet::CloudKey("IrrlichtDemo",0),_FILE_AND_LINE_);
  891. cloudClient->Get(&cloudQuery, packet->guid);
  892. }
  893. }
  894. break;
  895. case ID_FCM2_NEW_HOST:
  896. {
  897. if (packet->guid==rakPeer->GetMyGUID())
  898. {
  899. // Original host dropped. I am the new session host. Upload to the cloud so new players join this system.
  900. RakNet::CloudKey cloudKey("IrrlichtDemo",0);
  901. cloudClient->Post(&cloudKey, 0, 0, rakPeer->GetGuidFromSystemAddress(facilitatorSystemAddress));
  902. }
  903. }
  904. break;
  905. case ID_CLOUD_GET_RESPONSE:
  906. {
  907. RakNet::CloudQueryResult cloudQueryResult;
  908. cloudClient->OnGetReponse(&cloudQueryResult, packet);
  909. if (cloudQueryResult.rowsReturned.Size()>0)
  910. {
  911. PushMessage(RakNet::RakString("NAT punch to existing game instance"));
  912. natPunchthroughClient->OpenNAT(cloudQueryResult.rowsReturned[0]->clientGUID, facilitatorSystemAddress);
  913. }
  914. else
  915. {
  916. PushMessage(RakNet::RakString("Publishing new game instance"));
  917. // Start as a new game instance because no other games are running
  918. RakNet::CloudKey cloudKey("IrrlichtDemo",0);
  919. cloudClient->Post(&cloudKey, 0, 0, packet->guid);
  920. }
  921. cloudClient->DeallocateWithDefaultAllocator(&cloudQueryResult);
  922. }
  923. break;
  924. case ID_CONNECTION_ATTEMPT_FAILED:
  925. {
  926. PushMessage(RakNet::RakString("Connection attempt to ") + targetName + RakNet::RakString(" failed."));
  927. if (packet->systemAddress==facilitatorSystemAddress)
  928. PushMessage("Multiplayer will not work without the NAT punchthrough server!");
  929. }
  930. break;
  931. case ID_NAT_TARGET_NOT_CONNECTED:
  932. {
  933. RakNet::RakNetGUID recipientGuid;
  934. RakNet::BitStream bs(packet->data,packet->length,false);
  935. bs.IgnoreBytes(sizeof(RakNet::MessageID));
  936. bs.Read(recipientGuid);
  937. targetName=recipientGuid.ToString();
  938. PushMessage(RakNet::RakString("NAT target ") + targetName + RakNet::RakString(" not connected."));
  939. }
  940. break;
  941. case ID_NAT_TARGET_UNRESPONSIVE:
  942. {
  943. RakNet::RakNetGUID recipientGuid;
  944. RakNet::BitStream bs(packet->data,packet->length,false);
  945. bs.IgnoreBytes(sizeof(RakNet::MessageID));
  946. bs.Read(recipientGuid);
  947. targetName=recipientGuid.ToString();
  948. PushMessage(RakNet::RakString("NAT target ") + targetName + RakNet::RakString(" unresponsive."));
  949. }
  950. break;
  951. case ID_NAT_CONNECTION_TO_TARGET_LOST:
  952. {
  953. RakNet::RakNetGUID recipientGuid;
  954. RakNet::BitStream bs(packet->data,packet->length,false);
  955. bs.IgnoreBytes(sizeof(RakNet::MessageID));
  956. bs.Read(recipientGuid);
  957. targetName=recipientGuid.ToString();
  958. PushMessage(RakNet::RakString("NAT target connection to ") + targetName + RakNet::RakString(" lost."));
  959. }
  960. break;
  961. case ID_NAT_ALREADY_IN_PROGRESS:
  962. {
  963. RakNet::RakNetGUID recipientGuid;
  964. RakNet::BitStream bs(packet->data,packet->length,false);
  965. bs.IgnoreBytes(sizeof(RakNet::MessageID));
  966. bs.Read(recipientGuid);
  967. targetName=recipientGuid.ToString();
  968. PushMessage(RakNet::RakString("NAT punchthrough to ") + targetName + RakNet::RakString(" in progress (skipping)."));
  969. }
  970. break;
  971. case ID_NAT_PUNCHTHROUGH_SUCCEEDED:
  972. {
  973. if (packet->data[1]==1)
  974. {
  975. PushMessage(RakNet::RakString("Connecting to existing game instance"));
  976. RakNet::ConnectionAttemptResult car = rakPeer->Connect(packet->systemAddress.ToString(false), packet->systemAddress.GetPort(), 0, 0);
  977. RakAssert(car==RakNet::CONNECTION_ATTEMPT_STARTED);
  978. }
  979. }
  980. break;
  981. case ID_ADVERTISE_SYSTEM:
  982. if (packet->guid!=rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS))
  983. {
  984. char hostIP[32];
  985. packet->systemAddress.ToString(false,hostIP);
  986. RakNet::ConnectionAttemptResult car = rakPeer->Connect(hostIP,packet->systemAddress.GetPort(),0,0);
  987. RakAssert(car==RakNet::CONNECTION_ATTEMPT_STARTED);
  988. }
  989. break;
  990. }
  991. }
  992. // Call the Update function for networked game objects added to BaseIrrlichtReplica once the game is ready
  993. if (currentScene>=1)
  994. {
  995. unsigned int idx;
  996. for (idx=0; idx < replicaManager3->GetReplicaCount(); idx++)
  997. ((BaseIrrlichtReplica*)(replicaManager3->GetReplicaAtIndex(idx)))->Update(curTime);;
  998. }
  999. }
  1000. bool CDemo::IsKeyDown(EKEY_CODE keyCode) const {return KeyIsDown[keyCode];}
  1001. bool CDemo::IsMovementKeyDown(void) const {return KeyIsDown[KEY_UP] |
  1002. KeyIsDown[KEY_DOWN] |
  1003. KeyIsDown[KEY_LEFT] |
  1004. KeyIsDown[KEY_RIGHT] |
  1005. KeyIsDown[KEY_KEY_W] |
  1006. KeyIsDown[KEY_KEY_S] |
  1007. KeyIsDown[KEY_KEY_A] |
  1008. KeyIsDown[KEY_KEY_D];
  1009. }
  1010. void CDemo::PushMessage(RakNet::RakString rs)
  1011. {
  1012. outputMessages.Push(rs,_FILE_AND_LINE_);
  1013. if (whenOutputMessageStarted==0)
  1014. {
  1015. whenOutputMessageStarted=RakNet::GetTimeMS();
  1016. }
  1017. }
  1018. const char *CDemo::GetCurrentMessage(void)
  1019. {
  1020. if (outputMessages.GetSize()==0)
  1021. return "";
  1022. RakNet::TimeMS curTime = RakNet::GetTimeMS();
  1023. if (curTime-whenOutputMessageStarted>2500)
  1024. {
  1025. outputMessages.Pop(_FILE_AND_LINE_);
  1026. whenOutputMessageStarted=curTime;
  1027. }
  1028. if (outputMessages.GetSize()==0)
  1029. {
  1030. whenOutputMessageStarted=0;
  1031. return "";
  1032. }
  1033. return outputMessages.Peek().C_String();
  1034. }
  1035. #ifdef USE_IRRKLANG
  1036. void CDemo::startIrrKlang()
  1037. {
  1038. irrKlang = irrklang::createIrrKlangDevice();
  1039. if (!irrKlang)
  1040. return;
  1041. // play music
  1042. irrklang::ISound* snd = irrKlang->play2D(IRRLICHT_MEDIA_PATH "IrrlichtTheme.ogg", true, false, true);
  1043. if ( !snd )
  1044. snd = irrKlang->play2D("IrrlichtTheme.ogg", true, false, true);
  1045. if (snd)
  1046. {
  1047. snd->setVolume(0.5f); // 50% volume
  1048. snd->drop();
  1049. }
  1050. // preload both sound effects
  1051. ballSound = irrKlang->getSoundSource(IRRLICHT_MEDIA_PATH "ball.wav");
  1052. impactSound = irrKlang->getSoundSource(IRRLICHT_MEDIA_PATH "impact.wav");
  1053. }
  1054. #endif
  1055. #ifdef USE_SDL_MIXER
  1056. void CDemo::startSound()
  1057. {
  1058. stream = NULL;
  1059. ballSound = NULL;
  1060. impactSound = NULL;
  1061. SDL_Init(SDL_INIT_AUDIO);
  1062. if (Mix_OpenAudio(22050, AUDIO_S16, 2, 128))
  1063. return;
  1064. stream = Mix_LoadMUS(IRRLICHT_MEDIA_PATH "IrrlichtTheme.ogg");
  1065. if (stream)
  1066. Mix_PlayMusic(stream, -1);
  1067. ballSound = Mix_LoadWAV(IRRLICHT_MEDIA_PATH "ball.wav");
  1068. impactSound = Mix_LoadWAV(IRRLICHT_MEDIA_PATH "impact.wav");
  1069. }
  1070. void CDemo::playSound(Mix_Chunk *sample)
  1071. {
  1072. if (sample)
  1073. Mix_PlayChannel(-1, sample, 0);
  1074. }
  1075. void CDemo::pollSound(void)
  1076. {
  1077. SDL_Event event;
  1078. while (SDL_PollEvent(&event))
  1079. ;
  1080. }
  1081. #endif
粤ICP备19079148号